Construction of flags in R CMD SHLIB - r

I am having a lot of trouble understanding the steps that construct the compilation flags when using R CMD SHLIB. I use the following:
in ~/.R/Makevars define `CPPFLAGS=-O3'
in src/Makevars.win define PKG_CPPFLAGS = -O3
include Rcpp and RcppGSL as dependencies in the DESCRIPTION file
where the second step is clearly redundant, but I do it just in case PKG_CXXFLAGS was initialized to something different.
But when I run R CMD SHLIB I find my -O3 flags but also -UNDEBUG -Wall -pedantic -g -O0. Where can those additional flags be coming from? Can Rcpp and RcppGSL affect these flags in a way I can't control through my Makevars.in?

For per-user, or personal settings, I just use ~/.R/Makevars which will affect all R CMD SHLIB or R CMD COMPILE calls, including those from Rcpp.
You can also define them in per-project Makefiles, or src/Makevars, and besides the per-user files, you can of course edit the system-wide variant (which is where the other values that confused you came from). See the file $R_HOME/etc/Makeconf for the latter.
Lastly, DESCRIPTION has nothing to do here.

Related

Invoking R CMD SHLIB through system() doesn't find GSL library

I have a C program that uses GNU Scientific Library (GSL) for root finding and I want to make this into a shared library (.so or .dll) for use in R.
Say my GSL_MRE.c file looks like this:
#include <gsl/gsl_math.h>
#include <gsl/gsl_roots.h>
#include <gsl/gsl_errno.h>
#include <R.h>
int gsl_rootsolve ()
{
const gsl_root_fdfsolver_type *T;
gsl_root_fdfsolver *s;
T = gsl_root_fdfsolver_newton;
s = gsl_root_fdfsolver_alloc (T);
printf ("using %s method\n", gsl_root_fdfsolver_name (s));
gsl_root_fdfsolver_free (s);
return 0;
}
If I run the following in Terminal on MacOS 10.13.6:
$ R CMD SHLIB GSL_MRE.c -lgsl -lgslcblas -lm -L/opt/local/lib
($ is the terminal prompt) it creates GSL_MRE.so that I can load by executing in R:
R> dyn.load(paste("GSL_MRE", .Platform$dynlib.ext, sep = ""))
(R> is R prompt)
But when I try to create the .so file from R with system():
R> system("R CMD SHLIB GSL_MRE.c -lgsl -lgslcblas -lm -L/opt/local/lib")
It can't find the header files. I get:
GSL_MRE.c:1:10: fatal error: 'gsl/gsl_math.h' file not found
#include <gsl/gsl_math.h>
^~~~~~~~~~~~~~~~
1 error generated.
make: *** [GSL_MRE.o] Error 1
I've been trying to set all sorts of FLAGS in ~/.R/Makevars, but nothing works. My Makevars currently only contains the following line:
CC=gcc -Wall -Wextra
Why does system() from R not work? And how do I make the .so from R programmatically?
There are a few packages that wrap around the GSL, I recommend you study them. At a minimum you could use gsl-config (which you should test for) to derive include and linker statements. On my Uvuntu system:
edd#rob:~$ gsl-config --cflags
-I/usr/include
edd#rob:~$ gsl-config --libs
-L/usr/lib/x86_64-linux-gnu -lgsl -lgslcblas -lm
edd#rob:~$
More fundamentally, you got trapped between linking (where you correctly pointo to the GSL libraries) and compiling (where you have told the compiler where your GSL headers reside). You apprently need to tell it on your system.
Also, some packages provide facilities. My RcppGSL package offers some simple vector and matrix wrappers, but also deals with GSL detection so that for example my RcppZiggurat (which uses GSL RNGs) can use:
edd#rob:~$ cat git/rcppziggurat/src/Makevars
PKG_CPPFLAGS = -I. -I../inst/include
## Use the R_HOME indirection to support installations of multiple R version
PKG_LIBS = `$(R_HOME)/bin/Rscript -e "RcppGSL:::LdFlags()"`
edd#rob:~$
It's not a trivial problem as you need to sort our compiling and linking, but it has been done before so you can lean on that.

undefined references when using Rcpp

I am trying to build an R package that is a wrapper around a C library (and which uses gsl) in Windows. I can transition to Linux, if necessary
For better or worse, I put the make commands for the C library in Makevars.in.
I used Rstudio's Rcpp skeleton feature to create the package. I have installed Rtools 3.3 and using R 3.3.1
and I included Rcpp and RcppGSL in LinkingTo field of DESCRIPTION. I am still getting undefined reference errors for the make command
$(CXX) $(CXXFLAGS) $(OBJECTS) ../inst/libgraphm.a $(PKG_LIBS)
A few of the error are as follows
c:/Rtools/mingw_64/bin/g++ -shared -s -static-libgcc -o RGraphM.dll tmp.def graphmatch_rcpp.o RcppExports.o -L../inst -lgraphm -LC:/tools/gsl/lib/x64 -lgsl -lgslcblas -Ld:/Compiler/gcc-4.9.3/local330/lib/x64 -Ld:/Compiler/gcc-4.9.3/local330/lib -LC:/PROGRA~1/R/R-33~1.1/bin/x64 -lR
#cd graphm && /usr/bin/make
c:/Rtools/mingw_64/bin/g++ -O2 -Wall -mtune=core2 graphmatch_rcpp.o RcppExports.o ../inst/libgraphm.a -L../inst -lgraphm -LC:/tools/gsl/lib/x64 -lgsl -lgslcblas
graphmatch_rcpp.o: In function `PreserveStorage':
C:/Users/sadali/Documents/R/win-library/3.3/Rcpp/include/Rcpp/storage/PreserveStorage.h:10: undefined reference to `__imp_R_NilValue'
graphmatch_rcpp.o: In function `Vector':
C:/Users/sadali/Documents/R/win-library/3.3/Rcpp/include/Rcpp/vector/Vector.h:58: undefined reference to `Rf_allocVector'
graphmatch_rcpp.o: In function `Rcpp_ReplaceObject':
The answer to this similar (in my eyes) question seems to be inapplicable
Undefined reference errors when including Rcpp.h
as I am using LinkingTo and trying to create an R package
Edit: as the first answer suggested, I have tried building RcppZiggurat with the following Makevars.win :
PKG_CPPFLAGS = -I. -I../inst/include -IC:/tools/gsl/include
## Use the R_HOME indirection to support installations of multiple R version
PKG_LIBS = $(LDFLAGS) -L../inst -L$(LIB_GSL)/lib/x64 $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "RcppGSL:::LdFlags()")
I am getting these errors.
ziggurat.o:ziggurat.cpp:(.text+0x86): undefined reference to `gsl_rng_free'
ziggurat.o:ziggurat.cpp:(.text+0xa6): undefined reference to `gsl_rng_free'
ziggurat.o:ziggurat.cpp:(.text+0xc6): undefined reference to `gsl_rng_free'
ziggurat.o:ziggurat.cpp:(.text+0x1254): undefined reference to `gsl_rng_set'
I was able to get the windows build running successfully using this template for Makevars.win
https://github.com/adalisan/RGraphM/blob/master/src/Makevars.win.gen
and this script creates the Makevars.win
https://github.com/adalisan/RGraphM/blob/master/configure.win
Once the pre-built gsl windows libraries have been put in the directory defined by env. var LIB_GSL, both the compilation and linking steps worked.
One small issue is that the zip file for the pre-built libraries downloaded here include there are two subdirectories for two sub-architectures (i386 and x64)
You should make sure that you link against the right version and that -L"$(LIB_GSL)\lib\$(ARCH)" argument in the linker calls evaluates to the right directory for the sub-arch.
Thanks to the creators of Rcpp and RcppGSL for making the packaging of gsl-based code easier.
You have a misunderstanding of how this works:
The LinkingTo: field of DESCRIPTION does not linking, despite its name. It only helps for header files. Which is why your package compiled but did not link.
You need linker instructions. As has been said before, the mvabund and RcppZiggurat packages both link to the GSL using a tool from RcppGSL.
RcppZiggurat in particular may be a good example to follow as it is small. There is also an entire example package included in RcppGSL -- which we use as reference as well as in unit testing.

How do I linking to a non-standard library when building an R package

I'm trying to build the R openssl package and link it to an openssl library that is a newer version than the one in the systemwide lib64 directory.
The Makevars file simply has:
KG_CPPFLAGS=#cflags#
PKG_LIBS=#libs#
I can specify my local library by passing a custom library path in the configure script. But when I issue R CMD INSTALL, the linking command begins with
gcc -std=gnu99 -shared -L/usr/local/lib64 -o openssl.so [...objects...] -Lmy/path/here -lssl -lcrypto
As a result, the linker finds the wrong library (the one in /usr/local/lib64) instead of mine.
How do I adjust the linking command so that it looks for the library first in my directory, instead of the system folder.
(Background: I don't have root access and this older version of CentOS (5) doesn't support openssl v1, so I built v1 myself just to compile the R package. But I'm stuck at the linking stage due to whatever magic is happening by R CMD INSTALL.)
I solved this by passing arguments to R CMD INSTALL. I.e.:
R CMD INSTALL . --configure-vars="INCLUDE_DIR=$HOME/local/include LIB_DIR=$HOME/local/lib64"
But this varies for each package. There's no general solution.
Instead, read config and src/Makefile.in.

Makevar Settings for R from Homebrew

I install and use home-brew on my mac's and always run into configuration issues with a few packages. The latest being 'jpeg'.
This is primarily due to the packages not searching /usr/local/include and lib. I've bounced around the internet and bit's of R documentation, but I can't find much about the canonical way to set LDFLAGS and CFLAGS for all packages.
So the question is, what is the canonical way to set LDFLAGS and CFLAGS for all packages through Makevar?
My ~/.R/Makevars file currently looks like this:
CC=gcc-4.9
CXX=g++-4.9
R_XTRA_CFLAGS=-std=c99 -I/usr/local/include
LDFLAGS+=-L/usr/local/lib

How to reproduce ERROR seen by CRAN maintainer / how to add .R/Makevars

As part of my PhD project I have completely redesigned an early draft of my R package quantspec. After I uploaded the tar.gz-file I obtained via BUILD, which passed CHECK on my Windows 7 computer, using the webform, I received an email that one of the examples in my package produced an ERROR.
I've tested my package by installing it via
devtools::install_github("tobiaskley/quantspec", ref="develop")
on different computers (> 5) that are using Windows, Linux and MacOS as operating systems, but was unable to reproduce the ERROR reported.
EDIT: It seems to me that I'm missing some important step when building and checking the package. In Section 4.3.6 of Writing R Extensions it says that I should add to ~/.R/Makevars something like (for gfortran)
FCFLAGS = -g -O2 -mtune=native -fbounds-check
FFLAGS = -g -O2 -mtune=native -fbounds-check
How do I do that?
I've finally managed to reproduce the error.
For some reason, on all systems (> 5) I have used to test my package, checking of the array bounds was turned off. It can be switched on by options(CBoundsCheck = TRUE) or via an environment variable R_C_BOUNDS_CHECK=yes.

Resources