Executing R scripts during package installation
Asked Answered
T

1

8

Hopefully this has a straightforward answer, but I haven't been able to find it as yet.

I'm writing an R package, and when installed on Windows I want it to execute a script that searches for a system file i.e. list.files(path = "C:/Program Files/, ...) and then saves that path to the package directory as a text file for later reference.

I tried saving the script as src/install.libs.R but that stopped my package from building.

In case there is an alternative solution, I'm trying to save the path to the javaw.exe file that resides in the Program files directory (somewhere!), so that I can quickly call it in functions via system2().

Transmigrant answered 16/8, 2015 at 12:35 Comment(0)
M
10

There is no hook in R for this: executing code during installation.

There is, however, an entire set of hooks for package load or attachment. I often use .onLoad() for this. See e.g. how RcppGSL remembers what linker and compiler flag to use -- from R/inline.R:

.pkgglobalenv <- new.env(parent=emptyenv())

.onLoad <- function(libname, pkgname) {

    if (.Platform$OS.type=="windows") {
        LIB_GSL <- Sys.getenv("LIB_GSL")
        gsl_cflags <- sprintf( "-I%s/include", LIB_GSL )
        gsl_libs   <- sprintf( "-L%s/lib -lgsl -lgslcblas", LIB_GSL )
    } else {
        gsl_cflags <- system( "gsl-config --cflags" , intern = TRUE )
        gsl_libs   <- system( "gsl-config --libs"   , intern = TRUE )
    }

    assign("gsl_cflags", gsl_cflags, envir=.pkgglobalenv)
    assign("gsl_libs", gsl_libs, envir=.pkgglobalenv)
}

Next in this file are how to use them:

LdFlags <- function(print = TRUE) {
    if (print) cat(.pkgglobalenv$gsl_libs) else .pkgglobalenv$gsl_libs
}

CFlags <- function(print = TRUE) {
    if (print) cat(.pkgglobalenv$gsl_cflags) else .pkgglobalenv$gsl_cflags
}
Machado answered 16/8, 2015 at 12:44 Comment(8)
Do you know if there are plans to fix this? I know of situations where the .onLoad hook cannot make up for the lack of a post-install hook, as far as I know (my package needs to install a command line tool that is not itself part of the package).Crimple
I do not, but I too could make use of hooks during builds (for example to call roxygen(), or Rcpp::compileAttributes() during build) as well as after the build to, say, install r). Not sure if it will ever happen. You have a harder case to make as you insist on circumventing / avoiding the package system for which R Core may not have all that much sympathy...Machado
Yeah, I realise that. ;-)Crimple
At work we ship a few scripts with a few packages, we could use the hook there big time. The best we found is a one-time softlink from /usr/local/bin into the scripts/ directory of the installed package. As the link target gets refreshed, we have to do that just once for each script. This is still a pain, but at least only once per script and machine.Machado
Note that you can run a post-build hook, just put it as the last thing in the last R source file. I.e. something like zzz.R if you are not using Collate in DESCRIPTION, or the last file in Collate if you do. Of course this will not be run (or even included) for binary packages, these are already built. So it is kind of useless.Cobwebby
Not bad. There is also the pre-build hook of configure which can be free-form (for as long as it is mode 0755). And I do acknowledge the "kind of useless" here too ;-)Machado
@DirkEddelbuettel could you add a reference for configure? Having a hard time googling for it ...Felicific
@Felicific Hm, why do you add to a four-year old question? configure is related to autoconf (which that has tutorials, and term googles better). In general, see Writing R Extensions for a start.Machado

© 2022 - 2024 — McMap. All rights reserved.