简体   繁体   English

如何为 R 中的动态库加载指定(非 R)库路径?

[英]How to specify (non-R) library path for dynamic library loading in R?

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:当安装程序运行加载测试时,在编译后尝试在 R( tidyverse两个依赖tidyverse )中安装readxlhaven时,我不断收到以下错误:

** 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.我在LD_LIBRARY_PATH包含的本地 lib 路径(不适用于 R 包)中有libiconv.so ,并且我在 R 会话中验证了Sys.getenv("LD_LIBRARY_PATH")具有该目录。 Why can't R's dynamic library loader find this shared object?为什么 R 的动态库加载器找不到这个共享对象? 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?是否需要定义不同的 R 特定环境变量才能让 R 中的动态库加载器搜索我的本地库路径?

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.请注意,这不是 R 库路径的问题,而是 R 包具有的非 R 依赖项的问题。 If I were compiling and linking C++ code, gcc would use ld , and hence LD_LIBRARY_PATH to track down dynamic dependencies.如果我正在编译和链接 C++ 代码, gcc将使用ld ,因此使用LD_LIBRARY_PATH来跟踪动态依赖项。 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. R 似乎不尊重这种相当普遍的方法,而且我似乎找不到任何关于如何管理这些更细粒度的依赖问题的文档。


Additional Details额外细节

!> 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).我之前编译过libiconv因为它是其他东西的依赖项(现在不记得是什么了 - 鉴于当前问题,可能不是 R 包)。 I tried reinstalling it, but made no difference.我尝试重新安装它,但没有任何区别。


Edit编辑

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.通常, iconv方法是从glibc ,它在构建相关 R 包期间链接到。 For whatever reason, however, iconv is getting resolved to libiconv in this case, but it is not linked by the R packages during build.然而,无论出于何种原因,在这种情况下, iconv正在解析为libiconv ,但它在构建过程中并未由 R 包链接。

Original Workaround原始解决方法

One can make the linking to libiconv explicit by adding the following line to the haven/src/Makevars source file可以通过haven/src/Makevars添加到haven/src/Makevars源文件来明确链接到libiconv

PKG_LIBS=-liconv

which then let's you install from source R CMD INSTALL haven .然后让我们从源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.但是,编辑包感觉很麻烦,而且每次升级都需要这样做,这听起来很麻烦。

Cleaner Workaround更清洁的解决方法

Another option is to use withr::with_makevars , which allows one to temporarily control Makevars content.另一种选择是使用withr::with_makevars ,它允许临时控制Makevars内容。 With this technique, one can install directly from the repo:使用这种技术,可以直接从 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 .信用:@knb 建议我用ldd检查readxl.so ,结果证明这非常有用,因为它表明共享对象甚至没有尝试链接到libiconv Knowing that, I realized I could manually add the reference via the -liconv flag.知道这一点后,我意识到我可以通过-liconv标志手动添加引用。 Thanks @knb!谢谢@knb!

Additional Info附加信息

On the package side of things, relevant details about connecting libraries to R packages can be found in the guide for building libraries .在包方面,可以在构建库指南中找到有关将库连接到 R 包的相关详细信息。 On the system configuration side, the R-admin guide has some useful sections.在系统配置方面, R-admin 指南有一些有用的部分。

Are you running the code in RStudio Server?您是否在 RStudio Server 中运行代码? If so, the answer here may be useful.如果是这样,这里的答案可能有用。

I used to meet a similar error while loading dynamic library.我曾经在加载动态库时遇到过类似的错误。 The library was in a path contained in LD_LIBRARY_PATH .该库位于LD_LIBRARY_PATH包含的路径中。 When I ran the code in R console, it could load the dynamic library correctly.当我在 R 控制台中运行代码时,它可以正确加载动态库。 But when I ran it in RStudio, the same error in your post raised.但是当我在 RStudio 中运行它时,你的帖子中出现了同样的错误。

The reason is that RStudio Server has its own library search path environment.原因是 RStudio Server 有自己的库搜索路径环境。 You should specify the following configuration in /etc/rstudio/rserver.conf :您应该在/etc/rstudio/rserver.conf指定以下配置:

rsession-ld-library-path=/usr/lib64/:/usr/local/lib/:OTHER_PATH_OF_YOUR_LIB

Restart RStudio Server and the error should be fixed.重新启动 RStudio 服务器,错误应该被修复。

These libraries really should be standard on RH-based system too, and be found.这些库确实也应该是基于 RH 的系统的标准,并且可以找到。

If you must add them to R, you have to do so before you start R .如果必须将它们添加到 R,则必须在启动 R 之前这样做。 One way is via LD_LIBRARY_PATH , a better way is to edit a file in /etc/ld.so.conf.d/ (assuming RH/CentOS have that too).一种方法是通过LD_LIBRARY_PATH ,更好的方法是编辑/etc/ld.so.conf.d/的文件(假设 RH/CentOS 也有)。 Else maybe via /etc/environment .否则可能通过/etc/environment

Edit: If /etc/ is out of reach, you can do everything below $HOME .编辑:如果/etc/无法访问,您可以在$HOME执行所有操作。 Standard shell instantiation works, and R has its own .Rprofile and .Renviron .标准外壳实例化有效,R 有自己的.Rprofile.Renviron You can have those below $HOME for all your projects, and/or in a per-project directory---see help(Startup) .您可以在$HOME为所有项目和/或在每个项目的目录中使用这些内容---请参阅help(Startup)

I put the export LD_LIBRARY_PATH=... statements into a file ~/.profile .我将export LD_LIBRARY_PATH=...语句放入文件~/.profile This way, both command line R and RStudio Server are able to find the shared library.这样,命令行 R 和 RStudio Server 都能够找到共享库。

In my case, I was trying to get the Rglpk package to locate the libglpk.so file.就我而言,我试图让Rglpk包找到libglpk.so文件。 According to Stefaan Lippen's blog entry , the .profile file is the preferred location for these type of configurations not strictly related to bash .根据Stefaan Lippen 的博客条目.profile文件是这些与bash不严格相关的配置类型的首选位置。

Did you install R via rpm or compile it yourself?你是通过 rpm 安装 R 还是自己编译?

solution 1解决方案1

If you have the permission to modify the R executable (shell script), you can try this:如果你有修改R可执行文件(shell脚本)的权限,你可以试试这个:

Edit ~/.local/bin/R or /usr/local/bin/R or /usr/bin/R编辑~/.local/bin/R/usr/local/bin/R/usr/bin/R

#!/bin/bash
# Shell wrapper for R executable.

export LD_LIBRARY_PATH="<my_lib_Path>/readxl/libs/"
R_HOME_DIR=...
...
...

Solution 2解决方案2

Or you may vim ~/.local/bin/R或者你可以vim ~/.local/bin/R

#!/bin/bash
# Shell wrapper for R executable.

export LD_LIBRARY_PATH="<my_lib_Path>/readxl/libs/"

/usr/bin/R

then add ~/.local/bin to your PATH然后将~/.local/bin添加到您的PATH

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM