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

时间:2017-07-14 22:36:18

标签: r dynamic-loading install.packages

当安装程序运行加载测试时,尝试在R中编译readxlhaventidyverse的依赖关系)时,我一直收到以下错误:

** 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

我在libiconv.so中包含的本地lib路径(不适用于R包)中有LD_LIBRARY_PATH,我在我的R会话中验证Sys.getenv("LD_LIBRARY_PATH")有该目录。 为什么R的动态库加载器不能找到这个共享对象? 我需要定义一个不同的特定于R的环境变量来让R中的动态库加载器搜索我的本地lib路径吗?

请注意,这不是R库路径的问题,而是R包具有的非R依赖性。如果我正在编译和链接C ++代码,gcc将使用ld,因此LD_LIBRARY_PATH将跟踪动态依赖关系。 R似乎不尊重这种相当常见的方法,我似乎无法找到有关如何管理这些更细粒度的依赖性问题的任何文档。

其他详细信息

!> 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
 > 

我之前编译过libiconv,因为它是对其他东西的依赖(不记得现在的东西 - 可能不是R包给出当前的问题)。我尝试重新安装它,但没有任何区别。

修改

我还尝试在安装之前手动加载库:

> dyn.load(".local/lib/libiconv.so")
> is.loaded("libiconv")
[1] TRUE
> install.packages("tidyverse")

但它如上所述失败。

5 个答案:

答案 0 :(得分:9)

通常情况下,iconv方法是从glibc中获取的,iconv是在构建相关R包时链接的。但是,无论出于何种原因,libiconv在这种情况下会被解析为libiconv,但在构建期间它不会被R包链接。

原始解决方法

通过将以下行添加到haven/src/Makevars源文件

,可以显式链接到PKG_LIBS=-liconv
R CMD INSTALL haven

然后让您从源Makevars安装。但是,编辑软件包感觉很麻烦,而且每次升级都需要这样做,这听起来很麻烦。

清洁工作方法

另一种选择是使用withr::with_makevars,它允许用户暂时控制withr::with_makevars(c(PKG_LIBS="-liconv"), install.packages("haven"), assignment="+=") 内容。使用这种技术,可以直接从repo安装:

readxl.so

信用:@ knb建议我使用ldd检查-liconv,结果证明这是非常有用的,因为它显示共享对象不是甚至尝试链接到 libiconv 。知道了,我意识到我可以通过{{1}}标志手动添加引用。谢谢@knb!

其他信息

在包装方面,可以在the guide for building libraries中找到有关将库连接到R包的相关详细信息。在系统配置方面,the R-admin guide有一些有用的部分。

答案 1 :(得分:2)

您是否在RStudio Server中运行代码?如果是这样,这里的答案可能会有用。

我在加载动态库时遇到了类似的错误。该库位于LD_LIBRARY_PATH中包含的路径中。当我在R控制台中运行代码时,它可以正确加载动态库。但是当我在RStudio中运行它时,你的帖子中出现了同样的错误。

原因是RStudio Server有自己的库搜索路径环境。您应该在/etc/rstudio/rserver.conf中指定以下配置:

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

重新启动RStudio Server,错误应该修复。

答案 2 :(得分:2)

这些库确实应该是基于RH的系统的标准,并且可以找到。

如果必须将它们添加到R,则必须在启动R 之前执行。一种方法是通过LD_LIBRARY_PATH,更好的方法是在/etc/ld.so.conf.d/中编辑文件(假设RH / CentOS也有)。否则可以通过/etc/environment

修改:如果/etc/无法访问,您可以执行$HOME以下的所有操作。标准shell实例化有效,R有自己的.Rprofile.Renviron。对于所有项目,和/或每个项目目录,您可以拥有$HOME以下的项目 - 请参阅help(Startup)

答案 3 :(得分:0)

我将export LD_LIBRARY_PATH=...语句放入文件~/.profile中。 这样,命令行R和RStudio服务器都能够找到共享库。

就我而言,我试图获取Rglpk软件包来定位libglpk.so文件。 根据{{​​3}},对于与.profile不严格相关的这些类型的配置,bash文件是首选位置。

答案 4 :(得分:-1)

您是通过rpm安装R还是自己编译?

解决方案1 ​​

如果您有权修改R可执行文件(shell脚本),可以试试这个:

修改~/.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=...
...
...

解决方案2

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

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

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

/usr/bin/R

然后将~/.local/bin添加到您的PATH