R/prepare_package.R

Defines functions prepare_package

Documented in prepare_package

##' Prepare Package
##' 
##' This function prepares the package such that all the C / C++ source files
##' are concatenated into one file (for each source). This decreases
##' compilation time, and produces a tarball that can be used for submission
##' to CRAN.
##' 
##' @param build Build the package with \code{R CMD build}?
##' @param check Check the package with \code{R CMD check}?
##' @param install Install the package with \code{R CMD INSTALL}? Only
##'   done if \code{build} is \code{TRUE} as well.
##' @param copy.tarball If \code{build && copy.tarball}, we copy the tarball
##'   generated by \code{R CMD build} to the \code{"dist"} folder.
prepare_package <- function(build=TRUE, check=TRUE, install=FALSE, copy.tarball=TRUE) {
  
  owd <- getwd()
  on.exit( setwd(owd) )
  
  cat("Copying files to build directory...\n")
  ## check for necessary package files
  files <- list.files()
  
  stopifnot("DESCRIPTION" %in% files)
  
  ## get the package name from the DESCRIPTION file
  DESCRIPTION <- as.list( read.dcf("DESCRIPTION")[1, ] )
  pkg_name <- DESCRIPTION$Package
  pkg_version <- DESCRIPTION$Version
  
  ## copy the files to a 'build' directory
  buildDir <- file.path( tempdir(), pkg_name )
  if( file.exists(buildDir) ) {
    unlink(shQuote(buildDir), recursive=TRUE)
  }
  dir.create(buildDir, showWarnings=FALSE)
  system( paste("cp -r .", buildDir) )
  
  ## in the build directory, 'cat' all the src files together
  ## have a separate file for .c, .cpp files
  src_files <- list.files( full.names=TRUE, paste( sep='',
    buildDir, "/src"
  ) )
  
  ## but don't concatenate init.c; copy it separately
  src_files <- grep("init.c", src_files, value=TRUE, fixed=TRUE, invert=TRUE)
  
  ## regex: the regex to match for picking up files
  ## ext: the file extension to use on the outputted file
  concatenate_src <- function(regex, ext) {
    files <- grep( regex, src_files, value=TRUE )
    final <- paste( sep='', buildDir, "/src/", pkg_name, "_", gsub("\\.", "", ext), ext )
    system( paste("touch", final) )
    files <- files[ files != final ]
    files <- files[ !(files %in% grep("RcppExports", files, value=TRUE)) ]
    for( file in files ) {
      system( paste("cat", shQuote(file), ">>", shQuote(final)) )
      system( paste("echo '' >>", shQuote(final) ) ) ## adds a newline just in case
      system( paste("rm", file) )
    }
  }
  
  cat("Concatenating source files...\n")
  concatenate_src("c$", ".c")
  concatenate_src("cpp$", ".cpp")
  
  ## remove all the .o, .so, .dll files
  for( file in grep("o$|so$|dll$", list.files( full.names=TRUE, file.path( buildDir, "src" ) ), value=TRUE ) ) {
    file.remove(file)
  }
  
  setwd( normalizePath( file.path( buildDir, "../" ) ) )
  
  if (build) {
    cat("Building...\n\n")
    system( paste("R CMD build", gsub(".*/", "", buildDir)) )
    cat("Copying package tarball to 'dist' directory...\n")
    rx <- paste0("^", pkg_name, "_", pkg_version)
    pkg <- grep(rx, list.files(), value=TRUE)
    to <- file.path(owd, "dist", pkg)
    file.copy(pkg, to, overwrite=TRUE)
    cat("Done!\n\n")
  }
  
  ## check the package
  if (check) {
    cat("Running R CMD check...\n\n")
    system( paste("R CMD check --as-cran", paste(sep='', pkg_name, "_", pkg_version, ".tar.gz")))
    unlink( paste0(pkg_name, ".Rcheck"), recursive=TRUE )
  }
  
  ## install the package
  if (build && install) {
    cat("Installing package...\n\n")
    system( paste("R CMD INSTALL --preclean --no-multiarch", paste(sep='', pkg_name, "_", pkg_version, ".tar.gz")))
    cat("Done!\n")
  }
  
  ## remove the build dir
  if (build) {
    unlink(buildDir, recursive=TRUE)
    unlink( paste0(pkg_name, "_", pkg_version, ".tar.gz") )
  }
  
}

Try the Kmisc package in your browser

Any scripts or data that you put into this service are public.

Kmisc documentation built on May 29, 2017, 1:43 p.m.