4

I am building an R package whose description contains:

LinkingTo: Rcpp

The package has a fairly deep makefile structure. I know using R CMD build . creates and modifies variables such as CXX11FLAGS which must be passed down through subsequent layers of makefiles.

I suspect that LinkingTo also produces such a variable, which I must be aware of and pass along. I suspect this because, several layers down, I hit the error:

mycode.hpp:5:10: fatal error: Rcpp.h: No such file or directory
#include <Rcpp.h>

I'm not sure how to inform this file's makefile as to where Rcpp is. I suspect the hypothesized variable could be used, but I do not know that variable's name. Can anyone clarify?

Richard
  • 56,349
  • 34
  • 180
  • 251
  • See Writing R Extensions, and delete the question. It "just" sets the -I flag so that headers are found. Rebuild any odd (small) package using Rcpp and RcppArmadillo to verify. – Dirk Eddelbuettel Aug 04 '17 at 18:19
  • Also, before asking a _second_ question it would seem polite to offer feedback on an answer for a question you asked less than hour ago. – Dirk Eddelbuettel Aug 04 '17 at 18:19
  • @DirkEddelbuettel: I'd read the document prior to asking the question and didn't find answers. The process of "Setting the '-I' flag" must involve, I think, storing said set-I-flag in a variable which is passed around. It is unclear what this variable is. – Richard Aug 04 '17 at 18:49
  • @DirkEddelbuettel: This question is on a different topic from the first and I am addressing both as I am able. – Richard Aug 04 '17 at 18:49
  • "must involve, I think, storing said set-I-flag in a variable which is passed around" is just wrong. – Dirk Eddelbuettel Aug 04 '17 at 18:54
  • @DirkEddelbuettel: All the files are compiled with directives that appear as, e.g., `$(CXX) -c $< $(CXXFLAGS) $(INCDIRS)`. These variables are set by R at some point in the compilation process. If R wanted to pass an `-I` flag you speak of it must be either through this process or via an environmental variable. If there's another method, I'd be interested to hear about it. – Richard Aug 04 '17 at 18:59
  • I am really put off by your tone and attitude. Why don't you download anyone of my packages, say 'anytime' (on CRAN) which using Rcp, BH (headers only), RApiDatetime (export C function) to see where the -I comes from? Or look at RcppKalman (GitHub only) which uses Rcpp and RcppArmadillo via LinkingTo. No env.var. Just LinkingTo as I have tried to explain to you via way too many messages already. – Dirk Eddelbuettel Aug 04 '17 at 19:49
  • @DirkEddelbuettel: I think you have a simpler build process in mind than what I would like to use and that you've have structured your answers around that. [Elsewhere](https://stackoverflow.com/a/18594574/752843) you seem less dogmatic. Your insistence on it did cause me to put all the files in `src/` and this simplified the build. It was beautiful. However, it also eliminated all the structure of my project by blending together included libraries that would have been better left in subdirectories. This seems like poor code management and I'm disappointed that R implicitly encourages it. – Richard Aug 17 '17 at 01:23
  • Whatever bro. If you know it all better, by all means go for it. All I am offering it is some commentary on how R works based on the mere twenty years I have been making things work with it. – Dirk Eddelbuettel Aug 17 '17 at 01:44

2 Answers2

6

Here is LinkingTo: from a smaller in-progress package of mine:

LinkingTo: Rcpp, RcppArmadillo

When compiling, these two packages are both uses via -I... switches:

edd@bud:~/git/rcppkalman(master)$ ./cleanup 
edd@bud:~/git/rcppkalman(master)$ R CMD INSTALL .
* installing to library ‘/usr/local/lib/R/site-library’
* installing *source* package ‘RcppKalman’ ...
** libs
ccache g++ -I/usr/share/R/include -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/RcppArmadillo/include"    -fpic  -g -O3 -Wall -pipe -Wno-unused -pedantic -Werror -march=native -c RcppExports.cpp -o RcppExports.o
ccache g++ -I/usr/share/R/include -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/RcppArmadillo/include"    -fpic  -g -O3 -Wall -pipe -Wno-unused -pedantic -Werror -march=native -c expmMat.cpp -o expmMat.o
ccache g++ -I/usr/share/R/include -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/RcppArmadillo/include"    -fpic  -g -O3 -Wall -pipe -Wno-unused -pedantic -Werror -march=native -c kfpredict.cpp -o kfpredict.o
ccache g++ -I/usr/share/R/include -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/RcppArmadillo/include"    -fpic  -g -O3 -Wall -pipe -Wno-unused -pedantic -Werror -march=native -c kfupdate.cpp -o kfupdate.o
ccache g++ -I/usr/share/R/include -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/RcppArmadillo/include"    -fpic  -g -O3 -Wall -pipe -Wno-unused -pedantic -Werror -march=native -c ltidisc.cpp -o ltidisc.o
ccache g++ -I/usr/share/R/include -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/RcppArmadillo/include"    -fpic  -g -O3 -Wall -pipe -Wno-unused -pedantic -Werror -march=native -c rtssmooth.cpp -o rtssmooth.o
ccache g++ -I/usr/share/R/include -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/RcppArmadillo/include"    -fpic  -g -O3 -Wall -pipe -Wno-unused -pedantic -Werror -march=native -c tfsmooth.cpp -o tfsmooth.o
g++ -Wl,-S -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o RcppKalman.so RcppExports.o expmMat.o kfpredict.o kfupdate.o ltidisc.o rtssmooth.o tfsmooth.o -llapack -lblas -lgfortran -lm -lquadmath -L/usr/lib/R/lib -lR
installing to /usr/local/lib/R/site-library/RcppKalman/libs
** R
** demo
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
* DONE (RcppKalman)
edd@bud:~/git/rcppkalman(master)$ 

There is nothing else needed. Writing R Extensions says:

A package that wishes to make use of header files in other packages needs to declare them as a comma-separated list in the field 'LinkingTo' in the 'DESCRIPTION' file. For example

 LinkingTo: link1, link2

The 'LinkingTo' field can have a version requirement which is checked at installation.

Specifying a package in 'LinkingTo' suffices if these are C++ headers containing source code or static linking is done at installation: the packages do not need to be (and usually should not be) listed in the 'Depends' or 'Imports' fields. This includes CRAN package BH (https://CRAN.R-project.org/package=BH) and almost all users of RcppArmadillo (https://CRAN.R-project.org/package=RcppArmadillo) and RcppEigen (https://CRAN.R-project.org/package=RcppEigen).

For another use of 'LinkingTo' see *note Linking to native routines in other packages::.

and that is on point as can be seen from the (essentially empty) src/Makevars:

PKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)

which is the standard uses by RcppArmadillo to support the external linking for LAPACK and BLAS. Note that my package is a little behind as RcppArmadillo in its most recent release now uses this inst/skeleton/Makevars passes into every package created via RcppArmadillo.package.skeleton():

## optional
#CXX_STD = CXX11

PKG_CXXFLAGS = $(SHLIB_OPENMP_CXXFLAGS) 
PKG_LIBS = $(SHLIB_OPENMP_CFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)

to also support OpenMP where available. That is the current recommended form.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
0

I edited my Makefile to include the following dark magic:

VARS_OLD := $(.VARIABLES)
$(foreach v,                                        \
$(filter-out $(VARS_OLD) VARS_OLD,$(.VARIABLES)),   \
$(info $(v) = $($(v))))

This prints out all of the environmental variables passed to the make process by R when you run R CMD build ..

Digging in this revealed some very interesting variables:

ALL_CPPFLAGS = -I/usr/share/R/include -DNDEBUG  -I"/home/myuser/.R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include" 
CLINK_CPPFLAGS = -I"/home/myuser/.R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include"
R_INCLUDE_DIR = /usr/share/R/include

Note that these variables contain the -I flag and, thus, must be communicated to any part of the build process that relies on those.

By passing these between makefiles I was able to achieve compilation.

Richard
  • 56,349
  • 34
  • 180
  • 251