Skip to content

Commit

Permalink
R CMD check optionally reports on non-use of registration of native s…
Browse files Browse the repository at this point in the history
…ymbols

git-svn-id: https://svn.r-project.org/R/trunk@71981 00db46b3-68df-0310-9c12-caf00c1e9a41
  • Loading branch information
ripley committed Jan 16, 2017
1 parent 7785d1a commit 2f9cf02
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 9 deletions.
5 changes: 5 additions & 0 deletions doc/manual/R-ints.texi
Original file line number Diff line number Diff line change
Expand Up @@ -4100,6 +4100,11 @@ Default: false (but true for CRAN submission checks).
Number of trailing lines of test output to reproduce in the log. If
@code{0} all lines except the @R{} preamble are reproduced.
Default: 13.

@item _R_CHECK_SYMBOL_REGISTRATION_
If set to a true value, report if the entry points to register symbols
and suppress dynamic search are not found in a DLL.
Default: false (but true for CRAN submission checks).
@end vtable

CRAN's submission checks use something like
Expand Down
4 changes: 3 additions & 1 deletion src/library/tools/NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export("check_packages_in_dir",
export("CRAN_package_db",
"CRAN_check_results",
"CRAN_check_details",
"CRAN_memtest_notes",
"CRAN_memtest_notes",
"summarize_CRAN_check_status")

export(".print.via.format")
Expand Down Expand Up @@ -79,6 +79,7 @@ S3method("format", "check_package_license")
S3method("format", "check_packages_used")
S3method("format", "check_so_symbols")
S3method("format", "check_nonAPI_calls")
S3method("format", "check_RegSym_calls")
S3method("format", "check_url_db")
S3method("format", "checkDocFiles")
S3method("format", "checkDocStyle")
Expand Down Expand Up @@ -169,6 +170,7 @@ S3method("print", "check_packages_used", .print.via.format)
S3method("print", "check_po_files")
S3method("print", "check_so_symbols", .print.via.format)
S3method("print", "check_nonAPI_calls", .print.via.format)
S3method("print", "check_RegSym_calls", .print.via.format)
S3method("print", "check_url_db")
S3method("print", "check_vignette_index")

Expand Down
5 changes: 5 additions & 0 deletions src/library/tools/R/check.R
Original file line number Diff line number Diff line change
Expand Up @@ -2452,6 +2452,7 @@ setRlibs <-
else noteLog(Log)
printLog0(Log, paste(c(out, ""), collapse = "\n"))
nAPIs <- length(grep("Found non-API", out))
nRS <- length(grep("Found no call", out))
nBad <- length(grep(", possibly from ", out))
msg <- if (nBad) {
if(haveObjs)
Expand All @@ -2469,6 +2470,9 @@ setRlibs <-
if(nAPIs)
msg <- c(msg,
"Compiled code should not call non-API entry points in R.\n")
if(nRS)
msg <- c(msg,
"It is good practice to use registered native symbols and to disable symbol search.\n")
wrapLog("\n", paste(msg, collapse = " "), "\n",
"See 'Writing portable packages'",
"in the 'Writing R Extensions' manual.\n")
Expand Down Expand Up @@ -4725,6 +4729,7 @@ setRlibs <-
Sys.setenv("_R_CHECK_S3_METHODS_NOT_REGISTERED_" = "TRUE")
Sys.setenv("_R_CHECK_PACKAGE_DATASETS_SUPPRESS_NOTES_" = "TRUE")
Sys.setenv("_R_CHECK_PACKAGES_USED_IGNORE_UNUSED_IMPORTS_" = "TRUE")
Sys.setenv("_R_CHECK_SYMBOL_REGISTRATION_" = "TRUE")
R_check_vc_dirs <- TRUE
R_check_executables_exclusions <- FALSE
R_check_doc_sizes2 <- TRUE
Expand Down
70 changes: 62 additions & 8 deletions src/library/tools/R/sotools.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# File src/library/tools/R/sotools.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 2011-2015 The R Core Team
# Copyright (C) 2011-2017 The R Core Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -390,6 +390,9 @@ check_so_symbols <- if(.Platform$OS.type == "windows") {
tab2 <- setdiff(tab2, c("R_InputHandlers", "addInputHandler",
"removeInputHandler"))
if(length(tab2)) attr(tab, "nonAPI") <- tab2
tab2b <- setdiff(c("R_registerRoutines", "R_useDynamicSymbols"),
sub("^_", "", nms))
if(length(tab2b)) attr(tab, "RegSym") <- tab2b
class(tab) <- "check_so_symbols"
tab
}
Expand All @@ -407,11 +410,16 @@ check_so_symbols <- if(.Platform$OS.type == "windows") {
tab <- so_symbol_names_table[ind, , drop = FALSE]
attr(tab, "file") <- so
tab2 <- sub("^_", "", tab2)
tab2 <- intersect(tab2, nonAPI)
if ("removeInputHandler" %in% tab2)
tab2 <- setdiff(tab2, c("R_InputHandlers", "addInputHandler",

tab2a <- intersect(tab2, nonAPI)
if ("removeInputHandler" %in% tab2a)
tab2a <- setdiff(tab2a, c("R_InputHandlers", "addInputHandler",
"removeInputHandler"))
if(length(tab2)) attr(tab, "nonAPI") <- tab2
if(length(tab2a)) attr(tab, "nonAPI") <- tab2a

tab2b <- setdiff(c("R_registerRoutines", "R_useDynamicSymbols"), tab2)
if(length(tab2b)) attr(tab, "RegSym") <- tab2b

class(tab) <- "check_so_symbols"
tab
}
Expand Down Expand Up @@ -456,6 +464,7 @@ if(.Platform$OS.type == "windows") {

r_arch <- .Platform$r_arch
useST <- config_val_to_logical(Sys.getenv("_R_SHLIB_BUILD_OBJECTS_SYMBOL_TABLES_", "FALSE"))
useSR <- config_val_to_logical(Sys.getenv("_R_CHECK_SYMBOL_REGISTRATION_", "FALSE"))

compare <- function(x, strip_ = FALSE) {
## Compare symbols in the DLL and in objects:
Expand Down Expand Up @@ -505,9 +514,19 @@ if(.Platform$OS.type == "windows") {
.file_path_relative_to_dir(attr(x, "file"),
dir, TRUE),
class = "check_nonAPI_calls"))

bad <- c(bad, Filter(length, nAPIs))

if (useSR) {
nRS <- lapply(lapply(so_files, check_so_symbols, rarch = "i386"),
function(x) if(length(z <- attr(x, "RegSym")))
structure(z,
file =
.file_path_relative_to_dir(attr(x, "file"),
dir, TRUE),
class = "check_RegSym_calls"))
bad <- c(bad, Filter(length, nRS))
}

so_files <-
Sys.glob(file.path(dir, "libs/x64",
sprintf("*%s", .Platform$dynlib.ext)))
Expand All @@ -531,9 +550,19 @@ if(.Platform$OS.type == "windows") {
.file_path_relative_to_dir(attr(x, "file"),
dir, TRUE),
class = "check_nonAPI_calls"))

bad2 <- c(bad2, Filter(length, nAPIs))

if (useSR) {
nRS <- lapply(lapply(so_files, check_so_symbols, rarch = "x64"),
function(x) if(length(z <- attr(x, "RegSym")))
structure(z,
file =
.file_path_relative_to_dir(attr(x, "file"),
dir, TRUE),
class = "check_RegSym_calls"))
bad <- c(bad, Filter(length, nRS))
}

if(!length(bad) && !length(bad2)) return(invisible(NULL))

bad <- if(length(bad) && length(bad2)) rbind(bad, bad2)
Expand All @@ -548,6 +577,7 @@ if(.Platform$OS.type == "windows") {

r_arch <- .Platform$r_arch
useST <- config_val_to_logical(Sys.getenv("_R_SHLIB_BUILD_OBJECTS_SYMBOL_TABLES_", "FALSE"))
useSR <- config_val_to_logical(Sys.getenv("_R_CHECK_SYMBOL_REGISTRATION_", "FALSE"))

compare <- function(x) {
## Compare symbols in the so and in objects:
Expand Down Expand Up @@ -596,8 +626,18 @@ if(.Platform$OS.type == "windows") {
.file_path_relative_to_dir(attr(x, "file"),
dir, TRUE),
class = "check_nonAPI_calls"))

bad <- c(bad, Filter(length, nAPIs))

if (useSR) {
nRS <- lapply(lapply(so_files, check_so_symbols),
function(x) if(length(z <- attr(x, "RegSym")))
structure(z,
file =
.file_path_relative_to_dir(attr(x, "file"),
dir, TRUE),
class = "check_RegSym_calls"))
bad <- c(bad, Filter(length, nRS))
}
class(bad) <- "check_compiled_code"
bad
}
Expand Down Expand Up @@ -626,6 +666,20 @@ function(x, ...)
else character()
}

format.check_RegSym_calls <-
function(x, ...)
{
if(length(x))
c(gettextf("File %s:", sQuote(attr(x, "file"))),
if (length(x) > 1L) {
strwrap(paste("Found no calls to:",
paste(sQuote(x), collapse = ", ")),
indent = 2L, exdent = 4L)
} else paste(" Found no call to:", sQuote(x))
)
else character()
}

.shlib_objects_symbol_tables <-
function(file = "symbols.rds")
{
Expand Down

0 comments on commit 2f9cf02

Please sign in to comment.