Search code examples
c++rrcppr-packagelapacke

How to use OpenBlas Lapacke together with Rcpp


I have some running c++ code using the Lapacke version that comes with OpenBlas. I would like to include this code into an R package and transfer data between that function and R using the Rcpp package. But somehow the two seem not to like each other. As soon as I have #include <lapacke.h> and #include <Rcpp.h> in one source file it isn't compiling anymore. Both separately work fine. There is a whole bunch off error messages which as far as I can tell say that Rcpp is broken (e.g /home/Alex/R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include/Rcpp/traits/traits.h:32:15: error: expected ‘)’ before ‘__extension__’).

I have no idea why this happens. Is there a way to use both at the same time? Or should I do something completely different?

Here is a minimal example that gives me the error:

  1. I created a package using

    Rcpp::Rcpp.package.skeleton("LT", example_code = FALSE)
    
  2. I added a .cpp file to /src containing

    #include <lapacke.h>
    #include <Rcpp.h>
    
    int test_LAPACK(){
      return(1);
    }
    
  3. I added a Makvars file to /src containing

    PKG_CXXFLAGS = -I/opt/OpenBLAS/include
    PKG_LIBS =  -L/opt/OpenBLAS/lib -lopenblas -lpthread -lgfortran
    CXX_STD = CXX11
    
  4. Compile and install

    Rcpp::compileAttributes("LT")
    devtools::install("LT")
    

Solution

  • It actually works on my system following a standard sudo apt install liblapacke-dev provided I also change the include order.

    Witness:

    Source

    rob:/tmp/lapacke/LT$ cat src/lt.cpp 
    #include <Rcpp.h>
    #include <lapacke.h>
    
    int test_LAPACK(){
              return(1);
    }
    rob:/tmp/lapacke/LT$ ls src/      ## no Makevars needed
    lt.cpp
    rob:/tmp/lapacke/LT$ 
    

    Build

    rob:/tmp/lapacke/LT$ build.r 
    * checking for file ‘./DESCRIPTION’ ... OK
    * preparing ‘LT’:
    * checking DESCRIPTION meta-information ... OK
    * cleaning src
    * installing the package to process help pages
    * saving partial Rd database
    * cleaning src
    * checking for LF line-endings in source and make files and shell scripts
    * checking for empty or unneeded directories
    Removed empty directory ‘LT/R’
    * building ‘LT_1.0.tar.gz’
    
    rob:/tmp/lapacke/LT$
    

    Install

    rob:/tmp/lapacke/LT$ install.r LT_1.0.tar.gz 
    * installing *source* package ‘LT’ ...
    ** libs
    ccache g++ -I"/usr/share/R/include" -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include"    -fpic  -g -O3 -Wall -pipe   -march=native -c lt.cpp -o lt.o
    ccache g++ -Wl,-S -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o LT.so lt.o -L/usr/lib/R/lib -lR
    installing to /usr/local/lib/R/site-library/LT/libs
    ** help
    *** installing help indices
    ** building package indices
    ** testing if installed package can be loaded
    * DONE (LT)
    rob:/tmp/lapacke/LT$ 
    

    Run

    (After I added a line // [[Rcpp::export]], ran compileAtttributes() and rebuilt and installed.)

    rob:/tmp/lapacke/LT$ r -lLT -p -e'test_LAPACK()'
    [1] 1
    rob:/tmp/lapacke/LT$ 
    

    Summary

    Check your compiler. There is no fundamental reason this should not work, and it works here (Ubuntu 18.04).