定义元数据 (meta.yaml)#

conda-build 配方中的所有元数据都指定在 meta.yaml 文件中。请参见下面的示例

{% set version = "1.1.0" %}

package:
  name: imagesize
  version: {{ version }}

source:
  url: https://pypi.io/packages/source/i/imagesize/imagesize-{{ version }}.tar.gz
  sha256: f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5

build:
  noarch: python
  number: 0
  script: python -m pip install --no-deps --ignore-installed .

requirements:
  host:
    - python
    - pip
  run:
    - python

test:
  imports:
    - imagesize

about:
  home: https://github.com/shibukawa/imagesize_py
  license: MIT
  summary: 'Getting image size from png/jpeg/jpeg2000/gif file'
  description: |
    This module analyzes jpeg/jpeg2000/png/gif image header and
    return image size.
  dev_url: https://github.com/shibukawa/imagesize_py
  doc_url: https://pypi.python.org/pypi/imagesize
  doc_source_url: https://github.com/shibukawa/imagesize_py/blob/master/README.rst

除了 package/namepackage/version 之外,所有部分都是可选的。

标题必须只出现一次。如果它们出现多次,只记住最后一个。例如,package: 标题应该在文件中只出现一次。

包部分#

指定包信息。

包名称#

包的小写名称。它可能包含“ - ”,但不包含空格。

package:
  name: bsdiff4

包版本#

包的版本号。使用 PEP-386 verlib 约定。不能包含“ - ”。YAML 将诸如 1.0 之类的版本号解释为浮点数,这意味着 0.10 将与 0.1 相同。为了避免这种情况,请将版本号放在引号中,以便将其解释为字符串。

package:
  version: "1.1.4"

注意

构建后版本控制:在某些情况下,您可能直到构建完包后才能知道包的版本、构建号或构建字符串。在这些情况下,您可以执行 使用 Jinja 进行模板化 或利用 Git 环境变量继承的环境变量

源部分#

指定包的源代码来自哪里。源代码可以来自 tarball 文件、git、hg 或 svn。它可以是本地路径,并且可以包含补丁。

从 tarball 或 zip 存档获取源代码#

source:
  url: https://pypi.python.org/packages/source/b/bsdiff4/bsdiff4-1.1.4.tar.gz
  md5: 29f6089290505fc1a852e176bd276c43
  sha1: f0a2c9a30073449cfb7d171c57552f3109d93894
  sha256: 5a022ff4c1d1de87232b1c70bde50afbb98212fd246be4a867d8737173cf1f8f

如果提取的存档在其顶层只包含 1 个文件夹,其内容将向上移动 1 级,以便提取的包内容位于工作文件夹的根目录中。

您还可以为同一个源存档指定多个 URL。如果一个失败,它们将按顺序尝试。

source:
  url:
    - https://archive.linux.duke.edu/cran/src/contrib/ggblanket_6.0.0.tar.gz
    - https://archive.linux.duke.edu/cran/src/contrib/Archive/ggblanket/ggblanket_6.0.0.tar.gz
  sha256: cd2181fe3d3365eaf36ff8bbbc90ea9d76c56d40e63386b4eefa0e3120ec6665

从 git 获取源代码#

git_url 也可以是相对于配方目录的相对路径。

source:
  git_url: https://github.com/ilanschnell/bsdiff4.git
  git_rev: 1.1.4 # (Defaults to "HEAD")
  git_depth: 1 # (Defaults to -1/not shallow)

depth 参数与执行浅层克隆的能力有关。浅层克隆意味着您只从 Git 下载部分历史记录。如果您知道您只需要最新的更改,则可以说,git_depth: 1,这比克隆整个仓库更快。将其设置为 1 的缺点是,除非标签在该特定提交上,否则在您转到在 git_rev 中引用它时,您将没有该标签(例如)。如果您的 git_depth 不足以捕获 git_rev 中的标签,您将遇到错误。所以在上面的示例中,除非 1.1.4 是您要获取的最新提交,否则您可能会遇到错误。

从 hg 获取源代码#

source:
  hg_url: ssh://[email protected]/ilanschnell/bsdiff4
  hg_tag: 1.1.4

从 svn 获取源代码#

source:
  svn_url: https://github.com/ilanschnell/bsdiff
  svn_rev: 1.1.4 # (defaults to head)
  svn_ignore_externals: True # (defaults to False)
  svn_username: username  # Optional, if set must also have svn_password
  svn_password: password  # Optional, if set must also have svn_username

要访问受限的 SVN 存储库,请同时指定 svn_usernamesvn_password

注意

将凭据存储在纯文本中存在风险。或者,考虑使用环境变量

source:
  svn_username: {{ environ["SVN_USERNAME"] }}
  svn_password: {{ environ["SVN_PASSWORD"] }}

从本地路径获取源代码#

如果路径是相对路径,则它相对于配方目录。源代码在构建之前被复制到工作目录。

source:
  path: ../src

如果本地路径是 git 或 svn 存储库,您将获得在构建环境中定义的相应环境变量。git_url 或 hg_url 和路径作为源参数之间的唯一实际区别是 git_url 和 hg_url 将是存储库的克隆,而路径将是存储库的副本。使用路径允许您使用工作目录中的暂存和未提交的更改构建包。git_url 只能构建到最新的提交。

补丁#

补丁可以选择应用于源代码。

source:
  #[source information here]
  patches:
    - my.patch # the patch file is expected to be found in the recipe

Conda-build 自动确定补丁剥离级别。

目标路径#

在 conda-build 的工作目录中,您可以指定一个特定的文件夹来放置源代码。此功能是 conda-build 3.0 中的新功能。Conda-build 将始终将您放到同一个文件夹(构建文件夹/工作),但您决定将源代码解压到该文件夹中,还是嵌套更深。此功能在处理多个源代码时特别有用,但也适用于具有单个源代码的配方。

source:
  #[source information here]
  folder: my-destination/folder

文件名#

文件名键是 fn。以前在 URL 源类型中是必需的。现在不是必需的。

如果提供了 fn 键,则文件将使用该名称保存到磁盘。如果没有提供 fn 键,则文件将使用与 URL 的最后部分匹配的名称保存到磁盘。

例如,http://www.something.com/myfile.zip 具有 myfile.zip 的隐式文件名。用户可以通过手动指定 fn 来更改它。

source:
  url: http://www.something.com/myfile.zip
  fn: otherfilename.zip

从多个源代码获取源代码#

一些软件最容易通过聚合几个部分来构建。为此,conda-build 3.0 添加了对任意指定多个源代码的支持。

语法是源字典列表。此列表中的每个成员都遵循与早期 conda-build 版本的单个源代码相同的规则(如上所述)。每个成员的所有功能都受支持。

示例

source:
  - url: https://package1.com/a.tar.bz2
    folder: stuff
  - url: https://package1.com/b.tar.bz2
    folder: stuff
  - git_url: https://github.com/conda/conda-build
    folder: conda-build

在这里,两个 URL tarball 将进入一个文件夹,而 git 仓库将签出到它自己的空间。Git 不会克隆到非空文件夹。

注意

破折号在 YAML 语法中表示列表项。

构建部分#

指定构建信息。

每个需要路径的字段也可以处理通配符模式。匹配是从构建环境的顶部执行的,因此要匹配项目中的文件,您可以使用类似于以下模式的模式:“**/myproject/**/*.txt”。此模式将匹配项目中找到的任何 .txt 文件。

注意

对于以 * 开头的模式,需要引号 ("")。

使用 ** 进行递归通配仅在 conda-build >= 3.0 中受支持。

构建编号和字符串#

构建号应该为相同版本的新的构建递增。该数字默认为 0。构建字符串不能包含“ - ”。该字符串默认为默认的 conda-build 字符串加上构建号。

build:
  number: 1
  string: abc

当包受 conda_build_config.yaml 文件中的一个或多个变量影响时,将出现哈希。哈希由“使用”的变量组成 - 如果使用了任何东西,则您有一个哈希。如果您没有使用这些变量,那么您将没有哈希。有一些特殊情况不会影响哈希,例如 Python 和 R 或已经在构建字符串中占有一席之地的任何东西。

如果以下情况对任何依赖项都为真,则构建哈希将添加到构建字符串中

  • 包是构建、主机或运行依赖项中的显式依赖项

  • 包在 conda_build_config.yaml 中具有匹配的条目,该条目是对特定版本的固定,而不是下限

  • 该包不会被 ignore_version 忽略

或者

  • 包使用 {{ compiler() }} jinja2 函数

您还可以使用以下方法影响哪些变量被认为是哈希的

build:
  force_use_keys:
    - package_1
  force_ignore_keys:
    - package_2

这将确保 package_2 的值 *不会* 被认为是哈希,而 package_1 *将* 被认为是哈希,无论 conda-build 发现其检查是否使用它。

这可能有助于进一步拆分复杂的多输出构建,以确保构建每个包,或在使用更复杂的模板或脚本时确保正确的包哈希。

Python 入口点#

以下示例创建一个名为“bsdiff4”的 Python 入口点,该入口点调用 bsdiff4.cli.main_bsdiff4()

build:
  entry_points:
    - bsdiff4 = bsdiff4.cli:main_bsdiff4
    - bspatch4 = bsdiff4.cli:main_bspatch4

Python.app#

如果 osx_is_app 设置为 True,则入口点在 macOS 中使用 python.app 而不是 Python。默认值为 False

build:
  osx_is_app: True

跟踪功能#

将 track_features 添加到一个或多个选项将导致 conda 降低其优先级或“将其压低”。优先级最低的包是会在环境中激活最多 track_features 的包。在多个变体中,默认包是会激活最少 track_features 的包。

给定子目录中的任何两个包都不应该具有相同的 track_feature。

build:
  track_features:
    - feature2

保留 Python egg 目录#

这对于使用 setuptools 特定功能的一些软件包来说是必需的。默认值为 False

build:
  preserve_egg_dir: True

跳过将一些 .py 文件编译为 .pyc 文件#

有些软件包会附带不能编译的 .py 文件,例如包含模板的文件。还有一些软件包会附带不应该编译的 .py 文件,因为构建时无法确定将使用的 Python 解释器。在这些情况下,conda-build 可以跳过尝试编译这些文件。本节中使用的模式不需要 ** 来处理递归路径。

build:
  skip_compile_pyc:
    - "*/templates/*.py"          # These should not (and cannot) be compiled
    - "*/share/plugins/gdb/*.py"  # The python embedded into gdb is unknown

脚本#

用它代替 build.shbld.bat。对于简短的构建脚本,这会更方便。您可能需要使用 选择器 为不同的平台使用不同的脚本。

build:
  script: python setup.py install --single-version-externally-managed --record=record.txt

RPATH#

设置在 Linux 上使可执行文件可重定位时使用的 RPATH。这是一个 Linux 特性,在其他系统上会被忽略。默认值为 lib/

build:
  rpaths:
    - lib/
    - lib/R/lib/

强制文件#

强制始终包含文件,即使它们已在构建依赖项的环境中存在。例如,这可能需要用于创建 conda 本身的配方。

build:
  always_include_files:
    - bin/file1
    - bin/file2

重定位#

高级功能。您可以使用以下 4 个键来控制从构建环境到安装环境的可重定位文件

  • binary_relocation。

  • has_prefix_files。

  • binary_has_prefix_files。

  • ignore_prefix_files。

有关更多信息,请参阅 制作可重定位的软件包

二进制重定位#

是否应使用 macOS 上的 install_name_tool 或 Linux 上的 patchelf 使二进制文件可重定位。默认值为 True。它还接受 False,表示任何文件都不重定位,或一个文件列表,表示仅对列出的文件进行重定位。

build:
  binary_relocation: False

检测具有前缀的二进制文件#

二进制文件可能包含构建前缀,需要在安装时将其替换为安装前缀。Conda 可以自动识别和注册这些文件。默认值为 True

注意

默认值从 False 更改为 True,在 conda build 2.0 中。将其设置为 False 表示仍会执行二进制重定位(RPATH)替换,但不会替换二进制文件中的硬编码前缀。文本文件中的前缀仍将被替换。

build:
  detect_binary_files_with_prefix: False

Windows 处理二进制前缀替换的方式与 macOS 和 Linux 等类 Unix 系统非常不同。目前,我们不知道任何可执行文件或库在 Windows 上使用硬编码嵌入路径来定位其他库或程序数据。相反,Windows 遵循 DLL 搜索路径规则 或更本地地使用相对路径支持可重定位性。因此,conda 会忽略大多数前缀。但是,pip 会为 Python 入口点创建可执行文件,这些可执行文件确实在 Windows 上使用嵌入路径。因此,conda-build 默认情况下会检测所有文件中的前缀并记录它们。如果您在 Windows 上遇到路径长度错误,您应该尝试禁用 detect_binary_files_with_prefix。更新版本的 Conda,例如最近的 4.2.x 系列版本及更高版本,应该不会出现此问题,但早期版本的 conda 会错误地尝试应用任何二进制前缀替换。

二进制文件具有前缀文件#

默认情况下,conda-build 会尝试检测所有文件中的前缀。您也可以选择单独指定具有二进制前缀的文件。这允许您指定文件类型为二进制,而它可能由于某种原因被错误地检测为文本。二进制文件是包含空字节的文件。

build:
  binary_has_prefix_files:
    - bin/binaryfile1
    - lib/binaryfile2

具有前缀文件的文本文件#

文本文件(不包含空字节的文件)可能包含构建前缀,需要在安装时将其替换为安装前缀。Conda 会自动注册这些文件。包含构建前缀的二进制文件通常以不同的方式处理(请参阅 二进制文件具有前缀文件),但有些情况下,这样的二进制文件需要被视为普通的文本文件,在这种情况下,需要识别它们。

build:
  has_prefix_files:
    - bin/file1
    - lib/file2

忽略前缀文件#

用于从包含构建前缀替换为安装前缀的文件列表中排除构建配方中的一些或所有文件。

要忽略构建配方中的所有文件,请使用

build:
  ignore_prefix_files: True

要指定单个文件名,请使用

build:
  ignore_prefix_files:
    - file1

此设置独立于 RPATH 替换。使用 检测具有前缀的二进制文件 设置来控制该行为。

跳过构建#

指定 conda-build 是否应该跳过此配方的构建。对于定义特定于平台的配方特别有用。默认值为 False

build:
  skip: True  # [not win]

独立于体系结构的软件包#

允许您在构建软件包时指定“无体系结构”,从而使其与所有平台和体系结构兼容。无体系结构软件包可以安装在任何平台上。

从 conda-build 2.1 和 conda 4.3 开始,存在一种支持不同语言的新语法。将 noarch 键分配为 generic 会告诉 conda 不要尝试对内容进行任何操作。

build:
  noarch: generic

noarch: generic 对于静态 JavaScript 资产和源代码存档等软件包最有用。对于可以在任何 Python 版本上运行的纯 Python 软件包,您可以使用 noarch: python 值代替

build:
  noarch: python

noarch_python 的传统语法仍然有效,应该在您需要确保您的软件包可以安装在 conda 4.3 尚未可用的地方时使用。所有其他形式的无体系结构软件包都需要 conda >=4.3 才能安装。

build:
  noarch_python: True

警告

在撰写本文时,noarch 软件包不应该使用 预处理选择器noarch 软件包使用在构建它的平台中计算为 True 的指令构建,这可能会导致在其他平台上安装不正确或不完整。

包含构建配方#

完整的 conda-build 配方和渲染后的 meta.yaml 文件默认情况下包含在 软件包元数据 中。您可以使用以下方法禁用此功能

build:
  include_recipe: False

使用环境变量#

通常 build.shbld.bat 中的构建脚本不会传递来自命令行的环境变量。构建脚本只能看到 环境变量 中记录的环境变量。要“白名单”应该传递给构建脚本的环境变量

build:
  script_env:
    - MYVAR
    - ANOTHER_VAR

如果在构建过程中 conda-build 本身看到的环境中缺少列出的环境变量,则会发出 UserWarning,并且该变量仍然未定义。

此外,可以通过包含 = 后跟所需值来设置值

build:
  script_env:
   - MY_VAR=some value

注意

继承环境变量可能会使其他人难以从您的配方中复制二进制文件。谨慎使用此功能,或使用 = 语法显式设置值。

注意

如果您使用 --no-test--test 将构建和测试阶段分开,则需要确保构建时和测试时存在的环境变量匹配。如果您没有这样做,软件包哈希可能使用不同的值,并且您的软件包可能无法测试,因为哈希将不同。

导出运行时需求#

一些构建或主机 需求部分 会施加运行时需求。最常见的是,对于共享库(例如 libpng)来说是正确的,它们在构建时需要进行链接,并在运行时解析链接。使用 run_exports(conda-build 3 中新增)这样的运行时需求可以由主机需求隐式添加(例如 libpng 导出 libpng),并且使用 run_exports/strong 甚至可以由构建需求添加(例如 GCC 导出 libgcc)。

# meta.yaml of libpng
build:
  run_exports:
    - libpng

这里,因为没有指定任何特定类型的 run_exports,所以 libpng 的 run_exports 被认为是“弱”。这意味着它们只有在 libpng 位于主机部分时才会应用,此时它们会将其导出添加到运行部分。如果 libpng 列在构建部分,则 run_exports 不会应用于运行部分。

# meta.yaml of gcc compiler
build:
  run_exports:
    strong:
      - libgcc

还有 run_exports/weak,它等效于非特定类型的 run_exports,但如果要定义强和弱运行导出,它很有用。

run_exports 用于运行时之类的东西,其中运行时需要在主机和运行环境中存在,并且应该使用哪个运行时完全由构建部分中存在的内容决定。这种机制是我们在 Windows 上如何对齐适当软件的方式,我们必须在环境中的所有共享库中匹配使用的 MSVC 版本。

# meta.yaml of some package using gcc and libpng
requirements:
  build:
    - gcc            # has a strong run export
  host:
    - libpng         # has a (weak) run export
    # - libgcc       <-- implicitly added by gcc
  run:
    # - libgcc       <-- implicitly added by gcc
    # - libpng       <-- implicitly added by libpng

您可以直接表达版本约束,或使用在 其他 Jinja2 函数 中列出的任何 Jinja2 辅助函数。

例如,您可以使用 固定表达式 来获取相对于构建时存在的版本的灵活版本固定

build:
  run_exports:
    - {{ pin_subpackage('libpng', max_pin='x.x') }}

在这个例子中,如果 libpng 的版本是 1.6.34,这个固定表达式将被评估为 >=1.6.34,<1.7

如果构建和链接依赖项需要对运行环境施加约束,但并不一定需要引入额外的包,那么可以通过更改 Run_constrained 条目来实现。除了 weak/strong run_exports(它们会添加到 run 要求中)之外,weak_constrainsstrong_constrains 会添加到 run_constrained 要求中。使用这些,例如,可以表达兼容但非必需包的最小版本(如链接依赖项的可选插件,或某些系统属性)。

requirements:
  build:
    - build-tool                 # has a strong run_constrained export
  host:
    - link-dependency            # has a weak run_constrained export
  run:
  run_constrained:
    # - system-dependency >=min  <-- implicitly added by build-tool
    # - optional-plugin >=min    <-- implicitly added by link-dependency

请注意,run_exports 可以在构建部分和拆分包的每个输出的基础上进行指定。

run_exports 只影响直接命名的依赖项。例如,如果你有一个包含一个列出 run_exports 的编译器的元包,你也需要在元包中定义 run_exports,以便在人们安装你的元包时生效。这一点很重要,因为如果 run_exports 影响传递依赖项,你将会看到许多添加到共享库中的依赖项,而实际上它们并不是直接依赖项。例如,Python 使用 bzip2,它可以使用 run_exports 来确保人们使用兼容的 bzip2 构建版本。如果人们将 python 列为构建时依赖项,那么 bzip2 应该只对 Python 本身施加约束,而不应自动将其作为使用 Python 的事物的运行时依赖项。

此功能的潜在缺点是它会从下游用户手中夺走一些约束控制权。如果上游包具有有问题的 run_exports 约束,你可以在你的配方中通过在 build/ignore_run_exports 部分列出上游包名称来忽略它。

build:
  ignore_run_exports:
    - libstdc++

你也可以在 build/ignore_run_exports_from 部分列出 run_exports 约束来自的包。

build:
  ignore_run_exports_from:
    - {{ compiler('cxx') }}

固定运行时依赖项#

pin_depends 构建键可用于在输出配方或构建的包上强制执行固定行为。

有两种可能的行为:

build:
  pin_depends: record

当值为 record 时,conda-build 会记录所有要求,就像它们将被安装在一个名为 info/requires 的文件中一样。这些固定值不会出现在 conda render 的输出中,也不会影响输出包的实际运行依赖项。它只是在这个新文件中添加内容。

build:
  pin_depends: strict

当值为 strict 时,conda-build 会将固定值应用于实际元数据。这会影响 conda render 的输出,也会影响构建的最终结果。包依赖项将严格固定到构建字符串级别。这将取代 conda-build 可能执行的任何动态或兼容固定。

忽略过度链接/过度依赖检查中的文件#

构建部分中的 overlinking_ignore_patterns 键可用于忽略过度链接和过度依赖检查的文件模式。这在某些情况下很有用,例如加速具有许多文件的构建(大型重新打包作业)或你已知只有一小部分文件需要检查的构建。

这里允许使用通配符模式,但要注意你的引号,尤其是在有前导通配符的情况下。

谨慎使用此功能,因为过度链接检查通常可以防止你犯错。

build:
  overlinking_ignore_patterns:
    - "bin/*"

将共享库列入白名单#

构建键 missing_dso_whitelist 是一个动态共享对象 (DSO) 文件的通配符列表,在检查链接信息时应忽略这些文件。

在构建后阶段,会检查新创建的包中的共享库,以查找未由包的要求或预定义的系统库列表提供的链接。如果检测到此类库,则会产生警告 --no-error-overlinking 或错误 --error-overlinking

build:
  missing_dso_whitelist:

这些键允许向允许的库列表中添加内容。

构建键 runpath_whitelist 是一个路径的通配符列表,这些路径允许出现在包的共享库的运行路径中。所有其他运行路径都会导致在构建过程中打印警告消息。

build:
  runpath_whitelist:

要求部分#

指定构建和运行时要求。这些要求的依赖项会自动包含。

要求的版本必须遵循 conda 匹配规范。请参见 包匹配规范

构建#

构建包所需的工具。这些包在构建系统上运行,包括修订控制系统(Git、SVN)、make 工具(GNU make、Autotool、CMake)和编译器(真正的交叉编译、伪交叉编译或在不进行交叉编译时使用本地编译器),以及任何源代码预处理器。

提供“sysroot”文件的包,如 CDT 包(见下文),也属于构建部分。

requirements:
  build:
    - git
    - cmake

主机#

本节是在 conda-build 3.0 中添加的。它表示当目标平台不一定与原生构建平台相同时,需要特定于目标平台的包。例如,为了使配方能够“交叉兼容”,共享库要求必须列在主机部分,而不是构建部分,以便链接的共享库是针对目标平台的共享库,而不是针对原生构建平台的共享库。你还要包括需要解释器的包的基本解释器。换句话说,Python 包将在此处列出 python,而 R 包将列出 mro-baser-base

requirements:
  build:
    - {{ compiler('c') }}
    - {{ cdt('xorg-x11-proto-devel') }}  # [linux]
  host:
    - python

注意

当定义了构建和主机部分时,构建部分可以被认为是“构建工具” - 在原生平台上运行,但输出针对目标平台的结果。例如,一个在 linux-64 上运行,但针对 linux-armv7 的交叉编译器。

PREFIX 环境变量指向主机前缀。关于构建期间的激活,主机和构建环境都将被激活。构建前缀在主机前缀之后被激活,以便构建前缀(始终包含用于运行平台的原生可执行文件)优先于主机前缀,而主机前缀不保证提供原生可执行文件(例如,在交叉编译时)。

从 conda-build 3.1.4 开始,当同时定义了构建和主机前缀,或者使用 {{ compiler() }} Jinja2 函数时,构建和主机前缀始终是分开的。只有在主机部分不存在且 meta.yaml 中没有使用 {{ compiler() }} Jinja2 函数时,构建和主机才会合并。由于它们是分开的,因此在迁移配方时你可能会看到一些构建失败。例如,假设你有一个用于构建 Python 扩展的配方。如果你将编译器 Jinja2 函数添加到构建部分,但没有将 Python 依赖项从构建部分移到主机部分,你的配方将会失败。它会失败,因为主机环境是检测新文件的位置,但由于你只在构建环境中拥有 Python,因此你的扩展将被安装到构建环境中。不会检测到任何文件。此外,当 Python 未安装到主机环境中时,PYTHON 等变量也不会被定义。

在 Linux 上,通过使用 Anaconda Inc. 在 defaults 元通道中提供的编译器包,可以防止你的构建系统泄漏到已构建的软件中,方法是使用我们的 CDT(核心依赖树)包来处理任何“系统”依赖项。这些包是来自 CentOS6 的重新打包的库和头文件,它们被解压缩到我们伪交叉编译器的 sysroot 中,并会被它们自动找到。

请注意,什么算作“系统”依赖项是一个见仁见智的问题。Anaconda Distribution 选择不提供 X11 或 GL 包,因此我们使用 CDT 包来处理 X11。Conda-forge 选择提供 X11 和 GL 包。

在 macOS 上,你也可以使用 {{ compiler() }} 来获取 Anaconda Inc. 在 defaults 元通道中提供的编译器包。环境变量 MACOSX_DEPLOYMENT_TARGETCONDA_BUILD_SYSROOT 将由 conda-build 适当地设置(请参见 环境变量)。CONDA_BUILD_SYSROOT 将指定一个包含 macOS SDK 的文件夹。这些设置实现了向后兼容性,同时仍然提供对 C++14 和 C++17 的访问。请注意,conda-build 会通过解析 conda_build_config.yaml 来设置 CONDA_BUILD_SYSROOT。有关更多详细信息,请参见 Anaconda 编译器工具

简而言之:如果你使用 {{ compiler() }} Jinja2 来利用我们新的编译器,你必须将所有不严格属于构建工具的内容移到主机依赖项中。这包括 Python、Python 库以及你需要在构建中链接的任何共享库。构建工具的示例包括任何 {{ compiler() }}、Make、Autoconf、Perl(用于运行脚本,而不是安装 Perl 软件)以及 Python(用于运行脚本,而不是安装软件)。

运行#

运行该包所需的软件包。这些是在安装该包时自动安装的依赖项。软件包名称应遵循 软件包匹配规范

requirements:
  run:
    - python
    - argparse # [py26]
    - six >=1.8.0

要针对不同版本的 NumPy 构建配方并确保每个版本都是包依赖项的一部分,请在 meta.yaml 中列出 numpy x.x 作为需求,并使用带有 NumPy 版本选项的 conda-build,例如 --numpy 1.7

meta.yaml 文件中的行应直接写成 numpy x.x,不应包含任何数字。如果 meta.yaml 文件使用 numpy x.x,则需要使用带有 conda-build--numpy 选项。

requirements:
  run:
    - python
    - numpy x.x

注意

从 conda-build 3 开始,您可以使用 run_exports 来扩展构建和 host 部分中使用的软件包,这些软件包会自动添加到您的运行需求中,而不是手动指定运行需求。

运行受限#

在运行时可选但必须服从提供的附加约束(如果已安装)的软件包。

软件包名称应遵循 软件包匹配规范

requirements:
  run_constrained:
    - optional-subpackage =={{ version }}

例如,假设我们有一个环境,其中安装了版本为 1.0 的软件包“a”。如果我们安装了具有运行受限条目“a>1.0”的软件包“b”,那么 conda 需要升级环境中的“a”才能安装“b”。

这在虚拟软件包的上下文中特别有用,其中 run_constrained 依赖项不是 conda 管理的软件包,而是 虚拟软件包,它代表 conda 无法更改的系统属性。例如,linux 上的软件包可能会对 __glibc>=2.12 施加 run_constrained 依赖项。这是与 CentOS 6 一致的版本绑定。针对 glibc 2.12 构建的软件将与 CentOS 6 兼容。此 run_constrained 依赖项有助于 conda 告知用户,如果他们的系统 glibc 版本太旧,则无法安装给定软件包。

测试部分#

如果此部分存在,或者如果配方中存在 run_test.[py,pl,sh,bat] 文件,则在构建完成后将软件包安装到测试环境中,并在该环境中运行测试。

测试文件#

从配方复制到临时测试目录并在测试期间需要的测试文件。如果提供路径,则必须使用正斜杠。

test:
  files:
    - test-data.txt

源文件#

从源工作目录复制到临时测试目录并在测试期间需要的测试文件。

test:
  source_files:
    - test-data.txt
    - some/directory
    - some/directory/pattern*.sh

此功能是在 conda-build 2.0 中添加的。

测试需求#

除了运行时需求之外,您还可以指定测试期间需要的需求。您在上面描述的“运行”部分中指定的运行时需求在测试期间会自动包含在内。

test:
  requires:
    - nose

测试命令#

作为测试一部分运行的命令。

test:
  commands:
    - bsdiff4 -h
    - bspatch4 -h

Python 导入#

将在测试环境中导入的 Python 模块或软件包列表。

test:
  imports:
    - bsdiff4

这等效于拥有一个带有以下内容的 run_test.py

import bsdiff4

运行测试脚本#

如果脚本 run_test.sh ---或 .bat.py.pl ---是配方的一部分,则会自动运行该脚本。

注意

Python .py 和 Perl .pl 脚本仅分别作为 Python 和 Perl 软件包的一部分有效。

下游测试#

了解您的软件已成功构建并运行了测试是必要的,但不足以让整个软件系统保持运行。为了确信软件包的新构建不会破坏其他下游软件,conda-build 支持下游测试的概念。

test:
  downstreams:
    - some_downstream_pkg

这表示“当我构建此配方时,在您运行我这里的测试套件后,还要下载并运行依赖于我的软件包的 some_downstream_pkg。” Conda-build 负责确保您刚刚构建的软件包被安装到测试 some_downstream_pkg 的环境中。如果 conda-build 由于依赖项无法满足而无法创建该环境,它将跳过那些下游测试并向您发出警告。这通常发生在您构建软件包的新版本时,该版本将要求您重新构建下游依赖项。

下游规范是完整的 conda 规范,类似于需求部分。您可以在此处对规范进行版本限制

test:
  downstreams:
    - some_downstream_pkg  >=2.0

可以指定多个软件包来运行下游测试

test:
  downstreams:
    - some_downstream_pkg
    - other_downstream_pkg

但是,这并不意味着这些软件包是共同测试的。相反,每个软件包都会与您的新软件包进行可满足性测试,然后分别使用新软件包运行每个软件包的测试套件。

输出部分#

显式指定打包步骤。此部分支持多个输出,以及不同的软件包输出类型。格式是一个映射列表。子软件包的构建字符串由它们的运行时依赖项确定。此支持是在 conda-build 2.1.0 中添加的。

outputs:
  - name: some-subpackage
    version: 1.0
  - name: some-other-subpackage
    version: 2.0

注意

如果输出部分中指定了任何输出,则 conda-build 的默认打包行为将被绕过。换句话说,如果指定了任何子软件包,那么您将不会获得此配方的正常顶级构建,除非显式为其定义一个子软件包。这是一种替代现有的行为,而不是对它的补充。有关更多信息,请参阅 隐式元软件包。每个输出都可以有自己的版本和需求。此外,子软件包可以类似于 Pin downstream 施加下游固定以帮助保持软件包一致。

指定要包含在输出中的文件#

您可以通过以下三种方式之一指定要包含在软件包中的文件

  • 显式文件列表。

  • 将文件移动到构建前缀的脚本。

  • 以上两种方式

显式文件列表是相对于构建前缀根目录的相对路径。显式文件列表支持通配符表达式。目录名称也受支持,并且它们会递归地包含内容。

警告

在将 outputs/files 定义为一个列表而不指定 outputs/script 时,前缀中与通配符表达式之一匹配的任何文件(包括 host 依赖项安装的文件)都将包含在输出中。

outputs:
  - name: subpackage-name
    files:
      - a-file
      - a-folder
      - *.some-extension
      - somefolder/*.some-extension

可以通过将 files 定义为一个字典来实现对文件匹配的更大控制,该字典将要 include 的文件与要 exclude 的文件分开。在使用 include/exclude 时,只考虑当前配方安装的文件。即前缀中 host 依赖项安装的文件被排除在外。include/exclude 不能与 outputs/files 中直接列出的通配符表达式同时使用。匹配 include 和 exclude 表达式的文件将被排除在外。

outputs:
  - name: subpackage-name
    files:
      include:
        - a-file
        - a-folder
        - *.some-extension
        - somefolder/*.some-extension
      exclude:
        - *.exclude-extension
        - a-folder/**/*.some-extension

创建或将文件移动到构建前缀的脚本可以是任何类型的脚本。已知脚本类型只需要指定脚本名称即可。目前,已识别的扩展名列表为 py、bat、ps1 和 sh。

outputs:
  - name: subpackage-name
    script: move-files.py

如果文件扩展名不被识别,则必须指定解释器命令。

outputs:
  - name: subpackage-name
    script: some-script.extension
    script_interpreter: program plus arguments to run script

对于移动或创建文件的脚本,在每次脚本执行开始时都会提供一个工作目录的新副本。这确保脚本之间的结果相互独立。

注意

对于文件列表或脚本方法,拥有一个以上软件包包含给定文件并不被明确禁止,但可能会阻止同时安装这两个软件包。Conda 不允许这种情况,因为它会创建模棱两可的运行时条件。

同时给出脚本和文件时,将先运行脚本,然后仅打包显式文件列表中的文件。

子软件包需求#

与顶级配方一样,子软件包可以将零个或多个依赖项列为构建需求,并将零个或多个依赖项列为运行需求。

列为子软件包构建需求的依赖项仅在该子软件包的打包阶段可用。

子软件包不会自动继承其顶级配方的任何依赖项,因此子软件包需要的任何构建或运行需求都必须显式指定。

outputs:
  - name: subpackage-name
    requirements:
      build:
        - some-dep
      run:
        - some-dep

子软件包需求部分也可以包含依赖项列表,但没有构建部分或运行部分。这与拥有一个包含此依赖项列表的构建部分和一个包含相同依赖项列表的运行部分相同。

outputs:
  - name: subpackage-name
    requirements:
      - some-dep

您也可以在将给定(子)软件包安装为构建依赖项时施加运行时依赖项。例如,如果我们有一个总体的“compilers”软件包,并在其中包含 gcclibgcc 输出,我们可以强制使用 GCC 的配方包含匹配的 libgcc 运行时需求

outputs:
  - name: gcc
    run_exports:
      - libgcc 2.*
  - name: libgcc

有关更多信息,请参阅 导出运行时需求 部分。

注意

变体表达式在这里非常强大。您可以在 run_exports 条目中将版本需求表达为 Jinja 函数,以根据配方生成的 libgcc 的实际版本插入值。有关更多信息,请阅读 引用子软件包

隐式元软件包#

当将顶级软件包视为更小的子软件包的集合时,将顶级软件包定义为几个子软件包的组合可能很方便。如果您这样做并且没有定义与顶级软件包/名称匹配的子软件包名称,conda-build 会为您创建一个元软件包。此元软件包具有从其依赖子软件包中提取的运行时依赖项,以便获得准确的构建字符串。

示例:在此示例中,将为 subpackage-example 创建一个元软件包。它将依赖于 subpackage1subpackage2some-depsome-other-dep

package:
  name: subpackage-example
  version: 1.0

requirements:
  run:
    - subpackage1
    - subpackage2

outputs:
  - name: subpackage1
    requirements:
      - some-dep
  - name: subpackage2
    requirements:
      - some-other-dep
  - name: subpackage3
    requirements:
      - some-totally-exotic-dep

子软件包测试#

您可以独立于顶级软件包测试子软件包。每个独立软件包的独立测试脚本文件都在子软件包的测试部分下指定。这些文件支持与顶级 run_test.* 脚本相同的格式,即 .py、.pl、.bat 和 .sh。将来可能会扩展以支持其他脚本类型。

outputs:
  - name: subpackage-name
    test:
      script: some-other-script.py

默认情况下,run_test.* 脚本仅适用于顶级包。要将它们也应用于子包,请在脚本部分中明确列出它们。

outputs:
  - name: subpackage-name
    test:
      script: run_test.py

子包的测试要求可以使用子包测试的可选 test/requires 部分指定。子包测试在测试期间也会安装其运行时要求。

示例:在此示例中,subpackage-name 的测试安装了 some-test-depsubpackage-run-req,但没有安装 some-top-level-run-req

requirements:
  run:
    - some-top-level-run-req

outputs:
  - name: subpackage-name
    requirements:
      - subpackage-run-req
    test:
      script: run_test.py
      requires:
        - some-test-dep

输出类型#

Conda-build 支持创建除 conda 包之外的包。目前,该支持仅包括轮子,但随着需求的出现,可能还会出现其他类型。如果未指定类型,则默认值为 conda

requirements:
  build:
    - wheel

outputs:
  - name: name-of-wheel-package
    type: wheel

目前,您必须在顶级 requirements/build 部分中包含轮子包才能构建轮子。

在指定类型时,name 字段是可选的,它默认值为顶级食谱的 package/name 字段。

requirements:
  build:
    - wheel

outputs:
  - type: wheel

Conda-build 目前只知道如何测试 conda 包。Conda-build 支持使用 Twine 将包上传到 PyPI。有关接受的参数列表,请参见 conda-build 帮助输出 (conda-build --help),这些参数将传递给 Twine。

注意

您必须使用 pip 安装 Twine 才能使此功能正常工作。

关于部分#

指定有关包的识别信息。此信息显示在 Anaconda.org 频道中。

about:
  home: https://github.com/ilanschnell/bsdiff4
  license: BSD 3-Clause
  license_file: LICENSE
  license_family: BSD
  license_url: https://github.com/bacchusrx/bsdiff4/blob/master/LICENSE
  summary: binary diff and patch using the BSDIFF4 format
  description: |
    This module provides an interface to the BSDIFF4 format, command line interfaces
    (bsdiff4, bspatch4) and tests.
  dev_url: https://github.com/ilanschnell/bsdiff4
  doc_url: https://bsdiff4.readthedocs.io
  doc_source_url: https://github.com/ilanschnell/bsdiff4/blob/main/README.rst

许可文件#

将包含软件许可证的文件添加到包元数据中。许多许可证要求将许可证声明与包一起分发。文件名相对于源目录或食谱目录。该值可以是单个文件名,也可以是 YAML 列表,用于表示多个许可证文件。值也可以指向包含许可证信息的目录。目录条目必须以 / 后缀结尾(这是为了减少无意中包含非许可证文件;目录的所有内容将被无条件地递归添加)。

about:
  license_file:
    - LICENSE
    - vendor-licenses/

应用程序部分#

如果存在应用程序部分,则该包是应用程序,这意味着它会出现在 Anaconda Navigator 中。

入口点#

在 Navigator 中启动应用程序时调用的命令。

app:
  entry: ipython notebook

图标文件#

食谱中包含的图标文件。

app:
  icon: icon_64x64.png

摘要#

在 Navigator 中使用的包的摘要。

app:
  summary:  "The Jupyter Notebook"

自己的环境#

如果为 True,则通过 Navigator 安装应用程序会安装到其自己的环境中。默认值为 False

app:
  own_environment: True

额外部分#

一个无模式区域,用于以标准 YAML 形式存储非 conda 特定元数据。

示例:存储食谱维护者信息

extra:
  maintainers:
   - name of maintainer

使用 Jinja 进行模板化#

Conda-build 支持在 meta.yaml 文件中使用 Jinja 模板化。

示例:以下 meta.yaml 将与为 Git 存储库定义的 GIT 值一起使用。食谱包含在 Git 存储库的基目录中,因此 git_url../

package:
  name: mypkg
  version: {{ GIT_DESCRIBE_TAG }}

build:
  number: {{ GIT_DESCRIBE_NUMBER }}

  # Note that this will override the default build string with the Python
  # and NumPy versions
  string: {{ GIT_BUILD_STR }}

source:
  git_url: ../

Conda-build 检查您使用的 Jinja2 变量是否已定义,如果未定义,则会生成清晰的错误信息。

您还可以使用这些环境变量的另一种语法,允许设置默认值,尽管这有点冗长。

示例:使用允许默认值的语法的先前示例的版本

package:
  name: mypkg
  version: {{ environ.get('GIT_DESCRIBE_TAG', '') }}

build:
  number: {{ environ.get('GIT_DESCRIBE_NUMBER', 0) }}

  # Note that this will override the default build string with the Python
  # and NumPy versions
  string: {{ environ.get('GIT_BUILD_STR', '') }}

source:
  git_url: ../

使用模板化的另一个可能性是从下载的源代码中获取数据。

示例:处理项目的 setup.py 并获取版本和其他元数据

{% set data = load_setup_py_data() %}

package:
  name: conda-build-test-source-setup-py-data
  version: {{ data.get('version') }}

# source will be downloaded prior to filling in jinja templates
# Example assumes that this folder has setup.py in it
source:
  path_url: ../

这些功能与任何其他变量(如 Git 和 Mercurial)完全兼容。

将此任意扩展到其他功能需要在 Jinja 处理之前预定义函数,实际上意味着更改 conda-build 源代码。请参见 conda-build 问题跟踪器

有关更多信息,请参见 Jinja2 模板文档可用环境变量列表

Jinja 模板在构建过程中进行评估。要检索完全呈现的 meta.yaml,请使用 conda render 命令。

从其他文件加载数据#

Jinja2 提供了几个额外的函数,可用于从其他文件加载数据。它们是 load_setup_py_dataload_file_regexload_file_dataload_str_data

  • load_setup_py_data:从 setup.py 文件加载数据。这对于从项目的 setup.py 文件获取元数据(如版本)很有用。例如

    {% set data = load_setup_py_data() %}
    {% set version = data.get('version') %}
    package:
      name: foo
      version: {{ version }}
    
  • load_file_regex:在文件中搜索正则表达式,将第一个匹配项作为 Python re.Match 对象返回。

    例如,使用 load_file_regex(load_file, regex_pattern, from_recipe_dir=False) -> re.Match | None

    {% set version_match = load_file_regex(
      load_file="conda_package_streaming/__init__.py",
      regex_pattern='^__version__ = "(.+)"') %}
    {% set version = version_match[1] %}
    
    package:
      version: {{ version }}
    
  • load_file_data:解析 JSON、TOML 或 YAML 文件,并从其中加载数据。例如,您可以使用此功能从 pyproject.toml 加载诗歌配置。这特别有用,因为 setup.py 不再是定义项目元数据的唯一标准方法(请参见 PEP 517PEP 518)。

    {% set pyproject = load_file_data('pyproject.toml') %}
    {% set poetry = pyproject.get('tool', {}).get('poetry') %}
    package:
      name: {{ poetry.get('name') }}
      version: {{ poetry.get('version') }}
    
  • load_str_data:从字符串加载和解析数据。这类似于 load_file_data,但它接受字符串而不是文件作为参数。乍一看这似乎毫无意义,但您可以使用它通过环境变量传递更复杂的数据结构。例如

    {% set extra_deps = load_str_data(environ.get("EXTRA_DEPS", []), "json") %}
    requirements:
      run:
        - ...
        {% for dep in extra_deps %}
        - {{ dep }}
        {% endfor %}
    

    然后,您可以将 EXTRA_DEPS 环境变量传递给构建,如下所示

    EXTRA_DEPS='["foo =1.0", "bar >=2.0"]' conda build path/to/recipe
    

函数 load_setup_py_dataload_file_regexload_file_data 都接受参数 from_recipe_dirrecipe_dir。如果将 from_recipe_dir 设置为 true,则还必须传递 recipe_dir。在这种情况下,将相对于食谱目录搜索相关文件。否则,将在源代码中搜索该文件(如果需要,将在下载和解压缩后搜索)。如果给定文件是绝对路径,则不会搜索这两个目录。

函数 load_file_dataload_str_data 还接受 *args**kwargs,这些参数将逐字传递给用于解析文件的函数。对于 JSON,这将是 json.load;对于 TOML,是 toml.load;对于 YAML,是 yaml.safe_load

Conda-build 特定的 Jinja2 函数#

除了默认的 Jinja2 功能之外,在 conda-build 过程中还提供额外的 Jinja 函数:pin_compatiblepin_subpackagecompilerresolved_packages。请参见 额外的 Jinja2 函数,了解前 3 个函数的定义。resolved_packages 的定义如下

  • resolved_packages('environment_name'):返回列在 requirements:hostrequirements:build 中的最终包列表(以 package_name version build_string 的形式)。这包括将安装在主机或构建环境中的所有包(包括间接依赖项)。environment_name 必须是 hostbuild。此函数对于创建希望将其所有 *直接* 和 *间接* 依赖项固定到其精确匹配的元包很有用。例如

    requirements:
      host:
        - curl 7.55.1
      run:
      {% for package in resolved_packages('host') %}
        - {{ package }}
      {% endfor %}
    

    可能渲染为(取决于包依赖项和平台)

    requirements:
        host:
            - curl 7.55.1
        run:
            - ca-certificates 2017.08.26 h1d4fec5_0
            - curl 7.55.1 h78862de_4
            - libgcc-ng 7.2.0 h7cc24e2_2
            - libssh2 1.8.0 h9cfc8f7_4
            - openssl 1.0.2n hb7f436b_0
            - zlib 1.2.11 ha838bed_2
    

    在这里,resolved_packages 的输出是

    ['ca-certificates 2017.08.26 h1d4fec5_0', 'curl 7.55.1 h78862de_4',
    'libgcc-ng 7.2.0 h7cc24e2_2', 'libssh2 1.8.0 h9cfc8f7_4',
    'openssl 1.0.2n hb7f436b_0', 'zlib 1.2.11 ha838bed_2']
    

预处理选择器#

您可以在任何行中添加选择器,这些选择器用作预处理阶段的一部分。在读取 meta.yaml 文件之前,将评估每个选择器,如果其结果为 False,则会删除包含该选择器的行。选择器的形式为 # [<selector>],位于行的末尾。

source:
  url: http://path/to/unix/source    # [not win]
  url: http://path/to/windows/source # [win]

注意

预处理选择器在 Jinja 模板之后进行评估。

选择器是执行的有效 Python 语句。以下变量已定义。除非另有说明,否则变量为布尔值。

x86

如果系统架构为 x86,则为 True,包括 32 位和 64 位,适用于 Intel 或 AMD 芯片。

x86_64

如果系统架构为 x86_64,则为 True,即 64 位,适用于 Intel 或 AMD 芯片。

linux

如果平台为 Linux,则为 True。

linux32

如果平台为 Linux 且 Python 架构为 32 位并使用 x86,则为 True。

linux64

如果平台为 Linux 且 Python 架构为 64 位并使用 x86,则为 True。

armv6l

如果平台为 Linux 且 Python 架构为 armv6l,则为 True。

armv7l

如果平台为 Linux 且 Python 架构为 armv7l,则为 True。

aarch64

如果平台为 Linux 且 Python 架构为 aarch64,则为 True。

ppc64le

如果平台为 Linux 且 Python 架构为 ppc64le,则为 True。

s390x

如果平台为 Linux 且 Python 架构为 s390x,则为 True。

osx

如果平台为 macOS,则为 True。

arm64

如果平台为 macOS 或 Windows 且 Python 架构为 arm64,则为 True。

unix

如果平台为 macOS 或 Linux 或 emscripten,则为 True。

win

如果平台为 Windows,则为 True。

win32

如果平台为 Windows 且 Python 架构为 32 位,则为 True。

win64

如果平台为 Windows 且 Python 架构为 64 位,则为 True。

py

Python 版本,以整数形式表示,例如 2736。请参阅 CONDA_PY 环境变量

py3k

如果 Python 主版本为 3,则为 True。

py2k

如果 Python 主版本为 2,则为 True。

py27

如果 Python 版本为 2.7,则为 True。不建议使用此选择器,建议使用比较运算符(例如 py==27)。

py34

如果 Python 版本为 3.4,则为 True。不建议使用此选择器,建议使用比较运算符(例如 py==34)。

py35

如果 Python 版本为 3.5,则为 True。不建议使用此选择器,建议使用比较运算符(例如 py==35)。

py36

如果 Python 版本为 3.6,则为 True。不建议使用此选择器,建议使用比较运算符(例如 py==36)。

np

NumPy 版本,以整数形式表示,例如 111。请参阅 CONDA_NPY 环境变量

build_platform

conda 可执行文件的本地子目录

不建议使用 Python 版本选择器 py27py34 等,建议使用更通用的比较运算符。conda-build 将不会添加此系列中的其他选择器。

请注意,对于 conda 支持的每个具有 OS 和架构的子目录,都会为 OS 和架构分别创建两个预处理选择器,除非架构不是有效的 Python 表达式(特别是 *-32*-64)。

由于选择器是任何有效的 Python 表达式,因此可以实现复杂的逻辑

source:
  url: http://path/to/windows/source      # [win]
  url: http://path/to/python2/unix/source # [unix and py2k]
  url: http://path/to/python3/unix/source # [unix and py>=35]

注意

选择器只会删除它们所在的行,因此您可能需要在多行上放置相同的选择器

source:
  url: http://path/to/windows/source     # [win]
  md5: 30fbf531409a18a48b1be249052e242a  # [win]
  url: http://path/to/unix/source        # [unix]
  md5: 88510902197cba0d1ab4791e0f41a66e  # [unix]

注意

要选择多个操作系统,请使用 or 语句。虽然使用 skip: True  # [win and osx] 可能会很诱人,但这只有在平台同时为 windows 和 osx 时(即永远不会)才有效。

build:
   skip: True  # [win or osx]