贡献软件包
贡献过程可以分为三个步骤
-
步骤 1. 暂存过程(添加配方和许可证)。
在暂存过程的帮助下,将软件包的配方和许可证添加到 staged-recipes 存储库并创建一个 PR。
-
步骤 2. 暂存后过程。
一旦您的 PR 被合并,请查看我们的暂存后过程,了解后续步骤。
-
步骤 3. 维护软件包。
向
conda-forge
贡献软件包使您成为该软件包的维护者。了解更多关于维护者的角色。
以下章节将详细介绍每个步骤。
暂存过程
暂存过程,即添加软件包的配方,包含三个步骤
- 生成配方
- 检查清单
- 反馈和修订
生成配方
目前,有三种生成配方的方法
-
如果它是来自 CRAN 的 R 软件包,请首先使用 conda-forge R 配方助手脚本。如有必要,您可以手动编辑配方。
-
如果它是 python 软件包,您可以使用
grayskull
生成配方作为起点。注意Grayskull 是一个自动 conda 配方生成器。该项目的目标是为 conda-forge 生成简洁的配方,并最终取代 conda skeleton。目前,Grayskull 可以为 PyPI 上提供的 Python 软件包以及未在 PyPI 上发布且仅作为 GitHub 存储库提供的软件包生成配方。
grayskull
的安装和使用- 使用以下命令创建一个新环境:
conda create --name MY_ENV
。将MY_ENV
替换为环境名称。 - 激活这个新环境:
conda activate MY_ENV
。 - 运行
conda install -c conda-forge grayskull
安装grayskull
。 - 然后运行
grayskull pypi --strict-conda-forge YOUR_PACKAGE_NAME
生成配方。将YOUR_PACKAGE_NAME
替换为软件包名称。
您不一定需要使用
grayskull
,并且grayskull
生成的配方可能需要审查和编辑。阅读更多关于grayskull
以及如何使用它的信息,请点击这里。 - 使用以下命令创建一个新环境:
-
如果以上都不是,请在 示例配方 的帮助下在 staged-recipes 存储库 中生成一个配方,并根据需要进行修改。
您的最终配方应该没有注释(除非它们实际上与配方相关,而不是通用的指令注释),并遵循示例中的顺序。
如果您对任何细节不确定,请无论如何创建一个拉取请求。conda-forge 团队将审查它并帮助您对其进行更改。
如果您是第一次使用 conda-forge 构建您的第一个配方,下面提供了逐步说明和检查清单,以帮助您成功构建。
逐步说明
- 确保您的源代码可以作为单个文件下载。源代码应可作为存档 (.tar.gz、.zip、.tar.bz2、.tar.xz) 下载或在 GitHub 上标记,以确保可以对其进行验证。(有关更多详细信息,请参阅从 tarball 构建,而不是从仓库构建)。
- 从 GitHub 分叉并克隆 staged-recipes 存储库。
- 从 staged-recipes
main
分支检出一个新分支。 - 通过 CLI,cd 进入 ‘staged-recipes/recipes' 目录。
- 在您的分叉副本中,在 recipes 文件夹中为您的软件包创建一个新文件夹(即,
...staged-recipes/recipes/<name-of-package>
) - 从 example 目录复制 meta.yaml。以下步骤中的所有更改都将在复制的 meta.yaml 中进行(即,
...staged-recipes/recipes/<name-of-package>/meta.yaml
)。请保持 example 目录不变! - 根据需要修改复制的配方 (meta.yml)。要查看如何修改 meta.yaml,请查看配方 meta.yaml。
- 使用
openssl
工具生成源代码存档的 SHA256 密钥,如示例配方中所述。作为替代方案,您也可以转到 PyPi 上的软件包描述,您可以直接从那里复制 SHA256。 - 确保填写
test
部分。最简单的测试将简单地测试模块是否可以导入,如示例中所述。 - 删除
meta.yaml
文件中所有不相关的注释。
确保不要校验重定向页面的校验和。因此,例如,使用
curl -sL https://github.com/username/reponame/archive/vX.X.X.tar.gz | openssl sha256
检查清单
- 确保许可证和许可证系列描述符(可选)的大小写正确,并且许可证正确。请注意,需要区分大小写的输入(例如,Apache-2.0 而不是 APACHE 2.0)。建议对许可证字段使用 SPDX 标识符。(请参阅SPDX 标识符和表达式)
- 确保您的许可证需要许可证文件时,您已包含许可证文件 - 大多数许可证都需要。(请参阅这里)
- 如果您的项目包含测试,您需要决定在构建 conda-forge feedstock 时是否应执行这些测试。
- 确保所有测试至少在您的开发机器上成功通过。
- 推荐:在本地运行源代码上的测试,以确保配方在本地有效(请参阅在本地为暂存配方运行测试)。
- 确保您的更改不会干扰
recipes
文件夹中的其他配方(例如,example
配方)。
反馈和修订
完成 PR 后,您所要做的就是等待我们审查团队的反馈。
审查团队将通过指出改进之处和回答问题来协助您。一旦软件包准备就绪,审查员将批准并合并您的拉取请求。
合并 PR 后,我们的 CI 基础设施将构建软件包并使其在 conda 频道中可用。
如果您有疑问或一段时间没有收到回复,您可以通过在 GitHub 消息中包含 @conda-forge/staged-recipes
来通知我们。
暂存后过程
- PR 合并后,我们的 CI 服务将自动创建一个新的 git 仓库。例如,名为
pydstool
的软件包的配方将被移动到一个新的存储库 https://github.com/conda-forge/pydstool-feedstock。此过程通过conda-forge/staged-recipes
仓库上的 CI 作业自动完成。有时由于 API 速率限制而失败,并将自动重试。如果您的 feedstock 在一天左右后仍未创建,请联系conda-forge/core
团队寻求帮助。 - CI 服务将自动启用,并且将自动触发构建,这将构建 conda 软件包并上传到 https://anaconda.org/conda-forge
- 如果这是您的首次贡献,您将被添加到 conda-forge 团队,并获得 CI 服务的访问权限,以便您可以停止和重启构建。您还将获得新 git 存储库的提交权限。
- 如果您想更改配方,请从 fork 向 git 存储库发送 PR。主存储库的分支仅用于维护不同的版本。
Feedstock 存储库结构
一旦包含软件包配方的 PR 在 staged-recipes
存储库中合并,就会自动创建一个名为 <package-name>-feedstock
的新存储库。feedstock 由 conda 配方(关于构建软件包的内容和方式的说明)和必要的配置文件组成,用于使用免费提供的持续集成 (CI) 服务进行自动构建。
每个 feedstock 都包含使用我们的自动化配置工具 conda-smithy 自动生成的各种文件。广义上,每个 feedstock 都具有以下文件
recipe
此文件夹包含 meta.yaml
文件和构建软件包所需的任何其他文件/脚本。
LICENSE.txt
此文件是配方本身的许可证。此许可证与软件包许可证不同,软件包许可证是您在使用 meta.yaml
文件中的 license_file
提交软件包配方时定义的。
CI-files
这些是 Azure 和 TravisCI 等服务提供商的 CI 配置文件。
conda-forge.yml
此文件用于配置如何设置和构建 feedstock。对此文件进行任何更改通常需要重新渲染 feedstock。
维护者角色
维护者的工作是
- 通过合并来自 conda-forge 机器人的最终维护 PR 来保持 feedstock 更新。
- 通过以下方式使 feedstock 与源软件包的新版本保持一致
- 更新版本号和校验和。
- 确保 feedstock 的要求保持准确。
- 确保测试要求与更新后的软件包的要求相匹配。
- 回答 feedstock 问题跟踪器上关于软件包的最终问题。
一次添加多个软件包
如果您想添加多个相关的软件包,可以将它们在单个拉取请求中添加到 staged-recipes 中(在单独的目录中)。如果软件包是相互依赖的(即,正在添加的一个软件包将正在添加的一个或多个其他软件包列为要求),则构建脚本将能够找到仅存在于 staged-recipes 中的依赖项,只要构建以依赖项顺序完成即可。使用单个拉取请求可以让您快速设置软件包,而无需等待依赖链中的每个软件包都经过审查、构建并添加到 conda-forge
频道,然后再重新开始链中下一个配方的过程。
当合并包含多个相互依赖的配方的 PR 时,如果某个构建在其依赖项构建完成之前完成,则可能会发生错误。如果发生这种情况,您可以通过推送一个空提交来触发新的构建。
git commit --amend --no-edit && git push --force
同步 fork 以供将来使用
如果您想在将来添加其他软件包,您需要在 fork 上创建新分支之前重置您的 staged-recipes fork,添加新的软件包目录/配方,并创建一个拉取请求。此步骤确保您拥有 staged-recipes 存储库中包含的工具和配置文件的最新版本,并使拉取请求更易于审查。以下步骤将重置您的 staged-recipes fork,应从您的分叉 staged-recipes 目录的克隆中执行。
- 检出您的 main 分支
git checkout main
- 将 conda-forge/staged-recipes 存储库定义为
upstream
(如果您尚未这样做)。git remote add upstream https://github.com/conda-forge/staged-recipes.git
- 从 upstream main 分支拉取所有 upstream 提交。
git pull --rebase upstream main
- 将所有更改推送到您在 GitHub 上的 fork(确保 GitHub 上没有任何您需要的更改,因为它们将被覆盖)。
git push origin main --force
完成这些步骤后,您可以继续执行逐步说明中的步骤,以使用您现有的 staged-recipes fork 暂存您的新软件包配方。
配方 meta.yaml
recipe 目录中的 meta.yaml
文件是每个 conda 软件包的核心。它定义了构建和使用软件包所需的一切。
meta.yaml
是 yaml 格式,并使用 Jinja 模板进行增强。
meta.yaml
文件的结构和字段的完整参考可以在 conda-build 文档中的定义元数据 (meta.yaml) 部分找到。
在下文中,我们重点介绍特别重要和特定于 conda-forge 的信息和指南,按 meta.yaml
中的部分排序。
Source
从 tarball 构建,而不是从仓库构建
软件包应使用 url
键从 tarball 构建,而不是通过使用例如 git_url
直接从存储库构建。
此规则背后有几个原因
- 存储库通常比 tarball 大,会耗尽共享 CI 时间和带宽
- 存储库未进行校验和。因此,使用 tarball 可以更强烈地保证获得的下载用于构建的确实是预期的软件包。
- 在某些系统上,可能没有权限删除已创建的仓库。
填充 hash
字段
如果您的软件包在 PyPi 上,您可以从 PyPI 上软件包的页面获取 sha256 哈希值;在您软件包的文件页面上查找下载链接旁边的 SHA256
链接,例如 https://pypi.ac.cn/project/<your-project>/#files
。
您也可以从 Linux 上的命令行生成哈希值(如果您安装了下面必要的工具,也可以在 Mac 上生成)。
要生成 sha256
哈希值:openssl sha256 your_sdist.tar.gz
您可能需要 openssl 软件包,可在 conda-forge 上获得 conda install openssl -c conda-forge
。
确保不要校验重定向页面的校验和。因此,例如,使用
curl -sL https://github.com/username/reponame/archive/vX.X.X.tar.gz | openssl sha256
下载额外的源文件和数据文件
conda-build 3
支持每个配方多个源。示例可在 conda-build 文档中找到。
Build
跳过构建
在 build
部分中使用 skip
键以及选择器
您可以例如指定不构建 ...
- 在特定架构上
build:
skip: true # [win] - 对于特定 python 版本
build:
skip: true # [py<35]
选择器的完整描述在 conda 文档中。
可选:bld.bat
和/或 build.sh
在许多情况下,不需要 bld.bat
和/或 build.sh
文件。纯 Python 软件包几乎从不需要它们。
如果可以使用一行代码执行构建,您可以将此行代码放在 meta.yaml
文件的 build
部分的 script
条目中,代码为:script: "{{ PYTHON }} -m pip install . -vv"
。
记住始终将 pip
添加到主机要求中。
使用 pip
通常,Python 软件包应使用此行
build:
script: "{{ PYTHON }} -m pip install . -vv"
作为 meta.yml
文件或 bld.bat/build.sh
脚本文件中的安装脚本,同时将 pip
添加到主机要求中
requirements:
host:
- pip
应使用这些选项来确保软件包的干净安装,而无需其依赖项。这有助于确保我们只包含此软件包,而不会意外地将任何依赖项带入 conda 软件包中。
通常,纯 Python 软件包只需要 python
、setuptools
和 pip
作为 host
要求;真正的软件包依赖项仅是 run
要求。
Requirements
Build、host 和 run
Conda-build 区分三种不同类型的依赖项。在以下段落中,我们将简要概述哪些软件包放在哪里。有关详细说明,请参阅 conda-build 文档。
Build
构建依赖项在构建环境中是必需的,并且包含软件包主机上不需要的所有工具。
以下软件包是典型的 build
依赖项的示例
- 编译器(请参阅编译器)
- cmake
- make
- pkg-config
- CDT 软件包(请参阅核心依赖树软件包 (CDT))
Host
主机依赖项在构建阶段是必需的,但与构建软件包相反,它们必须存在于主机上。
以下软件包是 host
依赖项的典型示例
- 共享库 (c/c++)
- 链接到 c 库的 python/r 库(例如,请参阅针对 NumPy 构建)
- python, r-base
- setuptools, pip(请参阅使用 pip)
Run
运行依赖项仅在软件包运行时是必需的。运行依赖项通常包括
- 大多数 python/r 库
避免外部依赖项
作为一般规则:所有依赖项也必须由 conda-forge 打包。这对于确保我们所有软件包的 ABI 兼容性是必要的。
此规则只有少数例外
- 某些依赖项必须使用 CDT 软件包来满足(请参阅核心依赖树软件包 (CDT))。
- 某些软件包需要 root 访问权限(例如,设备驱动程序),而这些权限无法由 conda-forge 分发。应尽可能避免这些依赖项。
Pinning
链接共享 c/c++ 库会在软件包构建时使用的库的 ABI 上创建依赖关系。当较新版本中删除或修改先前存在的公开符号时,公开的接口会发生更改。
因此,至关重要的是要确保链接后仅使用具有兼容 ABI 的库版本。
在最佳情况下,您依赖的共享库
在这些情况下,您不必担心版本要求
requirements:
# [...]
host:
- readline
- libpng
在其他情况下,您必须手动指定 ABI 兼容的版本。
requirements:
# [...]
host:
- libawesome 1.1.*
有关 pinning 的更多信息,请参阅固定的依赖项。
在运行时约束软件包
run_constrained
部分允许在运行时定义对软件包的限制,而无需依赖软件包。它可用于限制可选依赖项的允许版本和定义不兼容的软件包。
定义非依赖项限制
假设一个软件包可以与 awesome-software
的版本 1 一起使用(如果存在),但并不严格依赖于它。因此,您希望让用户选择是否要使用带有或不带有 awesome-software
的软件包。让我们进一步假设该软件包与 awesome-software
的版本 2 不兼容。
在这种情况下,如果用户选择安装 awesome-software
,则可以使用 run_constrained
将 awesome-software
限制为版本 1.*
requirements:
# [...]
run_constrained:
- awesome-software 1.*
在这里,run_constrained
充当一种手段,以保护用户免受不兼容版本的影响,而不会引入不必要的依赖项。
定义冲突
有时软件包会相互干扰,因此在任何时候只能安装其中一个。结合不可满足的版本,run_constrained
可以定义阻止程序
package:
name: awesome-db
requirements:
# [...]
run_constrained:
- amazing-db ==9999999999
在此示例中,awesome-db
无法与 amazing-db
一起安装,因为没有软件包 amazing-db-9999999999
。
Test
所有配方都需要测试。以下是一些提示、技巧和理由。您应该如何测试取决于软件包的类型(python、c-lib、命令行工具等)以及该软件包可用的测试。但是,每个 conda 软件包都必须至少有一些测试。
简单的存在性测试
有时定义测试似乎很困难,例如由于
- 底层代码库的测试可能不存在。
- 测试套件可能需要太长时间才能在有限的 CI 基础设施上运行。
- 测试可能会占用太多带宽。
在这些情况下,conda-forge 可能无法执行规定的测试套件。
但是,这并不是配方没有测试的理由。至少,我们希望验证软件包是否已将所需的文件安装在所需的位置。这称为存在性测试。
可以在 meta.yaml
文件中的 test/commands
块中完成存在性测试。
在 posix 系统上,使用 test
实用程序和 $PREFIX
变量。
在 Windows 上,使用 exist
命令。请参阅下面的示例。
简单的存在性测试示例
test:
commands:
- test -f $PREFIX/lib/libboost_log$SHLIB_EXT # [unix]
- if not exist %LIBRARY_LIB%\\boost_log-vc140-mt.lib exit 1 # [win]
测试 python 软件包
有关测试的最佳信息,请参阅 conda build 文档 test 部分。
测试导入
python 软件包的最小测试应确保软件包可以成功导入。这可以通过 meta.yaml
中的以下节来完成
test:
imports:
- package_name
请注意,package_name
是 python 导入的名称;不一定是 conda 软件包的名称(它们有时是不同的)。
测试导入将捕获大部分打包错误,通常包括依赖项的存在。但是,它不能保证软件包能够正常工作。特别是,它不测试它是否与使用的依赖项版本一起正常工作。在某些情况下,顶层导入名称不包含任何可执行代码(例如,带有空 __init__.py
的软件包,或没有任何直接导入的软件包)。此测试将始终通过!在这些情况下,显式添加更多针对包含可执行代码的模块的导入(例如,package_name.core
)会有所帮助。
如果可能,最好运行代码本身的其他一些测试(测试套件)。
pip check
对于 PyPI 软件包,我们强烈建议将 pip check
作为 test.commands
部分的一部分包含在内
test:
commands:
- pip check
此命令将检查 Python 元数据中指定的所有依赖项是否已满足。
pip check
有时可能会失败,因为 PyPI 和 conda-forge 之间的元数据存在差异(例如,相同软件包名称不同)。在这些情况下,审查者必须评估该错误是否为误报。提示:使用 pip list
显示 pip check
“看到”的内容。
运行单元测试
这里的诀窍是在 Python 中运行单元测试有多种方法,包括 nose、pytest 等。
此外,有些软件包将测试与软件包一起安装,因此可以就地运行,而另一些软件包将测试与源代码一起保存,因此无法直接从已安装的软件包中运行。
测试要求
有时,运行测试需要一些软件包,但简单地使用该软件包则不需要。这通常是一个测试运行框架,例如 nose 或 pytest。您可以通过将其添加到 test stanza 中的 requirements 中来确保包含它
test:
imports:
- package_name
...
requires:
- pytest
复制测试文件
通常,测试文件不会与软件包一起安装。Conda 创建一个新的工作副本以执行构建配方的测试阶段,该副本不包含源软件包的文件。
您可以使用 source_files
部分包含测试所需的文件
test:
imports:
- package_name
requires:
- pytest
source_files:
- tests
- test_pkg_integration.py
commands:
- pytest tests test_pkg_integration.py
source_files
部分适用于文件和目录。
内置测试
某些软件包具有内置测试。在这种情况下,您可以将测试命令直接放在 test stanza 中
test:
...
commands:
python -c "import package_name; package_name.tests.runall()"
或者,您可以在 recipe 中添加一个名为 run_test.py
的文件,该文件将在测试时运行。这允许任意复杂的测试脚本。
pytest 测试
如果测试与软件包一起安装,pytest 可以使用以下命令为您查找并运行它们
test:
requires:
- pytest
commands:
- pytest --pyargs package_name
命令行实用程序
如果 Python 软件包安装了命令行实用程序,您可能需要测试它们是否已正确安装
test:
commands:
- util_1 --help
如果该实用程序实际上具有测试模式,那就太好了。否则,只需调用 --help
或 --version
或其他命令,至少可以测试它是否已安装并且可以运行。
测试 R 软件包
应测试 R 软件包以确保库加载成功。CRAN 软件包的所有 recipe 都应从 conda_r_skeleton_helper 开始,并将自动包含库加载测试。但是,许多 R 软件包还包含可以运行的 testthat
测试。虽然是可选的,但当软件包
- 提供与其他(已编译)库的接口(例如,
r-curl
、r-xml2
)时,鼓励进行额外的测试 - 扩展或集成许多其他 R 库的功能(例如,
r-vetiver
) - 是提供常用功能的基石 R 软件包(例如,
r-rmarkdown
)
测试 R 库加载
R 软件包的最低限度测试应确保可以成功导入交付的库。这在 meta.yaml
中通过以下方式完成
test:
commands:
- $R -e "library('PackageName')" # [not win]
- "\"%R%\" -e \"library('PackageName')\"" # [win]
请注意,PackageName
是 R 导入的名称;不一定是 conda 软件包的名称(例如,r-matrix
交付 Matrix
)。
运行 testthat
测试
带有 testthat
测试的 R 软件包的典型 test
部分如下所示
test:
requires:
- r-testthat
source_files:
- tests/
commands:
- $R -e "library('PackageName')" # [not win]
- $R -e "testthat::test_file('tests/testthat.R', stop_on_failure=TRUE)" # [not win]
- "\"%R%\" -e \"library('PackageName')\"" # [win]
- "\"%R%\" -e \"testthat::test_file('tests/testthat.R', stop_on_failure=TRUE)\"" # [win]
我们建议在 testthat
测试之前包含库加载检查。
首先,需要声明测试环境已安装 r-testthat
。这里可能需要额外的 requirements,尤其是当软件包具有经过测试的可选功能时。
如果任何 testthat
测试由于缺少软件包而失败,则鼓励维护人员将此情况告知上游存储库。一些 R 软件包具有可选功能,通常涉及在 DESCRIPTION
文件的 Suggests:
部分下列出的软件包。开发人员应使用 testthat::skip_if_not_installed()
函数来防止在未安装可选软件包时测试失败。当未完成此操作时,发布 Issue 或 Pull Request 将有助于改进 R 生态系统中的测试实践。
其次,需要声明从何处获取测试。R 软件包测试将在 tarball 的 tests/
目录中找到。这通常包括一个 tests/testthat.R
文件和 tests/testthat/test_*.R
下的其他测试。辅助目录和文件也可能存在,并且是特定测试所必需的。
conda-forge 上的默认 R 构建过程不会在最终构建中包含 tests/
目录。虽然可以这样做(通过 --install-tests
标志),但最好在 meta.yaml
中使用 tests.source_files
仅在测试阶段复制测试。
最后,使用 testthat::test_file()
函数测试 tests/testthat.R
文件,对于大多数软件包而言,该文件充当所有其他测试的主要入口点。默认情况下,此函数在测试失败时不会返回错误值,因此需要传递参数 stop_on_failure=TRUE
以确保测试失败传播到 conda-build。
在某些情况下,tests/testthat.R
文件不会编排各个测试。在这种情况下,可以改为使用以下命令测试 tests/testthat
目录
test:
commands:
- $R -e "testthat::test_dir('tests/testthat/', package='PackageName', load_package='installed')" # [not win]
- "\"%R%\" -e \"testthat::test_dir('tests/testthat/', package='PackageName', load_package='installed')\"" # [win]
在这种情况下,默认情况下,该函数将在任何失败时报错。同样,此处的 PackageName
指的是 R 库名称。
软件包外部的测试
请注意,conda-build 在安装软件包后在隔离的环境中运行测试 – 因此,此时它无法访问原始源 tarball。这是为了确保测试环境尽可能接近最终用户将看到的环境。
这使得运行未与软件包一起安装的测试非常困难。
为 staged recipes 本地运行测试
如果您想在本地在 staged-recipes 存储库中运行和构建软件包,请转到根存储库目录并运行 build-locally.py
脚本(您需要 Python 3)。然后,您可以按照提示选择要构建的变体。如果您要为 Linux 构建软件包,则需要您的机器上安装 Docker。对于 MacOS,它将提示您选择要下载 SDK 的位置(例如 export OSX_SDK_DIR=/opt
)。
$ cd ~/staged-recipes
$ python build-locally.py
如果您知道要构建哪个镜像,则可以将其指定为脚本的参数。
$ cd ~/staged-recipes
$ python build-locally.py <VARIANT>
其中 <VARIANT>
是 .ci_support/
目录中的文件名之一,例如 linux64
、osx64
和 linux64_cuda<version>
。
关于
手动打包许可证
有时,上游维护者未在其 tarball 中包含许可证文件,即使许可证要求这样做。
如果是这种情况,您可以将许可证添加到 recipe
目录(此处命名为 LICENSE.txt
),并在 meta.yaml 中引用它
about:
license_file: LICENSE.txt
在这种情况下,也请通知上游开发人员许可证文件丢失。
仅当下载的存档中没有许可证文件时,才应将许可证与 recipe 一起发布。如果存档中存在许可证文件,请将 license_file
设置为存档中许可证文件的路径。
SPDX 标识符和表达式
对于 recipe meta.yaml
中的 about: license
条目,建议使用 SPDX 标识符或表达式。
有关许可证,请参阅 SPDX 许可证标识符。有关许可证例外,请参阅 SPDX 许可证例外。有关表达式规范,请参阅 SPDX 规范 附录 D。以下是一些示例
Apache-2.0
Apache-2.0 WITH LLVM-exception
BSD-3-Clause
BSD-3-Clause OR MIT
GPL-2.0-or-later
LGPL-2.0-only OR GPL-2.0-only
LicenseRef-HDF5
MIT
MIT AND BSD-2-Clause
PSF-2.0
Unlicense
包含的依赖项的许可证
对于某些语言(Go、rust 等),当前的策略是将所有依赖项及其依赖项都包含在软件包中。当打包许可证文件时,这会带来一个问题,因为每个依赖项都需要将其许可证文件包含在 recipe 中。
对于某些语言,社区提供了可以自动化此过程的工具,从而可以自动包含所有需要的许可证文件。
Rust
cargo-bundle-licenses 可以包含在软件包的构建过程中,并将自动收集并添加软件包的所有依赖项的许可证文件。
有关详细说明,请访问项目页面,但以下可以找到一个简短示例。
首先,将许可证的收集作为构建过程的一个步骤包含在内。
build:
number: 0
script:
- cargo-bundle-licenses --format yaml --output THIRDPARTY.yml
- build_command_goes_here
然后,将该工具作为构建时依赖项包含在内。
requirements:
build:
- cargo-bundle-licenses
最后,确保生成的文件包含在 recipe 中。
about:
license_file:
- THIRDPARTY.yml
- package_license.txt
Go
go-licenses 可以包含在软件包的构建过程中,并将自动收集并添加软件包的所有依赖项的许可证文件。
有关详细说明,请访问项目页面,但以下可以找到一个简短示例。
首先,将许可证的收集作为构建过程的一个步骤包含在内。
build:
number: 0
script:
- go build [...]
- go-licenses save . --save_path="./license-files/"
然后,将该工具作为构建时依赖项包含在内。
requirements:
build:
- {{ compiler('go') }}
- go-licenses
最后,确保生成的文件包含在 recipe 中。
about:
license_file:
- LICENSE
- license-files/
我们不是律师,无法保证上述建议是正确的,也无法保证这些工具能够找到所有许可证文件。此外,我们无法承担任何责任或义务。始终由您负责仔细检查是否包含所有许可证,并验证任何生成的输出是否正确。
依赖项许可证的正确且自动化的打包是一个 正在进行的讨论。请随时添加您的想法。
额外
Recipe 维护者
维护者是负责维护和更新一个或多个 feedstock 存储库和软件包及其未来版本的个人。他们拥有对其维护的软件包的 feedstock 存储库的推送访问权限,并且可以将 pull request 合并到其中。
为软件包贡献 recipe 会自动使您成为该软件包的 maintainer
。请参阅 维护者角色 和 维护软件包 以了解有关维护者所做事情的更多信息。如果您希望成为某个软件包的维护者,则应联系当前的维护者,并在该软件包的 feedstock 中打开一个 issue,并使用以下命令
@conda-forge-admin,请添加用户 @username
其中 username 是要添加的新维护者的 GitHub 用户名。有关详细说明,请参阅 成为维护者 和 更新维护者列表。
Feedstock 名称
如果您希望 feedstock 的名称与 staged-recipes 中的软件包名称不同,则可以在该软件包的 recipe 中使用 feedstock-name
指令,如下所示
extra:
feedstock-name: <name>
此处,<name>
是您希望 feedstock 使用的名称。如果未指定,则名称将从 meta.yaml
中的顶级 name
字段中获取。
杂项
激活脚本
Recipe 允许具有激活脚本,当环境激活时,将 source
或 call
这些脚本。通常建议在可能的情况下避免使用激活脚本,因为人们并不总是以预期的方式激活环境,并且这些软件包随后可能会表现异常。
在 recipe 中使用它们时,可以随意将它们命名为 recipe 中的 activate.bat
、activate.sh
、deactivate.bat
和 deactivate.sh
。建议安装的脚本以软件包名称和分隔符 -
为前缀。以下是一些用于 Unix 和 Windows 的示例代码,这将使安装过程更容易。请随意使用它。
在 build.sh
中
# Copy the [de]activate scripts to $PREFIX/etc/conda/[de]activate.d.
# This will allow them to be run on environment activation.
for CHANGE in "activate" "deactivate"
do
mkdir -p "${PREFIX}/etc/conda/${CHANGE}.d"
cp "${RECIPE_DIR}/${CHANGE}.sh" "${PREFIX}/etc/conda/${CHANGE}.d/${PKG_NAME}_${CHANGE}.sh"
done
在 build.bat
中
setlocal EnableDelayedExpansion
:: Copy the [de]activate scripts to %PREFIX%\etc\conda\[de]activate.d.
:: This will allow them to be run on environment activation.
for %%F in (activate deactivate) DO (
if not exist %PREFIX%\etc\conda\%%F.d mkdir %PREFIX%\etc\conda\%%F.d
copy %RECIPE_DIR%\%%F.bat %PREFIX%\etc\conda\%%F.d\%PKG_NAME%_%%F.bat
:: Copy unix shell activation scripts, needed by Windows Bash users
copy %RECIPE_DIR%\%%F.sh %PREFIX%\etc\conda\%%F.d\%PKG_NAME%_%%F.sh
)
Jinja 模板
Recipe meta.yaml
可以包含在构建时评估的表达式。这些表达式以 Jinja 语法编写。
Jinja 表达式在 meta.yaml 中具有以下用途
-
它们允许定义变量以避免代码重复。对
version
使用变量允许在每次更新时仅更改版本一次。{% set version = "3.7.3" %}
package:
name: python
version: {{ version }}
source:
url: https://pythonlang.cn/ftp/python/{{ version }}/Python-{{ version }}.tar.xz
sha256: da60b54064d4cfcd9c26576f6df2690e62085123826cff2e667e72a91952d318 -
它们可以调用 conda-build 函数 以实现自动代码生成。示例包括编译器、cdt 软件包或
pin_compatible
函数。requirements:
build:
- {{ compiler('c') }}
- {{ compiler('cxx') }}
- {{ cdt('xorg-x11-proto-devel') }} # [linux]
- {{ cdt('libx11-devel') }} # [linux]或
requirements:
build:
- {{ compiler('c') }}
- {{ compiler('cxx') }}
host:
- python
- numpy
run:
- python
- {{ pin_compatible('numpy') }}
有关更多信息,请参阅 conda-build 文档中的 使用 Jinja 模板 部分。