Apache Arrow 夜间构建 Conda Forge 配方解析:dev/tasks/conda-recipes 目录结构与同步机制
2026/9/23 2:52:11 网站建设 项目流程
  • 数据工程
  • 大数据
  • 序列化
  • 数据分析

【免费下载链接】arrow

Apache Arrow is a multi-language toolbox for accelerated data interchange and in-memory processing

项目地址:https://gitcode.com/gh_mirrors/arrow13/arrow
点击查看免费下载

本指南以 Apache Arrow 仓库中dev/tasks/conda-recipes目录及其核心文档 README.md 为主线,深入剖析 Arrow 项目如何为crossbow 夜间持续集成(nightly CI)维护一套独立的 Conda Forge 构建配方。你将掌握这套配方与上游 conda-forge feedstock 的差异、meta.yaml的多输出(multi-output)结构、变体矩阵(.ci_support)与 CI 模板的组织方式,以及配方在“上游回迁(backport)”与“发布期前向移植(port)”两个方向上的同步工作流,并了解对应的构建脚本、测试策略与清理工具。

一、这套配方是什么:为开发版 Arrow 而生

Apache Arrow 的 conda 包在 conda-forge 上由 [arrow-cpp-feedstock] 与 [parquet-cpp-feedstock] 两个上游仓库(feedstock)维护,它们面向的是已发布版本。而 Arrow 主仓库内的dev/tasks/conda-recipes目录则是一份独立的配方副本,专供 crossbow 夜间测试使用,其特点是:

  • 跟随开发版本:配方中的ARROW_VERSION是一个由 CI 注入的 Jinja 模板变量,每次夜间构建都指向仓库当前的开发版本,而非固定的发布版本号;
  • 夜间频率验证:配方在 nightly 基础上持续构建与测试,任何对 C++/Python 接口的破坏性改动都会在合并前被这套构建尽早暴露;
  • 与上游配方保持同步:由于上游 feedstocks 会由 conda-forge 团队自动更新,本仓库的副本需要周期性回迁(backport)这些更新,以免因依赖矩阵陈旧导致构建漂移。

需要说明:由于配方中包含多个 vendored 文件(如.ci_support变体配置、Azure Pipelines 模板等),无法由 conda-smithy 在 Arrow 仓库内自动生成,因此必须依靠人工定期从上游同步,这正是本目录 README 反复强调“must be migrated periodically”的原因。

二、目录结构与文件角色

先给出 dev/tasks/conda-recipes 目录的完整文件清单及职责划分:

路径角色
arrow-cpp/meta.yaml主配方,定义apache-arrow包及其 6 个输出(outputs)
arrow-cpp/activate.sh环境激活脚本(随包分发)
arrow-cpp/test_read_parquet.pypyarrow 冒烟测试脚本,验证写/读 Parquet 闭环
parquet-cpp/meta.yaml防冲突元包(meta-package),兼容旧包名
azure.ymlAzure Pipelines 顶层入口(当前为空,实际任务模板由各平台文件提供)
azure.linux.yml/azure.osx.yml/azure.win.yml三平台 CI 模板(Jinja2 渲染)
azure.clean.yml清理任务模板
build_steps.shconda-smithy 生成的构建脚本(已适配 crossbow,容器内执行)
run_docker_build.shLinux 下启动 Docker 容器执行构建的入口脚本
clean.py清理 arrow-nightlies 频道上过期构建包的工具
conda-forge.ymlconda-forge 配置,当前为channel_priority: strict

从仓库结构可以推断,这套目录是一个“缩水版 feedstock”:它复用了 conda-forge feedstocks 的约定(.ci_supportmeta.yamlbuild_steps.shrun_docker_build.sh),但砍掉了上游完整的 CI 矩阵,改为由 crossbow 的任务配置驱动。

三、主配方 arrow-cpp/meta.yaml 深度解读

arrow-cpp/meta.yaml 是整套配方的核心。与 conda-forge 上游配方最大的不同,正如文件头注释所写:这里的ARROW_VERSION是模板变量,而非写死的版本号:

{% set version = ARROW_VERSION %} {% set cuda_enabled = cuda_compiler_version != "None" %} {% set build_ext_version = ARROW_VERSION %} {% set build_ext = "cuda" if cuda_enabled else "cpu" %} {% set proc_build_number = "0" %} {% set llvm_version = "15" %}

版本号ARROW_VERSION由 CI 环境注入(见 tasks.yml 中的ARROW_VERSION: {{ arrow.no_rc_version }}),因此同一份配方可以在任意开发提交上反复构建。build_ext变量把构建变体标记为cpucuda,并贯穿所有输出包。

3.1 六个输出(outputs)的职责划分

配方通过outputs字段一次性产出 6 个 conda 包,这是理解整份配方的关键:

  1. apache-arrow-proc:虚拟变体选择包(meta-package),用于在 conda 层面标记cpu/cuda构建变体。其构建字符串即为cpucuda,test 仅执行exit 0
  2. arrow-cpp-proc:为旧版“mutex-package”命名方案提供的兼容输出,依赖对应版本的apache-arrow-proc
  3. libarrow:真正的 C++ 库输出(build-arrow.sh/build-arrow.bat),包含run_exports声明pin_subpackage("libarrow", max_pin="x"),即下游包最多只能 pin 到主版本号(SemVer 兼容承诺)。
  4. arrow-cpp:旧命名方案兼容包(10.0.0 起改名,保留数个版本后移除),精确依赖对应版本的libarrow
  5. pyarrow:Python 绑定输出,build string形如py{{ CONDA_PY }}h{{ PKG_HASH }}_{{ PKG_BUILDNUM }}_{{ build_ext }},同时依赖精确版本(exact=True)的libarrow
  6. pyarrow-tests:包含 pyarrow 测试套件的包,仅在 CI 中按需构建与运行(详见第六节)。

3.2 CUDA 构建变体

配方对 CUDA 的处理非常精细,体现了 crossbow 配方“比上游更准确”的定位:

  • 通过cuda_compiler_version != "None"判定是否启用 CUDA,cuda_enabled同时驱动build_exttrack_features: "[arrow-cuda]"
  • skip: true # [cuda_compiler_version not in ("None", cuda_compiler_version_min)]保证只针对最小 CUDA 版本构建一次即可兼容所有后续版本——注释明确说明原因是 Arrow 仅使用libcuda而非libcudart
  • 通过missing_dso_whitelist豁免对libcuda.so.*(Linux)与nvcuda.dll(Windows)的依赖检查;
  • 在测试段中,CPU 构建会显式断言不存在libarrow_cuda相关产物,防止变体泄漏。

3.3 依赖矩阵与版本约定

host依赖列表完整覆盖了 Arrow C++ 构建所需的第三方库,并可交叉验证到 cpp/CMakeLists.txt 与 cpp/cmake_modules/ThirdpartyToolchain.cmake 中的依赖查找逻辑:

  • 核心压缩/编码:brotlibzip2lz4-csnappyzlibzstdorc
  • 列存格式:thrift-cppre2(Parquet 支持);
  • 内存与并发:boost-cpp >=1.70xsimdnlohmann_jsonrapidjsongflagsglog
  • Flight / Gandiva / Substrait:libgrpclibprotobuflibabseilclangdev {{ llvm_version }}llvmdev {{ llvm_version }}opensslaws-crt-cppaws-sdk-cppgoogle-cloud-cpplibutf8proc
  • Linux 特有:ucx(UCX 传输)、autoconf/make(vendored jemalloc 构建需要)。

配方还通过注释记录了多处“有意为之”的取舍,例如:Arrow 使用定制版 jemalloc 故不依赖 conda 的jemalloccpp-opentelemetry-sdk因上游 feedstock 问题暂未启用;Windows 上glog不参与run_exportsgoogle-cloud-cpp的静态依赖(libcrc32clibcurl)需显式补进 host。这些注释本身就是跨平台移植经验的浓缩。

3.4 安装后测试:头文件、动态库与“禁静态库”断言

libarrow输出的test.commands展示了 conda 包质量门禁的完整套路,覆盖三平台:

{% set headers = [ "arrow/api.h", "arrow/acero/api.h", "arrow/flight/types.h", "arrow/flight/sql/api.h", "gandiva/engine.h", "parquet/api/reader.h" ] %} {% for each_header in headers %} # headers - test -f $PREFIX/include/{{ each_header }} || (echo "{{ each_header }} not found" && exit 1) # [unix] - if not exist %LIBRARY_INC%\{{ "\\".join(each_header.split("/")) }} exit 1 # [win] {% endfor %}

测试要点可归纳为:

  • 头文件存在性:逐一检查arrow/api.harrow/acero/api.harrow/flight/types.harrow/flight/sql/api.hgandiva/engine.hparquet/api/reader.h,确保各子库头文件被打包;
  • 动态库存在性:按 CUDA 与否动态生成库清单(arrowarrow_aceroarrow_datasetarrow_flightarrow_flight_sqlarrow_substraitgandivaparquet,CUDA 时追加arrow_cuda),分别检查.so(Linux)、.dylib(macOS)、.dll/.lib(Windows);
  • 静态库“必须不存在”test ! -f ...a_static.lib检查,确保只发布共享库;
  • gdb 包装脚本:Linux 下校验libarrow.so.<so_version>-gdb.py、macOS 下校验libarrow.<so_version>.dylib-gdb.pyso_versionversion.split(".")计算得出,如 10.x →10x形式的 SONAME)。

四、parquet-cpp/meta.yaml:防冲突元包

parquet-cpp/meta.yaml 的文件头注释直接点明其使命:ARROW-3229: this is a meta-package to prevent conflicts in the future

自 Arrow 10.0.0 起,Parquet C++ 库已并入libarrow输出(见主配方中parquet-cpp <0.0a0run_constrained约束),因此单独的parquet-cpp包退化为一个占位元包

  • 版本固定为1.5.1(历史遗留版本号),skipwin32与旧 Python;
  • 精确依赖与ARROW_VERSION同版本的arrow-cpp(注释强调:上游 feedstock 中此处应为>=,本仓库配方刻意用=以严格锁定夜间构建版本);
  • 测试同样验证parquet/api/reader.h头文件与共享库的存在及静态库的缺失,保证元包与真实 lib 的一致性。

五、跨平台 CI 与构建脚本链路

5.1 crossbow 任务矩阵:dev/tasks/tasks.yml

配方的实际构建由 crossbow 的 dev/tasks/tasks.yml(第 229–372 行)驱动。文件中定义了conda-clean以及覆盖多平台 × 多变体的构建任务,例如:

  • conda-linux-x64-cpu-py3/conda-linux-x64-cuda-py3config: linux_64_cuda_compiler_versionNone/linux_64_cuda_compiler_version11.2
  • conda-linux-aarch64-cpu-py3conda-linux-ppc64le-cpu-py3等:覆盖 ARM64 与 PowerPC;
  • conda-osx-x64-cpu-py3/conda-osx-arm64-cpu-py3conda-win-x64-cpu-py3/conda-win-x64-cuda-py3

每个任务通过template: conda-recipes/azure.linux.yml等模板渲染出实际的 Azure Pipeline,并以config参数指向.ci_support中的具体变体文件;artifacts字段则声明了期望产出的包名模式(如libarrow-{no_rc_version}-(h[a-z0-9]+)_0_cpu.condapyarrow-{no_rc_version}-py38(h[a-z0-9]+)_0_cpu.conda)。

文件中还有一段非常重要的工程注释(第 233–242 行):

  • conda-forge 上pyarrowarrow-cpp在同一 feedstock 中构建,因为依赖矩阵以“Python × OS”为主维度;
  • dev/tasks/conda-recipes/.ci_support/自动生成文件,需要定期从 feedstock 同步,Arrow 仓库内部目前无法自动生成;
  • 不再运行arrow-r任务,因为对应 feedstock 非常稳定,复杂度已被arrow-cpp覆盖。

5.2 Azure Pipelines 模板

  • azure.linux.yml 在ubuntu-latest上执行:先做磁盘空间管理(清理 GHC、hostedtoolcache、JVM、dotnet 等并清理 Docker 镜像),再为非linux_64配置注册binfmt_misc(qemu-user-static),从而让 Docker 容器能以模拟方式构建aarch64/ppc64le;随后调用 run_docker_build.sh 在容器内完成构建。
  • azure.osx.yml 在macOS-11上执行:安装conda-forge-ci-setup=3、mangle homebrew 以避免与 conda 冲突、make_build_number生成 clobber 文件;特别地,osx_arm*配置会追加--no-test(模拟器上无法运行测试)。
  • azure.win.yml 对应 Windows 平台构建。

三份模板中通过{{ macros.azure_checkout_arrow() }}拉取 Arrow 源码,构建产物经macros.azure_upload_releasesmacros.azure_upload_anaconda上传,供arrow-nightlies频道分发。

5.3 Linux 容器构建:run_docker_build.sh + build_steps.sh

run_docker_build.sh 是 Linux 构建的入口,关键逻辑包括:

  • 计算ARROW_ROOT(仓库根)并以-v "${ARROW_ROOT}":/arrow:rw,z挂载进容器,同时以HOST_USER_ID对齐宿主 UID,保证容器内产物可写回宿主;
  • 若未设置CONFIG,则从.ci_support/linux_*枚举可用的变体名并提示用户选择;未设置DOCKER_IMAGE时,回退到condaforge/linux-anvil-comp7(若装有shyaml则从变体 YAML 中读取docker_image);
  • 通过DONE_CANARYconda-forge-build-done-${CONFIG})文件验证脚本完整执行到末尾。

build_steps.sh 是 conda-smithy 自动生成脚本的 crossbow 适配版(文件头注释明确提醒:下次从 conda-forge 更新本脚本时,需重新并入这些适配改动)。它依次执行:

  1. 写入~/.condarc指定 conda-build 的 root-dir;
  2. mamba install安装conda-forge-ci-setup=3conda-buildpipboa
  3. 调用setup_conda_rcrun_conda_forge_build_setupmake_build_number完成环境准备与构建号递增;
  4. 交叉编译场景(HOST_PLATFORM != BUILD_PLATFORM且非 Linux host)追加--no-test
  5. conda mambabuild一次性构建arrow-cppparquet-cpp两个配方,传入-m "${CI_SUPPORT}/${CONFIG}.yaml"变体文件与--clobber-file
  6. 若设置了R_CONFIG,则额外构建r-arrow配方(当前 crossbow 已不再启用该任务);
  7. touch金丝雀文件标记成功。

5.4 频道清理:clean.py

由于夜间构建每天都会向arrow-nightlies频道(https://conda.anaconda.org/arrow-nightlies)推送新包,clean.py 负责防止频道无限膨胀:

  • 覆盖linux-64linux-aarch64linux-ppc64leosx-64osx-arm64win-64六个平台;
  • 规则:超过 30 天(DELETE_BEFORE)的旧构建一律删除;30 天内每个(平台 × Python 版本 × 特性)组合最多保留 5 个版本(VERSIONS_TO_KEEP = 5);
  • 对缺少track_features列的包(如arrow-cpp-proc)做特判处理;conda search --json失败且报PackagesNotFoundError时视为无包可删;
  • 仅在命令行带FORCE参数时才真正执行anaconda remove -f,否则只打印待删清单。

六、pyarrow 与 pyarrow-tests:Python 侧的质量门禁

pyarrow输出测试段(arrow-cpp/meta.yaml 第 251–286 行)通过imports字段验证pyarrowpyarrow.datasetpyarrow.flightpyarrow.gandivapyarrow.parquetpyarrow.fspyarrow._s3fspyarrow._hdfs等模块可正常导入;CUDA 构建且非 Windows 时额外验证pyarrow.cuda(注释说明 Windows 上因nvcuda.dll无法找到而跳过)。此外还检查:

  • Python 相关动态库(libarrow_python.solibarrow_python_flight.so等)位于${SP_DIR}/pyarrow/下;
  • Python 绑定头文件arrow/python/pyarrow.h存在;
  • 测试文件不存在test ! -f ${SP_DIR}/pyarrow/tests/test_array.py),即生产包不带测试套件;
  • 执行冒烟脚本 test_read_parquet.py,其内容为构造pa.Table.from_pydict({"a": [1, 2]})pq.write_table写回,验证 pyarrow + Parquet 的读写闭环可用。

pyarrow-tests输出则承载完整的 Python 测试套件,其设计体现了对 CI 成本的精细控制:

  • 仅在linux64或 Python 3.11 上启用(注释指出 aarch64/ppc64le 为模拟执行、单次可达约 45 分钟,且各 Python 版本行为差异几乎为零,故只跑一个版本);
  • 依赖注入ARROW_TEST_DATA指向 testing/data 目录,并收集source_files: testing/data
  • 通过tests_to_skip累积跳过规则:无 GPU 跳过test_cuda;Linux 跳过会引发 SIGINT 的(test_csv and test_cancellation);模拟架构跳过test_debug_memory_pool_disabledtest_env_var_io_thread_count;macOS/Windows 跳过 S3 分区写入测试;ppc64le跳过 Gandiva 段错误用例与浮点截断用例等;
  • 最终以pytest pyarrow/ -rfEs -k "not (...)"运行剩余用例。

七、双向同步工作流:保持配方不腐烂的机制

README 的核心内容是关于配方同步的双向工作流,这是维护这套配方最关键的工程实践。

7.1 从上游 feedstock 回迁(backport)

README 明确论断:“在多数情况下,本仓库的配方比上游 feedstock 更准确”。这源于 Arrow 开发者对依赖与变体细节的持续修正。但上游 feedstocks 会定期收到 conda-forge 团队的自动化更新,因此需要将这些更新回迁到 crossbow 配方中,其中绝大多数改动触及:

  • 版本固定文件(version pinning):即.ci_support目录下的变体配置;
  • 其他 CI 相关配置文件

由于三个配方(arrow-cpp、parquet-cpp、以及历史 r-arrow)必须在同一个 CI 任务中构建,README 建议优先从 arrow-cpp feedstock 移植,以保证三者的矩阵与依赖版本一致。

回迁时具体操作分两部分:

  • 更新变体(Updating the variants):把arrow-cpp-feedstock/.ci_support下的配置文件整体复制到本仓库的.ci_support目录;
  • 更新 CI 配置(Updating the CI configurations):将上游.azure-pipelines/azure-pipelines-[linux|osx|win].yml移植到本地.azure-pipelines对应文件,保留 crossbow 相关部分(Arrow 仓库的 clone 步骤与 Jinja 模板变量),并把矩阵定义(如上游azure-pipelines-linux.yml中的矩阵)移动到 crossbow 的 tasks.yml 配置文件中。

7.2 向发布流程前向移植(port)

理论上,本仓库配方始终与 Arrow 当前开发版本保持一致,因此发布流程期间应把配方内容复制回上游 feedstocks,使 conda-forge 上的发布版包获得同样的配方改进。这构成了一个闭环:

conda-forge 上游 feedstock ──(定期回迁)──▶ dev/tasks/conda-recipes ▲ │ └──────────────(发布时移植)──────────────────┘

八、实操建议与本地验证

虽然这些配方面向 crossbow 夜间 CI,但本地也可以手动复现构建流程做验证。以 Linux 为例的参考命令序列(需具备 Docker 与 conda 环境):

# 1. 进入配方目录并指定变体(例如 CPU 构建) export CONFIG=linux_64_cuda_compiler_versionNone export ARROW_VERSION=<当前开发版本,如 17.0.0.dev123> export UPLOAD_PACKAGES=False # 2. 触发容器构建(产物输出到 build_artifacts) CI=azure ./dev/tasks/conda-recipes/run_docker_build.sh ./build_artifacts

在 Windows/macOS 上则可仿照 azure.osx.yml 的步骤:激活 base 环境、安装conda-forge-ci-setup=3conda-build、执行setup_conda_rc/make_build_number后,用conda build arrow-cpp -m ./.ci_support/${CONFIG}.yaml --clobber-file ./.ci_support/clobber_${CONFIG}.yaml --output-folder ./build_artifacts构建。注意:本地运行需要自行准备dev/tasks/conda-recipes/.ci_support/下的变体 YAML 文件(该目录由上游 feedstock 同步而来,不在仓库内)。

验证安装后的包质量时,可复用配方中的断言思路:检查六个关键头文件、各动态库存在、静态库缺失,以及运行 test_read_parquet.py 完成 pyarrow 读写冒烟。

九、小结

dev/tasks/conda-recipes是 Apache Arrow 夜间 CI 体系中承上启下的关键一环:它用一份“跟随开发版、面向 nightly”的配方,把 conda-forge 的构建约定(meta.yaml多输出、.ci_support变体矩阵、conda-smithy 生成脚本)与 Arrow 自身的构建矩阵(tasks.yml 中的多平台 × CUDA/CPU 任务)缝合在一起。理解这套目录,既能看清 Arrow 如何在不破坏 conda-forge 发布链的前提下持续验证开发分支,也能为其他想要自建“夜间包 + 发布包”双轨制配方的项目提供可复用的工程模板。

[arrow-cpp-feedstock]: 上游 conda-forge 的 arrow-cpp feedstock 仓库(位于 conda-forge 组织下) [parquet-cpp-feedstock]: 上游 conda-forge 的 parquet-cpp feedstock 仓库(位于 conda-forge 组织下)

  • 数据工程
  • 大数据
  • 序列化
  • 数据分析

【免费下载链接】arrow

Apache Arrow is a multi-language toolbox for accelerated data interchange and in-memory processing

项目地址:https://gitcode.com/gh_mirrors/arrow13/arrow
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询