Rcpp linking to external library (NLopt) - r

I'd need some help with building a Rcpp package linking to the NLopt library (http://ab-initio.mit.edu/wiki/index.php/NLopt).
I'm on Windows and using RStudio's 'Build & Reload'.
I've the following files in \src folder of the package:
\src
Makevars.in
Makevars.win
RcppExports.cpp
nlopt.h
nlopt.hpp
libnlopt.lib
libnlopt.def
libnlopt.a
libnlopt.dll
where I've copied the .lib (built using MinGW) and dll files of NLOpt to the \src folder in the hope that R would compile them itself. That doesn't seem to be the case, however, and for that reason I've added a Makevars file, where I try to link to the library.
When running from RStudio, I get the following error message that, I suppose, tells me that there is a problem with linking (cf. "undefined reference") to the NLop library:
installing to library 'C:/Users/g49128/Documents/R/win-library/3.2'
installing source package 'NewPackage' ...
** libs
g++ -m64 -shared -s -static-libgcc -o NewPackage.dll tmp.def RcppExports.o Rcpp_project_test.o -Lc:/Temp/R/Rcpp/NewPackage/src/libnlopt.a -Lc:/applications/extsoft/lib/x64 -Lc:/applications/extsoft/lib -LC:/PROGRA~1/R/R-32~1.2/bin/x64 -lR
Rcpp_project_test.o:Rcpp_project_test.cpp:(.text+0x73c): undefined reference to `__imp_nlopt_create'
So I suspect that I haven't got the Makevars right, not so well versed in those.
From consulting several CRAN packages, in particular nloptr, my current best guess on the content of both Makevars files is:
NLOPT_HOME = c:/Temp/R/Rcpp/NewPackage/src.
KG_CFLAGS = -I"$(NLOPT_HOME)"
PKG_LIBS = -L"$(NLOPT_HOME)/libnlopt.a"
where 'libnlopt.a' is the library and the environment variable 'NLOPT_HOME' holds the path to the library.
Could anyone tell me what I'm missing here? Any help would be much appreciated, thank you.

The nloptr package itself does that reliably. It uses the following Makevars.win:
# Copyright (C) 2010 Jelmer Ypma. All Rights Reserved.
# This code is published under the L-GPL.
#
# File: Makevars.win
# Author: Jelmer Ypma
# Date: 18 August 2010
#
# 09 June 2011: Windows support added thanks to Stefan Theussl and Uwe Ligges.
# NLOPT_HOME is the directory where a working installation of
# NLopt is located (within subdirectories NLOPT_VERSION/R_ARCH)
# 18 November 2011: Removed NLOPT_VERSION macro and adopted some other changes
# proposed by Brian Ripley to make nloptr work with his new toolchain.
# NLopt should now be located in NLOPT_HOME/R_ARCH (i.e. without
# version number)
# 19 February 2013: NLopt is compiled with --with-cxx option, in order to include
# the StoGo algorithm. This means that we now need to link to
# with -lnlopt_cxx and also link to the c++ library, -lstdc++.
# 7 November 2013: Changed PKG_CPPFLAGS to PKG_CFLAGS.
# 2 May 2014: Added quotes around include paths to allow for spaces in NLOPT_HOME.
# C Compiler options
PKG_CFLAGS = -I"$(NLOPT_HOME)$(R_ARCH)/include"
PKG_LIBS = -L"$(NLOPT_HOME)$(R_ARCH)/lib" -lnlopt_cxx
The requires that you have the correct NLOPT_HOME variable set.
You can sometimes download a corresponding pre-built library from a CRAN support site, but I do not see this here.

Related

R package development - How to handle C library linking errors on package install

Situation:
The R package I am developing exports a C function through R's .C.
The code in src/ where the function is defined compiles fine if libtiff is installed in the OS.
I'd like this functionality to be optional; just as there are "suggested" R packages, because it is not essential.
The problem
I found no way to tell R that a C function compilation is "suggested". Neither could I find a way to make compilation of code in src/ optional, or conditional to the presence of libtiff in the OS in some way.
My current Makevars says:
CC=ccache clang -Qunused-arguments
CXX=ccache clang++ -Qunused-arguments
CCACHE_CPP2=yes
PKG_LIBS = -ltiff
I have been searching for a solution all day, without success.
I've only just figured out how to use Makevars to look for libtiff:
TIFFSTATUS := $(shell $(LD) -ltiff; echo 0 || echo 1)
ifeq ($(TIFFSTATUS), 1)
... stuff?
The question
How can I properly tell R that a function using .C is optional (ie conditional to the availability of the libtiff dependencies).
Thanks.

ld: unknown option: -platform_version when building R packages from source

Certain R packages, such as mgcv, fail to compile from source with clang 10+ (under macOS 10.14 and R version 3.6+). The error reported during compilation is
ld: unknown option: -platform_version
How do I resolve this error and compile these packages?
The problem with ld is the same as in Clang 10 fails to link C++ application with CMake on macOS 10.12. However, the suggestion to add the flag -DCMAKE_CXX_FLAGS="-mlinker-version=305" is not applicable to the R package compilation process. For R, you need to add -mlinker-version=305 to LDFLAGS to your Makevars file, typically located in $HOME/.R/.
My Makevars is based on this GitHub gist. I changed LDFLAGS from this:
LDFLAGS+=-L$(HO)/llvm/lib -Wl,-rpath,$(HO)/llvm/lib
to this:
LDFLAGS+=-L$(HO)/llvm/lib -Wl,-rpath,$(HO)/llvm/lib -mlinker-version=305
That resolved the ld error when compiling mgcv from source.
For the igraph package, adding the mlinker flag to LDFLAGS was not enough; it had to be added to the C++ flags as well. In the gist Makevars above, this is done by adding -mlinker-version=305 to STD_FLAGS, which then adds the flag to CXX**FLAGS for all C++ versions.
UPDATE, June 24 2020: unfortunately, some packages (rJava in my case) fail to use the STD_FLAGS. My workaround was to put the mlinker flag in the C compiler invocation:
CC=$(CCACHE) $(HO)/llvm/bin/clang -mlinker-version=305

Building the R package, "later," generates undefined symbol

Updating installed packages for R-3.5.2 (in Slackware-14.2) the "later" package fails to load because of this error:
/usr/lib/R/library/later/libs/later.so: undefined symbol: __atomic_fetch_add_8,
Web searches and folks on the r-help mail list were not able to resolve this issue.
Earlier versions of "later" had no problems installing and updating.
All suggestions will be followed up.
Issue #73 on github discusses that on some platforms, one needs to add a flag -latomic even though std::atomic is part of the C++11 standard library.
Assuming you have C++11 installed on your Slackware 14.2, you should be able to:
git clone https://github.com/r-lib/later.git
nano later/src/Makevars # or whatever editor you prefer
# Change `PKG_LIBS = -pthread` to `PKG_LIBS = -pthread -latomic`
sudo R CMD INSTALL later
Update December 2019:
With the latest version of later, it now is:
git clone https://github.com/r-lib/later.git
nano later/src/Makevars.in # or whatever editor you prefer
# Change `PKG_LIBS = -pthread #extra_pkg_libs#` to `PKG_LIBS = -pthread -latomic #extra_pkg_libs#`
sudo R CMD INSTALL later

Rcpp Makevars related warning

I am the mantainer of few R packages that use Rcpp for some core calculations. Wishing to try a new feature of the Rcpp package as described in Rcpp 0.12.18 Rbloggers
To do so I did the following:
I created a Makevars and Makevars.win in my scr folder, both contaning the line CPPFLAGS += -DRCPP_USE_UNWIND_PROTECT
I added the SystemRequirements: GNU make entry in the DESCRIPTION file.
Btw that raises some issues that I wounder will make my package rejected on CRAN:
following Warning message in compiling my package:
checking compilation flags in Makevars ... WARNING Variables overriding user/site settings: CPPFLAGS: -o /dev/null -DRCPP_USE_UNWIND_PROTECT
Note: GNU make is a system requirement
I would like to know if it is possible to rewrite the Makevars to remove the warning and possibly, the Gnu make requirement
Thanks in advance for the attention
You want to use PKG_CPPFLAGS (or PKG_CXXFLAGS) as that is the per-package variant. What you altered is the system-wide version hence the warning.
More details are as always in the Writing R Extensions manual, otherwise the many existing example packages (all on CRAN and browseable at GitHub) can help too.
For example, here is the one-toggle-setting use case from the RcppExamples package:
PKG_CXXFLAGS = -DRCPP_NEW_DATE_DATETIME_VECTORS
(which is strictly-speaking no longer needed as the "new" Date and Datetime vector classes became the default a while ago).
Also, if you use this form you do not need the += and have no requirement to declare on GNU make -- another win.

How do I linking to a non-standard library when building an R package

I'm trying to build the R openssl package and link it to an openssl library that is a newer version than the one in the systemwide lib64 directory.
The Makevars file simply has:
KG_CPPFLAGS=#cflags#
PKG_LIBS=#libs#
I can specify my local library by passing a custom library path in the configure script. But when I issue R CMD INSTALL, the linking command begins with
gcc -std=gnu99 -shared -L/usr/local/lib64 -o openssl.so [...objects...] -Lmy/path/here -lssl -lcrypto
As a result, the linker finds the wrong library (the one in /usr/local/lib64) instead of mine.
How do I adjust the linking command so that it looks for the library first in my directory, instead of the system folder.
(Background: I don't have root access and this older version of CentOS (5) doesn't support openssl v1, so I built v1 myself just to compile the R package. But I'm stuck at the linking stage due to whatever magic is happening by R CMD INSTALL.)
I solved this by passing arguments to R CMD INSTALL. I.e.:
R CMD INSTALL . --configure-vars="INCLUDE_DIR=$HOME/local/include LIB_DIR=$HOME/local/lib64"
But this varies for each package. There's no general solution.
Instead, read config and src/Makefile.in.

Resources