Rcpp开发R包时C++17的std::cyl_bessel_i编译报错问题
问题复现
测试代码如下:
#include <cmath> #include <math.h> #include <Rcpp.h> // [[Rcpp::plugins("cpp17")]] // [[Rcpp::export]] double rcpp_hello_world(Rcpp::NumericVector x) { double z; z = std::cyl_bessel_i(0, x[0]); return z ; }
上述代码通过sourceCpp调用时可正常运行,但在R包开发场景下,执行Rcpp::compileAttributes()和devtools::document()时出现如下报错:
error: cyl_bessel_i is not a member of ‘std’ 11 | z = std::cyl_bessel_i(0, x[0]); | ^~~~~~~~~~~~ make: *** [/usr/lib64/R/etc/Makeconf:177: rcpp_hello_world.o] Error 1 ERROR: compilation failed for package ‘Package’
当前R包通过Rcpp.package.skeleton初始化创建,cyl_bessel_i是C++17版本新增至标准库的函数,运行环境为Arch Linux,使用gcc-12.1.0-2编译器、R-4.2.0-3版本。
故障原因
// [[Rcpp::plugins("cpp17")]] 标记仅对sourceCpp()的单文件即时编译流程生效,R包整体编译时不会读取源码中的Rcpp插件声明,默认使用的C标准版本低于C17,无法识别C++17新增的标准库函数,最终触发编译错误。
修复步骤
- 配置编译系统指定C++17标准:进入包的
src目录,编辑(不存在则新建)Makevars文件,写入如下配置:
如果需要兼容Windows平台编译,同步在同目录下新建/编辑CXX_STD = CXX17Makevars.win文件,写入完全相同的配置。 - 更新包描述文件配置:打开包根目录的
DESCRIPTION文件,添加C++17版本依赖声明:SystemRequirements: C++17 - 清理冗余头文件引用:代码中同时引入了C++版头文件
<cmath>和C版旧头文件<math.h>,后者会干扰标准库命名空间识别,直接删除#include <math.h>这行引用即可。 - 清除缓存重新编译:在R控制台执行以下命令,清理之前的编译中间产物后重新生成配置、编译:
Rcpp::compileAttributes() pkgbuild::clean_dll() devtools::document()
执行完上述步骤后即可正常完成包的编译,std::cyl_bessel_i函数可以被正常识别调用。
内容的提问来源于stack exchange,提问作者cookiemonster
相关产品推荐
相关产品推荐

