Rcpp 理解“Makevars”以链接到R包中的外部C库
我正在开发一个软件包,其中包括来自第三方库(SUNDIALS)的C代码。该包编译并使用以下执行静态链接的Rcpp 理解“Makevars”以链接到R包中的外部C库,rcpp,r-package,Rcpp,R Package,我正在开发一个软件包,其中包括来自第三方库(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)/
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中的示例,即-
Makevars
(以下)的PKG_LIBS=-L$(XML_DIR)/lib-lxml2)失败
失败,并显示以下错误消息
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.
当我将pkgldflags
指定为/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
位置获得正确的文件(用于链接)
整个软件包源代码可在以下位置找到-
任何帮助或指导都将不胜感激 系统范围的动态链接,就像在第二个失败的用例中一样,需要系统上的动态链接器的合作 这意味着在将库编译并复制到
/usr/local/lib
之后,通常必须运行sudo ldconfig
来更新链接器缓存
您可以通过查询ldconfig-p
的输出来检查库是否已知。在我的系统上,没有日晷:
edd@rob:~$ ldconfig -p | grep sundials
edd@rob:~$
相关地,您可以(本地)通过在中声明不同的目录来使用它们
/etc/ld.so.conf.d/somefile.conf
——但这当然是不可移植的,也无助于您使用指定用于CRAN的包
在第一个示例中,使用作为包的一部分构建的静态库是可行的,因为它不需要任何系统帮助。每次构建库都需要更长的时间。我正在为类似的问题而斗争,c.f。我目前的解决方法是在编译时设置
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)
但是,这并不能解决您的问题。比较这些错误消息,我发现了一个区别:在您的示例中,找不到库libsundails\u cvode.3.dylib
,而在我的示例中,它是@rpath/libaf.3.dylib
。这意味着您安装的库将自己标识为libsundails\u 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)
在您的情况下,第二个输出行不应该包含绝对路径,而应该只包含库的basename。我的安装使用brew
,它通常使用绝对路径作为库名称。在一些琐碎的测试中,我将R扩展与这些库链接起来没有问题
我认为有几种可能性:
- 从
尝试日晷brew
- 使用调整已安装库中的库路径
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
- 使用调整已安装库中的库路径
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
ldconfig
,但是有sudo-update\u-dyld\u-shared\u-cache
。运行此命令sudo update_dyld_shared_cache | grep sundials
会显示一条长消息,例如update_dyld_shared_cache:warning@rpath system framework的安装名称:/System/Library/PrivateFrameworks/AssetCacheStensions.framework/Versions/A/XPCServices/AssetCacheTheratorService.xpc/Contents/Frameworks/MobileDeviceLite.framework/Versions/A/MobileDeviceLite
。但是,如果静态与动态不那么重要,我现在不会做任何更改。我的下一个挑战是捆绑软件包,这样就没有在系统上安装库的先决条件(因为在Windows上安装日晷并不是那么简单)。谢谢你的回答。拉尔夫-谢谢你的回答。我尝试了你的方法(用-rpath
而不是rpath
做了一些细微的改变)。我收到以下消息(见下文)。任何建议都欢迎<代码>错误:dyn.load(文件,DLLpath=DLLpath,…)中的“Rcppsbmod”的包或命名空间加载失败:无法加载共享对象“/Library/Frameworks/R.framework/R.framework/Versions/3.4/Resources/Library/Rcppsbmod/libs/Rcppsbmod.so”:dlopen(/Library/Frameworks/R.framework/Versions/3.4/Resources/libs/Rcppsbmod.so,6):库未加载:libsundials\u cvode.3.dylib引用自:/Library/Frameworks/R.framework/Versions/3.4/Resources/Library/Rcppsbmod/libs/Rcppsbmod.so原因:找不到图像错误:加载失败libsundals_cvode.3.1.0.dylib libsundals_cvode.3.dylib libsundals_cvodes.a libsundals_cvodes.2.0.0.dylib libsundals_cvodes.2.dylib libsundals_cvodes.3.1.0.dylib libsundals_cvodes.3.dylibsundals_cvodes.a libsundals_cvodes.dylib@SN248您是如何安装Sundals库和安装Sundals的我认为Linux没有那么难。我特别想到的是Windows。无论如何,我希望用户能够使用这个软件包,即使他们没有安装日晷。我已经看到了这一点(nloptr、RCPPCAF),并将尝试复制那里正在做的事情。谢谢