skip to Main Content

I have recently started using a machine with Ubuntu 22.04 and I find that my existing (windows) .cpp files are no longer compiling with sourceCpp. The issue is that I require a compilation with at least C++14, and in fact I can successful compile the files using sourceCpp if I explicitly set the flag // [[Rcpp::plugins("cpp14")]].

My question is why R has chosen to use a lower version of C++ when C++17 is available and seems to be the default in simple programs? Compare the following two sample .cpp files, which seem to differ only in the inclusion of the RcppArmadillo libraries:

# 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;
}
# test_stan_with_more_complicated...

// [[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;
}

Running sourceCpp results in the following calls to the C++ compiler respectively:

using C++ compiler: ‘g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0’ 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

and

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

Apart from addition RcppArmadillo and fopenmp flag, the only difference seems to be in the C++ version:

diffchecker visualisation of sourceCpp output

My machine has the following compilers:

 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 sessionInfo() excerpt is:

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 

2

Answers


  1. The reason for this is the way that RcppArmadillo configures its C++ compilation settings. The default version with RcppArmadillo is gnu++11. The default setting from RcppArmadillo is applied by Rcpp.

    If you specifically want it to use another version of the C++ compiler then there are a couple of ways to do this:

    1. Add to environment Define the CXX_STD variable in the environment running R.
    export CXX_STD=CXX14
    
    1. Specify in code Add another directive to the .cpp file (just put this after the line // [[Rcpp::depends(RcppArmadillo)]]).
    // [[Rcpp::plugins(cpp14)]]
    

    I don’t have gnu++17 on my machine but both of the approaches above gave gnu++14 as the compiler for the latter .cpp file provided.

    Login or Signup to reply.
  2. In general, this is set by R as described in Writing R Extensions. R has been moving up the default compilers since release R 4.0.0 and if I recall correctly has been at C++17 since maybe R 4.2.0.

    In a fresh Docker container of Ubuntu 22.04 updated to R 4.4.0:

    # R CMD config CXX
    g++ -std=gnu++17
    #
    

    as expected as gcc / g++ version 11 is good enough. A good check is use a minimal RcppArmadillo example such as

    // [[Rcpp::depends(RcppArmadillo)]]
    #include <RcppArmadillo.h>
    // [[Rcpp::export]]
    arma::mat simple(arma::vec x) {
        return x * x.t();
    }
    /*** R
    simple(1:3)
    */
    

    which, when built via Rcpp::sourceCpp("armaex.cpp", verbose=TRUE) does get compiled via C++11 which looks like an oversight. In any event, you can override it easily for this use case too by setting a plugin as e.g. here for C++17:

    // [[Rcpp::depends(RcppArmadillo)]]
    #include <RcppArmadillo.h>
    // [[Rcpp::plugins(cpp17)]]
    // [[Rcpp::export]]
    arma::mat simple(arma::vec x) {
        return x * x.t();
    }
    /*** R
    simple(1:3)
    */
    

    In the Docker container I use this shows more than a screen of detail (when verbose=TRUE is set) including

    using C++ compiler: ‘g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0’
    using C++17
    g++ -std=gnu++17 -I"/usr/share/R/include" -DNDEBUG -I../inst/include -fopenmp  -I"/usr/lib/R/site-library/Rcpp/include" -I"/usr/lib/R/site-library/RcppArmadillo/include" -I"/tmp"     -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 arma.cpp -o arma.o
    g++ -std=gnu++17 -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -o sourceCpp_2.so arma.o -fopenmp -llapack -lblas -lgfortran -lm -lquadmath -L/usr/lib/R/lib -lR
    

    which shows that the setting takes effect overriding what the package (accidentally? over-eagerly?) sets.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search