Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rcpp: cannot open shared object file

Tags:

rcpp

arrayfire

I'm trying to develop an R package, which makes use of Arrayfire, thanks to Rcpp library. I've started writing a sample code (let's name it hello_world.cpp) which looks like this:

#include <arrayfire.h>

// [[Rcpp::export]]
bool test_array_fire(){
    af::randu(1, 4);    
    return true;
}

Then, I tried to compile it using a sourceCpp function

Rcpp::sourceCpp('src/hello_world.cpp')

My first suprise was the fact I had to set some flags manually (sourceCpp seems to ignore Makevars config when compiling a piece of C++ code). I did it with:

Sys.setenv("PKG_CXXFLAGS"="-std=c++11")
Sys.setenv("PKG_CPPFLAGS"="-I/opt/arrayfire/include/")
Sys.setenv("PKG_LIBS"="-L/opt/arrayfire/lib64/ -laf")

However, the code still does not compile properly. Each trial finishes with the following output:

Error in 'dyn.load("/tmp/RtmpHaODIU/sourceCpp-x86_64-pc-linux-gnu-1.0.2/sourcecpp_689c5adb8d/sourceCpp_14.so")':
unable to load shared object '/tmp/RtmpHaODIU/sourceCpp-x86_64-pc-linux-gnu-1.0.2/sourcecpp_689c5adb8d/sourceCpp_14.so':
  libaf.so.3: cannot open shared object file: No such file or directory

Unfortunately, I could not find an solution for my problem (even if some Stack Overflow questions raise issues which are more or less similar at first glance).

How can I fix it?

like image 864
KrzJoa Avatar asked Oct 14 '25 15:10

KrzJoa


1 Answers

The error occurs very late in the process when R tries to load the shared object file. This means that compilation and linking worked fine with the help of the environment variables you set. But in the final step the run-time linker does not know where libaf.so.3 is located. This is a configuration one normally does at the OS level, e.g. on my system

ralf@barra:~$ /sbin/ldconfig -p | grep libaf
        libafopencl.so.3 (libc6,x86-64) => /lib/libafopencl.so.3
        libafopencl.so (libc6,x86-64) => /lib/libafopencl.so
        libafcpu.so.3 (libc6,x86-64) => /lib/libafcpu.so.3
        libafcpu.so (libc6,x86-64) => /lib/libafcpu.so
        libaf.so.3 (libc6,x86-64) => /lib/libaf.so.3
        libaf.so (libc6,x86-64) => /lib/libaf.so

And if I try your example it works without problems with a shared object file that is linked against libaf:

ralf@barra:~$ ldd /tmp/RtmpcjY9dN/sourceCpp-x86_64-pc-linux-gnu-1.0.2/sourcecpp_13d33790279c/sourceCpp_7.so | grep libaf
        libaf.so.3 => /lib/libaf.so.3 (0x00007f21037ed000)

I expect that in your case the first command will provide no result and the second (adjusted) command will lead a "file not found"(?) error.

There are several ways to tell the run-time linker about the location of the library:

  • Edit /etc/ld.so.conf or (better) place a file in /etc/ld.so.conf.d/, c.f. http://arrayfire.org/docs/installing.htm#Linux.
  • Set LD_LIBRARY_PATH.
  • Add -Wl,-rpath,/opt/arrayfire/lib64/ to PKG_LIBS
  • Install ArrayFire into a directory that the linker searches by default. That's what I am doing since I compile from source and use the resulting DEB packages.

As for Rcpp::sourceCpp not respecting a Makevars file: The problem is that the C++ file you write cannot be used directly. Instead Rcpp attributes has to create additional wrapper functions, which is done in a temporary directory. Now one could in principle copy a Makevars file into that directory as well. However, one normally sets such variables with the help of Rcpp::plugins and Rcpp::depends attributes. For example, switching on C++11 is done using // [[Rcpp::plugins(cpp11)]]. For the other variables, you could write your own plugin or us the one provided by my RcppArrayFire.

However, I suggest you start with a package if that is your goal. Rcpp::sourceCpp is great for many things, but interfacing with a system installed library without the help of an R package is not one of them.

like image 64
Ralf Stubner Avatar answered Oct 18 '25 03:10

Ralf Stubner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!