3

I asked this question earlier, but am still unable to get it working. I am trying to install custom packages upon starting R. A lot of the code that is written by us right now is available for editing to the users. To try and protect the code, I am packaging the production level code and having the users install it on their machine during start up.

However, when I try to install packages in RProfile.site file, the program goes into a loop and R is constantly launched over and over. I noticed that a lock file for the package is created along with the package in the library folder within R.

Here is the code I have added to the site file:

if(length(grep("customPackage", installed.packages()[,1]))==0) { 
        install.packages("customPackage", repos=NULL, type="source") 
} 

When I try to run this code after starting R (without changing the site file), it installs the package perfectly fine and moves on. However, when I try to do it through the RProfile file, that's when it creates the problems.

Last time I tried resolving this issue (https://stackoverflow.com/questions/10610067/installing-packages-upon-starting-r-session), I thought Justin's suggestion of using the if statement check for packages would fix the problem. But this only seems to solve the problem for packages I install from CRAN and not custom packages.

Any help on this matter would be greatly appreciated!

Andrew Schulman
  • 3,395
  • 1
  • 21
  • 23
abhisarihan
  • 251
  • 3
  • 12

3 Answers3

4

I don't understand why you'd want to do this. Just have them point their .libPaths to the same place. i.e. instead of install.packages(...), just add a line in Rprofile.site that says

.libPaths('/path/to/common/libraries')
require("commonPackage")

Another thing that you might be able to do is make a system call. I don't know much about installing packages under Windows, but on Unix-alike, instead of using install.packages you could do something like this:

system("R --vanilla CMD INSTALL customPackage")

Among other things, the --vanilla flag causes R to be started without using the Rprofile.site file (Your problem is that the Rprofile.site file is being read when R starts, but the Rprofile.site file tells R to install a package which requires starting R, which in turns reads your Rprofile.site file... etc.). Presumably, R --no-site-file INSTALL customPackage would also work.

Edit

After consulting this SO answer, it looks like you could do something like this on Windows (assuming you have installed Rtools), although I haven't tested it.

system("Rcmd --vanilla INSTALL customPackage")
Community
  • 1
  • 1
GSee
  • 48,880
  • 13
  • 125
  • 145
  • I am trying to install these packages on each user's computer, hence there isn't a common place I can install these packages (unless it's on the network drive where I am getting the following error: ERROR: loading failed for 'i386', 'x64'. This happened when I added the .libPaths line and tried installing a package after that.) – abhisarihan Jul 17 '12 at 23:19
  • The `.libPaths` suggestion was to install packages on a network drive instead of on the users' computers. i.e. Whenever you want to update the version of a package that everyone is using, use the `lib` argument of `install.packages` from some non-user computer. Then, when a user starts a new R session, it will pick up the new version of the package. The suggestion for installing the package on each user's computer every time they start R (which is not advisable) was to use `system` and `Rcmd --vanilla INSTALL`. Did you try that? – GSee Jul 17 '12 at 23:39
  • Well, so I tried both, but I tried it with the .libPaths line in the RProfile.site file. Installing directly onto the network drive always caused me to get the ERROR: loading failed for 'i386', 'x64' error. The only workaround I can think of right now is to install the custom packages and update them on my machine and then copy them over to the network drive. I can have everyone's RProfile.site file just point to the network drive and I can maintain the installation on my end. It's not ideal, but it seems to work with the one install I have tried so far. – abhisarihan Jul 18 '12 at 14:28
  • When you install the packages on your machine, use the `lib` argument with the path to your network drive so that they are installed on the network drive. Then in the users' Rprofile, set `.libPaths` to that same directory – GSee Jul 18 '12 at 14:34
  • What's wrong with using the `system` call (aside from the fact that if the answer is `system` you should probably rethink the question)? – GSee Jul 18 '12 at 14:35
  • So that's what I had tried earlier (using the lib argument with the path to the network drive) and installing the package on the network from my machine. That was when I got the error I mentioned above. I believe it might be because I do not have access to the C drive on the network drive. I tried using the system call, but it does not recognize vanilla as a command. Without using vanilla, I was getting the same error trying to install the package on the network. – abhisarihan Jul 18 '12 at 15:07
  • Try `system("R --vanilla CMD INSTALL customPackage")` instead of `Rcmd` – GSee Jul 18 '12 at 15:45
  • Still get the same error. It goes through the install of the package, and then at the end it says: Error: loading failed Execution halted ERROR: loading failed for 'i386', 'x64' – abhisarihan Jul 18 '12 at 15:59
  • Can you install a package from the command line using `R --vanilla CMD INSTALL`? You have to be able to do that before wrapping a `system` call around it inside R will be of any use. – GSee Jul 18 '12 at 16:18
  • That's what I tried doing. That's where I am getting the error. – abhisarihan Jul 18 '12 at 16:41
  • Ha. Then read up on how to install packages under Windows. See the links in my answer. – GSee Jul 18 '12 at 16:42
  • Thanks for all the help man. I'll look through the links some more and see if I can find a more elegant solution. – abhisarihan Jul 18 '12 at 16:54
2

As GSee said, the problem is that install.packages runs R CMD INSTALL, which starts a new R process that reads the Rprofile.site file, resulting in a loop. Two ways to break the evil loop:

  1. Check that R is running interactively:

    if (interactive() && 
        length(grep("customPackage", installed.packages()[,1]))==0) { 
      install.packages("customPackage", repos=NULL, type="source") 
    }
    

    interactive() is FALSE when R CMD is running, so this breaks the loop.

  2. Set the R_PROFILE environment variable to an empty or invalid value, so the R session in R CMD won't run yours. Initialization at Start of an R Session says:

    If you want ‘~/.Renviron’ or ‘~/.Rprofile’ to be ignored by child R processes (such as those run by R CMD check and R CMD build), set the appropriate environment variable R_ENVIRON_USER or R_PROFILE_USER to (if possible, which it is not on Windows) "" or to the name of a non-existent file.

    Adapting that for Rprofile.site, you can set R_PROFILE to an empty or nonexistent file, before you call install.packages. For example:

    if (length(grep("customPackage", installed.packages()[,1]))==0) { 
      Sys.setenv(R_PROFILE = "/dev/null")
      install.packages("customPackage", repos=NULL, type="source") 
      Sys.unsetenv("R_PROFILE")
    }
    

    Then when R restarts to install packages, it reads an empty Rprofile.site file, so again you break the loop .

    If the call to install.packages is in .Rprofile, you can set R_PROFILE_USER in the same way.

The first method is simpler, and doesn't require you to worry about maybe overwriting an existing value of R_PROFILE.

Andrew Schulman
  • 3,395
  • 1
  • 21
  • 23
  • 1
    I had a call to `system("stty size", intern = T)` (then I was setting `options(width=x)` with `x` being the second number returned, to fit R output to terminal size) in my .Rprofile and it was crashing every time I tried to install a package, with a cryptic error. Took me some time to understand that my .Rprofile was called for each package I installed. `if(interactive())` was the best way to go. Thanks! – Vongo Nov 06 '19 at 10:24
  • `interactive()` did not work for me, it was still looping. `R --vanilla CMD INSTALL` did not work, either. Resetting `R_PROFILE_USER` did the trick! – bers Oct 15 '20 at 22:35
0

You can use the function below to install package(s) without reloading .Rprofile:

surround <- function(x, with) {
  paste0(with, x, with)
}

peq <- function(x, y) paste(x, y, sep = " = ")

install.packages.vanilla <- function(pkgs, ...){

  arguments <- as.list(match.call())[-1]

  if(!"repos" %in% names(arguments)){
    arguments$repos <- getOption("repos")
  }
  names_args <- names(arguments)

  installArgs <- purrr::map_chr(seq_along(arguments),
                                function(i){
                                  value <- arguments[[i]]
                                  peq(names_args[i], ifelse(length(value)<2, deparse(value), as.character(list(value))))
                                })
  installArgs <- stringr::str_replace_all(installArgs, "\"", "'")
  installCmd <- paste0("utils::install.packages(",
                       paste(installArgs, collapse = ", "),
                       ")")
  fullCmd <- paste(
    surround(file.path(R.home("bin"), "R"), with = "\""),
    "--vanilla",
    "--slave",
    "-e",
    surround(installCmd, with = "\"")
  )

  system(fullCmd)
  return(invisible())
}
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225