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

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

本文关键字:构建 找不到 编译器 Ubuntu Rcpp      更新时间:2023-10-16

我有一个依赖于Rcpp的包,它使用从src/的子目录编译的另外两个库。该软件包使用clang编译器在Mac OSX上构建良好。然而,在RStudio Ubuntu服务器上,它无法构建。构建的前两个步骤(在要链接的子目录中创建静态库)运行良好,我可以看到如下合理的构建命令:

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安装是什么?您可能应该运行Michael通过CRAN提供的二进制文件;它们是基于我的Debian上传;我也在一堆机器上运行这些
  • 原因是R通过$RHOME/etc/Makefconf"记住"其编译时设置。这应该只是CXX=g+=
  • 当你安装r-base-dev(从Ubuntu或CRAN的更新版本)时,你也会得到build-essential包以及所有常见的依赖项。有了这些,事情就行了

然而,如果你正在做一些特别的或当地的事情,那么你必须应对当地的变化。Ubuntu的基本设置被成千上万的人和日常工作所使用,包括Travis为无数GitHub repos构建的。

这是由于使用了一个过时/不寻常的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++代码的编译器/链接器,从而导致上面显示的问题,其中没有给出编译器参数。

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

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

上述解决方案不是特别健壮,但可以作为解决方案,以防机器无法升级。

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