Skip to content

Instantly share code, notes, and snippets.

@jjallaire
Created November 3, 2012 19:22

Revisions

  1. jjallaire created this gist Nov 3, 2012.
    109 changes: 109 additions & 0 deletions gistfile1.r
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,109 @@

    # Setup the build environment based on the specified dependencies. Returns an
    # opaque object that can be passed to .restoreEnvironment to reverse whatever
    # changes that were made
    .setupBuildEnvironment <- function(depends) {

    # discover dependencies
    buildEnv <- list()
    linkingToPackages <- c("Rcpp")
    for (package in depends) {

    # add a LinkingTo for this package
    linkingToPackages <- unique(c(linkingToPackages, package))

    # see if the package exports a plugin
    plugin <- .getInlinePlugin(package)
    if (!is.null(plugin)) {

    # get the plugin settings
    settings <- plugin()

    # merge environment variables
    pluginEnv <- settings$env
    for (name in names(pluginEnv)) {
    # if it doesn't exist already just set it
    if (is.null(buildEnv[[name]])) {
    buildEnv[[name]] <- pluginEnv[[name]]
    }
    # if it's not identical then append
    else if (!identical(buildEnv[[name]],
    pluginEnv[[name]])) {
    buildEnv[[name]] <- paste(buildEnv[[name]],
    pluginEnv[[name]]);
    }
    else {
    # it already exists and it's the same value, this
    # likely means it's a flag-type variable so we
    # do nothing rather than appending it
    }
    }

    # capture any LinkingTo elements defined by the plugin
    linkingToPackages <- unique(c(linkingToPackages,
    settings$LinkingTo))
    }
    }

    # if there is no buildEnv from a plugin then use the Rcpp plugin
    if (length(buildEnv) == 0) {
    buildEnv <- Rcpp:::inlineCxxPlugin()$env
    } else {
    # we are using a plugin -- confirm that the plugin includes the Rcpp
    # PKG_LIBS and if it doesn't then add them
    pkgLibs <- buildEnv$PKG_LIBS
    rcppLibs <- Rcpp:::RcppLdFlags()
    if (is.null(pkgLibs) || !grepl(rcppLibs, pkgLibs, fixed = TRUE))
    buildEnv$PKG_LIBS <- paste(pkgLibs, rcppLibs)
    }

    # set cxxFlags based on the LinkingTo dependencies (and also respect
    # any PKG_CXXFLAGS set by the plugin)
    pkgCxxFlags <- .buildPkgCxxFlags(linkingToPackages)
    buildEnv$PKG_CXXFLAGS <- paste(buildEnv$PKG_CXXFLAGS, pkgCxxFlags)

    # add cygwin message muffler
    buildEnv$CYGWIN = "nodosfilewarning"

    # create restore list
    restore <- list()
    for (name in names(buildEnv))
    restore[[name]] <- Sys.getenv(name, unset = NA)

    # set environment variables
    do.call(Sys.setenv, buildEnv)

    # return restore list
    return (restore)
    }

    .restoreEnvironment <- function(restore) {
    # variables to reset
    setVars <- restore[!is.na(restore)]
    if (length(setVars))
    do.call(Sys.setenv, setVars)

    # variables to remove
    removeVars <- names(restore[is.na(restore)])
    if (length(removeVars))
    Sys.unsetenv(removeVars)
    }


    # Get the inline plugin for the specified package (return NULL if none found)
    .getInlinePlugin <- function(package) {
    tryCatch(get("inlineCxxPlugin", asNamespace(package)),
    error = function(e) NULL)
    }

    # Build PKG_CXXFLAGS by from include directories of LinkingTo packages
    .buildPkgCxxFlags <- function(linkingToPackages) {
    pkgCxxFlags <- NULL
    for (package in linkingToPackages) {
    packagePath <- find.package(package, NULL, quiet=TRUE)
    pkgCxxFlags <- paste(pkgCxxFlags,
    paste0('-I"', packagePath, '/include"'),
    collapse=" ")
    }
    return (pkgCxxFlags)
    }