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

mer*_*erv 18 r dynamic-loading install.packages

当安装程序运行加载测试时,我在尝试安装时readxlhaven在R(tidyverse编译后的两个依赖项)中不断收到以下错误:

** 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
Run Code Online (Sandbox Code Playgroud)

我有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
 > 
Run Code Online (Sandbox Code Playgroud)

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


编辑

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

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

但它就像上面那样失败了.

mer*_*erv 10

通常,iconv从中获取该方法,该方法glibc在构建所讨论的R包期间链接.但是,无论出于何种原因,在这种情况下iconv都会得到解决libiconv,但在构建期间它不会被R包链接.

原始解决方法

libiconv通过将以下行添加到haven/src/Makevars源文件,可以使链接显式化

PKG_LIBS=-liconv
Run Code Online (Sandbox Code Playgroud)

然后让你从源码安装R CMD INSTALL haven.然而,编辑软件包感觉很糟糕,而且每次升级都需要这样做,这听起来很麻烦.

更清洁的解决方法

另一种选择是使用withr::with_makevars,它允许人们临时控制Makevars内容.使用这种技术,可以直接从repo安装:

withr::with_makevars(c(PKG_LIBS="-liconv"), install.packages("haven"), assignment="+=")
Run Code Online (Sandbox Code Playgroud)

信用:@ knb建议我检查一下readxl.so,ldd结果证明它非常有用,因为它表明共享对象甚至没有尝试链接到libiconv.知道了,我意识到我可以通过-liconv旗帜手动添加引用.谢谢@knb!

附加信息

在包的方面,有关将库连接到R包的相关详细信息可以在构建库的指南中找到.在系统配置方面,R-admin指南包含一些有用的部分.


小智 5

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

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

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

rsession-ld-library-path=/usr/lib64/:/usr/local/lib/:OTHER_PATH_OF_YOUR_LIB
Run Code Online (Sandbox Code Playgroud)

重新启动RStudio服务器,该错误应已解决。