Ubuntu22.04中引入RcppArmadillo导致R用C++11而非C++17编译的原因?
Rcpp编译时C++版本差异的原因分析
问题背景
近期切换到Ubuntu 22.04系统后,发现Windows环境下的.cpp文件无法通过sourceCpp编译,排查后确认代码需要至少C++14版本支持,添加// [[Rcpp::plugins("cpp14")]]标记后可成功编译。
核心疑问:明明C17可用且在简单程序中是默认版本,为什么引入RcppArmadillo库后,R会选择更低的C版本?
对比示例代码
无RcppArmadillo的版本(test_stan.cpp)
// [[Rcpp::depends(rstan)]] #include <stan/math.hpp> #include <iostream> // [[Rcpp::export]] int simple() { std::cout << "log normal(1 | 2, 3)=" << stan::math::normal_log(1, 2, 5) << std::endl; return 0; }
引入RcppArmadillo的版本
// [[Rcpp::depends(rstan)]] #include <stan/math.hpp> #include <iostream> #include <RcppArmadillo.h> // [[Rcpp::depends(RcppArmadillo)]] using namespace Rcpp; // [[Rcpp::export]] int simple() { std::cout << "log normal(1 | 2, 3)=" << stan::math::normal_log(1, 2, 5) << std::endl; return 0; }
编译命令差异
运行sourceCpp后,两个文件的编译命令仅在C++版本和少量附加参数上存在区别:
无RcppArmadillo的编译命令
g++ -std=gnu++17 -I"/usr/share/R/include" -DNDEBUG -I"/usr/local/lib/R/site-library/Rcpp/include/" -I"/usr/local/lib/R/site-library/RcppEigen/include/" -I"/usr/local/lib/R/site-library/RcppEigen/include/unsupported" -I"/usr/local/lib/R/site-library/BH/include" -I"/usr/local/lib/R/site-library/StanHeaders/include/src/" -I"/usr/local/lib/R/site-library/StanHeaders/include/" -I"/usr/local/lib/R/site-library/RcppParallel/include/" -I"/usr/local/lib/R/site-library/rstan/include" -DEIGEN_NO_DEBUG -DBOOST_DISABLE_ASSERTS -DBOOST_PENDING_INTEGER_LOG2_HPP -DSTAN_THREADS -DUSE_STANC3 -DSTRICT_R_HEADERS -DBOOST_PHOENIX_NO_VARIADIC_EXPRESSION -D_HAS_AUTO_PTR_ETC=0 -include '/usr/local/lib/R/site-library/StanHeaders/include/stan/math/prim/fun/Eigen.hpp' -D_REENTRANT -DRCPP_PARALLEL_USE_TBB=1 -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/rstan/include" -I"/home/rdpdp/Desktop/data/debug_gcc_version" -fpic -g -O2 -ffile-prefix-map=/build/r-base-H8urij/r-base-4.4.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -c test_stan.cpp -o test_stan.o
引入RcppArmadillo的编译命令
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I"/usr/local/lib/R/site-library/Rcpp/include/" -I"/usr/local/lib/R/site-library/RcppEigen/include/" -I"/usr/local/lib/R/site-library/RcppEigen/include/unsupported" -I"/usr/local/lib/R/site-library/BH/include" -I"/usr/local/lib/R/site-library/StanHeaders/include/src/" -I"/usr/local/lib/R/site-library/StanHeaders/include/" -I"/usr/local/lib/R/site-library/RcppParallel/include/" -I"/usr/local/lib/R/site-library/rstan/include" -DEIGEN_NO_DEBUG -DBOOST_DISABLE_ASSERTS -DBOOST_PENDING_INTEGER_LOG2_HPP -DSTAN_THREADS -DUSE_STANC3 -DSTRICT_R_HEADERS -DBOOST_PHOENIX_NO_VARIADIC_EXPRESSION -D_HAS_AUTO_PTR_ETC=0 -include '/usr/local/lib/R/site-library/StanHeaders/include/stan/math/prim/fun/Eigen.hpp' -D_REENTRANT -DRCPP_PARALLEL_USE_TBB=1 -I../inst/include -fopenmp -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/rstan/include" -I"/usr/local/lib/R/site-library/RcppArmadillo/include" -I"/home/rdpdp/Desktop/data/debug_gcc_version" -fpic -g -O2 -ffile-prefix-map=/build/r-base-H8urij/r-base-4.4.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -c test_stan_with_more_complicated_includes.cpp -o test_stan_with_more_complicated_includes.o
核心差异:前者使用-std=gnu++17,后者使用-std=gnu++11。
环境信息
编译器版本
dpkg --list | grep compiler ii g++ 4:11.2.0-1ubuntu1 amd64 GNU C++ compiler ii g++-11 11.4.0-1ubuntu1~22.04 amd64 GNU C++ compiler ii gcc 4:11.2.0-1ubuntu1 amd64 GNU C compiler ii gcc-11 11.4.0-1ubuntu1~22.04 amd64 GNU C compiler ii gfortran 4:11.2.0-1ubuntu1 amd64 GNU Fortran 95 compiler ii gfortran-11 11.4.0-1ubuntu1~22.04 amd64 GNU Fortran compiler ii libllvm14:amd64 1:14.0.0-1ubuntu1.1 amd64 Modular compiler and toolchain technologies, runtime library ii libllvm15:amd64 1:15.0.7-0ubuntu0.22.04.3 amd64 Modular compiler and toolchain technologies, runtime library ii libxkbcommon0:amd64 1.4.0-1 amd64 library interface to the XKB compiler - shared library ii rpcsvc-proto 1.4.2-0ubuntu6 amd64 RPC protocol compiler and definitions
R环境信息
R version 4.4.0 (2024-04-24) Platform: x86_64-pc-linux-gnu Running under: Ubuntu 22.04.4 LTS Matrix products: default BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0 attached base packages: [1] stats graphics grDevices utils datasets methods base loaded via a namespace (and not attached): [1] vctrs_0.6.5 cli_3.6.2 rlang_1.1.3 generics_0.1.3 [5] jsonlite_1.8.8 RcppParallel_5.1.7 glue_1.7.0 colorspace_2.1-0 [9] rstan_2.32.6 gridExtra_2.3 pkgbuild_1.4.4 stats4_4.4.0 [13] scales_1.3.0 fansi_1.0.6 StanHeaders_2.32.7 grid_4.4.0 [17] munsell_0.5.1 tibble_3.2.1 lifecycle_1.0.4 QuickJSR_1.1.3 [21] inline_0.3.19 compiler_4.4.0 codetools_0.2-19 dplyr_1.1.4 [25] pkgconfig_2.0.3 Rcpp_1.0.12 R6_2.5.1 tidyselect_1.2.1 [29] utf8_1.2.4 parallel_4.4.0 pillar_1.9.0 magrittr_2.0.3 [33] loo_2.7.0 tools_4.4.0 gtable_0.3.5 matrixStats_1.3.0 [37] ggplot2_3.5.1
原因解析
这个问题的核心是Rcpp依赖包的C++版本声明优先级:
- 仅依赖rstan的代码中,rstan(通过StanHeaders)会主动设置C17作为编译标准——Stan从2.26版本起就要求C17支持,因此编译命令中会出现
-std=gnu++17。 - 引入RcppArmadillo时,该包的默认编译标准为C11(部分旧版本或兼容性约束未更新配置)。Rcpp在处理多依赖时,会采用所有依赖中最低的兼容版本,或依赖包的声明会覆盖默认设置,最终导致编译标准被拉低到C11。
解决方法
- 显式在代码开头添加
// [[Rcpp::plugins("cpp14")]]或// [[Rcpp::plugins("cpp17")]],强制指定编译版本,覆盖依赖包的默认设置。 - 更新RcppArmadillo到最新版本(部分新版本已调整默认C++版本),或修改其编译配置文件。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

