跳转到内容

与您可能贡献过的其他 R 包相比,Arrow R 包是独一无二的,因为它构建在功能丰富的大型 Arrow C++ 实现之上。由于 R 包与 Arrow C++ 紧密集成,因此通常需要专用库副本(即,在开发过程中通常无法链接到系统版本的 libarrow)。

选项 1:使用 nightly libarrow 二进制文件

在 Linux、macOS 和 Windows 上,您可以使用与包含编译代码的其他包相同的工作流程(例如,从终端使用 `R CMD INSTALL .`,从 R 提示符使用 `devtools::load_all()`,或从 RStudio 使用“安装并重启”)。如果 `arrow/r/libarrow` 目录未填充,配置脚本将尝试下载最新的 nightly libarrow 二进制文件,将其解压缩到 `arrow/r/libarrow` 目录(macOS、Linux)或 `arrow/r/windows` 目录(Windows),然后继续照常构建 R 包。

大多数情况下,您无需更新 libarrow 版本,因为 R 包很少随 C++ 库的更新而更改;但是,如果您在重新构建 R 包时开始遇到错误,则可能必须删除 `libarrow` 目录(macOS、Linux)或 `windows` 目录(Windows)并进行“干净”的重新构建。您可以从终端使用 `R CMD INSTALL . --preclean` 执行此操作,从 RStudio 使用“构建”选项卡中的“清理并安装”选项执行此操作,或者如果您使用的是 R 包根目录中的 `Makefile`,则使用 `make clean` 执行此操作。

选项 2:使用本地 Arrow C++ 开发构建

如果您需要同时更改 libarrow 和 R 包代码,或者您无法在其他地方获得最新 libarrow 的二进制版本,则需要从源代码构建它。本节讨论如何设置配置为与 R 包一起使用的 C++ libarrow 构建。有关更通用的资源,请参阅 Arrow C++ 开发者指南

该过程主要分为五个步骤。

步骤 1 - 安装依赖项

构建 libarrow 时,默认情况下,如果找到合适的版本,将使用系统依赖项。如果系统依赖项不存在,libarrow 将在其自身的构建过程中构建它们。您需要在构建过程*之外*安装的唯一依赖项是 cmake(用于配置构建)和 openssl(如果您正在构建并支持 S3)。

为了加快构建速度,您可以选择预先在系统上安装更多 C++ 库依赖项(例如 lz4zstd 等),这样就不需要在 libarrow 构建中从源代码构建它们。

Ubuntu
sudo apt install -y cmake libcurl4-openssl-dev libssl-dev
macOS
brew install cmake openssl

步骤 2 - 配置 libarrow 构建

我们建议您将 libarrow 配置为构建到用户级目录而不是系统目录,以便进行开发工作。这是为了使您正在使用的开发版本不会覆盖您可能已经安装的 libarrow 的发行版本,并且您还可以使用多个版本的 libarrow(通过对不同版本使用不同的 `ARROW_HOME` 目录)。

在下面的示例中,libarrow 安装到名为 `dist` 的目录中,该目录与 arrow 签出具有相同的父目录。您的 Arrow R 包安装可以指向任何名称的任何目录,但我们建议*不要*将其放在 arrow git 签出目录中,因为不需要的更改可能会使其无法正常工作。

export ARROW_HOME=$(pwd)/dist
mkdir $ARROW_HOME

*Linux 上的特殊说明:*在启动 R 并使用 arrow 之前,您需要将 `LD_LIBRARY_PATH` 设置为您设置 `$ARROW_HOME` 的位置下的 `lib` 目录。一种方法是将其添加到您的配置文件中(我们在这里使用 `~/.bash_profile`,但您可能需要将其放在不同的文件中,具体取决于您的设置,例如,如果您使用 `bash` 以外的 shell)。在 macOS 上,您无需执行此操作,因为 macOS 共享库路径在构建时硬编码到其位置。

export LD_LIBRARY_PATH=$ARROW_HOME/lib:$LD_LIBRARY_PATH
echo "export LD_LIBRARY_PATH=$ARROW_HOME/lib:$LD_LIBRARY_PATH" >> ~/.bash_profile

首先在终端中导航到 arrow 存储库。您需要创建一个目录,C++ 构建将把其内容放入该目录中。我们建议您在 Arrow git 存储库的 `cpp` 目录内创建一个 `build` 目录(它被 git 忽略,因此您不会意外地签入它)。接下来,将目录更改为 `cpp/build` 内。

pushd arrow
mkdir -p cpp/build
pushd cpp/build

您将首先调用 `cmake` 来配置构建,然后调用 `make install`。对于 R 包,您需要使用 `-D` 标志启用 libarrow 中的几个功能。

Linux / Mac OS
cmake \
  -DCMAKE_INSTALL_PREFIX=$ARROW_HOME \
  -DCMAKE_INSTALL_LIBDIR=lib \
  -DARROW_COMPUTE=ON \
  -DARROW_CSV=ON \
  -DARROW_DATASET=ON \
  -DARROW_EXTRA_ERROR_CONTEXT=ON \
  -DARROW_FILESYSTEM=ON \
  -DARROW_INSTALL_NAME_RPATH=OFF \
  -DARROW_JEMALLOC=ON \
  -DARROW_JSON=ON \
  -DARROW_PARQUET=ON \
  -DARROW_WITH_SNAPPY=ON \
  -DARROW_WITH_ZLIB=ON \
  ..

`..` 指的是 C++ 源目录:您位于 `cpp/build` 中,源位于 `cpp` 中。

启用更多 Arrow 功能

要启用可选功能,包括:S3 支持、替代内存分配器和额外的压缩库,请将以下部分或全部标志添加到您对 `cmake` 的调用中(尾随的 `\` 使它们更容易粘贴到新行上的 bash shell 中)

  -DARROW_GCS=ON \
  -DARROW_MIMALLOC=ON \
  -DARROW_S3=ON \
  -DARROW_WITH_BROTLI=ON \
  -DARROW_WITH_BZ2=ON \
  -DARROW_WITH_LZ4=ON \
  -DARROW_WITH_SNAPPY=ON \
  -DARROW_WITH_ZSTD=ON \

其他可能有用的标志

  • 例如 `-DBoost_SOURCE=BUNDLED` 和 `-DThrift_SOURCE=BUNDLED`,或者任何其他依赖项 `*_SOURCE`,如果您拥有与 Arrow 无法正常工作的系统版本的 C++ 依赖项。这告诉构建从源代码编译它自己的依赖项版本。

  • `-DCMAKE_BUILD_TYPE=debug` 或 `-DCMAKE_BUILD_TYPE=relwithdebinfo` 可用于调试。您可能不希望一般这样做,因为调试构建的运行时速度比默认的 `release` 构建慢得多。

  • 如果您想使用静态库而不是动态库,请使用 `-DARROW_BUILD_STATIC=ON` 和 `-DARROW_BUILD_SHARED=OFF`。使用静态库,R 包就不会链接到错误的库,但这确实意味着如果您更改 C++ 代码,则必须重新编译 C++ 库和 R 包。编译器通常只会在动态库不存在时才链接到静态库,这就是我们需要设置 `-DARROW_BUILD_SHARED=OFF` 的原因。如果您在先前编译和安装后进行切换,则可能需要从 `$ARROW_HOME/dist/bin` 中删除 `.dll` 或 `.so` 文件。

*注意* `cmake` 对空格特别敏感,如果您看到错误,请检查您是否有任何错误的空格。

步骤 3 - 构建 libarrow

您也可以在此处命令的末尾添加 `-j#` 以通过并行运行来加快编译速度(其中 `#` 是您可用的核心数)。

cmake --build . --target install -j8

步骤 4 - 构建 Arrow R 包

构建 libarrow 后,您可以从 git 签出安装 R 包及其依赖项,以及其他开发依赖项。

popd # To go back to the root directory of the project, from cpp/build
pushd r
R -e "install.packages('remotes'); remotes::install_deps(dependencies = TRUE)"
R CMD INSTALL --no-multiarch .

`--no-multiarch` 标志使其仅在“主”架构上编译。这将为您路径中的 R 对应的架构进行编译。如果您在一个架构上编译,然后切换到另一个架构,请确保传递 `--preclean` 标志,以便为新架构重新编译 R 包代码。否则,您可能会看到诸如 `LoadLibrary failure: %1 is not a valid Win32 application` 之类的错误。

编译标志

如果在构建 C++ 扩展时需要设置任何编译标志,可以使用 `ARROW_R_CXXFLAGS` 环境变量。例如,如果您使用 `perf` 来分析 R 扩展,则可能需要设置

export ARROW_R_CXXFLAGS=-fno-omit-frame-pointer
重新编译 C++ 代码

使用此处描述的设置,您无需在迭代和处理 R 包时重新构建 Arrow 库,甚至无需重新构建 R 包中的 C++ 源代码。只有当您更改了 R 包中的 C++(即使那样,`R CMD INSTALL .` 也应该只需要重新编译已更改的文件)*或者* libarrow C++ 已更改并且 libarrow 与 R 包之间不匹配时,才需要重新构建这些文件。如果您发现每次安装软件包或运行测试时都重新构建其中一个或两个,则您的设置可能有问题。

对于完整构建:一个启用了所有与 R 相关的可选依赖项的 `cmake` 命令。使用其他语言进行开发可能也需要不同的标志。例如,要开发 Python,您还需要添加 `-DARROW_PYTHON=ON`(尽管此处已包含用于 Python 的所有其他标志)。

cmake \
  -DCMAKE_INSTALL_PREFIX=$ARROW_HOME \
  -DCMAKE_INSTALL_LIBDIR=lib \
  -DARROW_COMPUTE=ON \
  -DARROW_CSV=ON \
  -DARROW_DATASET=ON \
  -DARROW_EXTRA_ERROR_CONTEXT=ON \
  -DARROW_FILESYSTEM=ON \
  -DARROW_GCS=ON \
  -DARROW_INSTALL_NAME_RPATH=OFF \
  -DARROW_JEMALLOC=ON \
  -DARROW_JSON=ON \
  -DARROW_MIMALLOC=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 \
  ..

安装具有特定 git 引用的 R 包版本

如果您需要从特定存储库或 git 引用进行 arrow 安装,则在除 Windows 之外的大多数平台上,您可以运行

remotes::install_github("apache/arrow/r", build = FALSE)

build = FALSE 参数很重要,它允许安装过程访问位于 apache/arrowcpp/ 目录中的 C++ 源代码。

与其他安装方法一样,设置环境变量 LIBARROW_MINIMAL=falseARROW_R_DEV=true 将分别提供功能更全面的 Arrow 版本和更详细的输出。

例如,要从 apache/arrow 的(虚构的)分支 bugfix 安装,您可以运行

Sys.setenv(LIBARROW_MINIMAL="false")
remotes::install_github("apache/arrow/r@bugfix", build = FALSE)

开发人员可能希望使用此方法安装特定提交,并将其与其他 Arrow 开发环境或系统安装隔离开来(例如,我们在 arrowbench 中使用此方法安装与系统安装隔离的 libarrow 开发版本)。如果您已经安装了系统范围的 libarrow,则可能需要设置一些其他变量,以便将此构建与系统库隔离开来。

  • 将环境变量 FORCE_BUNDLED_BUILD 设置为 true 将跳过 pkg-config 对 libarrow 的搜索,并尝试从给定的仓库+引用中的相同源代码进行构建。

  • 您可能还需要将 Makevars 的 CPPFLAGSLDFLAGS 设置为 "",以防止安装过程尝试链接到已安装的系统版本的 libarrow。一种临时执行此操作的方法是包装您的 remotes::install_github() 调用,如下所示

withr::with_makevars(list(CPPFLAGS = "", LDFLAGS = ""), remotes::install_github(...))

环境变量总结

  • 有关大量决定构建方式和构建功能的环境变量,请参阅面向用户的安装文章
  • ARROW_OFFLINE_BUILD:设置为 true 时,构建脚本将不会下载预构建的 C++ 库二进制文件,或者如果需要,也不会下载 cmake。它将关闭任何需要下载的功能,除非它们在 ARROW_THIRDPARTY_DEPENDENCY_DIRtools/thirdparty_download/ 子文件夹中可用。create_package_with_all_dependencies() 会创建该子文件夹。

故障排除

请注意,在对 libarrow 进行任何更改后,您必须重新安装它并运行 make cleangit clean -fdx . 以删除 r/src/ 目录中的任何缓存的目标代码,然后再重新安装 R 包。仅当您更改 libarrow 源代码时才需要这样做;如果您只是在 r/ 内编辑 R 或 C++ 代码,则无需手动清除目标文件。

Arrow 库 - R 包不匹配

如果 libarrow 和 R 包版本不一致,您将看到如下错误

Error: package or namespace load failed for ‘arrow' in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/Library/Frameworks/R.framework/Versions/4.0/Resources/library/00LOCK-r/00new/arrow/libs/arrow.so':
  dlopen(/Library/Frameworks/R.framework/Versions/4.0/Resources/library/00LOCK-r/00new/arrow/libs/arrow.so, 6): Symbol not found: __ZN5arrow2io16RandomAccessFile9ReadAsyncERKNS0_9IOContextExx
  Referenced from: /Library/Frameworks/R.framework/Versions/4.0/Resources/library/00LOCK-r/00new/arrow/libs/arrow.so
  Expected in: flat namespace
 in /Library/Frameworks/R.framework/Versions/4.0/Resources/library/00LOCK-r/00new/arrow/libs/arrow.so
Error: loading failed
Execution halted
ERROR: loading failed

要解决此问题,请尝试重新构建 Arrow 库

多个版本的 libarrow

如果您从用户级目录安装,并且您已经在系统目录中安装了先前版本的 libarrow,则在安装 R 包时可能会遇到以下错误

Error: package or namespace load failed for ‘arrow' in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/Library/Frameworks/R.framework/Versions/4.0/Resources/library/00LOCK-r/00new/arrow/libs/arrow.so':
  dlopen(/Library/Frameworks/R.framework/Versions/4.0/Resources/library/00LOCK-r/00new/arrow/libs/arrow.so, 6): Library not loaded: /usr/local/lib/libarrow.400.dylib
  Referenced from: /usr/local/lib/libparquet.400.dylib
  Reason: image not found

如果发生这种情况,您需要确保在构建 arrow 时不让 R 链接到您的系统库。您可以通过多种不同的方式来做到这一点

  • MAKEFLAGS 环境变量设置为 "LDFLAGS="(请参阅下面的示例),这是推荐的实现方法
  • 使用 {withr} 的 with_makevars(list(LDFLAGS = ""), ...)
  • LDFLAGS= 添加到您的 ~/.R/Makevars 文件中(最不推荐的方法,尽管这是在线建议的常见调试方法)
MAKEFLAGS="LDFLAGS=" R CMD INSTALL .

rpath 问题

如果包安装/加载失败并出现如下错误

  ** testing if installed package can be loaded from temporary location
  Error: package or namespace load failed for 'arrow' in dyn.load(file, DLLpath = DLLpath, ...):
  unable to load shared object '/Users/you/R/00LOCK-r/00new/arrow/libs/arrow.so':
  dlopen(/Users/you/R/00LOCK-r/00new/arrow/libs/arrow.so, 6): Library not loaded: @rpath/libarrow.14.dylib

请确保已传递 -DARROW_INSTALL_NAME_RPATH=OFF(这在 macOS 上很重要,可以防止链接时出现问题,并且在其他平台上是无操作的)。或者,尝试将环境变量 R_LD_LIBRARY_PATH 设置为 Arrow C++ 在 make install 中放置的任何位置,例如 export R_LD_LIBRARY_PATH=/usr/local/lib,然后重试安装 R 包。

从源代码安装时,如果 R 和 C++ 库版本不匹配,安装可能会失败。如果您之前已安装库并想要升级 R 包,则需要先更新 Arrow C++ 库。

有关任何其他构建/配置难题,请参阅C++ 开发人员指南

其他安装问题

安装 arrow R 包时会触发许多脚本。对于不与底层代码交互的包用户,这些脚本应该无需配置即可正常工作,并引入最完整的组件(例如,我们托管的官方二进制文件)。但是,了解这些脚本可以帮助包开发人员在脚本出现问题或安装出现问题时进行故障排除。有关更多信息,请参阅关于 R 包安装的文章