Skip to content

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

Closed
@richfitz

Description

@richfitz

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions