我正在开发一个包含来自第三方库(SUNDIALS)的C代码的软件包。包使用以下执行静态链接的Makevars
文件进行编译和工作(即,能够解决测试ODE)
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
(下方)的Makevars
}失败
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
失败,并显示以下错误消息。
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
时,我不确定为什么要在其他位置查找库。
顺便说一句,SUNDIALS包编译并使用以下命令的测试示例
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
位置提供了正确的文件(用于链接)。
整个软件包源代码可以在 - https://github.com/sn248/Rcppsbmod
找到任何帮助或指导都将受到高度赞赏!
答案 0 :(得分:3)
我正在与类似的问题作斗争,c。 Runtime linking R-extension on MacOS。我目前的解决方法是在编译时设置rpath
。在你的情况下,这意味着:
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
。您可以使用
$ 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扩展与这些库链接没有问题。
我看到了几种可能性:
brew
尝试SUNDIAL。使用
调整已安装库中的库路径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
答案 1 :(得分:2)
系统范围的动态链接,如第二个失败的用例,需要系统上动态链接器的配合。
这意味着在构建并将库复制到/usr/local/lib
之后,通常必须运行sudo ldconfig
来更新链接器缓存。
您可以通过ldconfig -p
的输出来查看是否知道库。在我的系统上,没有日,,
edd@rob:~$ ldconfig -p | grep sundials
edd@rob:~$
相关地,您可以(本地)通过声明它们来使用不同的目录
/etc/ld.so.conf.d/somefile.conf
- 但这当然不是便携式的,也无法帮助您使用为CRAN指定的包。
使用您在第一个示例中构建的静态库作为包的一部分,因为不需要任何系统帮助。每次构建库只需要更长的时间。