1

I have a working C++ library and I'm trying to expose a function to R through Rcpp, I have the following directory setup

├── CMakeLists.txt
├── DESCRIPTION
├── install_log.txt
├── LICENSE
├── mock_data.csv
├── NAMESPACE
├── R
│   └── RcppExports.R
├── README.md
├── scripts
│   ├── generate_synthetic_data.cpp
│   └── run_synthetic.cpp
├── src
│   ├── collectors
│   │   ├── base_collector.hpp
│   │   ├── file_collector.cpp
│   │   └── file_collector.hpp
│   ├── data
│   │   ├── cluster.hpp
│   │   ├── time_series.cpp
│   │   ├── time_series.hpp
│   ├── data.hpp
│   ├── exponential_family
│   │   ├── mv_normal_inv_wishart.hpp
│   │   ├── mv_normal_inv_wishart_imp.hpp
│   │   ├── mv_normal_wishart.cpp
│   │   ├── mv_normal_wishart.hpp
│   │   └── options.hpp
│   ├── linear_model
│   │   ├── mv_fixed_covariance.cpp
│   │   └── mv_fixed_covariance.hpp
│   ├── Makevars
│   ├── models
│   │   ├── ar_model.cpp
│   │   ├── ar_model.hpp
│   │   └── base_model.hpp
│   ├── random
│   │   ├── inv_wishart.hpp
│   │   ├── mvn.hpp
│   │   ├── mvn_precision.hpp
│   │   ├── polya_gamma
│   │   │   ├── PolyaGamma.cpp
│   │   │   ├── PolyaGamma.h
│   │   │   └── RNG
│   │   │       ├── CPURNG.cpp
│   │   │       ├── CPURNG.hpp
│   │   └── wishart.hpp
│   ├── RcppExports.cpp
│   ├── RcppExports.o
│   ├── rcpp_functions.cpp
│   ├── rcpp_functions.h
│   ├── samplers
│   │   ├── beta_sampler.cpp
│   │   ├── beta_sampler.hpp
│   │   ├── gamma_sampler.cpp
│   │   ├── gamma_sampler.hpp
│   │   ├── g_sampler.cpp
│   │   ├── g_sampler.hpp
│   │   ├── phi_sampler.cpp
│   │   ├── phi_sampler.hpp
│   │   ├── sigma_sampler.cpp
│   │   ├── sigma_sampler.hpp
│   │   ├── weights_sampler.cpp
│   │   └── weights_sampler.hpp
│   └── utils
│       ├── argparse.hpp
│       ├── data_utils.cpp
│       ├── data_utils.hpp
│       ├── math_utils.cpp
│       ├── math_utils.hpp
│       ├── string_utils.cpp
│       ├── string_utils.hpp
│       ├── vector_utils.cpp
│       └── vector_utils.hpp
├── test
│   ├── test_ar_model.cpp
│   ├── test_vector_utils.cpp
│   └── test_wishart.cpp
└── MyPackage_1.0.tar.gz 

The function I am trying to expose is declared in src/rcpp_functions.h and defined in src/rcpp_functions.cpp, it looks something like:

#include <RcppEigen.h>
#include <vector>
#include <vector_utils.hpp>
#include <time_series.hpp>
#include <ar_model.hpp>

using Eigen::MatrixXd;
using Eigen::VectorXd;
using std::vector;

Rcpp::NumericVector predictiveLogLikelihood(
    const Rcpp::List &timeSerie, const Eigen::MatrixXd &bChain,
    const Eigen::MatrixXd &gammaChain, const Rcpp::List &alphaChains,
    const Rcpp::List &phiChains, const Eigen::MatrixXd &sigmaChain) {

  convert from R to C++ objects & do some stuff
}

From R I run compileAttributes(pkgdir = ".", verbose = getOption("verbose")) And get the files R/RcppExports.R, src/RcppExports.cpp

My temporary Makevars is pretty ugly and looks like:

CXX_STD = CXX14

SOURCES=$(wildcard **/*.cpp)

OBJECTS = RcppExports.o $(SOURCES:.cpp=.o)

PKG_CPPFLAGS = -I"." -I"./collectors" -I"./data" -I"./exponential_family"  \
    -I"./linear_model" -I"./models" -I"./random" -I"./random/polya_gamma" \
    -I"./random/polya_gamma/RNG" -I"./samplers" -I"./utils" \
    -I"./usr/include/eigen3/" \
    -DUSE_R -D"USE_R" -w -z,defs

PKG_LIBS = -lgsl

all: $(SHLIB)

$(SHLIB): $(OBJECTS)

For the moment I think it's good enough as I don't really need to distribute the package (though suggestions on how to improve it are really welcome)

When I run from the terminal:

R -e "library(devtools); install()"

The compilation is fine but I get the following error:

*** installing help indices
** building package indices
** testing if installed package can be loaded
Error: package or namespace load failed for ‘MyPackage’ in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/home/mario/R/x86_64-pc-linux-gnu-library/3.5/MyPackage/libs/MyPackage.so':
  /home/mario/R/x86_64-pc-linux-gnu-library/3.5/MyPackage/libs/MyPackage.so:
 undefined symbol: _Z23predictiveLogLikelihoodRKN4Rcpp6VectorILi19ENS_15PreserveStorageEEERK

Given the name of the symbol, I guess it refers to the Rcpp function (I don't have any other predictiveLogLikelihood function)

I am probably missing out something very obvious but I've been stuck on this problem for a couple of days, looked at all Rcpp packages and the package RcppExamples

Edit 1 The output of the compilation is

>R -e "library(devtools); install()"
....
Running /usr/lib/R/bin/R CMD INSTALL \
ttmp/Rtmp412bar/MyPackage_1.0.tar.gz --install-tests 
* installing to library ‘/home/mario/R/x86_64-pc-linux-gnu-library/3.5’
* installing *source* package ‘MyPackage’ ...
** libs

g++ -std=gnu++14 -I"/usr/share/R/include" -DNDEBUG -I"." -I"./collectors" -I"./data" -I"./exponential_family" -I"./linear_model" -I"./models" -I"./random" -I"./random/polya_gamma" -I"./random/polya_gamma/RNG" -I"./samplers" -I"./utils" -I"./usr/include/eigen3/" -DUSE_R -D"USE_R" -w -z,defs -I"/home/mario/R/x86_64-pc-linux-gnu-library/3.5/Rcpp/include" -I"/home/mario/R/x86_64-pc-linux-gnu-library/3.5/RcppArmadillo/include" -I"/home/mario/R/x86_64-pc-linux-gnu-library/3.5/RcppEigen/include" -I"/home/mario/R/x86_64-pc-linux-gnu-library/3.5/RcppGSL/include"    -fpic  -g -O2 -fdebug-prefix-map=/build/r-base-oUvOgu/r-base-3.5.1=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c RcppExports.cpp -o RcppExports.o

(This is done for all the source files)

g++ -std=gnu++14 -I"/usr/share/R/include" -DNDEBUG -I"." -I"./collectors" -I"./data" -I"./exponential_family" -I"./linear_model" -I"./models" -I"./random" -I"./random/polya_gamma" -I"./random/polya_gamma/RNG" -I"./samplers" -I"./utils" -I"./usr/include/eigen3/" -DUSE_R -D"USE_R" -w -z,defs -I"/home/mario/R/x86_64-pc-linux-gnu-library/3.5/Rcpp/include" -I"/home/mario/R/x86_64-pc-linux-gnu-library/3.5/RcppArmadillo/include" -I"/home/mario/R/x86_64-pc-linux-gnu-library/3.5/RcppEigen/include" -I"/home/mario/R/x86_64-pc-linux-gnu-library/3.5/RcppGSL/include"    -fpic  -g -O2 -fdebug-prefix-map=/build/r-base-oUvOgu/r-base-3.5.1=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c collectors/file_collector.cpp -o collectors/file_collector.o

Building the shared object

g++ -std=gnu++14 -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o MyPackage.so RcppExports.o samplers/weights_sampler.o samplers/sigma_sampler.o samplers/g_sampler.o samplers/gamma_sampler.o samplers/phi_sampler.o samplers/beta_sampler.o exponential_family/mv_normal_wishart.o linear_model/mv_fixed_covariance.o models/ar_model.o utils/string_utils.o utils/math_utils.o utils/vector_utils.o utils/data_utils.o data/generate_synthetic_data.o data/time_series.o collectors/file_collector.o -lgsl -L/usr/lib/R/lib -lR


installing to /home/mario/R/x86_64-pc-linux-gnu-library/3.5/MyPackage/libs
** R
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded

ERROR

Error: package or namespace load failed for ‘MyPackage’ in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/home/mario/R/x86_64-pc-linux-gnu-library/3.5/MyPackage/libs/MyPackage.so':
  /home/mario/R/x86_64-pc-linux-gnu-library/3.5/MyPackage/libs/MyPackage.so: undefined symbol: _Z23predictiveLogLikelihoodRKN4Rcpp6VectorILi19ENS_15PreserveStorageEEERKN5Eigen6MatrixIdLin1ELin1ELi0ELin1ELin1EEES9_S4_S4_S9_
Error: loading failed
Execution halted
mariob6
  • 469
  • 1
  • 6
  • 16
  • 1
    I find it odd that you have only a single objst file in your directory listing (`RcppExports.o`). Can you post the output from the package compilation, especially the last line where the library is linked? – Ralf Stubner Dec 06 '18 at 09:42
  • You are using cmake, but you have a hand-written makefile? – Matthieu Brucher Dec 06 '18 at 09:45
  • 1
    @MatthieuBrucher, the library works as a standalone C++ library for which I use CMake, and a R package for which I use the Makevars file. – mariob6 Dec 06 '18 at 10:15
  • OK, then link against the proper libraries or compile the proper files. See the duplicate. – Matthieu Brucher Dec 06 '18 at 10:15
  • @RalfStubner I updated the question with the compilation output :) – mariob6 Dec 06 '18 at 10:22
  • 1
    Also: If you must reinvent the build system for R packages and it breaks, you get to keep the pieces. This was a simple error in a somewhat overly complicated attempt. – Dirk Eddelbuettel Dec 06 '18 at 14:30

1 Answers1

2

In the list of object files that are linked there is one file missing: rcpp_functions.o. You could add this to OBJECTS in the Makevars file:

OBJECTS = RcppExports.o rcpp_functions.o $(SOURCES:.cpp=.o)

Alternatively you could use

SOURCES = $(wildcard *.cpp) $(wildcard **/*.cpp)

OBJECTS = $(SOURCES:.cpp=.o)
Ralf Stubner
  • 26,263
  • 3
  • 40
  • 75