MacOS Catalina下GraalVM安装R包(如Rcpp)失败求助
解决GraalVM R运行时在MacOS Catalina安装Rcpp等编译型包的符号缺失错误
我之前在MacOS Catalina上使用GraalVM CE Java8 20.0.0时,也碰到过完全一样的问题——简单R代码能正常运行,但安装Rcpp这类需要编译的包就会出现__ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev符号缺失的DLL加载错误。这个问题的核心是C++标准库ABI兼容性不匹配,下面是具体的原因和解决办法:
问题根源
GraalVM自带的R运行时(FastR)打包了独立的编译环境,但在MacOS Catalina上,它默认的C编译选项没有和系统的libc++完全兼容。__cxx11前缀的符号属于C11引入的新ABI标准,而GraalVM的FastR默认编译配置可能没有启用这个ABI,导致编译出来的R包共享对象无法正确加载。
而你本地的RStudio能正常安装,是因为它用的是系统原生R或者你单独安装的R,这些环境的编译配置和MacOS Catalina的clang/libc++完全对齐,不存在ABI差异。
解决办法
方法1:通过环境变量强制对齐C++ ABI(直接用GraalVM的R命令安装)
在终端里先设置以下环境变量,再执行安装命令:
# 设置C++编译选项,强制使用C++11 ABI和系统libc++ export CXXFLAGS="-std=c++11 -stdlib=libc++ -D_GLIBCXX_USE_CXX11_ABI=1" export LDFLAGS="-stdlib=libc++" # 安装Rcpp $GRAALVM_HOME/bin/R -e 'install.packages("Rcpp", type="source")'
方法2:在Java代码中注入环境变量后安装
如果是通过Java代码调用安装,需要在创建R Context前设置对应的环境变量:
import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Source; import java.util.HashMap; import java.util.Map; public class GraalRTest { public static void main(String[] args) { // 设置GraalVM路径 String graalHome = System.getenv("GRAALVM_HOME"); System.setProperty("org.graalvm.home", graalHome); // 配置编译环境变量 Map<String, String> env = new HashMap<>(System.getenv()); env.put("CXXFLAGS", "-std=c++11 -stdlib=libc++ -D_GLIBCXX_USE_CXX11_ABI=1"); env.put("LDFLAGS", "-stdlib=libc++"); // 创建带环境变量的R Context Context rcontext = Context.newBuilder("R") .allowAllAccess(true) .allowHostClassLoading(true) .allowIO(true) .allowNativeAccess(true) .allowCreateThread(true) .environment(env) // 注入环境变量 .build(); // 安装Rcpp Source installSource = Source.create("R", "install.packages(\"Rcpp\", type=\"source\")"); rcontext.eval(installSource); } }
方法3:升级GraalVM到新版本
你当前使用的20.0.0是2020年的旧版本,后续的GraalVM版本(比如21.x或22.x的CE Java8分支)已经修复了不少MacOS Catalina下的兼容性问题。升级后,默认的编译配置可能已经适配了系统的C++库,不需要手动设置环境变量就能正常安装R包。
内容的提问来源于stack exchange,提问作者MLearner
相关产品推荐
相关产品推荐

