How to use OpenBlas Lapacke together with Rcpp - c++

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:
I created a package using
Rcpp::Rcpp.package.skeleton("LT", example_code = FALSE)
I added a .cpp file to /src containing
#include <lapacke.h>
#include <Rcpp.h>
int test_LAPACK(){
return(1);
}
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
Compile and install
Rcpp::compileAttributes("LT")
devtools::install("LT")

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).

Related

C++ writing JSON with JSONCPP

I was trying to use the JSONCPP library to work with JSON documents in C++.
Reading another question here, I saw this example and tried to implement:
#include "json/json.h"
int main(){
Json::Value event;
Json::Value vec(Json::arrayValue);
vec.append(Json::Value(1));
vec.append(Json::Value(2));
vec.append(Json::Value(3));
event["competitors"]["home"]["name"] = "Liverpool";
event["competitors"]["away"]["code"] = 89223;
event["competitors"]["away"]["name"] = "Aston Villa";
event["competitors"]["away"]["code"] = vec;
std::cout << event << std::endl;
}
But I keep getting this error:
json2.cpp:(.text+0x1c): referência não definida para "Json::Value::Value(Json::ValueType)"
/usr/bin/ld: json2.cpp:(.text+0x30): referência não definida para "Json::Value::Value(Json::ValueType)"
json2.cpp is the file's name, as it looks like.
Being a /usr/bin/ld a link error, I tried to add as parameter the directory path to the compile command but the error persists
Does anyone know how to fix it?
It’s all about how you build/install the library and specify the headers in the source. Since you didn’t mention what method you took to build the library, I’ll demonstrate three solutions I got to work on Ubuntu 20.04 LTS.
Install the Package
Most straightforward way is to install via apt:
$ sudo apt-get install libjsoncpp-dev
The header files will be installed to /usr /include/jsoncpp/json and can be included in json2.cpp as:
#include <jsoncpp/json/json.h>
And compile by adding the linker flag as:
$ g++ json2.cpp -o json2 -ljsoncpp
Amalgamated Source
Inside of the top-level directory of the jsoncpp repository, you can amalgamate the source by:
$ python amalgamate.py
By default, this will generate all necessary source and header files in the dist/ directory, and there is no need to link the library. Include in json2.cpp as:
#include <json/json.h>
As indicated in the build instructions, jsoncpp.cpp will have to be incorporated into your project:
$ g++ json2.cpp dist/jsoncpp.cpp -Idist -o json2
Cmake
From the top-level directory of the jsoncpp repository:
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=release -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF -DARCHIVE_INSTALL_DIR=. -G "Unix Makefiles" ..
$ make; make install
This will install the header files to /usr/local/include/json. Include in json2.cpp as:
#include <json/json.h>
And compile by adding the linker flag as:
$ g++ json2.cpp -o json2 -ljsoncpp

Tensorflow c++ api

I recently tensorflow cpp api from a way below(on MacOS Catalina ):
1. I first Install Bazel 0.23.0
2. download tensorflow:
$ git clone https://github.com/tensorflow/tensorflow
cd tensorflow # cd to the top-level directory created
$ ./configure
bazel build //tensorflow:libtensorflow_cc.so
# build C library
$ bazel build //tensorflow:libtensorflow.so
After install I run the code below:
#include "tensorflow/core/public/session.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/platform/env.h"
int main(){
return 0;
}
with. command below:
g++ -I/usr/local/Cellar/libtensorflow/2.1.0_1/include -L/usr/local/Cellar/libtensorflow/2.1.0_1/lib -ltensorflow -ltensorflow_cc -ltensorflow_framework -std=c++11 main.cc -o main.o
but I get Error below:
/usr/local/Cellar/libtensorflow/2.1.0_1/include/tensorflow/core/framework/device_attributes.pb.h:17:2: error:
This file was generated by an older version of protoc which is
#error This file was generated by an older version of protoc which is
^
/usr/local/Cellar/libtensorflow/2.1.0_1/include/tensorflow/core/framework/device_attributes.pb.h:18:2: error:
incompatible with your Protocol Buffer headers. Please
#error incompatible with your Protocol Buffer headers. Please
I used libprotoc 3.11.4.
what should I do? what is wrong?

Speed up RcppArmadillo: How to link to OpenBlas in an R package

I am working on an R package which uses RcppArmadillo. I am trying to take advantage of faster matrix multiplication found in OpenBLAS. In the documentation of the C++ armadillo library, it says if we have OpenBLAS on our machine then Armadillo would use OpenBLAS instead of BLAS. However, when I compile my R package, I get something like this:
g++ -m64 -std=c++11 -shared -L/usr/lib64/R/lib -Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -o PackageTest.so class1.o class2.o class3.o class4.o class5.o class6.o class7.o RcppExports.o class8.o class9.o class10.o -L/usr/lib64/R/lib -lRlapack -L/usr/lib64/R/lib -lRblas -lgfortran -lm -lquadmath -L/usr/lib64/R/lib -lR
So it is compiling with the -lRlapack and -lRblas options. How can I properly modify the Makevars and Makevars.win files to have RcppArmadillo compile the package with the option -lopenblas? My attempt to solve this problem was to modify the Makevars file in the following way:
PKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
PKG_CXXFLAGS =-fopenmp -std=c++11 -lopenblas
PKG_CXX1XFLAGS = $(PKG_CXXFLAGS)
The package did compile with -lopenblas, but is this the best way to do it?
That is a problem with your RedHat installation which chose to rely on the internal LAPACK sources for R when installing R --- plus the fact that RcppArmadillo uses whatever R uses.
On my Debian/Ubuntu based machine, it happens differently. Ie for
R> library(Rcpp)
R> cppFunction("arma::mat foo(arma::mat x) { return x + x;} ", depends="RcppArmadillo", verbose=TRUE)
I get (inter alia)
g++ -Wl,-S -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions \
-Wl,-z,relro -o sourceCpp_4.so file677111d81351.o \
-fopenmp -llapack -lblas -lgfortran -lm -lquadmath \
-L/usr/lib/R/lib -lR
and we see -llapack -lblas -lgfortran as expected.
Instructions for compiling R, OpenBLAS and linking R with OpenBLAS (GNU/Linux)
I believe your biggest problem is linking R to the OpenBLAS library. So the steps I write below can help you succeed in this link.
Compiling OpenBLAS
Initially download the R and OpenBLAS(Open Optimized BLAS Library) source codes in OpenBLAS. In the file directory, perform the following steps.
tar -zxvf OpenBLAS*
cd OpenBLAs*
make -j $nproc
sudo make install
export LD_LIBRARY_PATH=/opt/OpenBLAS/lib/
or
git clone https://github.com/xianyi/OpenBLAS.git
cd OpenBLAS*
make -j $nproc
sudo make install
export LD_LIBRARY_PATH=/opt/OpenBLAS/lib/
Note: This will make the compilation run faster using all the features of your CPU. To know the number of cores, do: nproc.
Compiling Armadillo C++ with OpenBLAS
For those who use C++ codes in R using the Rcpp library, setting up the Armadillo with the OpenBLAS library may be of some benefit.
tar -xvf armadillo*
cd armadillo*
./configure -DCMAKE_PREFIX_PATH=/opt/OpenBLAS/lib/
cmake . -DCMAKE_PREFIX_PATH=/opt/OpenBLAS/lib/
make -j $nproc
sudo make install
Note: Further details regarding the compilation of the Armadillo library can be found at https://gitlab.com/conradsnicta/armadillo-code.
Compiling R with OpenBLAS
After compiling OpenBLAS, download the R code. It is not necessary to compile R to make use of OpenBLAS, but compiling the language may bring some benefits that may be insignificant depending on what is being done in R. That way, download the source code of the language R.
Note: In my operating system, Arch Linux, OpenBLAS) was installed in the /opt directory. Search for the OpenBLASinstallation directory in your GNU/Linux distribution.
In the directory where the R was downloaded, do the following:
tar -zxvf R*
cd R-* && ./configure --enable-R-shlib --enable-threads=posix --with-blas="-lopenblas -L/opt/OpenBLAS/lib -I/opt/OpenBLAS/include -m64 -lpthread -lm"
make -j $nproc
sudo make install
Most likely the OpenBLAS library will be bound to R. To check, run in the R the sessionInfo() code. Something like the output below should appear:
Matrix products: default
BLAS/LAPACK: /opt/OpenBLAS/lib/libopenblas_haswellp-r0.3.6.dev.so
If linking does not occur, follow the steps outlined in the code below.
We need to link the R with the file libopenblas_*, created in the process of compiling the library OpenBLAS. In my case, the file is ibopenblas_haswellp-r0.2.20.so. Look for this in /opt/OpenBLAS/lib or in the directory where OpenBLAS was installed on your GNU/Linux system. Also look for the libRblas.so file directory found in the R language installation directory. In Arch, this directory is /usr/local/lib64/R/lib.
cd /usr/local/lib64/R/lib
mv libRblas.so libRblas.so.keep
ln -s /opt/OpenBLAS/lib/libopenblas_haswellp-r0.2.20.so libRblas.so
Start a section of language R and do sessionInfo(). You should note something like:
Matrix products: default
BLAS/LAPACK: /opt/OpenBLAS/lib/libopenblas_haswellp-r0.3.6.dev.so
To make use of multithreaded processing, do export OPENBLAS_NUM_THREADS=1 before starting a R section.
NOTE: For intel processors,sudo cpupower frequency-set -g performance, can boost performance. Read more at https://wiki.archlinux.org/index.php/CPU_frequency_scaling.

Unable to reproduce minimal working example Rcpp

I downloaded and installed the Rcpp package recently in order to speed up the code of my own package using some C++ code.
The first thing I do is making a package with Rcpp.package.skeleton(name="firstpackage"):
> Rcpp.package.skeleton(name="firstpackage")
Creating directories ...
Creating DESCRIPTION ...
Creating NAMESPACE ...
Creating Read-and-delete-me ...
Saving functions and data ...
Making help files ...
Done.
Further steps are described in './firstpackage/Read-and-delete-me'.
Adding Rcpp settings
>> added Imports: Rcpp
>> added LinkingTo: Rcpp
>> added useDynLib directive to NAMESPACE
>> added importFrom(Rcpp, evalCpp) directive to NAMESPACE
>> added example src file using Rcpp attributes
>> compiled Rcpp attributes
>> added Rd file for rcpp_hello_world
This generates a file system with folders man, R and src as it should. However the files Makevars, Makevars.win and rcpp_hello_world.h are missing in these folders, if I compare with the example on page 66-67 in the book Seamless R and C++ Integration with Rcpp. Why aren't these files generated like in the example? After installing firstpackage I cannot use the function rcpp_hello_world() so I guess it is because of the missing files.
edit: It is clear now that the problem is not the missing files but something else. I tried again, now exactly following the instructions:
> Rcpp.package.skeleton("ruben")
Creating directories ...
Creating DESCRIPTION ...
Creating NAMESPACE ...
Creating Read-and-delete-me ...
Saving functions and data ...
Making help files ...
Done.
Further steps are described in './ruben/Read-and-delete-me'.
Adding Rcpp settings
>> added Imports: Rcpp
>> added LinkingTo: Rcpp
>> added useDynLib directive to NAMESPACE
>> added importFrom(Rcpp, evalCpp) directive to NAMESPACE
>> added example src file using Rcpp attributes
>> compiled Rcpp attributes
>> added Rd file for rcpp_hello_world
Then I look at the files. (a bit weird but the file structure appears to be the same)
> system("tree ruben")
Folder PATH listing for volume OSDisk
Volume serial number is A811-3ED9
C:\USERS\N14083\DOCUMENTS\RUBEN
ÃÄÄÄman
ÃÄÄÄR
ÀÄÄÄsrc
Then I install the newly created package:
> system("R CMD INSTALL ruben")
* installing to library 'C:/Users/n14083/Documents/R/win-library/3.1'
* installing *source* package 'ruben' ...
** libs
*** arch - i386
Warning: running command 'make -f "C:/PROGRA~1/R/R-31~1.1/etc/i386/Makeconf" -f "C:/PROGRA~1/R/R-31~1.1/share/make/winshlib.mk" SHLIB_LDFLAGS='$(SHLIB_CXXLDFLAGS)' SHLIB_LD='$(SHLIB_CXXLD)' SHLIB="ruben.dll" OBJECTS="RcppExports.o rcpp_hello_world.o"' had status 127
ERROR: compilation failed for package 'ruben'
* removing 'C:/Users/n14083/Documents/R/win-library/3.1/ruben'
Warning message:
running command 'R CMD INSTALL ruben' had status 1
The installation fails:
library(ruben)
Error in library(ruben) : there is no package called ‘ruben’
edit: solution Download the Windows toolset (http://cran.at.r-project.org/doc/manuals/R-admin.html#The-Windows-toolset) and set the PATH correctly, in my case:
pathRtools <- paste(c("c:\\Rtools\\bin",
"C:\\Rtools\\gcc-4.6.3\\bin",
"c:\\PROGRA~2\\MIKTEX~1.9\\miktex\\bin",
"C:\\PROGRA~1\\R\\R-3.1.1\\bin\\i386",
"c:\\windows",
"c:\\windows\\system32"), collapse=";")
Sys.setenv(PATH=pathRtools)
setwd("C:/Users/n14083/Documents")
system("R CMD INSTALL ruben")
and then restart R.
The book was current when it was written. As you now observe, the header is no longer included, neither are the Makevars as they are no longer needed.
That is because we now build with Rcpp Attributes. It is easier.
It still all works (of course).
Log below.
R> Rcpp.package.skeleton("ruben")
Creating directories ...
Creating DESCRIPTION ...
Creating NAMESPACE ...
Creating Read-and-delete-me ...
Saving functions and data ...
Making help files ...
Done.
Further steps are described in './ruben/Read-and-delete-me'.
Adding Rcpp settings
>> added Imports: Rcpp
>> added LinkingTo: Rcpp
>> added useDynLib directive to NAMESPACE
>> added importFrom(Rcpp, evalCpp) directive to NAMESPACE
>> added example src file using Rcpp attributes
>> compiled Rcpp attributes
>> added Rd file for rcpp_hello_world
R>
So let's look at the files:
R> system("tree ruben")
ruben
├── DESCRIPTION
├── man
│   ├── rcpp_hello_world.Rd
│   └── ruben-package.Rd
├── NAMESPACE
├── R
│   └── RcppExports.R
├── Read-and-delete-me
└── src
├── RcppExports.cpp
└── rcpp_hello_world.cpp
3 directories, 8 files
R>
And use them:
R> system("R CMD INSTALL ruben")
* installing to library ‘/usr/local/lib/R/site-library’
* installing *source* package ‘ruben’ ...
** libs
g++ -I/usr/share/R/include -DNDEBUG -I"/usr/local/lib/R/site-library/Rcpp/include" -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -g -O3 -Wall -pipe -Wno-unused -pedantic -c rcpp_hello_world.cpp -o rcpp_hello_world.o
g++ -I/usr/share/R/include -DNDEBUG -I"/usr/local/lib/R/site-library/Rcpp/include" -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -g -O3 -Wall -pipe -Wno-unused -pedantic -c RcppExports.cpp -o RcppExports.o
g++ -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o ruben.so RcppExports.o rcpp_hello_world.o -L/usr/lib/R/lib -lR
installing to /usr/local/lib/R/site-library/ruben/libs
** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
* DONE (ruben)
R>
And it obviously works:
R> library(ruben)
R> rcpp_hello_world()
[[1]]
[1] "foo" "bar"
[[2]]
[1] 0 1
R>
So please substantiate the claim
After installing firstpackage I cannot use the function rcpp_hello_world() so I guess it is because of the missing files.
Running this skeleton is part of every unit test run so this has been tested literally thousands of time since the book was written.

How to build and load shared library on rstudio for package that uses C/C++ files in src folder inside a subdirectory?

I have a R package that I'm working on that contains code written in C and C++ under the src folder. Currently, the package compiles and works on Rstudio as it follows the default directory structure. As the project builds, I want to be able to organize my code under src, within subfolders. Following directions from "Writing R extensions" - Compiling under sub-directories, I have made a folder called 'test'(/src/test) which now contains all my files(*.c, *.cpp, *.h) and modified my Makevars like so -
SOURCES_C = $(wildcard test/*.c)
SOURCES_CPP = $(wildcard test/*.cpp)
PKG_CPPFLAGS= -I${R_HOME}/include -I.
PKG_LIBS = -L${R_HOME}/lib
CXX_STD = CXX11
OBJECTS =$(SOURCES_CPP:.cpp=.o) $(SOURCES_C:.c=.o)
all : $(SHLIB)
#PKG_CFLAGS= -Wall
clean : rm -f *.o
I want to be able to compile the program in this state, where the C/C++ files are under subfolders inside src. Using the aforementioned Makevars -> the separate object files are being built from the test folder with the correct flags and compiler, for all C/CPP files. However, there are some discrepancies with the build command for the shared object. This is the log when compiling the files under src/test which fails with an undefined symbol error.
gcc -std=gnu99 -shared -L/usr/local/lib64 -o BioCro.so test/BBox.o test/Climate.o test/Compound.o test/Grid.o test/LeafOptics.o test/Maths.o test/Normal.o test/Point3D.o test/Ray.o test/Triangle.o test/Vector3D.o test/runFastTracer.o test/Assigncropcent.o test/AuxBioCro.o test/AuxCropGro.o test/AuxMaizeGro.o test/AuxcaneGro.o test/Auxcropcent.o test/AuxwillowGro.o test/BioCro.o test/CalculateBiogeochem.o test/Calculate_Soil_Layer_Temperature.o test/CanA.o test/CanAC_3D.o test/Century.o test/Copy_CropCent_To_DayCent_Structure.o test/Copy_SoilWater_BioCro_To_CropCent.o test/CropGro.o test/CropGro_c.o test/Filling_BioCro_SoilStructure.o test/assignManagement.o test/c3CanA.o test/c3EvapoTrans.o test/c3photo.o test/c4photo.o test/caneGro.o test/createNULLc3tree.o test/cropcent.o test/dailywillow.o test/denitrify.o test/diffusiv.o test/eC4photo.o test/getIdirIdiff.o test/getsoilprop.o test/leachdly.o test/maizeGro.o test/methane.o test/microclimate_for_3Dcanopy.o test/nitrify.o test/nox_pulse.o test/pi_funcs.o test/printcropcentoutput.o test/test_mainC.o test/tgmodel.o test/tracegas.o test/update_3Dcanopy_structure.o test/wfps.o test/willowCent.o test/willowGro.o -L/usr/local/R-3.1.0/lib64/R/lib -L/usr/local/R-3.1.0/lib64/R/lib -lR
installing to /home/vashist1/R/x86_64-unknown-linux-gnu-library/3.1/BioCro/
** R
** data
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** installing vignettes
** testing if installed package can be loaded
Error in dyn.load(file, DLLpath = DLLpath, ...) :
unable to load shared object '/home/vashist1/R/x86_64-unknown-linux-gnu-library/3.1/BioCro/libs/BioCro.so':
/home/vashist1/R/x86_64-unknown-linux-gnu-library/3.1/BioCro/libs/BioCro.so:
undefined symbol: _ZTVN10__cxxabiv117__class_type_infoE
Error: loading failed
Compared with the successful log which builds successfully!
g++ -shared -L/usr/local/lib64 -o BioCro.so Assigncropcent.o AuxBioCro.o AuxCropGro.o AuxMaizeGro.o AuxcaneGro.o Auxcropcent.o AuxwillowGro.o BBox.o BioCro.o CalculateBiogeochem.o Calculate_Soil_Layer_Temperature.o CanA.o CanAC_3D.o Century.o Climate.o Compound.o Copy_CropCent_To_DayCent_Structure.o Copy_SoilWater_BioCro_To_CropCent.o CropGro.o CropGro_c.o Filling_BioCro_SoilStructure.o Grid.o LeafOptics.o Maths.o Normal.o Point3D.o Ray.o Triangle.o Vector3D.o assignManagement.o c3CanA.o c3EvapoTrans.o c3photo.o c4photo.o caneGro.o createNULLc3tree.o cropcent.o dailywillow.o denitrify.o diffusiv.o eC4photo.o getIdirIdiff.o getsoilprop.o leachdly.o maizeGro.o methane.o microclimate_for_3Dcanopy.o nitrify.o nox_pulse.o pi_funcs.o printcropcentoutput.o runFastTracer.o test_mainC.o tgmodel.o tracegas.o update_3Dcanopy_structure.o wfps.o willowCent.o willowGro.o -L/usr/local/R-3.1.0/lib64/R/lib -lR
installing to /home/vashist1/R/x86_64-unknown-linux-gnu-library/3.1/BioCro/libs
1) The shared object compiles using g++ under default conditions, whereas under subdirectory conditions the compiler used is gcc. Can I change that behaviour via Makevars?
2) Further research allowed me to find that the undefined symbol error is a linking error fixed by the -L/-l flag. However, the -L flag is the same for both build commands. Is there any other library I am failing to link which is linked by default?
I ran into the same issue. Looking at the example of the RSiena package mentioned as an example in "Writing R Extensions" section 1.2.1.3 I noticed that that package still has some .cpp files not in a subdirectory. So I added a dummy.cpp file in src/ with the following contents:
void dummy (void)
{
}
After this g++ was correctly used for the linking step and the .so file was created as expected.
In my case it turns out that I don't need to change the Makevars files as I first mentioned in my answer. Even without the change below (so only having the dummy.cpp file present in src/) linking is done correctly.
I'll leave it in in case it may help someone else with a (slightly) different setup.
And add the corresponding .o file in the list of $(OBJECTS) variable in the Makevars file:
OBJECTS = $(SOURCES:.cpp=.o) dummy.o