Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid R code causes invalid registration interface, and cryptic error on compilation #134

Closed
richfitz opened this issue Dec 8, 2020 · 1 comment

Comments

@richfitz
Copy link
Contributor

richfitz commented Dec 8, 2020

If the package that is the target of cpp_register contains invalid R code, then the failure of tools::package_native_routine_registration_skeleton leaves the package in an unloadable state with no indication of the underlying problem:

Reprex:

path <- tempfile()
dir.create(path)
dir.create(file.path(path, "src"))
dir.create(file.path(path, "R"))
writeLines(c("Package: pkg", "Version: 0.1.0", "LinkingTo: cpp11"),
           file.path(path, "DESCRIPTION"))
writeLines("useDynLib(pkg, .registration = TRUE)",
           file.path(path, "NAMESPACE"))
writeLines(c("[[cpp11::register]]",
             "double add(double a, double b) {",
             "  return a + b;",
             "}"),
           file.path(path, "src", "code.cpp"))
## Any syntactically incorrect R:
writeLines("f <- function(x", file.path(path, "R", "code.R"))
cpp11::cpp_register(path)
pkgload::load_all(path)

which gives the error:

Loading pkg
ℹ 1 functions decorated with [[cpp11::register]]
✔ generated file cpp11.R
✔ generated file cpp11.cpp
Re-compiling pkg
─  installing *source* package ‘pkg’ ...
   ** using staged installation
   ** libs
   g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG  -I'/home/rich/lib/R/library/cpp11/include' -g -Wall -Wextra -pedantic -Wmaybe-uninitialized -Wno-unused-parameter -Wno-unused-variable -O2   -fpic  -g -O2 -fdebug-prefix-map=/build/r-base-7BvS0x/r-base-4.0.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c code.cpp -o code.o
   code.cpp:2:30: warning: ‘cpp11::register’ scoped attribute directive ignored [-Wattributes]
    double add(double a, double b) {
                                 ^
   g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG  -I'/home/rich/lib/R/library/cpp11/include' -g -Wall -Wextra -pedantic -Wmaybe-uninitialized -Wno-unused-parameter -Wno-unused-variable -O2   -fpic  -g -O2 -fdebug-prefix-map=/build/r-base-7BvS0x/r-base-4.0.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c cpp11.cpp -o cpp11.o
   cpp11.cpp: In function ‘void R_init_pkg(DllInfo*)’:
   cpp11.cpp:20:33: error: ‘CallEntries’ was not declared in this scope
      R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
                                    ^~~~~~~~~~~
   /usr/lib/R/etc/Makeconf:181: recipe for target 'cpp11.o' failed
   make: *** [cpp11.o] Error 1
   ERROR: compilation failed for package ‘pkg’
─  removing ‘/tmp/RtmpWQKwSR/devtools_install_6916495ebf34/pkg’
Error in (function (command = NULL, args = character(), error_on_status = TRUE,  : 
  System command 'R' failed, exit status: 1, stdout + stderr (last 10 lines):
E>                               ^
E> g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG  -I'/home/rich/lib/R/library/cpp11/include' -g -Wall -Wextra -pedantic -Wmaybe-uninitialized -Wno-unused-parameter -Wno-unused-variable -O2   -fpic  -g -O2 -fdebug-prefix-map=/build/r-base-7BvS0x/r-base-4.0.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c cpp11.cpp -o cpp11.o
E> cpp11.cpp: In function ‘void R_init_pkg(DllInfo*)’:
E> cpp11.cpp:20:33: error: ‘CallEntries’ was not declared in this scope
E>    R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
E>                                  ^~~~~~~~~~~
E> /usr/lib/R/etc/Makeconf:181: recipe for target 'cpp11.o' failed
E> make: *** [cpp11.o] Error 1
E> ERROR: compilation failed for package ‘pkg’
E> * removing ‘/tmp/RtmpWQKwSR/devtools_insta
[...]
Type .Last.error.trace to see where the

The issue seems to stem fro get_call_entries wrapping tools::package_native_routine_registration_skeleton in a silent try:

  try(
    tools::package_native_routine_registration_skeleton(path,
      con,
      character_only = FALSE,
      include_declarations = TRUE
    ),
    silent = TRUE
  )

without which the underlying error would have been revealed:

Error in parse(file, keep.source = keep.source) : 
  /tmp/RtmpAK7co3/file699a2cbec253/R/code.R:2:0: unexpected end of input
1: f <- function(x
   ^

We've seen this a couple of times in the wild and it's a head-scratcher each time.

@jimhester
Copy link
Member

I have ran into this as well, perhaps we can just remove the try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants