Understanding `Makevars` for linking to external C library in R package

僤鯓⒐⒋嵵緔 提交于 2019-12-04 12:15:25

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) 

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)

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.

I see several possibilities:

  • 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
    

    to use absolute paths.

  • Adjust the library path in your installed libraries with

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

    and set rpath as above.

  • Adjust the name of the library your R extension is looking for with this addition to 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
    

System-wide dynamic linking, as in your second use case which fails, requires the cooperation of the dynamic linker on your system.

That means after build and copyring the libraries to /usr/local/lib you must typically run sudo ldconfig to update the linker cache.

You can check if the libraries are know by grep'ing through the output of ldconfig -p. On my system, no sundials:

edd@rob:~$ ldconfig -p | grep sundials
edd@rob:~$ 

Relatedly you can (locally) use different directories by declaring them in /etc/ld.so.conf.d/somefile.conf -- but that is of course not portable and would not help you with a package designated for CRAN.

The use of static libraries you build as part of your package as in your first example would work as it does not require any system assistance. It just takes longer the build the libraries each time.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!