I have looked at multiple places but failed to find a simple example for my problem.
What I need is to be able to use multiple .so files which I have (together with .h files).
A simple example would be:
I have the following files: a.h, a.cpp the function jeden - this is my R library, accessor.cpp which exposes to R the function dwa from external library libdwa.so. I have the header file dwa.h and this library libdwa.so.
I can manage building binary package (and everything works fine) only and only then when I put the library file libdwa.so into the directory '/usr/lib' (I use Debian). But it is not partable solution.
Where I should put the library "dwa" files (dwa.h and libdwa.so) and what flags add in the Makevars file to get portable solution?
I summarize my results here. I believe some extremaly simple examples are useful at start.
2 external libraries put inside inst:
/inst/include/dwa.h
/inst/include/trzy.h
/inst/jeden/libdwa.so
/inst/jeden/libtrzy.so
configure file /configure has the form (test6 is a name of the package):
#!/bin/bash
rpath=$(${R_HOME}/bin/Rscript -e 'cat(file.path(.libPaths()[1], "test6", "jeden"))') #'
sed -e"s|@rpath@|"${rpath}"|" src/Makevars.in > src/Makevars
exit 0
The file /src/Makevars.in has the form:
CXX_STD = CXX11
PKG_CPPFLAGS = -I../inst/include/ -I.
PKG_LIBS = -ldwa -ltrzy -L../inst/jeden -Wl,-rpath,@rpath@
The /src/accessor.cpp expose the libraries function to R:
#include <Rcpp.h>
#include "../inst/include/dwa.h"
#include "../inst/include/trzy.h"
// [[Rcpp::export]]
Rcpp::String r_dwa() {
Rcpp::String res = dwa();.
return res;
}
// [[Rcpp::export]]
Rcpp::String r_trzy() {
Rcpp::String res = trzy();.
return res;
}
Pure R library _/src/hello_world.cpp_ also exists:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
String hello_world() {
String hw = "Hello World";
return hw ;
}
Finaly /NAMESPACE file:
useDynLib("test6", .registration=TRUE)
import("Rcpp")
importFrom("utils", "object.size", "packageVersion")
exportPattern("^[[:alpha:]]+")
Building source and binary packages was successful but only source one is usefull as the binary has path to the libraries written rigidly.
Let's assume you have a directory structure like
/opt/dwa/include/dwa.h
/opt/dwa/lib/libdwa.so
In that case you could use is src/Makevars:
PKG_CPPFLAGS = -I/opt/dwa/include
PKG_LIBS = -L/opt/dwa/lib -ldwa -Wl,-rpath,/opt/dwa/lib
Of course, this is still not portable, since the path to the library and header files is hard coded. To circumvent this, one uses a template file, e.g. src/Makevars.in
PKG_CPPFLAGS = @DWA_INC@
PKG_LIBS = @DWA_LIB@
and writes a configure script that inspects the environment and creates src/Makevars based on the findings. There are different strategies for writing configure scripts. I typically use autoconf, e.g. in RcppArrayFire or dqmagic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With