It's not uncommon for utilities (in R or other languages/tools) to be able to deal with simple file paths and schema-based URLs (e.g., https://...
or file:///...
), I think the number of tools that equally deal with Windows' UNC paths (i.e., \serversharepath
) is much less. While I believe that R is doing it just fine for finding the files (otherwise you'd have other problems by having your only two .libPaths()
be UNC shares), the underlying tools (including gcc
) might not.
I think the way-forward is to install the new package(s) into a directory that is not a network share. I also think this can be a temporary location, where the packages, once installed, can be moved/migrated over to the network share.
Below is a function that simplifies creation of a temporary directory, install to that directory, then move to the network share. (It doesn't actually check if the tgt
directory is a network share, the assumption is that you would not need to use this is your first library path is local.)
#' Install a package(s) using a temp-local directory
#'
#' On Windows, if '.libPaths()' starts with a UNC network share,
#' package compilation might not work correctly. This function creates
#' a temporary local directory, executes the desired code in 'expr',
#' and moves any new packages into the normal first library path.
#'
#' @param expr expression such as 'install.packages("car")' or
#' 'devtools::install_github(...)'; the expression must natively
#' install into the first of '.libPaths()', but if you try something
#' like 'install.packages(.., lib="some/other/path"), then the
#' temporary libpath will not be used (and may fail)
#' @param tgt character, the directory to move the isntalled
#' package(s)
#' @param cleanup logical, whether to remove the temporary libpath
#' @return nothing
with_local_libpath <- function(expr, tgt = .libPaths()[1], cleanup = TRUE) {
if (length(tgt) > 1) {
warning("'tgt' must be length 1")
tgt <- tgt[[1]]
}
if (length(tgt) < 1 || !dir.exists(tgt)) {
stop("'tgt' must be length 1 and an existing directory")
}
dir.create(tmplib <- tempfile(pattern = "local_libpath_"))
message("Local (temp) libpath: ", sQuote(tmplib))
oldlib <- .libPaths()
.libPaths(c(tmplib, oldlib))
on.exit(.libPaths(oldlib), add = TRUE)
force(expr)
newstuff <- list.files(tmplib, full.names = TRUE)
if (length(newstuff)) {
newdirs <- file.path(oldlib[1], basename(newstuff))
message("New packages found: ", paste(sQuote(basename(newstuff)), collapse = ", "))
message("Moving to: ", sQuote(tgt))
file.copy(newstuff, tgt, recursive = TRUE)
if (cleanup) {
message("Cleaning up")
unlink(tmplib, recursive = TRUE)
}
} else {
message("No new packages found (?)")
}
invisible()
}
I tested this with some simple examples, but not extensively, so caveat emptor. I don't have a network-mounted lib-path, so I'll force one (to a server I maintain):
.libPaths(c("\\myserver/r2evans/R/win.library/3.5", .libPaths()))
Failing installation:
remotes::install_github("gaborcsardi/notifier@d92b1b6")
# Downloading GitHub repo gaborcsardi/notifier@d92b1b6
# v checking for file 'C:Users
2AppDataLocalTempRtmpWgKbkW
emotes43cc57193c83gaborcsardi-notifier-d92b1b6/DESCRIPTION' (377ms)
# - preparing 'notifier':
# v checking DESCRIPTION meta-information
# - checking for LF line-endings in source and make files and shell scripts
# - checking for empty or unneeded directories
# - building 'notifier_1.0.0.tar.gz'
#
# Installing package into '\myserver/r2evans/R/win.library/3.5'
# (as 'lib' is unspecified)
# * installing *source* package 'notifier' ...
# ** R
# ** inst
# Error in file.create(to[okay]) :
# (converted from warning) cannot create file 'myserver/r2evans/R/win.library/3.5/notifier/R.ico', reason 'No such file or directory'
# * removing '\myserver/r2evans/R/win.library/3.5/notifier'
# In R CMD INSTALL
# Error: Failed to install 'notifier' from GitHub:
# (converted from warning) installation of package 'C:/Users/r2/AppData/Local/Temp/RtmpWgKbkW/file43cc60c05cc/notifier_1.0.0.tar.gz' had non-zero exit status
(I chose a specific version because of https://github.com/gaborcsardi/notifier/issues/22. While the error is different than your error, I suspect that the failure is for a similar/related reason.)
Successful installation:
with_local_libpath(remotes::install_github("gaborcsardi/notifier@d92b1b6"))
# Local (temp) libpath: 'C:Users
2AppDataLocalTempRtmpWgKbkWlocal_libpath_43ccbf98e2'
# Downloading GitHub repo gaborcsardi/notifier@d92b1b6
# v checking for file 'C:Users
2AppDataLocalTempRtmpWgKbkW
emotes43cc7cb66d1fgaborcsardi-notifier-d92b1b6/DESCRIPTION' (396ms)
# - preparing 'notifier':
# v checking DESCRIPTION meta-information
# - checking for LF line-endings in source and make files and shell scripts
# - checking for empty or unneeded directories
# - building 'notifier_1.0.0.tar.gz'
#
# Installing package into 'C:/Users/r2/AppData/Local/Temp/RtmpWgKbkW/local_libpath_43ccbf98e2'
# (as 'lib' is unspecified)
# * installing *source* package 'notifier' ...
# ** R
# ** inst
# ** byte-compile and prepare package for lazy loading
# ** help
# *** installing help indices
# converting help for package 'notifier'
# finding HTML links ... done
# notify html
# ** building package indices
# ** testing if installed package can be loaded
# *** arch - i386
# *** arch - x64
# * DONE (notifier)
# In R CMD INSTALL
# New packages found: 'notifier'
# Moving to: '\myserver/r2evans/R/win.library/3.5'
# Cleaning up