I keep getting the following error when attempting to install readxl
or haven
in R (both dependencies of tidyverse
) post-compilation, when the installer runs the loading test:
** testing if installed package can be loaded
Error in dyn.load(file, DLLpath = DLLpath, ...) :
unable to load shared object '<my_lib_Path>/readxl/libs/readxl.so':
<my_lib_path>/readxl/libs/readxl.so: undefined symbol: libiconv
Error loading failed
I have libiconv.so
in a local lib path (not for R packages) that is included in LD_LIBRARY_PATH
and I've verified in my R session that Sys.getenv("LD_LIBRARY_PATH")
has that directory.
Why can't R's dynamic library loader find this shared object? Is there a different R-specific environment variable I need to define to have the dynamic library loader in R search my local lib path?
Please note that this is not an issue with an R library path, but instead for a non-R dependency that an R package has. If I were compiling and linking C++ code, gcc
would use ld
, and hence LD_LIBRARY_PATH
to track down dynamic dependencies. R doesn't appear to respect this rather common approach, and I can't seem to find any documentation on how to manage these more fine-grained dependency issues.
!> sessionInfo()
R version 3.3.3 (2017-03-06)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
>
I had previously compiled libiconv
because it was a dependency for something else (don't recall what now - likely not an R package given current problems). I tried reinstalling it, but made no difference.
I have also tried manually loading the library prior to installation:
> dyn.load(".local/lib/libiconv.so")
> is.loaded("libiconv")
[1] TRUE
> install.packages("tidyverse")
but it fails just as above.
Normally, the iconv
method is picked up from glibc
, which is linked to during build of the R packages in question. For whatever reason, however, iconv
is getting resolved to libiconv
in this case, but it is not linked by the R packages during build.
One can make the linking to libiconv
explicit by adding the following line to the haven/src/Makevars
source file
PKG_LIBS=-liconv
which then let's you install from source R CMD INSTALL haven
. However, editing packages feels hacky, plus this is something that will need to be done every upgrade, which sounds like a hassle.
Another option is to use withr::with_makevars
, which allows one to temporarily control Makevars
content. With this technique, one can install directly from the repo:
withr::with_makevars(c(PKG_LIBS="-liconv"), install.packages("haven"), assignment="+=")
Credit: @knb suggested that I inspect the readxl.so
with ldd
and this turned out to be super useful because it showed that the shared object wasn't even trying to link to libiconv. Knowing that, I realized I could manually add the reference via the -liconv
flag. Thanks @knb!
On the package side of things, relevant details about connecting libraries to R packages can be found in the guide for building libraries. On the system configuration side, the R-admin guide has some useful sections.