繁体   English   中英

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

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

当安装程序运行加载测试时,在编译后尝试在 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

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

请注意,这不是 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")

但如上所述它失败了。

通常, iconv方法是从glibc ,它在构建相关 R 包期间链接到。 然而,无论出于何种原因,在这种情况下, iconv正在解析为libiconv ,但它在构建过程中并未由 R 包链接。

原始解决方法

可以通过haven/src/Makevars添加到haven/src/Makevars源文件来明确链接到libiconv

PKG_LIBS=-liconv

然后让我们从源R CMD INSTALL haven 但是,编辑包感觉很麻烦,而且每次升级都需要这样做,这听起来很麻烦。

更清洁的解决方法

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

withr::with_makevars(c(PKG_LIBS="-liconv"), install.packages("haven"), assignment="+=")

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

附加信息

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

您是否在 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 服务器,错误应该被修复。

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

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

编辑:如果/etc/无法访问,您可以在$HOME执行所有操作。 标准外壳实例化有效,R 有自己的.Rprofile.Renviron 您可以在$HOME为所有项目和/或在每个项目的目录中使用这些内容---请参阅help(Startup)

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

就我而言,我试图让Rglpk包找到libglpk.so文件。 根据Stefaan Lippen 的博客条目.profile文件是这些与bash不严格相关的配置类型的首选位置。

你是通过 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

暂无
暂无

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

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