1

This is my first question and I'll try to do my best to write a good one. Please let me know if you need any other information.

I'm going to start with a brief background so you can understand what I'm trying to accomplish and why. Then I'll ask my specific question.

I'm currently developing a package using Rcpp/RcppGSL. I'm using C/C++ because some of the computations I'll be doing will be over very large data sets and they need to be fast. (I'm also a research assistant; I don't always get to choose how we do things.) I'm definitely a novice with respect to C/C++. And to my understanding, C is (almost) a subset of C++. So, I've taken this to mean that I can, essentially, import and run all of my C code as C++ code (sans a few changes). Therefore, I should be able to integrate my C code into an R package using Rcpp/RcppGSL.

After I had all of my C code working, I started actually assembling the R package. I realize now this was a mistake. I should have started the development in RStudio.

I believe I have an issue with R not being able to find GSL, making me think the path variable is incorrect. I think this because I am able to get the given test functions for Rcpp to work, along with a few of my own test functions. However, whenever I try getting RcppGSL to work, specifically, whenever I use CTRL+SHIFT+L on my package, I get the following error:

Error in dyn.load(dllfile) : unable to load shared object '/home/max/research/qeadan/rcnetwork/src/rcnetwork.so': /home/max/research/qeadan/rcnetwork/src/rcnetwork.so: undefined symbol: gsl_vector_alloc

So, after seeing this, I looked at the following sources: Advanced R by Wickham, R Packages by Wickham, Seamless R and C++ Integration with Rcpp by Eddelbuettel, and Writing R Extensions by R Core Team (author check?) and the following SO posts (though there have been more): downloading the gsl headers into the R package is suggested; the package was borked; and the linking wasn't taking place. Nothing I've found directly addresses my issue.

Hence, I suppose my question has two parts: a) am I actually correct as to what I think the error is? and b) would someone please give me a reference that will tell me, or simply tell me, how to fix this? I'm sure the solution is simple; I just don't know how to do it, nor do I know where to look.

I've included my code, NAMESPACE, and Makevars.in folder.

Here is a version of the function I'm trying to export. I've commented out lines that require other functions I've written in C but still produce the same error I'm getting without new ones.

#include <RcppGSL.h>
#include "rootedCorrelationHeaders.h"

using namespace Rcpp;
using namespace RcppGSL;

// [[Rcpp::export]]
Rcpp::List ccm(SEXP datas, SEXP correls, double alpha){

RcppGSL::matrix<double> data = datas;
Rcpp::CharacterVector correl = correls;

//Create C/C++ types
gsl_matrix *cm1, *cm2;


//Get matrix dimensions from GSL matrix
int ROW = (int) data.nrow();
int COL = (int) data.ncol();

//Create structure to hold sorted matrices
//sm *split; //requires outside struct

//Allocate memory to data structure
//split = smAlloc(ROW, COL); //requires outside function

return Rcpp::List::create(Rcpp::Named("Comparison")= ROW,
                          Rcpp::Named("Correl1") = alpha,
                          Rcpp::Named("Correl2") = correl);

} 

Here is my NAMESPACE file. But, honestly, I don't really understand it.

useDynLib(rcnetwork, .registration=TRUE)
exportPattern("^[[:alpha:]]+") 
import(RcppGSL)
importFrom(Rcpp, evalCpp, sourceCpp)

Here is my Makevars.in file. Again, I don't really understand it.

# Set by configure
GSL_CFLAGS = @GSL_CFLAGS@
GSL_LIBS = @GSL_LIB@
RCPP_LDFLAGS = @RCPP_LDFLAGS@

# Combine with standard arguments for R
PKG_CPPGLAGS = $ (GSL_CFLAGS)
PKG_LIBS = $ (GSL_LIBS) $(RCPP_LDFLAGS)

Lastly, here are the relevant parts of the DESCRIPTION file (added as edit per duckmayr's comment).

License: GPL (>= 2)
LazyData: TRUE
Depends: R (>= 3.6.2)
Imports: 
    Rcpp,
    RcppGSL,
    plot.matrix
LinkingTo:
    Rcpp,
    RcppGSL,
    plot.matrix
SystemRequirements: GNU GSL

As a final note, running the command

R.version

yields the following output:

platform       x86_64-pc-linux-gnu         
arch           x86_64                      
os             linux-gnu                   
system         x86_64, linux-gnu           
status                                     
major          4                           
minor          0.0                         
year           2020                        
month          04                          
day            24                          
svn rev        78286                       
language       R                           
version.string R version 4.0.0 (2020-04-24)
nickname       Arbor Day                

Lastly, a fix I've seen a few times on multiple posts is to use the function

compileAttributes()

In particular, people generally have to use it twice. I've done this and it doesn't change anything. It actually doesn't give any output in the console (just in case that's a red flag).

In advance, thank you so much for your help and your time.

Max Black
  • 13
  • 3
  • Do you have `RcppGSL` in the `Linking To` field of your `DESCRIPTION` file? If not add it there (see [here](http://adv-r.had.co.nz/Data-structures.html#data-frames) for more details). For standalone scripts, you use the `// [[Rcpp::depends(RcppGSL)]]` you've used to set `-I` flags, while for packages, you use the Linking To field. – duckmayr Jun 20 '20 at 19:11
  • 1
    I do! I'll add it to the question, that way everyone can see it. Thank you. I'll try removing the `// [[Rcpp::depends(RcppGSL)]]` from my script. – Max Black Jun 20 '20 at 19:17
  • (It's a very long post and you clearly have done a lot of work but you need to be careful. Some information can be stale, some information can be wrong. I.e. `people generally have to use it twice` is a) no longer correct (there once was a bug, it is fex) and b) if you already work inside RStudio then _you_ run it zero times because it is generally running for you.) – Dirk Eddelbuettel Jun 20 '20 at 19:19
  • @duckmayr I tried removing `// [[Rcpp::depends(RcppGSL)]]` but it still yields the same error. – Max Black Jun 20 '20 at 19:20
  • 1
    In general, I recommend to start with the simplest possible example concerning your issue. Which, for a package using GSL via RcppGSL is to use the embedded example paackage (see `examples/RcppGSLExample` in your RcppGSL installation) and see if that works for you. – Dirk Eddelbuettel Jun 20 '20 at 19:20
  • @DirkEddelbuettel Thank you! I will try that right away and report back. – Max Black Jun 20 '20 at 19:21
  • 2
    I just shipped it "as is" to the [RHub Buider](https://builder.r-hub.io/) testing it on macOS (as I don't have macOS here) and it worked just fine: https://builder.r-hub.io/status/RcppGSLExample_0.0.3.tar.gz-a96b5f25e8b844be96f8d3e7553b92e3 – Dirk Eddelbuettel Jun 20 '20 at 19:24
  • (There is a trivial note about a variable being different between documentation and code which I'll fix.) But it a) builds and so b) links fine against the GSL and c) even runs. So there you have a working example. – Dirk Eddelbuettel Jun 20 '20 at 19:25
  • @DirkEddelbuettel So, I couldn't find what you were referring to locally, so I just downloaded the package from GitHub and tried running it. I tried making the package. I receive the same error mentioned above, with a small change. `Error in dyn.load(dllfile) : unable to load shared object '/home/max/research/qeadan/testing/rcppgsl-master/src/RcppGSL.so': /home/max/research/qeadan/testing/rcppgsl-master/src/RcppGSL.so: undefined symbol: RcppGSL_fastLm`. Is something wrong with my path variable, like I suspected? – Max Black Jun 20 '20 at 20:10
  • @DirkEddelbuettel I'm confused as to how macOS is tying in here. I'm not using macOS. Maybe I'm missing something? – Max Black Jun 20 '20 at 20:11
  • My bad. I misread. Linux is even better/simpler/easier :) – Dirk Eddelbuettel Jun 20 '20 at 20:11
  • I will log what I did as answer as we are outgrowing the comments here. – Dirk Eddelbuettel Jun 20 '20 at 20:12

1 Answers1

1

Let's look at a simple working example. I start by copying what is included in the package:

edd@rob:~$ cp -ax /usr/local/lib/R/site-library/RcppGSL/examples/RcppGSLExample/ /tmp/
edd@rob:~$ cd /tmp/RcppGSLExample/                                                                       
edd@rob:/tmp/RcppGSLExample$ R CMD build .                                                               
* checking for file ‘./DESCRIPTION’ ... OK
* preparing ‘RcppGSLExample’:
* checking DESCRIPTION meta-information ... OK
* cleaning src                       
* checking for LF line-endings in source and make files and shell scripts
* checking for empty or unneeded directories
* building ‘RcppGSLExample_0.0.3.tar.gz’
                                                    
edd@rob:/tmp/RcppGSLExample$ R CMD check RcppGSLExample_0.0.3.tar.gz 
* using log directory ‘/tmp/RcppGSLExample/RcppGSLExample.Rcheck’
* using R version 4.0.1 (2020-06-06)
* using platform: x86_64-pc-linux-gnu (64-bit)
* using session charset: UTF-8                                                                           
* checking for file ‘RcppGSLExample/DESCRIPTION’ ... OK
* this is package ‘RcppGSLExample’ version ‘0.0.3’                                                       
* checking package namespace information ... OK
* checking package dependencies ... OK         
* checking if this is a source package ... OK    
* checking if there is a namespace ... OK                                                                
* checking for executable files ... OK          
* checking for hidden files and directories ... OK
* checking for portable file names ... OK
* checking for sufficient/correct file permissions ... OK
* checking whether package ‘RcppGSLExample’ can be installed ... OK
* checking installed package size ... OK
* checking package directory ... OK
* checking DESCRIPTION meta-information ... OK
* checking top-level files ... OK
* checking for left-over files ... OK                                                                    
* checking index information ... OK
* checking package subdirectories ... OK
* checking R files for non-ASCII characters ... OK
* checking R files for syntax errors ... OK
* checking R files for non-ASCII characters ... OK
* checking R files for syntax errors ... OK
* checking whether the package can be loaded ... OK
* checking whether the package can be loaded with stated dependencies ... OK
* checking whether the package can be unloaded cleanly ... OK
* checking whether the namespace can be loaded with stated dependencies ... OK
* checking whether the namespace can be unloaded cleanly ... OK
* checking loading without being on the library search path ... OK
* checking dependencies in R code ... OK
* checking S3 generic/method consistency ... OK
* checking replacement functions ... OK
* checking foreign function calls ... OK
* checking R code for possible problems ... OK
* checking Rd files ... OK
* checking Rd metadata ... OK
* checking Rd cross-references ... OK
* checking for missing documentation entries ... OK
* checking for code/documentation mismatches ... WARNING
Codoc mismatches from documentation object &apos;colNorm&apos;:
colNorm
  Code: function(G)
  Docs: function(M)
  Argument names in code not in docs:
    G
  Argument names in docs not in code:
    M
  Mismatches in argument names:
    Position: 1 Code: G Docs: M

* checking Rd \usage sections ... OK
* checking Rd contents ... OK
* checking for unstated dependencies in examples ... OK
* checking line endings in shell scripts ... OK
* checking line endings in C/C++/Fortran sources/headers ... OK
* checking line endings in Makefiles ... OK
* checking compilation flags in Makevars ... OK
* checking for GNU extensions in Makefiles ... OK
* checking for portable use of $(BLAS_LIBS) and $(LAPACK_LIBS) ... OK
* checking use of PKG_*FLAGS in Makefiles ... OK
* checking compilation flags used ... OK
* checking compiled code ... OK
* checking examples ... OK
* checking PDF version of manual ... OK
* DONE

Status: 1 WARNING
See
  ‘/tmp/RcppGSLExample/RcppGSLExample.Rcheck/00check.log’
for details.

edd@rob:/tmp/RcppGSLExample$ 

(The one WARNING is something I'll fix in the sources.) This should give you a working example.

If your package does not build then compare its files with the ones of the working example. This in DESCRIPTION, NAMESPACE, src/Makevars and more.

Because the example package is small, this should be quick. But it is hard for to remotely guess which (possibly small but important) step you may have missed.

Last but not least, you also of course need the GSL itself installed as both the run-time and development package. For me on Ubuntu 20.04 that is

edd@rob:/tmp/RcppGSLExample$ dpkg -l| grep libgsl | cut -c-80
ii  libgsl-dev                                 2.5+dfsg-6build1                 
ii  libgsl23:amd64                             2.5+dfsg-6build1                 
ii  libgslcblas0:amd64                         2.5+dfsg-6build1                 
edd@rob:/tmp/RcppGSLExample$ 
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Thank you for the detailed response! I have downloaded the package "rcppgsl-master" from GitHub; I then entered the project; afterwards, I then went to try and build the example (CTRL+SHIFT+B), it then gave me the following `error: Error: package or namespace load failed for ‘RcppGSL’ in dyn.load(file, DLLpath = DLLpath, ...):` Does this mean something is wrong with the path specified in the NAMESPACE? Was I supposed to change something there? It is identical to the error I am having with my package. And since your package is working, I am wondering what else may be wrong. – Max Black Jun 20 '20 at 20:29
  • I didn't have room to say this on my comment above, but thank you for everything so far! Wait, somehow I missed the last paragraph on your answer. Let me process that. – Max Black Jun 20 '20 at 20:29
  • I am out of gas. You seem to insist on writing lots and fast. Maybe you should re-read what I wrote more slowly and repeat what I did the way I did it. *There is a reason I spelled it out in detail.* I a) did not ask you to download anything from GitHub, but b) asked you to operate on content of the package you have and c) showed you the commands to run, on the command-line. If you insist on not doing any of that then I regret having wasted all this time putting it together for no use. – Dirk Eddelbuettel Jun 20 '20 at 20:32
  • So, I have done everything you've asked. I was able to reproduce almost all of the results. The part where my output differs is that when using the command `dpkg -l| grep libgsl | cut -c-80` there is no output. However, after checking my package against the working example, I realized I was missing a Makevars file. I only had a Makevars.in file. After copying the example's Makevars file, I was able to get my code working. Should I be concerned that I did not get any output from the command above? Thank you again for your time and energy. – Max Black Jun 21 '20 at 00:33
  • 1
    That makes it clearer. You tried to sprint before you figured out how to walk. _Every package needs a `src/Makevars`_. You must have one. You didn't so you had those linker errors. We use a _computed one_ which is generated _from the `src/Makevars.in`_. Those are details you do need to deal with now, but you will need to acquire more knowledge about _how_ a package works and how to put a _non-trivial one_ (as you have GSL depependency) together. There is no free lunch, and there are no shortcuts. I like working from functioning examples which is why I sent you to the example package. – Dirk Eddelbuettel Jun 21 '20 at 01:04