了解用于链接到 R 包中的外部 C 库的`Makevars` [英] Understanding `Makevars` for linking to external C library in R package

查看:68
本文介绍了了解用于链接到 R 包中的外部 C 库的`Makevars`的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个包,其中包含来自第三方库 (SUNDIALS) 的 C 代码.该包使用以下执行静态链接的 Makevars 文件编译和工作(即,能够解决测试 ODE)

I am working on a package which includes C code from third-party library (SUNDIALS). The package compiles and works (i.e., is able to solve a test ODE) with the following Makevars file performing static linking

CXX=clang++

PKG_CPPFLAGS = -I../inst/include
PKG_LDFLAGS = /usr/local/lib
PKG_LIBS= $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) $(PKG_LDFLAGS)/libsundials_cvode.a $(PKG_LDFLAGS)/libsundials_nvecserial.a

然而,一个稍微修改的版本(基于 R-Exts 中的示例,即 -PKG_LIBS = -L$(XML_DIR)/lib -lxml2) of Makevars(下面)失败

However, a slightly modified version (based on the example in R-Exts, i.e. - PKG_LIBS = -L$(XML_DIR)/lib -lxml2) of Makevars (below) fails

CXX=clang++

PKG_CPPFLAGS = -I../inst/include
PKG_LDFLAGS = /usr/local/lib
PKG_LIBS= $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) -L$(PKG_LDFLAGS) -lsundials_cvode -lsundials_nvecserial -lm

失败并显示以下错误消息.

fails with the following error message.

Error: package or namespace load failed for ‘Rcppsbmod’ in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/Library/Frameworks/R.framework/Versions/3.4/Resources/library/Rcppsbmod/libs/Rcppsbmod.so':
  dlopen(/Library/Frameworks/R.framework/Versions/3.4/Resources/library/Rcppsbmod/libs/Rcppsbmod.so, 6): Library not loaded: libsundials_cvode.3.dylib
  Referenced from: /Library/Frameworks/R.framework/Versions/3.4/Resources/library/Rcppsbmod/libs/Rcppsbmod.so
  Reason: image not found
Error: loading failed
Execution halted
ERROR: loading failed
* removing ‘/Library/Frameworks/R.framework/Versions/3.4/Resources/library/Rcppsbmod’
* restoring previous ‘/Library/Frameworks/R.framework/Versions/3.4/Resources/library/Rcppsbmod’

Exited with status 1.

当我将 PKG_LDFLAGS 指定为 /usr/local/lib 时,我不确定为什么它会在另一个位置寻找库.

I am not sure why it is looking for the libraries in another location when I am specifying PKG_LDFLAGS as /usr/local/lib.

顺便说一下,SUNDIALS 包编译并使用以下命令的测试示例

As an aside, the test example which comes which the SUNDIALS package compiles and works with the following command

gcc -Wall cvRoberts_dns.c -o cvRoberts_dns.exe -I/usr/local/include -L/usr/local/lib/ -lsundials_cvode -lsundials_nvecserial -lm

因此,我知道该库已正确安装,并且在 /usr/local/lib 位置提供了正确的文件(用于链接).

So, I know that the library is installed properly and correct files (for linking) are available at /usr/local/lib location.

整个包源代码可以在 - https://github.com/sn248/Rcppsbmod一个>

The entire package source code can be found at - https://github.com/sn248/Rcppsbmod

任何帮助或指导将不胜感激!

Any help or guidance will be highly appreciated!

推荐答案

我正在解决类似的问题,c.f.MacOS 上的运行时链接 R-extension.我目前的解决方法是在编译时设置 rpath.在您的情况下,这意味着:

I am fighting with similar issues, c.f. Runtime linking R-extension on MacOS. My current workaround is to set the rpath at compile time. In your case that would mean:

CXX=clang++

PKG_CPPFLAGS = -I../inst/include
PKG_LDFLAGS = /usr/local/lib
PKG_LIBS= $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) -L$(PKG_LDFLAGS) -lsundials_cvode -lsundials_nvecserial -lm -Wl,-rpath,$(PKG_LDFLAGS) 

然而,这并不能解决您的问题.比较错误消息,我看到一个区别:在您的情况下,未找到库 libsundials_cvode.3.dylib,而在我的情况下,它是 @rpath/libaf.3.dylib>.这意味着您安装的库将自身标识为 libsundials_cvode.3.dylib.您可以使用

However, this does not fix your problems. Comparing the error messages I see one difference: In your case the library libsundials_cvode.3.dylib is not found, while in my case it is @rpath/libaf.3.dylib. This means that the library you installed identifies itself as libsundials_cvode.3.dylib. You can check this with

$ otool -L /usr/local/lib/libsundials_cvode.3.dylib 
/usr/local/lib/libsundials_cvode.3.dylib:
    /usr/local/opt/sundials/lib/libsundials_cvode.3.dylib (compatibility version 3.0.0, current version 3.1.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0)

在您的情况下,第二个输出行不应包含绝对路径,而应仅包含库的基本名称.我的安装使用 brew,它通常使用绝对路径作为库名称.在一些琐碎的测试中,我将 R 扩展与这些库链接起来没有问题.

In your case the second output line should not contain an absolute path but only the basename of the library. My installation uses brew, which typically uses absolute paths as library names. In some trivial tests I had no problem with linking an R extension with these libraries.

我看到了几种可能性:

  • 试试 brew 中的 SUNDIAL.
  • 使用

  • Try SUNDIAL from brew.
  • Adjust the library path in your installed libraries with

install_name_tool -id /usr/local/lib/libsundials_cvode.3.dylib /usr/local/lib/libsundials_cvode.3.dylib

使用绝对路径.

使用

install_name_tool -id '@rpath/libsundials_cvode.3.dylib' /usr/local/lib/libsundials_cvode.3.dylib

并像上面一样设置 rpath.

Makevars

all: $(SHLIB)
    @if command -v install_name_tool; then install_name_tool -change libsundials_cvode.3.dylib /usr/local/lib/libsundials_cvode.3.dylib $(SHLIB); fi

这篇关于了解用于链接到 R 包中的外部 C 库的`Makevars`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆