I’m migrating this from a StackOverflow discussion, because I think it will be easier to have a discussion of what’s happening here. The issue is a package that has compiled code from both representations of Stan models and Rcpp functions. A minimally reproducible example can be found in my rcppstan repository. After adding infrastructure from the rstantools package to support Stan models, I get this error from devtools::check()
:
#> ❯ checking R code for possible problems ... NOTE
#> meanC: no visible binding for global variable ‘_rcppstan_meanC’
#> Undefined global functions or variables:
#> _rcppstan_meanC
And indeed, when I try to call the R function that uses the meanC
function, I get an error saying Error in meanC(x) : object '_rcppstan_meanC' not found
.
From what I can tell, here is what is changing when I modify the package to work with rstan, and thus the likely cause.
-
When only using Rcpp, the following is in the
src/RcppExports.cpp
:static const R_CallMethodDef CallEntries[] = { {"_rcpptest_timesTwo", (DL_FUNC) &_rcpptest_timesTwo, 1}, {NULL, NULL, 0} }; RcppExport void R_init_rcpptest(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); }
-
When Stan is incorporated, that code is no longer generated in the
src/RcppExports.cpp
file. Instead, it appears that this is being handles by thesrc/init.cpp
file created by the rstantools package. The relevant chunk from that file is here:static const R_CallMethodDef CallEntries[] = { {NULL, NULL, 0} }; void attribute_visible R_init_rcppstan(DllInfo *dll) { // next line is necessary to avoid a NOTE from R CMD check R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, TRUE); // necessary for .onLoad() to work }
@bgoodri has been very helpful on the StackOverflow question, and suggested I remove src/init.cpp
. However, this caused a new error:
make: *** No rule to make target 'init.o', needed by 'rcppstan.so'. Stop.
rm stan_files/uni_irt.cc
ERROR: compilation failed for package 'rcppstan'
@bgoodri further suggested changing the line in src/Makevars{.win}
from:
OBJECTS = $(SOURCES:.stan=.o) init.o
to just
OBJECTS = $(SOURCES:.stan=.o)
This solved the compilation problem, but has possibly added more confusion. Following these edits, this code now appears in src/RcppExports.cpp
as expected:
static const R_CallMethodDef CallEntries[] = {
{"_rcppstan_meanC", (DL_FUNC) &_rcppstan_meanC, 1},
{NULL, NULL, 0}
};
RcppExport void R_init_rcppstan(DllInfo *dll) {
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);
}
However, I now get new errors in devtools::check()
:
#> ❯ checking R code for possible problems ... NOTE
#> meanC: no visible binding for global variable ‘_rcppstan_meanC’
#> Undefined global functions or variables:
#> _rcppstan_meanC
#>
#> ❯ checking compiled code ... NOTE
#> File ‘rcppstan/libs/rcppstan.so’:
#> Found no calls to: ‘R_registerRoutines’, ‘R_useDynamicSymbols’
#>
#> It is good practice to register native routines and to disable symbol
#> search.
#>
#> See ‘Writing portable packages’ in the ‘Writing R Extensions’ manual.
It appears that even though the registration is happening in src/RcppExports.cpp
, it is for some reason not being recognized when the package builds/installs. The updated repo with all of these change is here: rcppstan. Any help would be greatly appreciated! Thanks!