Ubuntu 上的 Rcpp 库无法构建(找不到编译器)

Rcpp Library Won't Build (Can't find Compiler) on Ubuntu

我有一个依赖于 Rcpp 的包,并使用了从 src/ 中的子目录编译的另外两个库。该软件包使用 clang 编译器在 Mac OSX 上构建良好。但是,在 RStudio Ubuntu 服务器上,它无法构建。构建的前两个步骤(在 link 中的子目录中创建静态库)工作正常,我可以看到如下所示的合理构建命令:

g++ -Wall -I../../inst/include/ --std=c++11 -lhts -L../htslib/ -lz -lm -c -o someLibFile.o someLibFile.cpp

然而,在构建过程的最后一步,它尝试构建 Rcpp 代码并绑定到库,由于某种原因,它似乎无法将编译器命令放在前面( g++) 并且只输出命令的后半部分。

 -o mypackage.so RcppExports.o temp.o -lhts -lpbbam -Lpbbam/ -L/htslib/ -Lpbbam/ -L/mnt/software/r/R/3.1.1/usr/lib/R/lib -lR

相比之下,在 Mac 上它构建得很好,在这个最终命令前面附加 clang++ 和其他标志:

 clang++ -std=c++11 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/Library/Frameworks/R.framework/Resources/lib -L/usr/local/lib -o pbbamr.so LoadData.o RcppExports.o temp.o -lhts -lpbbam -Lpbbam/ -Lhtslib/ -Lpbbam/ -F/Library/Frameworks/R.framework/.. -framework R -Wl,-framework -Wl,CoreFoundation

如何在这一步使用 Ubuntu 上的 g++ 编译器?我有一个自定义的 Makevars 文件,但它只是为了在子目录中构建依赖项,所以我不知道为什么这会导致任何问题(因为它适用于 Mac OSX).

更多信息

如果我删除 Makevars 文件,似乎可以找到编译器。但是,我正在使用的 Makevars 文件本质上是 R 扩展指南中给出的示例的直接副本,其中添加了一个启用 C++11 的示例:

 CXX_STD = CXX11
.PHONY: all mylibs

all: $(SHLIB)
    $(SHLIB): mylibs

mylibs:
    (cd subdir; make)

删除行 CXX_STD 后,它确实会在命令前面添加一个编译器。

简述:

  • 你的 R 安装是什么?您可能应该 运行 迈克尔通过 CRAN 提供的二进制文件;它们基于我的 Debian 上传;我 运行 这些也在一堆机器上
  • 原因是 R 'remembers' 其编译时设置通过 $RHOME/etc/Makefconf。这应该只是 CXX=g+=.
  • 当您安装 r-base-dev(来自 Ubuntu 或来自 CRAN 的更新版本)时,您还会获得 build-essential 软件包以及所有常见的依赖项。有了这些东西就可以了。

但是,如果您正在做一些特殊的或本地的事情,那么您必须处理本地更改。基本 Ubuntu 设置被成千上万的人和日常工作使用——包括 Travis 为无数 GitHub 回购构建。

这是由于使用 outdated/unusual R 安装导致的,它对 C++11 的支持很差。解决此问题的最佳方法是升级到更新版本的 R,或使用标准 R 安装 (sudo apt-get install r-base-dev)。下面描述了一个糟糕的解决方法。

问题原因和不好的解决方法

在编写使用 C++11 的 R 扩展时,通常在 Makevars 文件中设置 CXX_STD = CXX11 或在 DESCRIPTION 文件中列出 SystemRequirements: C++11。这些将触发 R 使用 Makeconf 文件(位于 file.path(R.home(), "etc/Makeconf"))中的以下标志设置的编译器。

CXX1X
CXX1XFLAGS
CXX1XPICFLAGS
CXX1XSTD

请注意,其中一些可能已在此文件中设置,但并非所有设置都可能表明存在问题。如果这些设置有问题或未设置,R 似乎使用空字符串 "" 作为 C++ 代码的 compiler/linker,导致上面显示的没有给出编译器参数的问题。

如果升级不是一个选项并且您需要在已知机器上部署,一个解决方法是通过制作一个更特殊的 Makevars 文件来手动设置 C++11。例如,您可以:

  • Makevars 文件中删除 CXX_STD=CXX11 行。
  • DESCRIPTION 文件中删除 SystemRequirements: C++11
  • 添加 --std=c++11PKG_CPPFLAGSPKG_CFLAGSPKG_CXXFLAGS 或用于编译代码的任何变量所需的任何其他要求,以手动设置所需的标志(假设机器的编译器确实支持 C++11)。

上述解决方案不是特别可靠,但可以在机器无法升级的情况下用作变通方法。

感谢@DirkEddelbuettel 不仅撰写 Rcpp 而且愿意在 Whosebug 上支持它并帮助解决此类问题。