开发指南#
本节为希望为 C++ 代码库做出贡献的开发者提供信息。
注意
由于该项目的大多数开发者都在 Linux 或 macOS 上工作,因此并非所有功能或开发者工具都统一支持 Windows。如果您使用的是 Windows,请查看在 Windows 上开发。
编译器警告级别#
CMake 选项 BUILD_WARNING_LEVEL
用于在预设的编译器警告级别之间切换,我们使用这些级别来确保代码整洁。对于发布版本,默认警告级别为 PRODUCTION
,而对于调试版本,默认值为 CHECKIN
。
当调试版本使用 CHECKIN
时,如果使用 gcc 和 clang,则会添加 -Werror
,导致任何警告都会构建失败;使用 MSVC 时会设置 /WX
,效果相同。
运行单元测试#
CMake 选项 -DARROW_BUILD_TESTS=ON
启用单元测试可执行文件的构建。然后,您可以通过启动所需的жно запустить их все сразу, запустив исполняемый файл ctest
(входит в состав пакета CMake).
可能的调用方式如下:
$ ctest -j16 --output-on-failure
其中,-j16
选项最多并行运行 16 个测试,利用多个 CPU 内核和硬件线程。
运行基准测试#
CMake 选项 -DARROW_BUILD_BENCHMARKS=ON
启用基准测试可执行文件的构建。然后,您可以通过从命令行启动相应的可执行文件来单独运行基准测试,例如:
$ ./build/release/arrow-builder-benchmark
注意
为了获得有意义的基准测试数据,强烈建议以 Release
模式构建,以便启用编译器优化。
代码风格、代码检查和 CI#
本项目遵循Google C++ 风格指南,但有以下例外:
我们将行长度限制放宽到 90 个字符。
为了支持构建 C++/CLI (ARROW-1134),我们在头文件中使用
NULLPTR
宏(而不是nullptr
),该宏在src/arrow/util/macros.h
中定义。我们放宽了指南中关于结构体的规则。对于公共头文件,我们应该仅将结构体用于主要作为简单数据容器的对象,在这种情况下,公开所有内部成员是可以的,并且任何方法主要都是为了方便。对于私有头文件,规则进一步放宽,即使类型不需要访问控制,也可以在方便的情况下使用结构体,即使它们可能不是简单的数据容器。
我们更喜欢使用指针作为输出和输入/输出参数(风格指南在某些情况下建议使用可变引用)。
我们在 GitHub Actions 上的持续集成构建会在各种平台和配置上运行单元测试套件,包括使用 Address Sanitizer 和 Undefined Behavior Sanitizer 来检查各种错误行为模式,例如内存泄漏。此外,代码库还进行了一些代码风格和代码整洁度检查。
为了通过 CI 构建,您修改的 Git 分支必须通过以下检查:
使用项目当前版本的
clang
进行 C++ 构建,并且在使用-DBUILD_WARNING_LEVEL=CHECKIN
时没有编译器警告。请注意,gcc
不会捕获某些类型的警告(例如-Wdocumentation
,请参阅下文)。通过各种 C++(和其他)风格检查,使用 Archery 的
lint
子命令进行检查。这也可以通过本地运行archery lint --cpplint --clang-format --clang-tidy --fix
来修复.CMake 文件通过风格检查,可以通过运行
archery lint --cmake-format --fix
来修复。这需要 Python 3 和 cmake_format(注意:这目前在 Windows 上不起作用)。
在拉取请求上,“Dev / Lint”流水线将运行这些检查,并报告需要修复的文件/行(如果有)。
为了解决 LLVM 主要版本之间 clang-format
行为的差异,我们固定了所使用的 clang-format
的版本。您可以通过在 .env 中查找 CLANG_TOOLS
变量值来确认当前固定的版本。请注意,版本必须完全匹配;较新版本(即使是补丁版本)也无法使用。LLVM 可以通过系统包管理器或像 Conda 或 Homebrew 这样的包管理器安装,但请注意,它们可能不会提供所需的确切版本。或者,可以从 LLVM 网站 直接下载二进制文件。
为了方便起见,除了 Archery 之外,还可以通过构建运行 C++ 风格检查。为此,请构建一个或多个目标:format
(用于 clang-format)、lint_cpp_cli
、lint
(用于 cpplint)或 clang-tidy
。例如:
$ cmake -GNinja ../cpp ...
$ ninja format lint clang-tidy lint_cpp_cli
根据您安装 clang-format 的方式,构建系统可能无法找到它。在这种情况下,调用 CMake 将显示如下错误:
-- clang-format 12 not found
或者,如果安装了错误的版本:
-- clang-format found, but version did not match "^clang-format version 12"
您可以使用环境变量 $CLANG_TOOLS_PATH
或在调用 CMake 时传递 -DClangTools_PATH=$PATH_TO_CLANG_TOOLS
来提供包含 clang-format 可执行文件和其他可执行文件的目录的显式路径。例如:
# We unpacked LLVM here:
$ ~/tools/bin/clang-format --version
clang-format version 12.0.0
# Pass the directory containing the tools to CMake
$ cmake ../cpp -DClangTools_PATH=~/tools/bin/
...snip...
-- clang-tidy found at /home/user/tools/bin/clang-tidy
-- clang-format found at /home/user/tools/bin/clang-format
...snip...
为了使代码检查对每个人都更具可重复性,我们提供了一个可以从存储库根目录执行的 docker compose
目标:
$ docker compose run ubuntu-lint
或者,在打开的拉取请求上,评论机器人可以为您格式化 C++ 代码(它将推送一个提交到分支,然后可以拉取该分支)。只需评论以下内容:
@github-actions autotune
使用 include-what-you-use (IWYU) 清理包含#
我们偶尔会使用 Google 的 include-what-you-use 工具(也称为 IWYU)来删除不必要的导入。
要开始使用 IWYU,您必须首先按照项目文档中的说明构建它. 一旦 include-what-you-use
可执行文件位于您的 $PATH
中,您必须在新源码外 CMake 构建目录中使用 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
运行 CMake,如下所示:
mkdir -p $ARROW_ROOT/cpp/iwyu
cd $ARROW_ROOT/cpp/iwyu
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DARROW_BUILD_BENCHMARKS=ON \
-DARROW_BUILD_BENCHMARKS_REFERENCE=ON \
-DARROW_BUILD_TESTS=ON \
-DARROW_BUILD_UTILITIES=ON \
-DARROW_COMPUTE=ON \
-DARROW_CSV=ON \
-DARROW_DATASET=ON \
-DARROW_FILESYSTEM=ON \
-DARROW_FLIGHT=ON \
-DARROW_GANDIVA=ON \
-DARROW_HDFS=ON \
-DARROW_JSON=ON \
-DARROW_PARQUET=ON \
-DARROW_S3=ON \
-DARROW_WITH_BROTLI=ON \
-DARROW_WITH_BZ2=ON \
-DARROW_WITH_LZ4=ON \
-DARROW_WITH_SNAPPY=ON \
-DARROW_WITH_ZLIB=ON \
-DARROW_WITH_ZSTD=ON \
..
为了使 IWYU 能够在代码库中所需的组件上运行,必须通过 CMake 配置标志启用它。完成后,您可以通过运行辅助脚本 iwyu.sh
在整个代码库上运行 IWYU:
IWYU_SH=$ARROW_ROOT/cpp/build-support/iwyu/iwyu.sh
./$IWYU_SH
由于这非常耗时,您可以使用特殊的“match”选项检查与某些字符串模式匹配的文件子集:
./$IWYU_SH match $PATTERN
例如,如果您想对 src/arrow/array
中的所有文件进行 IWYU 检查,您可以运行:
./$IWYU_SH match arrow/array
检查 ABI 和 API 稳定性#
要构建 ABI 合规性报告,您需要安装两个工具:abi-dumper
和 abi-compliance-checker
。
在调试模式下构建 Arrow C++,或者您可以使用 -Og
,它也可以使用必要的符号进行构建,但包含一些代码优化。构建完成后,您可以使用以下命令生成 ABI 报告:
abi-dumper -lver 9 debug/libarrow.so -o ABI-9.dump
上述版本号可以随意选择。由于我们要比较版本,您现在应该使用 git checkout
签出要与之比较的版本,并使用不同的版本号重新运行上述命令。生成两个报告后,您可以使用以下命令构建比较报告:
abi-compliance-checker -l libarrow -d1 ABI-PY-9.dump -d2 ABI-PY-10.dump
然后,报告将以 HTML 格式生成在 compat_reports/libarrow
中。
API 文档#
我们在头文件中使用 Doxygen 风格的注释(///
)来为希望在 API 文档中显示的类和函数添加注释。
当使用 clang
并在使用 -DBUILD_WARNING_LEVEL=CHECKIN
构建时,会使用 -Wdocumentation
标志,该标志会检查一些常见的文档不一致问题,例如使用 \param
记录了某些但并非所有函数参数。有关更多信息,请参阅 LLVM 文档警告部分。
虽然我们将 API 文档作为基于 Sphinx 的主文档站点的一部分发布,但您也可以随时使用 Doxygen 构建 C++ API 文档。从 cpp/apidoc
目录运行以下命令
doxygen Doxyfile
这需要安装 Doxygen。
Apache Parquet 开发#
要构建 Apache Parquet 的 C++ 库,请在调用 CMake 时添加标志 -DARROW_PARQUET=ON
。要构建支持加密的 Apache Parquet,请在调用 CMake 时添加标志 -DPARQUET_REQUIRE_ENCRYPTION=ON
。可以使用 parquet
make target 构建 Parquet 库和单元测试
make parquet
在 Linux 和 macOS 上,如果您的系统上没有安装 Apache Thrift,或者您使用 -DThrift_SOURCE=BUNDLED
进行构建,则必须安装 bison
和 flex
软件包。在 Windows 上,我们会在从源代码构建 Thrift 时自动处理这些构建依赖项。
运行 ctest -L unittest
将运行所有已构建的 C++ 单元测试,而 ctest -L parquet
将仅运行 Parquet 单元测试。单元测试依赖于环境变量 PARQUET_TEST_DATA
,该变量依赖于仓库 apache/parquet-testing 的 git 子模块
git submodule update --init
export PARQUET_TEST_DATA=$ARROW_ROOT/cpp/submodules/parquet-testing/data
这里 $ARROW_ROOT
是 Arrow 代码库的绝对路径。
Arrow Flight RPC#
除了 Arrow 依赖项之外,Flight 还需要
gRPC(大约 >= 1.14)
Protobuf(>= 3.6,早期版本可能有效)
c-ares(gRPC 使用)
默认情况下,Arrow 会在构建 Flight 时尝试下载并构建这些依赖项。
可以通过传递 -DARROW_FLIGHT=ON
来构建可选的 flight
库和测试。
cmake .. -DARROW_FLIGHT=ON -DARROW_BUILD_TESTS=ON
make
您还可以使用额外依赖项的现有安装。构建时,设置环境变量 gRPC_ROOT
和/或 Protobuf_ROOT
和/或 c-ares_ROOT
。
我们正在针对最新版本的 gRPC 进行开发。从 https://forge.conda.org.cn/ 获取的 grpc-cpp
软件包是一种以跨平台方式获取 gRPC 的可靠方法。您可以尝试将系统库用于 gRPC 和 Protobuf,但这些库可能太旧了。在 macOS 上,您可以尝试 Homebrew
brew install grpc