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().

Jordan Mackie
  • 1,193
  • 10
  • 17

1 Answers1

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
}
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • 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). – Konrad Rudolph Aug 16 '15 at 12:48
  • 1
    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... – Dirk Eddelbuettel Aug 16 '15 at 12:54
  • 1
    Yeah, I realise that. ;-) – Konrad Rudolph Aug 16 '15 at 12:58
  • 1
    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. – Dirk Eddelbuettel Aug 16 '15 at 12:59
  • 2
    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. – Gabor Csardi Aug 16 '15 at 22:59
  • 1
    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 ;-) – Dirk Eddelbuettel Aug 16 '15 at 23:22
  • @DirkEddelbuettel could you add a reference for `configure`? Having a hard time googling for it ... – maxheld Oct 29 '19 at 21:28
  • 1
    @maxheld 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. – Dirk Eddelbuettel Oct 29 '19 at 21:36