2

Context: trying to efficiently resolve my no visibile binding CMD check problems.

I've tried both flavors of captureOutput:

cmd_output <- R.utils::captureOutput(devtools::check(args="--no-tests"))
cmd_output <- utils::capture.output(devtools::check())

and sink

sink("cmd_output.txt")
devtools::check(args="--no-tests")
sink()
unlink("cmd_output.txt")

to no avail. I end up with the output of devtools::document() when I want the CMD NOTEs and WARNINGs.

Thomas
  • 43,637
  • 12
  • 109
  • 140
Andrew
  • 9,090
  • 8
  • 46
  • 59
  • 2
    This is the same issue as here: https://github.com/hadley/devtools/issues/315. Basically, devtools uses `system`, which doesn't provide a flexible interface for controlling output, so you're probably out of luck. Use a `system2` call to `R CMD check` to get around this, or call the quality control functions in tools directly. – Thomas Jul 08 '15 at 18:18
  • very helpful - thanks -- any chance you could suggest the syntax for calling R CMD check via system2? proving to be very abstract to google. `system2("R", args = c("CMD", "check", "something goes here?"))` – Andrew Jul 08 '15 at 20:53

2 Answers2

6

Here's the non-devtools workflow that I follow for building and checking a package. Note that checks have to be performed on the tarball, not the package directory, so you have to build first. devtools does this invisibly, but you have to make it explicit.

Assume you're in the directory containing the package directory (i.e., one level up from the package directory).

pkg <- "packagename"
version <- read.dcf(paste('.',pkg,'DESCRIPTION',sep='/'))[,'Version']
# build
system2("R", paste0("CMD build ", pkg), stdout = "build.txt", stderr = "build.txt")
# check
system2("R", paste0("CMD check ", pkg, "_", version, ".tar.gz --as-cran"), stdout = "check.txt", stderr = "check.txt")
# install
system2("R", paste0("CMD INSTALL -l ",Sys.getenv('R_HOME'),"/library ", pkg), stdout = "install.txt", stderr = "install.txt")

This will dump the output from each command into its own text file.

You can also specify wait = FALSE to run these in a separate process without holding up your R. That might be useful if your checks take a long time because you can proceed with other work from within R.

Hadley also suggested that if you use check() you could access the check file that is generated automatically by R CMD check, which would be located here:

chk <- check()
# install log
file.path(chk, paste0(as.package(".")$package, ".Rcheck"), "00install.out")
# check log
file.path(chk, paste0(as.package(".")$package, ".Rcheck"), "00check.log")

That may more may not be more convenient.

Thomas
  • 43,637
  • 12
  • 109
  • 140
1

Possibly not useful in all cases but a quick and easy solution is to simply reprex() the output of check():

check_output <- reprex::reprex(devtools::check(), wd = ".")

Note that you can use comment = "" if you don't want outputs prefixed with "#>".

EDIT: I found this solution while trying to address the same problem - efficiently addressing 'no visible binding' warnings. For others looking to do the same thing, here's a function that will pull out a character vector of variables that can be put in a call to globalVariables():

# Helper function to get global variables to specify before running devtools::check()
get_missing_global_variables <- function(wd = getwd()) {
  
  # Run devtools::check() and reprex the results
  check_output <- reprex::reprex(input = sprintf("devtools::check(pkg = '%s', vignettes = FALSE)\n", wd), 
                                 comment = "")
  
  # Get the lines which are notes about missing global variables, extract the variables and 
  # construct a vector as a string
  missing_global_vars <- check_output %>% 
    stringr::str_squish() %>% 
    paste(collapse = " ") %>% 
    stringr::str_extract_all("no visible binding for global variable '[^']+'") %>% 
    `[[`(1) %>% 
    stringr::str_extract("'.+'$") %>%
    stringr::str_remove("^'") %>%
    stringr::str_remove("'$") %>%
    unique() %>%
    sort()
  
  # Get a vector to paste into `globalVariables()`
  to_print <- if (length(missing_global_vars) == 0) {
    "None" 
  } else { 
    missing_global_vars %>% 
      paste0('"', ., '"', collapse = ", \n  ") %>% 
      paste0("c(", ., ")")
  }
  
  # Put the global variables in the console
  cat("Missing global variables:\n", to_print)
  
  # Return the results of the check
  invisible(missing_global_vars)
  
}
wurli
  • 2,314
  • 10
  • 17