了解用于链接到 R 包中的外部 C 库的`Makevars` [英] Understanding `Makevars` for linking to external C library in R package
问题描述
我正在开发一个包,其中包含来自第三方库 (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屋!