Search code examples
c++rrcpprcpparmadillo

Unable to build the RcppArmadillo.package.skeleton test package: Multiple definition of `R_init_<name>'


I was trying to build the RcppArmadillo.package.skeleton test package. As usual, I do in R:

> library("Rcpp")
> library("RcppArmadillo")
> RcppArmadillo.package.skeleton("test")
> compileAttributes()
> library(tools)
> package_native_routine_registration_skeleton(".", "src/init.c", character_only=F)

So far, this looks good:

$ cat test/src/init.c 
#include <R.h>
#include <Rinternals.h>
#include <stdlib.h> // for NULL
#include <R_ext/Rdynload.h>

/* FIXME: 
   Check these declarations against the C/Fortran source code.
*/

/* .Call calls */
extern SEXP _test_rcpparma_bothproducts(SEXP);
extern SEXP _test_rcpparma_hello_world();
extern SEXP _test_rcpparma_innerproduct(SEXP);
extern SEXP _test_rcpparma_outerproduct(SEXP);

static const R_CallMethodDef CallEntries[] = {
    {"_test_rcpparma_bothproducts", (DL_FUNC) &_test_rcpparma_bothproducts, 1},
    {"_test_rcpparma_hello_world",  (DL_FUNC) &_test_rcpparma_hello_world,  0},
    {"_test_rcpparma_innerproduct", (DL_FUNC) &_test_rcpparma_innerproduct, 1},
    {"_test_rcpparma_outerproduct", (DL_FUNC) &_test_rcpparma_outerproduct, 1},
    {NULL, NULL, 0}
};

void R_init_test(DllInfo *dll)
{
    R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
    R_useDynamicSymbols(dll, FALSE);
}

But it does not compile:

$ R CMD build test
* checking for file ‘test/DESCRIPTION’ ... OK
* preparing ‘test’:
* checking DESCRIPTION meta-information ... OK
* cleaning src
* installing the package to process help pages
      -----------------------------------
* installing *source* package ‘test’ ...
** using staged installation
** libs
g++ -std=gnu++14 -I"/usr/include/R/" -DNDEBUG  -I"/home/<user>/R/x86_64-pc-linux-gnu-library/3.6/Rcpp/include" -I"/usr/lib/R/library/RcppArmadillo/include" -D_FORTIFY_SOURCE=2 -fopenmp  -fpic  -march=x86-64 -mtune=generic -O2 -pipe -fno-plt  -c RcppExports.cpp -o RcppExports.o
gcc -I"/usr/include/R/" -DNDEBUG  -I"/home/<user>/R/x86_64-pc-linux-gnu-library/3.6/Rcpp/include" -I"/usr/lib/R/library/RcppArmadillo/include" -D_FORTIFY_SOURCE=2  -fpic  -march=x86-64 -mtune=generic -O2 -pipe -fno-plt  -c init.c -o init.o
g++ -std=gnu++14 -I"/usr/include/R/" -DNDEBUG  -I"/home/<user>/R/x86_64-pc-linux-gnu-library/3.6/Rcpp/include" -I"/usr/lib/R/library/RcppArmadillo/include" -D_FORTIFY_SOURCE=2 -fopenmp  -fpic  -march=x86-64 -mtune=generic -O2 -pipe -fno-plt  -c rcpparma_hello_world.cpp -o rcpparma_hello_world.o
g++ -std=gnu++14 -shared -L/usr/lib64/R/lib -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -o test.so RcppExports.o init.o rcpparma_hello_world.o -fopenmp -llapack -lblas -lgfortran -lm -lquadmath -L/usr/lib64/R/lib -lR
/usr/bin/ld: init.o: in function `R_init_test':
init.c:(.text+0x0): multiple definition of `R_init_test'; RcppExports.o:RcppExports.cpp:(.text+0xd0): first defined here
collect2: error: ld returned 1 exit status
make: *** [/usr/share/R//make/shlib.mk:6: test.so] Error 1
ERROR: compilation failed for package ‘test’
* removing ‘/tmp/RtmpW9PqbR/Rinst8c72353a56e/test’
      -----------------------------------
ERROR: package installation failed

The critical error here is

init.c:(.text+0x0): multiple definition of `R_init_test'; RcppExports.o:RcppExports.cpp:(.text+0xd0): first defined here

Note

Note that the character_only=F argument in package_native_routine_registration_skeleton is required as described here; otherwise the command fails with no native symbols were extracted.

Software

Arch Linux 5.3.10, R 3.6.1, Rcpp 1.0.3


Solution

  • You don't need to use utils::package_native_routine_registration_skeleton() in this case, since Rcpp::compileAttributes() adds the necessary code to src/RcppExport.cpp. This function is called by RcppArmadillo::RcppArmadillo.package.skeleton().

    Alternatively, you can create a src/init.c file and call Rcpp::compileAttributes() again. In that case there will be no registration code in src/RcppExport.cpp. Typically that is only necessary when you have some other functions to register that do not use Rcpp attributes.