- 数据工程
- 大数据
- 序列化
- 数据分析
【免费下载链接】arrow
Apache Arrow is a multi-language toolbox for accelerated data interchange and in-memory processing
本指南以 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.py | pyarrow 冒烟测试脚本,验证写/读 Parquet 闭环 |
parquet-cpp/meta.yaml | 防冲突元包(meta-package),兼容旧包名 |
azure.yml | Azure Pipelines 顶层入口(当前为空,实际任务模板由各平台文件提供) |
azure.linux.yml/azure.osx.yml/azure.win.yml | 三平台 CI 模板(Jinja2 渲染) |
azure.clean.yml | 清理任务模板 |
build_steps.sh | conda-smithy 生成的构建脚本(已适配 crossbow,容器内执行) |
run_docker_build.sh | Linux 下启动 Docker 容器执行构建的入口脚本 |
clean.py | 清理 arrow-nightlies 频道上过期构建包的工具 |
conda-forge.yml | conda-forge 配置,当前为channel_priority: strict |
从仓库结构可以推断,这套目录是一个“缩水版 feedstock”:它复用了 conda-forge feedstocks 的约定(.ci_support、meta.yaml、build_steps.sh、run_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变量把构建变体标记为cpu或cuda,并贯穿所有输出包。
3.1 六个输出(outputs)的职责划分
配方通过outputs字段一次性产出 6 个 conda 包,这是理解整份配方的关键:
apache-arrow-proc:虚拟变体选择包(meta-package),用于在 conda 层面标记cpu/cuda构建变体。其构建字符串即为cpu或cuda,test 仅执行exit 0。arrow-cpp-proc:为旧版“mutex-package”命名方案提供的兼容输出,依赖对应版本的apache-arrow-proc。libarrow:真正的 C++ 库输出(build-arrow.sh/build-arrow.bat),包含run_exports声明pin_subpackage("libarrow", max_pin="x"),即下游包最多只能 pin 到主版本号(SemVer 兼容承诺)。arrow-cpp:旧命名方案兼容包(10.0.0 起改名,保留数个版本后移除),精确依赖对应版本的libarrow。pyarrow:Python 绑定输出,build string形如py{{ CONDA_PY }}h{{ PKG_HASH }}_{{ PKG_BUILDNUM }}_{{ build_ext }},同时依赖精确版本(exact=True)的libarrow。pyarrow-tests:包含 pyarrow 测试套件的包,仅在 CI 中按需构建与运行(详见第六节)。
3.2 CUDA 构建变体
配方对 CUDA 的处理非常精细,体现了 crossbow 配方“比上游更准确”的定位:
- 通过
cuda_compiler_version != "None"判定是否启用 CUDA,cuda_enabled同时驱动build_ext、track_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 中的依赖查找逻辑:
- 核心压缩/编码:
brotli、bzip2、lz4-c、snappy、zlib、zstd、orc; - 列存格式:
thrift-cpp、re2(Parquet 支持); - 内存与并发:
boost-cpp >=1.70、xsimd、nlohmann_json、rapidjson、gflags、glog; - Flight / Gandiva / Substrait:
libgrpc、libprotobuf、libabseil、clangdev {{ llvm_version }}、llvmdev {{ llvm_version }}、openssl、aws-crt-cpp、aws-sdk-cpp、google-cloud-cpp、libutf8proc; - Linux 特有:
ucx(UCX 传输)、autoconf/make(vendored jemalloc 构建需要)。
配方还通过注释记录了多处“有意为之”的取舍,例如:Arrow 使用定制版 jemalloc 故不依赖 conda 的jemalloc;cpp-opentelemetry-sdk因上游 feedstock 问题暂未启用;Windows 上glog不参与run_exports、google-cloud-cpp的静态依赖(libcrc32c、libcurl)需显式补进 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.h、arrow/acero/api.h、arrow/flight/types.h、arrow/flight/sql/api.h、gandiva/engine.h、parquet/api/reader.h,确保各子库头文件被打包; - 动态库存在性:按 CUDA 与否动态生成库清单(
arrow、arrow_acero、arrow_dataset、arrow_flight、arrow_flight_sql、arrow_substrait、gandiva、parquet,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.py(so_version由version.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.0a0的run_constrained约束),因此单独的parquet-cpp包退化为一个占位元包:
- 版本固定为
1.5.1(历史遗留版本号),skip掉win32与旧 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-py3:config: linux_64_cuda_compiler_versionNone/linux_64_cuda_compiler_version11.2;conda-linux-aarch64-cpu-py3、conda-linux-ppc64le-cpu-py3等:覆盖 ARM64 与 PowerPC;conda-osx-x64-cpu-py3/conda-osx-arm64-cpu-py3、conda-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.conda、pyarrow-{no_rc_version}-py38(h[a-z0-9]+)_0_cpu.conda)。
文件中还有一段非常重要的工程注释(第 233–242 行):
- conda-forge 上
pyarrow与arrow-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_releases与macros.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_CANARY(conda-forge-build-done-${CONFIG})文件验证脚本完整执行到末尾。
build_steps.sh 是 conda-smithy 自动生成脚本的 crossbow 适配版(文件头注释明确提醒:下次从 conda-forge 更新本脚本时,需重新并入这些适配改动)。它依次执行:
- 写入
~/.condarc指定 conda-build 的 root-dir; mamba install安装conda-forge-ci-setup=3、conda-build、pip、boa;- 调用
setup_conda_rc、run_conda_forge_build_setup、make_build_number完成环境准备与构建号递增; - 交叉编译场景(
HOST_PLATFORM != BUILD_PLATFORM且非 Linux host)追加--no-test; - 用
conda mambabuild一次性构建arrow-cpp与parquet-cpp两个配方,传入-m "${CI_SUPPORT}/${CONFIG}.yaml"变体文件与--clobber-file; - 若设置了
R_CONFIG,则额外构建r-arrow配方(当前 crossbow 已不再启用该任务); - 以
touch金丝雀文件标记成功。
5.4 频道清理:clean.py
由于夜间构建每天都会向arrow-nightlies频道(https://conda.anaconda.org/arrow-nightlies)推送新包,clean.py 负责防止频道无限膨胀:
- 覆盖
linux-64、linux-aarch64、linux-ppc64le、osx-64、osx-arm64、win-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字段验证pyarrow、pyarrow.dataset、pyarrow.flight、pyarrow.gandiva、pyarrow.parquet、pyarrow.fs、pyarrow._s3fs、pyarrow._hdfs等模块可正常导入;CUDA 构建且非 Windows 时额外验证pyarrow.cuda(注释说明 Windows 上因nvcuda.dll无法找到而跳过)。此外还检查:
- Python 相关动态库(
libarrow_python.so、libarrow_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_disabled与test_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=3与conda-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
相关推荐
Apache Arrow 中 conda-forge Recipes 的维护与同步机制:跨平台打包实践解析
Apache Arrow 中 conda forge Recipes 的维护与同步机制:跨平台打包实践解析 Apache Arrow 在仓库中维护着一套与 co
数据工程数据分析大数据Apache Arrow PyArrow 完整安装指南:Conda/Pip/源码构建与 conda-forge 包选型
Apache Arrow PyArrow 完整安装指南:Conda/Pip/源码构建与 conda forge 包选型 本篇技术指南围绕 Apache Arro
数据工程数据分析大数据Zipline 的 conda 二进制包构建指南:从 conda recipes 到可发布 channel
Zipline 的 conda 二进制包构建指南:从 conda recipes 到可发布 channel 本文以 Zipline 仓库中 conda/READ
金融科技数据分析
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考