7

I am trying to build an R package with Rcpp code which uses an external library. I had previously asked SO about how to use an external C library in a package here. The problem I have facing is as soon as I include the following line of code

y = N_VNew_Serial(3);

I am getting the error

sundials_test.o:sundials_test.cpp:(.text+0x2ba): undefined reference to `N_VNew_Serial'
collect2: ld returned 1 exit status
Error in Rcpp::sourceCpp("src/sundials_test.cpp") : 
  Error occurred building shared library

I do not get an error with the line

N_Vector y = NULL;

so, I think the connection to the library is working fine. I have also confirmed that the function declaration for N_VNewSerial() is in the nvector/nvector_serial.h In case you need to look at entire package code, it is available here

The code for the particular Rcpp file is paste below

#include <Rcpp.h>

// #include <iostream.h>
#include <cvode/cvode.h>               /* prototypes for CVODE fcts., consts. */
#include <nvector/nvector_serial.h>    /* serial N_Vector types, fcts., macros */
#include <cvode/cvode_dense.h>         /* prototype for CVDense */
#include <sundials/sundials_dense.h>   /* definitions DlsMat DENSE_ELEM */
#include <sundials/sundials_types.h>   /* definition of type realtype */

using namespace Rcpp;

void InitialConditions (NumericVector x){

  N_Vector y = NULL;
  // y = N_VNew_Serial(3);
  //
  // NV_Ith_S(y,0) = 1;
  // NV_Ith_S(y,1) = 2;
  // NV_Ith_S(y,2) = 3;


}

I am not sure why the code is reporting undefined reference to one function but not to another in the same header file though, and any help in understanding the solving this error would be highly appreciated.

Thanks!

SN248

Community
  • 1
  • 1
Satya
  • 1,708
  • 1
  • 15
  • 39

1 Answers1

6

That is a link error and not a compile error. The compilation succeeded letting you get to the link step. But

sundials_test.o:sundials_test.cpp:(.text+0x2ba): \
  undefined reference to `N_VNew_Serial'
collect2: ld returned 1 exit status
Error in Rcpp::sourceCpp("src/sundials_test.cpp") : 
  Error occurred building shared library

is very clear: R cannot build a shared library because you did not link against the object code (from Sundials, I presume) which provides it.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Thank you very much for your response @Dirk. I don't know how I would go about linking against object code. Could you help in that process? I don't have sundials installed on my windows machine. I am trying to make the package so that I don't have to install the library, so I have included all the source and header file in the package itself. Thanks! – Satya Jun 14 '16 at 19:53
  • Well you are [trying to declare them here](https://github.com/AleMorales/RcppSundials.R/blob/master/src/Makevars#L5-L21). Maybe some files are missing? Or maybe the dependency does *not* get to the link step? Dunno, but that is your problem here. – Dirk Eddelbuettel Jun 14 '16 at 19:54
  • Thanks for the response, just to be clear - that is not the `Makevars` file from my package. The `Makevars` file of my package is - https://github.com/sn248/Rcppsbmod/blob/master/src/Makevars.win, I was under the impression that in order to include an external library, all I had to do was to provide header files and source files from that library and not the shared libraries that are built while installing the package, but I could be very wrong here. Any insights here would be very helpful. Thanks! – Satya Jun 14 '16 at 20:05
  • An example of compiling and linking the example code from the package is `gcc -Wall cvRoberts_dns.c -o cvRoberts_dns.exe -I/usr/local/include -L/usr/local/lib/ -lsundials_cvode -lsundials_nvecserial -lm`, I am not sure how linking is done when the library is not installed. – Satya Jun 14 '16 at 20:09
  • 2
    In that very last example you use two sundials (sub-)libraries: `-lsundials_cvode -lsundials_nvecserial`. You need to do the same with your R package, and that is a) independent of whether or not you use Rcpp and b) clearly documented in Writing R Extensions. – Dirk Eddelbuettel Jun 14 '16 at 20:23
  • 1
    As a side note, @SN248, you should not be using `Rcpp::sourceCpp()` to compile this code. Instead, you should be building and reloading the package. – coatless Jun 15 '16 at 05:26
  • Thank you @Coatless for your suggestion, I edited the `PKG_LIBS` in `Makevars` to look like - `PKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) -lsundials_cvode -lsundials_nvecserial -lm`, since I have the libraries installed in `/usr/local/lib` directory of my OS X machine and rebuilt the package, it seems there is a problem in loading `.dylib` files now - here is the new error message - – Satya Jun 15 '16 at 10:11
  • `Error in dyn.load(file, DLLpath = DLLpath, ...) : unable to load shared object '/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcppsbmod/libs/Rcppsbmod.so': dlopen(/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcppsbmod/libs/Rcppsbmod.so, 6): Library not loaded: libsundials_cvode.1.dylib Referenced from: /Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcppsbmod/libs/Rcppsbmod.so Reason: image not found Error: loading failed Execution halted ERROR: loading failed` – Satya Jun 15 '16 at 10:15
  • Is it possible to ship these files also along with the package? e.g., in the `/inst/lib` folder? I assume they will be platform specific also. – Satya Jun 15 '16 at 10:39
  • A CRAN package may not contain compiled code, so no libraries in `inst/lib`. Other packages do this by building the library in the configuration step, then have the 'normal' package build use it. Now, to be plain, what you are trying to do here is somewhat advanced. It is doable, and being done, but it something rather suited for a developer with the knowledge of @coatless or myself. It is becoming somewhat clearer that you are not entirely familiar with more basic steps so I do not think we can coach you all that is needed with 200 char increments here. Step back, and learn more basics. – Dirk Eddelbuettel Jun 15 '16 at 11:21
  • Thank you for your comment. Could you point me to any resources (apart from Writing R-extensions page) where this is addressed? An example of interest to me where this is done is the package you previously linked to - https://github.com/AleMorales/RcppSundials.R, but a simpler example that you know of would also be helpful. Thanks! – Satya Jun 15 '16 at 14:06
  • Hi @Coatless, could you take a look at the problem I am having and help me or guide me in resolving this issue? Thanks! – Satya Jun 15 '16 at 20:15
  • Although, not a solution, I have been able to get a version working with libraries installed on the system. The relevant `Makevars` is `PKG_CPPFLAGS= -I../inst/include/ -I src/sundials PKG_LIBS= $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) /usr/local/lib/libsundials_cvode.a /usr/local/lib/libsundials_nvecserial.a` – Satya Jul 10 '16 at 15:06