跳到主要内容

知识库

使用 Github 代码搜索查找示例

Github 的 代码搜索 是一个非常实用的工具,可以在 conda-forge 中查找配方示例。您可以使用一些技巧来充分利用搜索。

  • 将搜索范围限制为 org:conda-forge
  • 将路径限制为您想要的文件类型。这通常意味着
    • path:meta.yaml 用于主元数据文件。
    • path:recipe/*.sh 用于 Unix 构建脚本。
    • path:recipe/*.bat 用于 Windows 构建脚本。

就是这样,有了这两个修饰符,您就可以完成很多工作!一些示例包括

配置您的浏览器以设置搜索快捷方式

例如,在 Chrome 中,您可以转到 chrome://settings/searchEngines 并添加一个新条目,内容如下:

  • 名称:conda-forge 配方
  • 快捷方式:cf
  • URL:https://github.com/search?type=code&q=org%3Aconda-forge+%s

这样,您只需键入 cf your-search-here 即可进行超快速查询!

使用 CMake

CMake 可用于在 build.shbld.bat 脚本中构建更复杂的项目。

如果您正在使用 cmake,请务必将其作为 build 部分的构建要求。您可能还需要包含 makeninja,具体取决于您的平台和构建工具。在 Windows 上,您也可以使用 nmake 进行构建,但这不需要显式包含。

requirements:
build:
- cmake
- make # [not win]
- ninja # [win]

对于使用 FindPython 模块的 CMake 项目,您可以通过传递 -DPython_EXECUTABLE="$PYTHON"(macOS 或 Linux)或 -DPython_EXECUTABLE="%PYTHON%"(Windows)作为命令行选项来告诉 CMake 使用哪个 Python。较旧的 CMake 项目可能需要类似但略有不同的选项。

提示

不要忘记,根据您使用的 CMake 模块,您必须使用不同的命令

或者如果您仍在使用已弃用的 FindPythonLibs: -DPYTHON_EXECUTABLE=...

一些可选但有用的 CMake 选项

  • -DCMAKE_BUILD_TYPE=Release 配置为发布版本。最好在初始 cmake 调用时完成此操作,因为某些软件包会根据此标志构建不同的构建配置。
  • -DCMAKE_INSTALL_PREFIX=$PREFIX 指定安装位置。
  • -DCMAKE_INSTALL_LIBDIR=lib 库将放置在 $PREFIX/lib 中,有时项目会安装到 lib64 或类似的目录中,但在 conda-forge 上,我们将共享库简单地保存在 lib 中。
  • -DBUILD_SHARED_LIBS=ON 指示 CMake 构建共享库而不是静态库。
  • -DCMAKE_FIND_FRAMEWORK=NEVER-DCMAKE_FIND_APPBUNDLE=NEVER 阻止 CMake 使用系统范围的 macOS 软件包。
  • ${CMAKE_ARGS} 添加由 conda-forge 内部定义的变量。这是启用各种 conda-forge 增强功能(如 CUDA 构建)所必需的。

以下是一些基本命令,供您开始使用。这些命令取决于您的源代码布局,并非旨在“按原样”使用。

build.sh 的 CMake 行(macOS/Linux)

cmake CMakeLists.txt -DPython3_EXECUTABLE="$PYTHON"
cmake --build . --config Release

bld.bat 的 CMake 行(Windows)

cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DPython3_EXECUTABLE="%PYTHON%"
if errorlevel 1 exit /b 1
cmake --build . --config Release
if errorlevel 1 exit /b 1

另请参阅下面 Windows 部分中的 bld.bat,以获取更多示例。

其他有用的 cmake 选项包括 -B<directory>-S<directory>,用于指定构建和源目录。

从 autotools 构建迁移到 CMake 构建

一些软件包维护 autotools 构建和 cmake 构建。一些维护者希望切换到 cmake 构建,因为这样可以轻松提供 Windows 构建。这些构建在很大程度上彼此不 ABI 兼容。以下是一些您应该检查的内容:

  1. 检查两个库在 linux 上是否具有相同的 SONAME

    运行 readelf -d /path/to/lib.so

  2. 检查两个库是否具有相同的安装名称,并且具有相同的兼容性和当前版本。

    运行 otool -L /path/to/lib.dylib。第二行应为您提供三个信息:

  3. 检查两个库中的文件列表是否相同。

  4. 检查您是否使用了与 autoconf 构建相同的选项。

  5. 检查导出的符号是否相同。

  6. 检查其他打包信息是否保持不变,例如,是否提供了相同的 pkg-config 信息。

Windows 上的特殊性

本文档介绍了在 Windows 上构建时 conda-forge 和 conda-build 的信息和示例。

本地测试

您应该知道的第一件事是,即使您没有 Windows 机器,也可以在本地测试软件包的 Windows 构建。Microsoft 在 此网站 上提供了免费的官方 Windows 虚拟机 (VM)。如果您不熟悉 VM 系统或在安装 Microsoft 的 VM 时遇到问题,请使用通用的网络搜索进行探索 — 虽然这些主题超出了本文档的范围,但在更广泛的互联网上有很多关于它们的讨论。

要引导 conda 环境并安装 conda-build,请考虑使用 miniforge

执行构建

build-locally.py 脚本尚不支持 Windows(欢迎 PR!)。您现在可以使用 conda build recipe/ -m .ci_support/choose_your_config.yaml 作为权宜之计。

测试本地构建

因为我们直接使用 conda-build 而不是 build-locally.py,所以我们可以使用 local 通道

conda create -n my-new-env -c local my-package

关于本地代码的注意事项

为了在 Windows 上编译本地代码(C、C++ 等),您需要在 VM 上安装 Microsoft 的 Visual C++ 构建工具。您必须安装特定版本的这些工具 — 这是为了保持 Python 中使用的编译库之间的兼容性,如本 Python Wiki 页面所述。当前相关的版本是

  • 对于 Python 3.5–3.12+:Visual C++ 14.x

虽然您可以通过安装完整 Visual Studio 开发环境的正确版本来获取这些工具,但您可以通过安装独立的“构建工具”软件包来节省大量时间和带宽。您可以从 Visual Studio 订阅 中获取它们。要下载构建工具,您需要一个 Microsoft 帐户。进入 Visual Studio 订阅页面后,您可能还需要加入 Dev Essentials 计划。完成后,您可以单击“下载”选项卡并搜索“Build Tools for Visual Studio 2022”。在 conda-forge 完全 迁移到 Visual Studio 2022 之前,您可能仍然需要安装“Build Tools for Visual Studio 2019”才能在本地构建 feedstock。根据您的需求和可用的硬盘空间,您可以使用 Visual Studio Build Tools 2019 安装程序 直接安装 VC-2019,也可以使用 Visual Studio Build Tools 2022 安装程序 同时安装 VC-2022 和 VC-2019,确保选中“MSVC v142 - VS 2019 C++ x64/x86 build tools (v14.29)”的可选框。

如果您需要更多信息。请参阅 Python Wiki 页面上的 Windows 编译器

简单的基于 CMake 的 bld.bat

一些项目为 CMake 提供了构建项目的钩子。以下示例 bld.bat 文件演示了如何为此类项目构建传统的核外构建。

基于 CMake 的 bld.bat

setlocal EnableDelayedExpansion

:: Make a build folder and change to it.
mkdir build
cd build

:: Configure using the CMakeFiles
cmake -G "NMake Makefiles" ^
-DCMAKE_INSTALL_PREFIX:PATH="%LIBRARY_PREFIX%" ^
-DCMAKE_PREFIX_PATH:PATH="%LIBRARY_PREFIX%" ^
-DCMAKE_BUILD_TYPE:STRING=Release ^
..
if errorlevel 1 exit 1

:: Build!
nmake
if errorlevel 1 exit 1

:: Install!
nmake install
if errorlevel 1 exit 1

以下 feedstock 是已部署的此构建结构的示例

为不同的 VC 版本构建

在 Windows 上,不同的 Visual C 版本具有不同的 ABI,因此软件包需要为不同的 Visual C 版本构建。软件包与其构建时使用的 VC 版本绑定,并且某些软件包对 VC 版本有特定要求。例如,python 2.7 需要 vc 9,python 3.5 需要 vc 14

使用 conda-build 3.xvc 可以用作使用 compiler Jinja 语法时的选择器。

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

要跳过使用特定 vc 版本进行构建,请添加 skip 语句。

build:
skip: true # [win and vc<14]

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

使用 vs2022

recipe/conda_build_config.yaml 文件中

c_compiler:    # [win]
- vs2022 # [win]
cxx_compiler: # [win]
- vs2022 # [win]

您可以查看 此 PR 中的更改。

进行这些更改后,不要忘记使用 conda-smithy 重新渲染(要手动重新渲染,请从命令行使用 conda smithy rerender)。

CMD/Batch 语法的提示和技巧

Windows 配方默认依赖于 CMD/Batch 脚本 (.bat)。Batch 语法与 Unix 上的 Bash 等有所不同,因此我们在此处收集了一些提示,以帮助您在不熟悉此脚本语言的情况下入门。

  • 首先检查您是否需要编写 Batch 脚本!简单的配方可能不需要 shell 特定的代码,并且可以用不可知的方式编写。使用 meta.yaml 中的 build.script 项(请参阅 conda-build 文档)。此项可以接受字符串或字符串列表(每行一个)。
  • SS64 的 CMD 帮助页面 是关于 CMD/Batch 语法的任何类型问题的最佳资源。
  • 在 conda-forge 中搜索现有的 .bat 脚本,并通过示例学习。请参阅此 所有 Batchfile 的示例查询
  • 您可以从 Microsoft 免费试用 Windows VM。设置一个具有您喜欢的虚拟化解决方案的 VM,以调试您的 CMD 语法。还有一些最小的在线模拟器,即使并非所有 CMD 功能都存在,也可以帮助您入门基础知识。例如,这个 Windows 95 模拟器 具有或多或少还可以的 MS-DOS 提示符。

特殊的依赖项和软件包

编译器

编译器是具有特殊语法的依赖项,并且始终添加到 requirements/build 中。

目前支持五种编译器

  • C
  • cxx
  • Fortran
  • Go
  • Rust

需要所有五种编译器的软件包将定义

requirements:
build:
- {{ compiler('c') }}
- {{ compiler('cxx') }}
- {{ compiler('fortran') }}
- {{ compiler('go') }}
- {{ compiler('rust') }}
注意

适当的编译器运行时软件包将自动添加到软件包的运行时要求中,因此无需指定 libgcclibgfortran。有关 conda-build 3 如何处理编译器的更多信息,请参阅 conda 文档

交叉编译

conda-forge 默认对 Linux、macOS 和 Windows 上的 x86_64 软件包进行本地构建,因为这是为默认 CI 运行器提供支持的架构。也支持其他架构,但不能保证它们具有本地构建。在那些我们无法提供本地 CI 运行器的平台上,我们仍然可以求助于交叉编译或模拟。

交叉编译意味着为与构建过程运行的架构不同的架构构建软件包。鉴于 x86_64 运行器非常丰富,最常见的交叉编译设置将以 x86_64 运行器为目标,目标为非 x86_64 架构。

交叉编译术语通常区分两种类型的机器

  • 构建:运行构建过程的机器。
  • 主机:我们为其构建软件包的机器。
注意

一些交叉编译文档也可能区分第三种类型的机器,即目标机器。您可以在 此 Stack Overflow 问题 中阅读更多相关信息。对于 conda-forge 的目的,我们将认为目标机器与主机相同。

如何启用交叉编译

交叉编译设置取决于 build_platformtarget_platform conda-build 变量

  • build_platformconda-build 运行的平台,它定义了 $BUILD_PREFIX 中的 build 环境。
  • target_platform:软件包将安装在其上的平台。定义了 $PREFIXhost 环境的平台。默认为 build_platform 的值。

要更改 target_platform 的值并启用交叉编译,您必须使用 conda-forge.yml 中的 build_platform 映射,然后 重新渲染 feedstock。这将生成适当的 CI 工作流程和 conda-build 输入元数据。另请参阅 test,了解如何在交叉编译时跳过测试阶段。如果需求元数据和构建脚本编写正确,则软件包应该可以正常工作。但是,在某些情况下,它需要进行一些调整;请参阅下面的示例了解一些常见情况。

注意

build_platformtarget_platform 变量在构建脚本中作为环境变量公开(例如 $build_platform),也在 meta.yaml 选择器中作为 Jinja 变量公开(例如 # [build_platform != target_platform])。

除了这两个变量之外,conda-forge 的自动化(例如 conda-forge-ci-setup、编译器激活软件包等)还设置了一些环境变量,这些变量可以帮助进行交叉编译设置

  • CONDA_BUILD_CROSS_COMPILATION:当 build_platformtarget_platform 不同时设置为 1
  • CONDA_TOOLCHAIN_BUILD:构建平台预期的 autoconf 三元组。
  • CONDA_TOOLCHAIN_HOST:主机平台预期的 autoconf 三元组。
  • CMAKE_ARGS:使用 CMake 进行交叉编译所需的参数。在构建脚本中将其传递给 cmake
  • MESON_ARGS:使用 Meson 进行交叉编译所需的参数。在构建脚本中将其传递给 meson。请注意,还会自动为您创建一个 交叉构建定义文件
  • CC_FOR_BUILD:以构建平台为目标的 C 编译器。
  • CXX_FOR_BUILD:以构建平台为目标的 C++ 编译器。
  • CROSSCOMPILING_EMULATOR:主机平台的 qemu 二进制文件的路径。在交叉编译时对于运行测试很有用。

这一切都由 conda-build 版本 3 中引入的两个主要功能支持

将需求放在 build 或 host 中

经验法则是

  • 如果需要在构建期间运行,则放在 build 中。
  • 如果需要在目标主机上可用,则放在 host 中。
  • 如果两个条件都为真,则两者都属于。

但是,此规则有一些例外;最值得注意的是 Python 交叉编译(见下文)。

交叉编译示例

软件包需要在其配方中进行一些更改才能与交叉编译兼容。以下是一些示例。

使用 autotools 进行交叉编译的简单 C 库可能如下所示

requirements:
build:
- {{ compiler("c") }}
- make
- pkg-config
- gnuconfig

在构建脚本中,它需要更新配置文件并在交叉编译时保护任何测试

# Get an updated config.sub and config.guess
cp $BUILD_PREFIX/share/gnuconfig/config.* .

# Skip ``make check`` when cross-compiling
if [[ "${CONDA_BUILD_CROSS_COMPILATION:-}" != "1" || "${CROSSCOMPILING_EMULATOR:-}" != "" ]]; then
make check
fi

使用 CMake 进行交叉编译的简单 C++ 库可能如下所示

requirements:
build:
- {{ compiler("cxx") }}
- cmake
- make

在构建脚本中,它需要更新 cmake 调用并在交叉编译时保护任何测试

# Pass ``CMAKE_ARGS`` to ``cmake``
cmake ${CMAKE_ARGS} ..

# Skip ``ctest`` when cross-compiling
if [[ "${CONDA_BUILD_CROSS_COMPILATION:-}" != "1" || "${CROSSCOMPILING_EMULATOR:-}" != "" ]]; then
ctest
fi

类似地,对于 Meson,meta.yaml 需要

requirements:
build:
- {{ compiler("c") }}
- {{ compiler("cxx") }}
- meson
- make

以及 build.sh 中的此内容

# Pass ``MESON_ARGS`` to ``meson``
meson ${MESON_ARGS} builddir/

使用 Cython 和 NumPy 的 C API 的简单 Python 扩展可能如下所示

requirements:
build:
- {{ compiler("c") }}
- cross-python_{{ target_platform }} # [build_platform != target_platform]
- python # [build_platform != target_platform]
- cython # [build_platform != target_platform]
- numpy # [build_platform != target_platform]
host:
- python
- pip
- cython
- numpy
run:
- python
- {{ pin_compatible("numpy") }}

对于 MPI,构建平台需要 openmpi,因为编译器包装器是二进制文件,但 mpich 不是必需的,因为编译器包装器是脚本(请参阅 示例

requirements:
build:
- {{ mpi }} # [build_platform != target_platform and mpi == "openmpi"]
host:
- {{ mpi }}
run:
- {{ mpi }}

在构建脚本中,openmpi 编译器包装器可以通过将环境变量 OPAL_PREFIX 设置为 $PREFIX 来使用主机库。

if [[ "$CONDA_BUILD_CROSS_COMPILATION" == "1" && "${mpi}" == "openmpi" ]]; then
export OPAL_PREFIX="$PREFIX"
fi

这种方法在实际应用中还有更多变体。因此,这并非旨在详尽无遗,而仅仅是提供一个起点和一些指南。请查看 其他配方以获取更多示例

在交叉编译的 Python 软件包中使用 CMake 查找 NumPy

如果您正在通过 CMake 构建带有 NumPy 的 Python 扩展,并且您希望它在交叉编译中工作,则需要在构建脚本中将以下行添加到 CMake 调用之前

Python_INCLUDE_DIR="$(python -c 'import sysconfig; print(sysconfig.get_path("include"))')"
Python_NumPy_INCLUDE_DIR="$(python -c 'import numpy;print(numpy.get_include())')"
CMAKE_ARGS="${CMAKE_ARGS} -DPython_EXECUTABLE:PATH=${PYTHON}"
CMAKE_ARGS="${CMAKE_ARGS} -DPython_INCLUDE_DIR:PATH=${Python_INCLUDE_DIR}"
CMAKE_ARGS="${CMAKE_ARGS} -DPython_NumPy_INCLUDE_DIR=${Python_NumPy_INCLUDE_DIR}"
CMAKE_ARGS="${CMAKE_ARGS} -DPython3_EXECUTABLE:PATH=${PYTHON}"
CMAKE_ARGS="${CMAKE_ARGS} -DPython3_INCLUDE_DIR:PATH=${Python_INCLUDE_DIR}"
CMAKE_ARGS="${CMAKE_ARGS} -DPython3_NumPy_INCLUDE_DIR=${Python_NumPy_INCLUDE_DIR}"

关于交叉编译的 Python 软件包的详细信息

交叉编译 Python 软件包比其他软件包稍微复杂一些。主要的痛点是我们需要一个可执行的 Python 解释器(即 build 中的 python),它知道如何提供关于目标平台的准确信息。由于这未获得官方支持,因此需要一系列权宜之计才能使其工作。有关更多信息,请参阅 PEP720此问题中的讨论

实际上,对于 conda-forge,这导致了 meta.yaml 中需要的两个额外的元数据位

  • build 要求中添加 cross-python_{{ target_platform }},由 cross-python-feedstock 提供。这是 crossenv Python 解释器的包装器,其中包含 一些激活逻辑,用于调整一些 crossenv 权宜之计,以便它们更好地与 conda-build 设置一起工作。
  • 使用 [build_platform != target_platform] 选择器将一些与 Python 相关的软件包从 host 复制到 build
    • python 本身,以支持 crossenv
    • 非纯 Python 软件包(即,它们附带编译的库),在构建软件包时需要存在,例如 cythonnumpy

根据 PEP720 的术语,conda-forge 设置实现了“伪造目标环境”方法。更具体地说,这将在构建脚本运行之前导致以下更改

  • $BUILD_PREFIX/venv 中修改后的 crossenv 安装,模拟 $PREFIX 的架构。
  • $BUILD_PREFIX/bin 中指向 crossenv 安装的转发器二进制文件。
  • crossenv 安装中公开 $BUILD_PREFIX site-packages 的符号链接,该安装也包含在 $PYTHONPATH 中。
  • 将所有 $PREFIX site-packages 复制到 $BUILD_PREFIX(编译库除外)。

总而言之,这导致了一个设置,其中 conda-build 可以运行 $BUILD_PREFIX 架构的 python 解释器,该解释器可以看到 $PREFIX 中的软件包(编译位由 $BUILD_PREFIX 中相应的对应物提供),并充分模拟该目标架构。

模拟构建

当无法进行交叉编译时,可以求助于模拟。这是一种使用虚拟机 (QEMU) 模拟目标平台的技术,这会产生很大的开销。但是,conda-build 会将目标平台视为本地平台,因此配方通常只需要进行很少的更改。

要启用模拟构建,您必须使用 conda-forge.yml 中的 provider 映射。此键将 build_platform 映射到一个 provider,该 provider 将用于模拟平台。conda-smithy 将知道如何检测 provider 是本地支持该平台还是需要模拟,并将调整适当的 CI 步骤以确保 QEMU 运行该过程。通过 重新渲染 feedstock 确保应用更改。

请注意,目前仅支持通过模拟的 Linux 架构。

警告

模拟构建非常缓慢,并且会对 conda-forge CI 资源造成额外的压力。如果可能,请考虑使用交叉编译来代替。仅在万不得已的情况下才使用模拟构建。

模拟示例

配置 conda-forge.yml 以模拟 linux-ppc64le,但对 linux-64linux-aarch64 使用原生 runners。这之所以可行,是因为 Azure 本身不支持 linux-ppc64le,因此 conda-smithy 将添加 QEMU 步骤来模拟它。但是,Azure 和 Travis CI 分别原生支持 linux-64linux-aarch64,因此无需模拟。

provider:
linux_aarch64: travis
linux_ppc64le: azure
linux_64: azure

Rust Nightly

许多 rust 包依赖于 rust 编译器的 nightly 版本。考虑到这种快速的发布节奏,conda-forge 尚未拉取每个版本。相反,rust nightly 版本会根据需要拉取到 conda-forge/rust-feedstockdev 分支中。对于新版本,请在该 feedstock 上提交 issue。

要在您的 feedstock 中启用 rust nightly 编译器,请按照上面的部分操作,然后在 conda_build_config.yaml 文件中添加 rust_dev 频道

channel_sources:
- conda-forge/label/rust_dev,conda-forge

核心依赖树软件包 (CDT)

应避免使用 conda-forge 频道之外的依赖项(请参阅避免外部依赖项)。但是,也有一些例外情况

某些依赖项与系统非常接近,因此未与 conda-forge 一起打包。这些依赖项必须使用核心依赖树 (CDT) 软件包来满足。

CDT 软件包由重新打包的 CentOS/AlmaLinux 二进制文件组成,版本可以是 7、8 或 9,具体取决于用户选择和平台。我们使用集中的 repo conda-forge/cdt-builds 来管理 CDT 软件包的构建,而不是为它们生成 feedstock。(请注意,历史上我们确实使用过 feedstock,但这种做法已被弃用)。要添加新的 CDT,请在 conda-forge/cdt-builds repo 上提交 PR。

为什么 CDT 不好?

  1. CDT 重新打包了库的旧版本。
  2. 因此,软件包中的较新功能将不会被下游 conda 软件包使用,这些软件包会检查所构建库的版本。例如:CentOS 7 打包库中的 OpenGL 功能可用,但任何更新的功能都无法使用。
  3. 我们不保证用户系统提供的版本是兼容的。我们只有 __glibc>=2.17 约束,并且我们假设 CentOS 7 的 GLIBC 下限及其对应的 CDT 下限是等效的。
  4. 我们不保证用户的系统会提供该库。

何时应使用 CDT?

  1. 当库使用系统特定的配置时。一些示例包括
    1. linux-pam:这是一个允许插入式身份验证模块的库,这些模块的配置文件通常位于 /etc/pam.d 中。问题在于插入式模块位于特定于发行版的位置。例如:/usr/lib/x86_64-linux-gnu/security/。默认模块内置于 $CONDA_PREFIX/lib/security 中的 conda 软件包中,但用于系统范围配置的自定义模块安装在 /usr/lib/x86_64-linux-gnu/security/ 中。因此,我们需要修补模块以同时查找这两个目录,但是目录 /usr/lib/x86_64-linux-gnu/security/ 是特定于发行版的,并且很难检测到。
  2. 当 conda 打包的库无法正常工作时。例如:新的 glibc 软件包意味着我们将不得不编辑所有 conda 软件包二进制文件的 elf 解释器。

有哪些好的例子?

  1. OpenCL 加载器(ocl-icdocl-icd-system 一起)提供了一个 OpenCL 加载库。加载器将查找 $CONDA_PREFIX/etc/OpenCL/vendors 中给出的 OpenCL 实现。例如:Pocl 是一个 conda 打包的实现,可在 CPU 上运行 OpenCL。NVIDIA OpenCL 或 ROCm OpenCL 等供应商特定的实现未进行 conda 打包,因此我们必须依赖系统。通过安装 ocl-icd-system,我们使加载器能够查找 /etc/OpenCL/vendors 中的配置,这是所有 linux 发行版的配置目录。这为我们提供了两全其美的方案。您不需要系统级别的软件包来运行 OpenCL,因为我们有一个 conda 打包的安装,但是如果存在由特定硬件加速的系统范围的实现,我们可以使用这些实现。

libGL

请注意,依赖于 OpenGL 和/或 libGL 的软件包不应再使用 CDT。相反,请使用来自 libglvnd-feedstock 的 host 依赖项 libgl-devel

requirements:
host:
- libgl-devel # [linux]

其他 OpenGL API 变体,例如 libegl-devellibgles-devellibglx-devellibopengl-devel 也可用,并且将自动添加非开发 run_exports 依赖项。

针对 NumPy 构建

链接到 NumPy 的软件包需要在依赖项部分进行特殊处理。在 setup.py 中找到 numpy.get_include() 或在 .pyx.pyd 文件中找到 cimport 语句是该软件包链接到 NumPy 的明显标志。

在链接的情况下,您需要使用 pin_compatible 函数以确保在运行时拥有兼容的 numpy 版本

host:
- numpy

在撰写本文时(2025 年 1 月),以上内容等效于以下内容,

host:
- numpy 1.22 # [py==39]
- numpy 1.22 # [py==310]
- numpy 1.23 # [py==311]
- numpy 1.26 # [py==312]

尽管 numpy 2.0 的持续迁移已经应用于许多 feedstock,在这种情况下,pinning 看起来像

host:
- numpy 2.0 # [py==39]
- numpy 2.0 # [py==310]
- numpy 2.0 # [py==311]
- numpy 2.0 # [py==312]

有关 pinning 在撰写本文时对应的具体内容,请参阅 pinning 存储库 https://github.com/conda-forge/conda-forge-pinning-feedstock/blob/main/recipe/conda_build_config.yaml#L742

在任何一种情况下,实际的运行时要求都通过 numpy 的 run-export 确定,即

  • 如果您针对 numpy 1.2x 构建,则为 >=1.2x,<2
  • 如果您针对 numpy 2.0 构建,则为 >=1.19,<3
  • 如果您针对 numpy 2.1 或 2.2 构建,则为 >=1.21,<3

如果您正在构建的软件包对 numpy 有更高的最低要求,请将其添加到 run

host:
# leave this unpinned!
- numpy
run:
- numpy >={{ the_lower_bound_your_package_needs }}

JupyterLab 扩展

典型的 JupyterLab 扩展同时具有 Python 和 JavaScript 组件。这些组件应打包在一起,以防止 node 需要在用户机器上获取软件包的 JavaScript 端。要打包扩展,构建应具有以下 meta.yaml 代码段

build:
noarch: python


requirements:
host:
- python {{ python_min }}.*
- nodejs
- pip
run:
- python >={{ python_min }}
- nodejs
- jupyterlab >=2

请在您的 recipe 中使用以下 build.sh 脚本

#!/usr/bin/env bash
set -ex

$PYTHON -m pip install . -vv
npm pack ${PKG_NAME}@${PKG_VERSION}
mkdir -p ${PREFIX}/share/jupyter/lab/extensions/js
cp ${PKG_NAME}-${PKG_VERSION}.tgz ${PREFIX}/share/jupyter/lab/extensions/js

由于这是一个 noarch recipe,因此构建脚本只需要在 linux-64 上运行。另请注意,我们不需要在软件包构建期间或任何 post-link 脚本中运行 jupyter labextension installjupyter lab build。这是因为 JupyterLab 将在下次运行时自行运行构建步骤。${PREFIX}/share/jupyter/lab/extensions/js 目录是 JupyterLab 已知的在执行此构建步骤时从中构建的目录。

消息传递接口 (MPI)

注意

本节源自 Min 的笔记:https://hackmd.io/ry4uI0thTs2q_b4mAQd_qg

conda-forge 中的 MPI 变体

如何在 conda-forge 中最好地处理 MPI 变体?

有几种广泛的情况

  • 软件包需要特定的 MPI 提供程序(简单!)
  • 软件包可以与任何 MPI 提供程序(例如 mpich、openmpi)一起使用
  • 软件包可以使用/不使用 MPI

请注意,有时用户希望使用在 conda-forge 中构建的、针对我们的 MPI 库但链接到运行时外部 MPI 库的软件包。如果您对此过程感兴趣,请参阅使用外部消息传递接口 (MPI) 库 以了解详细信息。

构建 MPI 变体

在 conda_build_config.yaml 中

mpi:
- mpich
- openmpi

在 meta.yaml 中

requirements:
host:
- {{ mpi }}

并使用以下命令重新渲染

conda-smithy rerender -c auto

以生成构建矩阵。

包含 no-mpi 构建

某些软件包(例如 hdf5)可能需要 no-mpi 构建,以及 mpi 构建。为此,请将 nompi 添加到 mpi 矩阵中

mpi:
- nompi
- mpich
- openmpi

并在您的构建中应用适当的条件

requirements:
host:
- {{ mpi }} # [mpi != 'nompi']
run:
- {{ mpi }} # [mpi != 'nompi']

首选提供程序(通常为 nompi)

到目前为止,mpi 提供程序没有明确的偏好。在选择 MPI 提供程序时,mpi 元软件包的互斥性允许通过安装 mpi 提供程序在 mpi 提供程序之间进行选择,例如

conda install mpich ptscotch

conda install openmpi ptscotch

这不适用于 nompi,因为 mpi 元软件包没有 nompi 变体。而且可能不应该有,因为某些使用 mpi 构建的软件包不会阻止 env 中可能具有 mpi 变体的其他软件包使用库的 no-mpi 变体(例如,长期以来,fenics 将 mpi 与 no-mpi hdf5 一起使用,因为当时还没有并行 hdf5。这可以正常工作,尽管某些功能可能不可用)。

通常,如果存在偏好,则将是串行构建,这样软件包的安装程序/请求者仅在显式请求时才获得 mpi 构建。在这种情况下,我们对 nompi 变体使用更高的构建编号。

这是一个构建部分的示例

{% if mpi == 'nompi' %}
# prioritize nompi variant via build number
{% set build = build + 100 %}
{% endif %}
build:
number: {{ build }}

# add build string so packages can depend on
# mpi or nompi variants explicitly:
# `pkg * mpi_mpich_*` for mpich
# `pkg * mpi_*` for any mpi
# `pkg * nompi_*` for no mpi

{% if mpi != 'nompi' %}
{% set mpi_prefix = "mpi_" + mpi %}
{% else %}
{% set mpi_prefix = "nompi" %}
{% endif %}
string: "{{ mpi_prefix }}_h{{ PKG_HASH }}_{{ build }}"
注意

{{ PKG_HASH }} 避免了大多数变体上的构建字符串冲突,但对于从默认构建字符串中排除的软件包(例如 Python 本身)则不然。如果软件包是为多个 Python 版本构建的,请使用

string: "{{ mpi_prefix }}_py{{ py }}h{{ PKG_HASH }}_{{ build }}"

mpi4py 中所示

此构建部分创建以下软件包

  • pkg-x.y.z-mpi_mpich_h12345_0
  • pkg-x.y.z-mpi_openmpi_h23456_0
  • pkg-x.y.z-nompi_h34567_100

这具有以下后果

  • nompi 变体是首选的,除非显式请求 mpi 变体,否则将默认安装。
  • 可以使用 pkg=*=mpi_{{ mpi }}_* 显式请求 mpi 变体
  • 可以使用 pkg=*=mpi_* 请求任何 mpi 变体,忽略提供程序
  • 可以使用 pkg=*=nompi_* 显式请求 nompi 变体

如果使用此库构建会在变体上创建运行时依赖项,则可以将构建字符串 pinning 添加到 run_exports

例如,如果针对 nompi 变体构建可以与任何已安装的版本一起使用,但使用给定的 mpi 提供程序构建需要与该 mpi 一起运行

build:
...
{% if mpi != 'nompi' %}
run_exports:
- {{ name }} * {{ mpi_prefix }}_*
{% endif %}

如果所有变体都应根据构建时选择的变体创建严格的运行时依赖项(即,如果 nompi 构建无法针对 mpich 构建运行),请删除 if mpi... 条件。

完整示例

结合以上所有内容,这是一个完整的 recipe,其中包含

  • nompi、mpich、openmpi 变体
  • run-exports 应用在构建时所做的 mpi 选择到运行时,其中 nompi 构建可以使用 mpi 运行,但反之则不然。
  • 默认情况下首选 nompi 变体
  • 仅在 Windows 上构建 nompi

这与 hdf5 中的做法相符。

# conda_build_config.yaml
mpi:
- nompi
- mpich # [not win]
- openmpi # [not win]
# meta.yaml
{% set name = 'pkg' %}
{% set build = 0 %}

# ensure mpi is defined (needed for conda-smithy recipe-lint)
{% set mpi = mpi or 'nompi' %}

{% if mpi == 'nompi' %}
# prioritize nompi variant via build number
{% set build = build + 100 %}
{% endif %}

build:
number: {{ build }}

# add build string so packages can depend on
# mpi or nompi variants explicitly:
# `pkg * mpi_mpich_*` for mpich
# `pkg * mpi_*` for any mpi
# `pkg * nompi_*` for no mpi

{% if mpi != 'nompi' %}
{% set mpi_prefix = "mpi_" + mpi %}
{% else %}
{% set mpi_prefix = "nompi" %}
{% endif %}
string: "{{ mpi_prefix }}_h{{ PKG_HASH }}_{{ build }}"

{% if mpi != 'nompi' %}
run_exports:
- {{ name }} * {{ mpi_prefix }}_*
{% endif %}

requirements:
host:
- {{ mpi }} # [mpi != 'nompi']
run:
- {{ mpi }} # [mpi != 'nompi']

然后,依赖于此软件包的软件包可以显式选择适当的 mpi 构建

# meta.yaml

requirements:
host:
- {{ mpi }} # [mpi != 'nompi']
- pkg
- pkg * mpi_{{ mpi }}_* # [mpi != 'nompi']
run:
- {{ mpi }} # [mpi != 'nompi']
- pkg * mpi_{{ mpi }}_* # [mpi != 'nompi']

mpi 元软件包的互斥性允许 mpi_* 解析为与 mpi_{{ mpi }}_* 相同的结果(如果 {{ mpi }} 也是直接依赖项),尽管显式声明可能更好。

仅 mpi 示例

如果没有首选的 nompi 变体,则需要 mpi 的 recipe 会简单得多。这就是所需要的全部内容

# conda_build_config.yaml
mpi:
- mpich
- openmpi
# meta.yaml
requirements:
host:
- {{ mpi }}
run:
- {{ mpi }}

MPI 编译器软件包

不要在 recipe 的 requirements/build 部分中使用 [openmpi,mpich]-[mpicc,mpicxx,mpifort] 元软件包;MPI 编译器包装器包含在主要的 openmpi/mpich 软件包中。如上所示,只需将 openmpi/mpich 添加到 requirements/host 部分,并在 requirements/build 中正常使用相应编译器的编译器指令即可。

OpenMP

您可以通过将 llvm-openmp 软件包添加到 meta.yamlbuild 部分,在 macOS 上启用 OpenMP。对于 Linux,默认情况下 OpenMP 支持处于启用状态,但最好显式依赖于 libgomp 软件包,它是 GNU 项目的 OpenMP 实现。

# meta.yaml
requirements:
build:
- llvm-openmp # [osx]
- libgomp # [linux]

切换 OpenMP 实现

在 macOS 上,仅支持 LLVM 的 OpenMP 实现 llvm-openmp。即使在使用 GNU 的 gfortran 编译的 Fortran 代码中也使用此实现。

在 Linux 上(aarch64 除外),软件包链接到 GNU 的 libgomp.so.1,但可以通过执行以下操作将安装时的 OpenMP 库从 GNU 切换到 LLVM。

conda install _openmp_mutex=*=*_llvm

可以通过执行以下操作将 OpenMP 库切换回 GNU 的 libgomp。

conda install _openmp_mutex=*=*_gnu
注意

OpenMP 库切换是可能的,因为 LLVM 的实现除了 LLVM 的符号(最初来自 Intel)外,还具有 GNU 的符号。由 gccg++gfortran 生成的目标文件将具有 GNU 的符号,因此可以切换底层库。但是,由 clangclang++ 生成的目标文件将具有 LLVM 的符号,因此底层 OpenMP 库无法切换到 GNU 的库。

您可能希望切换到 LLVM 的一个原因是该实现是 fork 安全的。保留使用 GNU 实现的一个原因是 libgomp 中的 OpenMP 目标卸载符号(如 GOMP_target)在 LLVM 中是空桩,因此不起作用。

yum_requirements.txt

可以通过在 feedstock 的 recipe 目录中名为 yum_requirements.txt 的文件中逐行列出软件包名称,使用 yum 将依赖项安装到构建容器中。

在极少数情况下,yum 安装的依赖项是可以接受的。这些情况包括

  • 在测试阶段满足 CDT 软件包的要求
  • 安装仅用于测试的软件包

更改 yum_requirements.txt 后,rerender 以更新配置。

BLAS

如果软件包需要 BLAS、CBLAS、LAPACK、LAPACKE 中的一个,请在 recipe 的 host 中使用以下内容,

requirements:
host:
- libblas
- libcblas
- liblapack
- liblapacke
注意

您应该仅指定软件包需要的库。(即,如果软件包不需要 LAPACK,请删除 liblapack 和 liblapacke)

在 recipe 构建时,以上要求将下载 NETLIB 的参考实现,并针对这些实现构建您的 recipe。在运行时,默认情况下将使用以下软件包。

- openblas   # [not win]
- mkl # [win]

如果软件包需要特定实现的内部 API 以进行更多控制,您可以拥有,

requirements:
host:
# Keep mkl-devel here for pinning
- mkl-devel {{ blas_impl == "mkl" }}
- {{ blas_impl }} {{ blas_impl != "mkl" }}
run:
- libblas * *{{ blas_impl }}
- {{ blas_impl }}

这将为您提供针对不同 blas 实现的矩阵构建。如果您只想支持特定的 blas 实现,

requirements:
host:
- openblas
run:
- libblas * *openblas
- openblas
注意

不应再使用 blas_* 功能。

切换 BLAS 实现

您可以通过执行以下操作来切换您的 BLAS 实现,

conda install "libblas=*=*mkl"
conda install "libblas=*=*openblas"
conda install "libblas=*=*blis"
conda install "libblas=*=*accelerate"
conda install "libblas=*=*netlib"

这将更改 BLAS 实现,而不会更改依赖于 BLAS 的 conda 软件包。

以下旧命令也受支持。

conda install "blas=*=mkl"
conda install "blas=*=openblas"
conda install "blas=*=blis"
conda install "blas=*=accelerate"
conda install "blas=*=netlib"
注意

如果您想提交到特定的 blas 实现,可以通过在您的环境中 pinning blas 实现来防止 conda 切换回。要提交到 mkl,请将 blas=*=mkl 添加到 <conda-root>/envs/<env-name>/conda-meta/pinned,如 conda-docs 中所述。

它是如何工作的

在 recipe 构建时,使用 netlib 软件包。这意味着下游软件包将链接到 libblas=*=*netlib 中的 libblas.so.3,并且将仅使用参考实现的符号。

libblaslibcblas 版本控制基于参考 LAPACK 版本控制,在撰写本文时为 3.8.0。由于 BLAS API 是稳定的,因此下游软件包将仅 pinning 到 libblaslibcblas3.*。另一方面,liblapackliblapacke pinning 到 3.8.*

除了上述 netlib 软件包之外,还有其他变体,例如 libblas=*=*openblas,它将 openblas 作为依赖项,并具有从 libblas.so.3libopenblas.so 的符号链接。libblas=3.8.0=*openblasopenblas 依赖项 pinning 到已知支持 BLAS 3.8.0 API 的版本。这意味着,在安装时,用户可以选择他们喜欢的 BLAS 实现,而无需了解所需的 BLAS 实现的版本。

微架构优化构建

conda 虚拟软件包 包括 __archspec,它向 solver 公开处理器架构。但是,不应在 recipe 中直接使用 __archspec;相反,用户应依赖 microarch-level 辅助软件包(在 staged-recipes#24306 中贡献)。

在学习如何使用它之前,请阅读这些注意事项

  • 添加微架构变体可能会导致构建矩阵中条目过多。不要过度使用它。
  • 这些优化的构建应仅在性能提升显著时使用。
  • 最好是,项目应依赖于运行时调度来进行特定于架构的优化。
  • 如果软件包已经太大,请考虑为架构优化的变体使用较小的输出。

要在您的 feedstock 中实现微架构优化构建,您最终会得到类似以下的内容

recipe/conda_build_config.yaml
microarch_level:
- 1
- 3 # [unix and x86_64]
- 4 # [unix and x86_64]
recipe/meta.yaml
# ...
{% set build = 0 %}

build:
number: {{ build }} # [not (unix and x86_64)]
number: {{ build + 100 }} # [unix and x86_64 and microarch_level == 1]
number: {{ build + 300 }} # [unix and x86_64 and microarch_level == 3]
number: {{ build + 400 }} # [unix and x86_64 and microarch_level == 4]

requirements:
build:
- x86_64-microarch-level {{ microarch_level }} # [unix and x86_64]
- {{ compiler('c') }}
# ...
# ...
优先考虑您首选的微架构

run_exports 元数据仅设置为下限,以允许在 CI 中进行测试。这意味着 level=2 软件包可以安装在 level=3 机器中。确保为首选微架构分配更高的构建编号(通常为最高级别)。

就是这样!microarch-level 软件包背后的激活脚本已经为您注入了必要的编译器标志。由于它们也具有 run_exports 条目,因此您的软件包将具有必要的运行时要求,以确保安装最合适的变体。有关更多信息,请参阅 此评论microarch-level-feedstock README

Matplotlib

conda-forge 上的 matplotlib 分为两个部分。核心库在 matplotlib-base 中。实际的 matplotlib 软件包是这个核心库加上 pyqt。大多数(即使不是全部)在运行时依赖于 matplotlib 的软件包都应将此依赖项列为 matplotlib-base,除非它们显式需要 pyqt。这样做的目的是,显式安装 matplotlib 的用户将获得具有 pyqt 的全功能安装。但是,pyqt 是一个相当大的软件包,因此不间接要求它是为了提高性能。请注意,如果您导入链接到 libX11matplotlib 部分,您可能需要在您的 recipe 中包含一个带有以下内容的 yum_requirements.txt 文件

xorg-x11-server-Xorg

如果您导入链接到 libX11matplotlib 部分。

pybind11 ABI 约束

有时,当使用 pybind11 的不同 python 库通过较低级别的 C++ 接口进行交互时,两个库之间的底层 ABI 必须匹配。为了简化此用例,我们有一个 pybind11-abi 元软件包,可以在构建的 host 部分中使用。它的版本是全局 pinning 的,并且它本身具有 run export,这意味着 host 中包含此软件包的构建将在运行时对其进行约束。此外,pybind11 对 ABI 元软件包具有 run 约束,以帮助确保一致的使用。

要在构建中使用此软件包,请将其放在 host 环境中,如下所示

requirements:
host:
- pybind11-abi

空 Python 软件包

对于在更高版本的 Python 中引入的某些功能,Python 社区创建了 backport,这使得这些功能也可用于早期版本的 Python。这里的一个示例是 dataclasses,它是在 Python3.7 中引入的,但也作为 Python3.6 的 backport 提供。因此,大多数上游软件包仅对特定版本的 Python 强制使用这些 backport,否则会排除它们。

目前,在 conda-forge 中实现此限制的唯一方法是使用 skips,这会限制相应的 conda-forge recipe 成为 noarch

因此,某些 conda-forge recipe 仅在特定 Python 版本上创建实际软件包,而在其他情况下则为空占位符。这使它们可以在所有 Python 版本下安全安装,并使使用 skips 变得不必要。

类似地,某些软件包只是软件包的平台特定依赖项,例如 pywin32,并且具有辅助元软件包,可以帮助 recipe 保持 noarch。所需实际软件包的版本可以使用 run_constrained 进行控制,即使对于并非在所有平台上都可用的软件包也是如此。

当前可用的软件包

名称可用平台空平台
backports.strenumpython >=3.8,<3.11python >=3.12
dataclassespython >=3.6,<3.7python >=3.7
enum34python =2.7python >=3.4
pywin32-on-windowswindowsunix
typingpython >=3

非版本特定的 Python 软件包

对于某些依赖项,上游维护人员列出了需要这些软件包的 Python 版本,即使这些软件包实际上可以在所有 Python 版本下安装。

目前,在 conda-forge 中实现此限制的唯一方法是使用 skips,这会限制相应的 conda-forge recipe 成为 noarch

因此,conda-forge 社区维护了一个软件包列表,这些软件包即使原始软件包仅在某些版本中需要,也可以安全地在所有 Python 版本下安装。

例如,软件包 pyquil要求 importlib-metadata 用于 python <3.8,但实际上也可以安全地安装在 python >=3.8 下。

当前可用的软件包

  • exceptiongroup
  • importlib-metadata

Noarch 构建

Noarch 软件包是不特定于架构的软件包,因此只需要构建一次。

在 meta.yaml 的 build 部分中将这些软件包声明为 noarch,可以减少共享 CI 资源。因此,所有符合 noarch 软件包条件的软件包都应声明为 noarch。

Noarch python

build 部分中的 noarch: python 指令使纯 Python 软件包只需构建一次。

为了符合 noarch python 软件包的条件,必须满足以下所有标准

  • 没有编译的扩展
  • 没有 post-link 或 pre-link 或 pre-unlink 脚本
  • 没有特定于操作系统的构建脚本
  • 没有 python 版本特定的要求
  • 除了 python 版本外,没有 skips。如果 recipe 仅适用于 py3,请删除 skip 语句,并在 hostrun 部分中添加 python 的版本约束。
  • 不使用 2to3
  • 不使用 setup.py 中的 scripts 参数
  • 如果在 setup.pysetup.cfg 中定义了 console_scripts entry_points,它们也会列出meta.yamlbuild 部分中
  • 没有 activate 脚本

所有采用 noarch: python 的 recipe 通常都应按照以下示例使用 python_min 变量

recipe/meta.yaml
name: package
source:
# ...
build:
noarch: python
# ...
requirements:
host:
- python {{ python_min }}
# ...
run:
- python >={{ python_min }}
# ...

test:
requires:
- python {{ python_min }}
# ...

有关此语法的更多详细信息,请参阅 CFEP-25。如果您需要覆盖此语法,您可以在 recipe 顶部添加 Jinja2 set 语句(或 v1 recipe 的等效 context 变量),如下所示

recipe/meta.yaml
{% set python_min = "3.10" %}

也可以通过向您的 recipe 添加包含如下 map 的 conda_build_config.yaml 文件来实现相同的效果

recipe/conda_build_config.yaml
python_min:
- "3.10"

如果您选择这条路线,则需要在添加 conda_build_config.yaml 文件后重新渲染 feedstock

downstream 测试中,将 noarch: python 软件包与 test.requires 部分中的 python {{ python_min }} pins 一起使用,可能会导致 upstream 软件包失败,如果测试所需的 Python 版本与 upstream 软件包的 Python 版本冲突。根据哪个更重要,有两种解决方法。

  1. upstream 软件包中的 downstream 测试约束为仅在 python_min 上运行。
  2. downstream 软件包的测试要求中删除 python_min 要求。

或多或少,当在 python_min 上测试 downstream 软件包是最重要的事情时,您更喜欢第一种解决方案。当使用 downstream 软件包测试 upstream 软件包的所有 Python 版本是最重要的事情时,您更喜欢第二种解决方案。

提示

在您的 noarch: python 配方中显式添加 python_min,可以有效地确保在 conda-build 时强制执行软件包元数据中所需的 Python 版本,因为如果软件包所需的 Python 版本比 python_min 新,构建将会失败。

注意

虽然 noarch: python 不适用于选择器,但它适用于版本约束。skip: True # [py2k] 可以替换为主机和运行子节中受约束的 python 版本:例如 python >=3 而不是仅 python

注意

只有 console_scripts 入口点必须在 meta.yaml 中列出。其他入口点与 noarch 不冲突,因此不需要额外处理。

注意

noarch 是关于软件包源代码的声明,而不是其安装环境。即使某个软件包的依赖项在给定平台上不可用,该软件包仍然被认为是 noarch。如果是这种情况,当 conda 尝试安装该软件包时,将显示一条有用的错误消息,描述哪个依赖项找不到。如果该依赖项稍后可用,您的软件包将可以在该平台上安装,而无需对 feedstock 进行任何更改。

默认情况下,noarch 软件包在 Linux 上构建,并且所有依赖项必须在 Linux 上可用。

提示

如果 noarch 软件包无法在 Linux 上构建,可以在 conda-forge.yml 中提供一个或多个 noarch_platforms。一个例子是 pywin32-on-windows,它在 Linux 和 Windows 上构建,并使用 build_number 偏移来创建一对软件包,例如 dataclasses

提示

您可以构建特定于平台的 noarch 软件包,以包含取决于目标操作系统的运行时需求。请参阅下面的迷你教程。

如果现有的 python 软件包符合转换为 noarch 软件包的条件,您可以通过打开新 issue 并包含 @conda-forge-admin, please add noarch: python 来请求所需的更改。

具有操作系统特定依赖项的 Noarch 软件包

可以构建具有运行时需求的 noarch 软件包,这些运行时需求取决于目标操作系统(Linux、Windows、MacOS),而与架构(amd64、ARM、PowerPC 等)无关。这种方法依赖于三个概念

  1. 虚拟软件包。以双下划线为前缀,conda 使用它们来表示系统属性,作为安装时求解器的约束。我们将使用 __linux__win__osx,它们仅在运行平台分别为 Linux、Windows 或 MacOS 时才存在。__unix 同时存在于 Linux 和 MacOS 中。请注意,此功能仅在 conda 4.10 或更高版本上完全可用
  2. conda-forge.ymlnoarch_platforms 选项。
  3. conda-build 3.25.0 或更高版本 更改了依赖于所用虚拟软件包的构建哈希。

这个想法是为每个需要不同依赖项的操作系统生成不同的 noarch 软件包。假设您有一个纯 Python 软件包,完全符合 noarch: python 的条件,但在 Windows 上它需要 windows-only-dependency。您可能有类似这样的内容

recipe/meta.yaml(原始)
name: package
source:
# ...
build:
number: 0
requirements:
# ...
run:
- python
- numpy
- windows-only-dependency # [win]

作为非 noarch,这意味着构建矩阵将至少包含 12 个输出:三个平台,乘以四个 Python 版本。随着 arm64aarch64ppc64le 的加入,情况会更糟。如果我们用另一种方法替换它,我们可以将其减少到两个输出!

recipe/meta.yaml(修改后)
name: package
source:
# ...
build:
number: 0
noarch: python
requirements:
host:
- python {{ python_min }}.*
# ...
run:
- python >={{ python_min }}
- numpy
- __unix # [unix]
- __win # [win]
- windows-only-dependency # [win]

不要忘记使用选择器指定平台虚拟软件包!否则,求解器将无法正确选择变体。

默认情况下,conda-forge 将仅在 linux_64 CI runner 上构建 noarch 软件包,因此只有 # [unix] 选择器为真。但是,我们可以使用 conda-forge.yml 中的 noarch_platforms 选项来更改此行为

conda-forge.yml
noarch_platforms:
- linux_64
- win_64

这将为每个软件包提供两个 runner!完美!所有这些更改都需要 feedstock rerender 才能应用。请参阅 Rerendering feedstocks

如果您需要在所有三个操作系统上都有条件依赖项,可以这样做

recipe/meta.yaml
name: package
source:
# ...
build:
number: 0
noarch: python
requirements:
# ...
run:
- python >={{ python_min }}
- numpy
- __linux # [linux]
- __osx # [osx]
- __win # [win]
- linux-only-dependency # [linux]
- osx-only-dependency # [osx]
- windows-only-dependency # [win]
conda-forge.yml
noarch_platforms:
- linux_64
- osx_64
- win_64

再次提醒,在添加/修改这些文件后,请记住重新渲染,以便应用更改。

Noarch generic

待办事项

添加一些关于大量使用 noarch: generic 的 r 软件包的信息

多输出配方

conda-build 能够通过 meta.yaml 中的 outputs 部分从单个配方创建多个软件包工件。这在多种情况下很有用,包括

outputs 的常见陷阱

这是使用 outputs 时常见陷阱的非详尽列表。

  • 通常,使用与任何输出名称都不匹配的顶级名称会更简单。如果顶级名称与 feedstock 名称不同,请确保在 meta.yaml 中设置 extra.feedstock-name。请参阅 rich-feedstock。请注意,顶级名称为 rich-split,feedstock 名称为 rich,主输出也是 rich
  • build.shbld.bat 脚本仅自动用于顶级软件包。考虑为输出中的脚本使用其他文件名。请参阅 gdal-feedstock 以获取示例。
  • outputs[].script 字段只能设置为脚本名称。如果您更喜欢传递 shell 命令,则必须使用 outputs[].build.script。分别比较 geopandas-feedstockgym-feedstock
  • 通常为顶级脚本设置的某些 PIP_* 环境变量不会自动为输出设置。如果您在输出中调用 pip,您可能需要传递其他标志。请参阅 napari-feedstock。此问题在 conda/conda-build#3993 中跟踪。

构建矩阵

目前,python, vc, r-base 将为每个受支持的版本创建一个作业矩阵。如果 python 只是构建依赖项而不是运行时依赖项(例如:软件包的构建脚本是用 Python 编写的,但软件包不依赖于 Python),请使用 build 部分

以下内容暗示 python 只是构建依赖项,并且不会创建 Python 矩阵。

build:
- python
host:
- some_other_package

请注意,host 应该是非空的,或者使用 compiler jinja 语法,或者将 build/merge_build_host 设置为 True,以使 build 部分与 host 不同。

以下内容暗示 python 是运行时依赖项,并且将为每个受支持的 Python 版本创建一个 Python 矩阵。

host:
- python

conda-forge.yml 的构建矩阵在 conda-smithy=3 中已删除。要获取构建矩阵,请在配方文件夹内创建一个 conda_build_config.yaml 文件。例如,以下内容将为您提供 2 个构建,您可以在 meta.yaml 中使用选择器 vtk_with_osmesa

vtk_with_osmesa:
- False
- True

在此更改后,您需要重新渲染 feedstock。

需要更新的 macOS SDK

conda-forge 使用 macOS SDK 10.13 构建软件,以便可以将它们部署到所有 macOS 10.13 或更高版本。有时,某些软件包需要更新的 SDK 才能构建。虽然可以使用以下配方更改来覆盖默认版本 10.13,但这应作为最后的手段。如果您认为您需要这样做,请咨询核心团队。

要使用新的 SDK,请在 recipe/conda_build_config.yaml 中添加以下内容

# Please consult conda-forge/core before doing this
MACOSX_SDK_VERSION: # [osx and x86_64]
- "10.15" # [osx and x86_64]

请注意,如果您收到的错误消息说找不到标头或未定义宏,则应执行此操作。这将使您的软件包使用更新的 SDK 进行编译,但以 10.13 作为部署目标。警告:由于有缺陷的符号可用性检查,如果您执行上述操作,某些软件包可能会使用 10.15 中的功能。例如,查找 clock_gettime 的软件包会将其视为弱符号,但该软件包可能没有处理弱符号的代码路径,在这种情况下,您需要更新 c_stdlib_version(以前为 MACOSX_DEPLOYMENT_TARGET),如下所述。

在增加 SDK 版本后,如果您收到错误消息,指出某个函数仅适用于 macOS x.x,则在 recipe/conda_build_config.yaml 中执行以下操作,

# Please consult conda-forge/core before doing this
c_stdlib_version: # [osx and x86_64]
- "10.15" # [osx and x86_64]
MACOSX_SDK_VERSION: # [osx and x86_64]
- "10.15" # [osx and x86_64]

recipe/meta.yaml 中,添加以下内容以确保用户的系统兼容。

requirements:
build:
- {{ stdlib("c") }}

请注意,stdlib 元软件包生成的 __osx 上的 run-export 需要 conda>=4.8

使用旧 SDK 的较新 C++ 功能

libc++ 库使用 Clang 可用性注释来标记某些符号在以附带系统 libc++ 的 macOS 版本为目标时不可用。Clang 始终假定使用系统 libc++。

conda-forge 构建基础架构以 macOS 10.13 为目标,并且某些较新的 C++ 功能(如 fs::path)在该平台上标记为不可用,因此构建中止

...
error: 'path' is unavailable: introduced in macOS 10.15
...
note: 'path' has been explicitly marked unavailable here
class _LIBCPP_TYPE_VIS path {

但是,由于 conda-forge 附带了自己的(现代)libcxx,我们可以忽略这些检查,因为这些符号实际上是可用的。为此,请将 _LIBCPP_DISABLE_AVAILABILITY 添加到定义中。例如

CXXFLAGS="${CXXFLAGS} -D_LIBCPP_DISABLE_AVAILABILITY"

PyPy 构建

有关 PyPy 和 conda-forge 的更多信息,请参阅用户文档中的 使用 PyPy 作为解释器

要为 pypy 构建您的 python 软件包,请等待机器人发送 PR,如果在依赖项构建完成后未发送 PR,请联系 conda-forge/bot 团队。

要仅为 pypy 或 cpython 添加依赖项,请执行以下操作:

requirements:
run:
- spam # [python_impl == 'cpython']
- ham # [python_impl == 'pypy']
注意

您需要在进行上述更改后重新渲染 feedstocks,以便 python_impl 变量可用于 conda-build

要跳过 pypy 构建,请执行以下操作:

build:
skip: True # [python_impl == 'pypy']

如果某些内容在 PyPy 构建中失败,但在 CPython 构建中通过,请联系 @conda-forge/help-pypy。

使用 setuptools_scm

Python 模块 setuptools_scm 可用于从元数据(例如 git 标签)自动管理软件包的版本。因此,软件包的版本字符串未在软件包中的任何位置指定,而是在安装时编码在其中。

对于 conda-build,这意味着必须将 setuptools_scm 作为 host 依赖项包含在内。此外,还需要注意,元数据通常在源中不可用。有两种方法可以继续操作

  • 对于 PyPI 上也提供的 Python 软件包:使用 PyPi tarball 作为源,因为它将具有编码的元数据(以 setuptools_scm 知道如何找到它的方式)。

  • 使用版本字符串指定环境变量 SETUPTOOLS_SCM_PRETEND_VERSION。如果指定,此环境变量是 setuptools_scm 的主要来源。有两种方法可以做到这一点

    • 如果您使用构建脚本,请在 build.sh 中指定

      export SETUPTOOLS_SCM_PRETEND_VERSION="$PKG_VERSION"

      并在 bld.bat 中指定

      set SETUPTOOLS_SCM_PRETEND_VERSION=%PKG_VERSION%

      您可以在其中使用已使用版本字符串设置的 PKG_VERSION,请参阅 环境变量

    • 否则,如果您直接从 meta.yaml 构建,请使用例如

      build:
      # [...]
      script_env:
      - SETUPTOOLS_SCM_PRETEND_VERSION={{version}}
      script: "{{ PYTHON }} -m pip install . -vv"

需要更新的 glibc 版本

Conda-forge 的目标是为尽可能多的用户构建,这意味着我们的目标是 CentOS 7 中的 glibc 2.17,这允许软件包安装在基本上任何 linux 系统(2014 年之后)上。

但是,某些 feedstocks 可能已经需要更新的 glibc 版本。要在 linux 上使用带有 glibc 2.282.34 的更新 sysroot,请将以下内容放在您的构建部分中。

requirements:
build:
- {{ compiler('c') }}
- {{ stdlib('c') }}

并将以下内容添加到 recipe/conda_build_config.yaml

c_stdlib_version:          # [linux]
- "2.28" # [linux]

这涵盖了构建时的标头/库,并且还将在 __glibc 虚拟软件包上创建相应的 run-export。

默认情况下,conda-forge 构建基础架构在新映像上使用旧的 sysroot,这意味着 docker 映像中存在的 glibc 不是我们编译的目标。这有几个优点,也意味着通常您不必担心手动更改映像。

但是,如果出于某种原因您想覆盖映像版本,您可以通过在配方的 conda-forge.yml 中设置以下内容并重新渲染来实现。

os_version:             # example of possible values
linux_64: cos7
linux_aarch64: alma8
linux_ppc64le: alma9

在 feedstock 进行二进制重新打包(即,不从源代码编译)的特殊情况下,请确保您使用尽可能旧的映像,以匹配配方的 c_stdlib_version。例如,如果您使用默认的 c_stdlib_version 2.17,则设置 os_version: linux_*: cos7;如果您使用 c_stdlib_version 2.28,则将其设置为 alma8

CUDA 构建

尽管提供的 CI 机器没有 GPU,但 conda-forge 确实提供了构建启用 CUDA 的软件包的机制。有关更多信息,请参阅 使用 CUDA 的配方的维护者指南。如果 feedstock 需要访问其他资源(如 GPU),请参阅以下 部分

常见问题和已知问题

在 Windows 上找不到 nvcuda.dll

用于在 Windows 上安装 CUDA 工具包的 脚本 无法提供 nvcuda.dll 作为安装的一部分,因为 CI 机器中没有物理 GPU。因此,您可能会在 conda build 的后处理步骤中遇到链接错误

WARNING (arrow-cpp,Library/bin/arrow_cuda.dll): $RPATH/nvcuda.dll not found in packages,
sysroot(s) nor the missing_dso_whitelist.

.. is this binary repackaging?

目前,您必须将 nvcuda.dll 添加到 missing_dso_whitelist

build:
...
missing_dso_whitelist:
- "*/nvcuda.dll" # [win]

我的 feedstock 不再构建旧的 CUDA 版本

随着新的 CUDA 版本定期发布,conda-forge 需要定期决定在资源约束内支持多少个版本。截至 2025 年 1 月,conda-forge 支持 CUDA 11 和 12。

要更新到最新支持的版本,请 重新渲染 feedstock。根据上次更新的时间,feedstock 可能还需要其他修复。

需要 GPU 或长时间运行构建的软件包

conda-forge 可以访问 OpenStack 服务器,该服务器提供 GPU 构建和长时间运行构建(超出通常的 6 小时限制)。如果您的软件包需要 GPU 才能构建或测试,或者其编译时间太长,目前是手动在 CI 之外完成的,您可以请求访问这些 runner。为此,请执行以下操作

  1. conda-forge/admin-requests 中打开 PR。按照仓库 README 中的说明进行操作。请注意,您需要请求您想要访问的资源类型(例如,GPU runner 或长时间运行的 CPU 构建)。合并后,这将为您的 feedstock 启用自托管的 Github Actions runner。
  2. 为了触发这些 runner 的作业,维护者必须阅读并同意 open-gpu-server 使用条款。您需要在 open-gpu-server 仓库中打开 PR,如其 README 中所述。每个维护者只需执行一次此操作(例如,如果您维护多个 feedstocks)。
  3. 最后,您可以配置您的 feedstock 以使用自托管的 runner。在步骤 (1) 中的 PR 合并后,admin-requests 将创建一个 PR。但是,由于 Github 施加的安全措施,当它们修改 Github Actions 工作流程时,无法进行自动重新渲染。您需要在您的机器上运行 conda-smithy rerender 手动重新渲染它,然后提交并推送结果。
注意

由于一些技术和法律限制,某些常用的自动化基础架构不适用于这些 runner。如上所述,conda-forge 机器人将无法再自动重新渲染您的 feedstock。自动合并也将无法正常运行。另请注意,conda-forge 机器人将无法触发自托管的 runner。关闭并重新打开 PR 将不起作用,但具有足够权限的维护者可以通过推送空提交手动触发它。

Apple Silicon 构建

新的 Apple M1 处理器是 conda-forge osx-arm64 构建支持的第一个 Apple Silicon。为了使新构建通过 交叉编译 可用,需要对软件包及其依赖项进行迁移。这些构建是实验性的,因为其中许多未经测试。

要请求特定软件包及其所有依赖项的迁移

  1. 您的软件包可能已经在迁移过程中。请检查 arm osx addition 迁移 的状态。如果您的软件包已经在迁移过程中,它将出现在相应的标题下(已完成、PR 中、等待父项等)。
  2. 检查有问题的 feedstock,看看是否已经存在 issue 或 pull request。在这里打开 issue 也可以,因为这可能需要几次迭代,尤其是在许多依赖项也需要构建的情况下。
  3. 如果没有正在进行的操作,请查看当前的 conda-forge-pinning
  4. 如果该软件包未在那里列出,请创建一个 PR,将软件包名称添加到 osx_arm64.txt 中的随机位置。迁移机器人应开始为仓库及其依赖项创建自动 pull request。
  5. 在几个小时内,状态页面 应反映相关软件包的进度,并帮助您跟踪进度。如果可以,请伸出援手!
  6. feedstock 维护者(可能没有 M1)将努力进行任何必要的更改以通过持续集成。如果您对特定软件包有深入了解, 参与进来,但最重要的是耐心和礼貌
  7. 一旦新构建可从 anaconda.org 获得,请通过测试软件包并报告任何问题以及成功案例来帮助维护者!

预发布版本构建

配方维护者可以通过将预发布版本添加到 devrc 标签,使其在 conda-forge 上可用。

这些标签的语义通常应遵循 Python 本身遵循的 指南

  • rcBetaRelease Candidate (RC)。没有新功能。仅错误修复。
  • devPre-AlphaAlpha。这些仍然是软件包,在 dev 版本和最终版本之间可能会发生重大更改。
注意

不使用 alphabeta 标签。鉴于目前为止 conda-forge 频道上标签的使用率不高,似乎没有必要引入太多标签。devrc 似乎是一个不错的折衷方案。

注意

某些软件包(例如 black)遵循发布周期,其中它们从未发布过非 beta/alpha 版本。在这些情况下,这些软件包的 conda 软件包不需要发布到预发布标签。

创建预发布版本构建

要创建 devrc 软件包,可以向 feedstock 的 devrc 分支发出 PR。此分支必须更改 recipe/conda_build_config.yaml 文件以指向 <package_name>_dev<package_name>_rc 标签。

例如,matplotlib rc 版本将包括

channel_targets:
- conda-forge matplotlib_rc

如果 B 的预发布版本依赖于 A 的预发布版本,则 A 应具有,

channel_targets:
- conda-forge A_rc

而 B 应具有,

channel_sources:
- conda-forge/label/A_rc,conda-forge
channel_targets:
- conda-forge B_rc

在其各自 feedstock 的 recipe/conda_build_config.yaml 中。

注意

需要重新渲染才能使这些更改反映在 CI 文件中。channel_targets 条目映射

安装预发布版本构建

使用 conda CLI

使用以下命令,但将 PACKAGE_NAME 替换为您要安装的软件包,并将 LABEL 替换为 rcdev

conda install -c conda-forge/label/PACKAGE_NAME_LABEL -c conda-forge PACKAGE_NAME

例如,让我们从 rc 标签安装 matplotlib

conda install -c conda-forge/label/matplotlib_rc -c conda-forge matplotlib

使用 environment.yml

使用 MatchSpec 来指定您的软件包

dependencies:
- conda-forge/label/matplotlib_rc::matplotlib=3.7.0rc1

或者,您可以使用 channels 部分来启用 matplotlib_rc 频道

channels:
- conda-forge/label/matplotlib_rc
dependencies:
- matplotlib=3.7.0.rc1

预发布版本排序

如果您希望向您的 devrc 构建添加数字,您应该遵循 Continuum 发布的关于 conda 中版本排序的 指南。另请参阅 conda 4.2.13 的源代码。这里的 tl;dr 是 conda 的排序方式如下

< 1.0
< 1.1dev1 # special case 'dev'
< 1.1.0dev1 # special case 'dev'
== 1.1.dev1 # 0 is inserted before string
< 1.1.0rc1
< 1.1.0

因此,请确保您标记您的软件包,以便 conda-build 吐出的软件包名称将对使用 rc 标签上传的软件包进行排序,使其高于使用 dev 标签上传的软件包。

如何更新您的 feedstock token?

要重置您的 feedstock token 并修复上传问题,请按照以下步骤操作

  1. 转到 conda-forge/admin-requests 仓库,并将 examples/example-token-reset.yml 复制到 requests/ 文件夹。
  2. 在 YML 文件中添加您的 feedstock 的名称。添加名称时,请不要在末尾添加“-feedstock”。例如:对于 python-feedstock,只需添加 python

使用 arch_rebuild.txt

如果 feedstock 需要使用不同的架构/平台(例如 ppc64leaarch64)重新构建,您可以将其添加到 arch_rebuild.txt。检查 迁移状态,查看您的软件包是否已在队列中等待迁移。如果不是,您可以通过打开到 conda-forge-pinning-feedstock 仓库 的 PR,将 feedstock 添加到 arch_rebuild.txt。一旦 PR 合并,迁移机器人将遍历 arch_rebuild.txt 中的 feedstock 列表,并为任何新的 feedstocks 及其依赖项打开迁移 PR,从而启用 aarch64/ppc64le 构建。

迁移器和迁移

当软件包的全局 pinnings 中进行任何更改时,host 部分需要该软件包的整个软件包堆栈都需要更新和重建。手动执行可能非常繁琐,这就是迁移可以提供帮助的地方。迁移自动化了向 feedstock 提交更改的过程,并且是 regro-cf-autotick-bot 职责的组成部分。

有几种迁移类型,您可以在 制作迁移器 中阅读相关内容。要生成这些迁移,您可以使用迁移器,它们是为 conda-forge 中受影响的软件包自动创建 pull request 的机器人。要在一个或多个 pin 中提出迁移,迁移器会使用 yaml 文件向 pinning feedstock 发出 PR,该文件在 migrations 文件夹中表达对全局 pinning 文件的更改。一旦 PR 合并,就会构建依赖关系图。之后,机器人将遍历该图,逐个迁移所有节点(feedstocks),并为这些 feedstocks 发出 PR。

通常,机器人会自动生成这些迁移。但是,当首次创建或添加 pin 时,可能需要手动添加一个。为此,您可以按照 更新软件包 pins 中提到的步骤进行操作。

迁移的进行方式是

  1. 您在 conda-forge-pinning-feedstockmigrations 文件夹中创建一个 PR,其中包含一个新的 yaml 文件,表示迁移。
  2. 一旦 PR 合并,机器人就会拾取它,构建迁移器图,并开始迁移过程。
  3. 仅当满足以下条件时,才会为节点(feedstock)发出迁移 PR
- The node depends on the changed pinnings.
- The node has no dependencies that depend on the new pinnings and have not been migrated.
  1. 过程 3 继续,直到迁移完成,并且通过最终 PR 将更改应用于全局 pinning 文件。在此步骤之后,我们说此迁移已结束。

有时,您可能会收到针对您的软件包的迁移 PR,但您不想合并它。在这种情况下,您应该将该 PR 设置为草稿状态,但绝不应关闭它。如果您关闭 PR,这会让机器人认为另一个实现迁移的 PR 已合并,从而使迁移继续在图上迭代;但是,下游依赖项会失败,因为父项(我们关闭 PR 的那个)实际上并未重建。保持 PR 处于打开或草稿状态的另一个好处是,将来如果有人想帮忙,他们可能会提供帮助。

在某些情况下,迁移 PR 可能不会被打开。请查看我们的状态页面上的迁移,以查看是否存在任何问题。这可能会显示仍有依赖项需要迁移,在这种情况下,最好的方法是等待(或者如果可能,提供帮助迁移这些依赖项)。如果出现机器人错误,将有一个指向 CI 任务的链接,以提供有关可能出现的问题的更多详细信息。在这些情况下,请提出 issue 并包含尽可能多的信息。

值得注意的是,您也可以选择自己创建迁移 PR。如果机器人出错且仍在调查中,或者迁移 PR 被意外关闭,这可能是一个不错的选择。要手动迁移 PR

  1. Fork feedstock 并在本地克隆它
  2. 创建一个新分支
  3. 在 feedstock 中创建目录 .ci_support/migrations(如果不存在)
  4. 将 migrator 从 conda-forge-pinning 的 migrators 复制到 .ci_support/migrations 并提交
  5. 重新渲染 feedstock
  6. 推送这些更改并打开一个 PR

conda-forge 构建的安全注意事项

所有 conda-forge 软件包都由互联网上的陌生人在公共云基础设施上使用您可能没有检查过的源代码构建,因此如果您或您的团队需要高 level 的安全性,则不应使用 conda-forge 软件包。如果您希望至少进行这么多监督,您也可以自由下载 recipes 并自行重建它们。但是,许多人一直都在使用 conda-forge,没有任何问题,以下是 conda-forge 在某些方面为帮助安全所做的一些事情

  1. Sources(您在其中指定软件包的源代码来自何处)可以从 GitHub、PyPI 或其他来源拉取,并且始终使用 sha256 哈希,因此移动标签或上传新的 sdist 不会导致自动软件包重建。此外,一旦软件包被接受并制成 feedstocks,只有该 feedstock 的维护者才有权合并提交给该 feedstock 的 PR。
  2. 每个 feedstock 只能上传该 feedstock 的软件包。这是通过使用 cf-staging 渠道强制执行的,构建首先发送到该渠道。然后,机器人评估提交的 feedstock 是否有权构建其提交的软件包,然后才会将构建中继到 conda-forge 渠道。这有助于防止不良行为者访问不起眼的 feedstock,然后尝试将包含恶意代码的构建推送到关键的基础设施软件包(例如,OpenSSL 或 Python)。
  3. 我们有 artifact-validation 用于验证上传到 anaconda.org 的所有 conda-forge artifacts。此验证扫描各种与安全相关的项目,例如覆盖某些软件包关键部分的 artifacts。
  4. 我们有一个专门的安全和系统子团队,他们努力工作,以确保安全并维护对 conda-forge 使用的凭据和服务/系统的适当访问。

如果您发现 conda-forge 存在与安全相关的问题,请查看我们的 安全策略,了解如何负责任地报告它。

上游项目的重大更改

我们不时地对上游项目进行更改,以便它们更好地集成到 conda-forge 生态系统中。我们在此处列出了一些(但不是全部)针对特定项目的更改以及任何相关的文档。

Python

我们携带了一整套 python 补丁,这些补丁更改了围绕搜索路径、conda 环境中的环境隔离以及某些操作系统限制的一些核心行为。有关更多详细信息,请参阅 python feedstock