I made a R package which uses Rcpp and which requires the libquadmath library (to use the multiprecision numbers of boost). On my personal laptop (Ubuntu 18.04), it works "as is". On win-builder it works by setting PKGLIBS = -lquadmath or PKGLIBS = $(FLIBS) in the Makevars file. But I also checked on r-hub with these settings and for the Fedora Linux distribution (R-devel, clang, gfortran) I get a failure.
This failure is:
/home/docker/R/BH/include/boost/multiprecision/float128.hpp:40:10: fatal error: 'quadmath.h' file not found
So I'm fearing that my package will not pass the CRAN checks. What is the way to go?
You write that you set "PKGLIBS = -lquadmath or PKGLIBS = $(FLIBS)". Those are linker instructions.
You write that fatal error: 'quadmath.h' file not found. That is a compiler error.
Now, the error comes from float128.hpp which happens to be in a package I maintain, so I took a quick look:
#if defined(BOOST_MP_USE_FLOAT128)
extern "C" {
#include <quadmath.h>
}
So you could suppress the inclusion by trying to ensure BOOST_MP_USE_FLOAT128. Other than that, I would recommend to look at the Boost documentation for package multiprecision. They may have a hint or two.
Edit: I took a quick peep at the multiprecision documentation but didn't see any leads. For other Boost libraries I have often started from some of the example but I am less familiar with this one.
Edit 2: Your example is also not exactly reproducible. I run Ubuntu here too, and the Boost float128.cpp example works fine on my box via g++ -o fl128 fl128.cpp -lquadmath (when save as fl128.cpp). You may need to do some discovery in a configure script to see why the other Linux systems at RHub fail.
Related
I'm trying to install JAGS through homebrew so I can use it in R. I am getting the following warning every time I install:
Warning: jags dependency gcc was built with a different C++ standard
library (libstdc++ from clang). This may cause problems at runtime.
Then, when I try to install rjags in R, I get the following error:
configure: error: "cannot link to JAGS library in /usr/local/Cellar/jags/4.3.0_2/lib."
ERROR: configuration failed for package ‘rjags’
* removing ‘/usr/local/lib/R/4.0/site-library/rjags’
I also tried following the installation guide in the JAGS 4.3.0 readme. This yielded the same error once I moved to R.
Googling leads me to the following links, none of which seem closely related enough to help me:
https://github.com/Homebrew/brew/issues/4904
https://github.com/Homebrew/homebrew-core/issues/32112
Link different C++ standard libraries on Mac OS X
Here also is the entire result of my brew doctor
(base) aridf#Aris-MacBook-Pro ~ % brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!
Warning: "config" scripts exist outside your system or Homebrew directories.
`./configure` scripts often look for *-config scripts to determine if
software packages are installed, and which additional flags to use when
compiling and linking.
Having additional scripts in your path can confuse software installed via
Homebrew if the config script overrides a system or Homebrew-provided
script of the same name. We found the following "config" scripts:
/Users/aridf/opt/anaconda3/bin/icu-config
/Users/aridf/opt/anaconda3/bin/krb5-config
/Users/aridf/opt/anaconda3/bin/freetype-config
/Users/aridf/opt/anaconda3/bin/xslt-config
/Users/aridf/opt/anaconda3/bin/libpng16-config
/Users/aridf/opt/anaconda3/bin/libpng-config
/Users/aridf/opt/anaconda3/bin/xml2-config
/Users/aridf/opt/anaconda3/bin/python3-config
/Users/aridf/opt/anaconda3/bin/curl-config
/Users/aridf/opt/anaconda3/bin/ncursesw6-config
/Users/aridf/opt/anaconda3/bin/pcre-config
/Users/aridf/opt/anaconda3/bin/python3.8-config
Warning: Unbrewed dylibs were found in /usr/local/lib.
If you didn't put them there on purpose they could cause problems when
building Homebrew formulae, and may need to be deleted.
Unexpected dylibs:
/usr/local/lib/libtcl8.6.dylib
/usr/local/lib/libtk8.6.dylib
Warning: Unbrewed header files were found in /usr/local/include.
If you didn't put them there on purpose they could cause problems when
building Homebrew formulae, and may need to be deleted.
Unexpected header files:
/usr/local/include/fakemysql.h
/usr/local/include/fakepq.h
/usr/local/include/fakesql.h
/usr/local/include/itcl.h
/usr/local/include/itcl2TclOO.h
/usr/local/include/itclDecls.h
/usr/local/include/itclInt.h
/usr/local/include/itclIntDecls.h
/usr/local/include/itclMigrate2TclCore.h
/usr/local/include/itclTclIntStubsFcn.h
/usr/local/include/mysqlStubs.h
/usr/local/include/odbcStubs.h
/usr/local/include/pqStubs.h
/usr/local/include/tcl.h
/usr/local/include/tclDecls.h
/usr/local/include/tclOO.h
/usr/local/include/tclOODecls.h
/usr/local/include/tclPlatDecls.h
/usr/local/include/tclThread.h
/usr/local/include/tclTomMath.h
/usr/local/include/tclTomMathDecls.h
/usr/local/include/tdbc.h
/usr/local/include/tdbcDecls.h
/usr/local/include/tdbcInt.h
/usr/local/include/tk.h
/usr/local/include/tkDecls.h
/usr/local/include/tkPlatDecls.h
Warning: Unbrewed .pc files were found in /usr/local/lib/pkgconfig.
If you didn't put them there on purpose they could cause problems when
building Homebrew formulae, and may need to be deleted.
Unexpected .pc files:
/usr/local/lib/pkgconfig/tcl.pc
/usr/local/lib/pkgconfig/tk.pc
Warning: Unbrewed static libraries were found in /usr/local/lib.
If you didn't put them there on purpose they could cause problems when
building Homebrew formulae, and may need to be deleted.
Unexpected static libraries:
/usr/local/lib/libtclstub8.6.a
/usr/local/lib/libtkstub8.6.a
Thanks!
The solution, per https://gist.github.com/casallas/8411082, was to change ~/.R/Makedir to the following:
CC=clang
CXX=clang++
Then reinstall the package in R
I can only find information on how to install a ready-made R extension package, but it is nowhere mentioned which commands a developer of an extension package has to use during daily development. I am using Rcpp and I am on Windows.
If this were a typical C++ project, it would go like this:
edit
make # oops, typo
edit # fix typo
make # oops, forgot an #include
edit
make # good; updates header dependencies for subsequent 'make' automatically
./fooreader # test it
make install # only now I'm ready
Which commands do I need for daily development of an Rcpp package project?
I've allocated a skeleton project using these commands from the R command line:
library(Rcpp)
Rcpp.package.skeleton("FooReader", example_code=FALSE,
author="My Name", email="my.email#example.com")
This allocated 3 files:
DESCRIPTION
NAMESPACE
man/FooReader-package.Rd
Now I dropped source code into
src/readfoo.cpp
with these contents:
#include <Rcpp.h>
#error here
I know I can run this from the R command line:
Rcpp::sourceCpp("D:/Projects/FooReader/src/readfoo.cpp")
(this does run the compiler and indicates the #error).
But I want to develop a package ultimately.
There is no universal answer for everybody, I guess.
For some people, RStudio is everything, and with some reason. One can use the package creation facility to create an Rcpp package, then edit and just hit the buttons (or keyboard shortcuts) to compile and re-load and test.
I also work a lot on a shell, so I do a fair amount of editing in Emacs/ESS along with R CMD INSTALL (where thanks to ccache recompilation of unchanged code is immediate) with command-line use via r of the littler package -- this allows me to write compact expressions loading the new package and evaluating: r -lnewpackage -esomeFunc(somearg) to test newpackage::someFunc() with somearg.
You can also launch the build and test from Emacs. As I said, it all depends.
Both those answers are for package, where I do real work. When I just test something in a single file, I do that in one Emacs buffer and sourceCpp() in an R session in another buffer of the same Emacs. Or sometimes I edit in Emacs and run sourceCpp() in RStudio.
There is no one answer. Find what works for you.
Also, the first part of your question describes the initial setup of a package. That is not part of the edit/compile/link/test cycle as it is a one off. And for that too do we have different approaches many of which have been discussed here.
Edit: The other main misunderstanding of your question is that once you have package you generally do not use sourceCpp() anymore.
In order to test an R package, it has to be installed into a (temporary) library such that it can be attached to a running R process. So you will typically need:
R CMD build . to build package_version.tar.gz
R CMD check <package_version.tar.gz> to test your package, including tests placed into the testsfolder
R CMD INSTALL <package_version.tar.gz> to install it into a library
After that you can attach the package and test it. Quite often I try to use a more TTD approach, which means I do not have to INSTALL the package. Running the unit tests (e.g. via R CMD check) is enough.
All that is independent of Rcpp. For a package using Rcpp you need to call Rcpp::compileAttributes() before these steps, e.g. with Rscript -e 'Rcpp::compileAttributes()'.
If you use RStudio for package development, it offers a lot of automation via the devtools package. I still find it useful to know what has to go on under the hood and it is by no means required.
I am a little bit confused on how to efficiently prepare the R package, so that it will be compatible across all needed system platforms. This is needed so that the new version of package will be accepted by CRAN. The main difficulty comes from compiling external C++ shared library, and optionally CUDA version if the compiler is available. To support this flow I've created specific Makefile, unfortunately using GNU-extensions. It works fine on Linux, OSX and when executed manually via gmake on Solaris. Relevant part is here:
# Checking whether nvcc compiler is available
NVCC_TEST = $(shell basename $(shell which nvcc 2> /dev/null)"")
ifeq ($(NVCC_TEST),nvcc)
ALL_LIBS += libcucubes_gpu.so
ALL_OBJS += $(GPU_OBJS)
ALL_FLAGS += $(GPU_FLAGS)
else
ALL_OBJS += gpu_fallback.o
endif
Turns out that, when running R CMD INSTALL (...) on Solaris, the installation fails on something like this:
make: Fatal error in reader: Makefile, line 39: Unexpected end of line seen
ERROR: compilation failed for package 'libcucubes'
As it turns out, it is caused by the fact that Solaris' version of make is executed instead of GNU-compatible gmake (I've tested it works fine), even though it is available. My question is whether there is any simple way to force usage of gmake here, for the R package build. In general I know I could use autotools to solve compatibility issues during installation, but it seems to bring too much complexity for that simple case. Any advices will be really appreciated, thanks!
If you can't get your build process to use gmake instead of Solaris's pure POSIX make, you can use this hack:
Make a dedicated directory for this hack: mkdir $HOME/make_hack
Softlink gmake asmakein that directory: ln -s /path/to/gmake $HOME/make_hack/make
Set your PATH: PATH=$HOME/make_hack:$PATH
Now, run your build process using that PATH, and it should use gmake. Hopefully it just uses make from its PATH envval and not some hardcoded full path.
Yeah, it's a hack. But it's probably a lot easier than modifying the build process to use gmake instead of make.
From Writing R Extensions:
If you really must require GNU make, declare it in the DESCRIPTION
file by
SystemRequirements: GNU make
and ensure that you use the value of environment variable MAKE (and
not just make) in your scripts.
configure scripts are the preferred solution though. BTW, in general a Makevars file is also preferred over a full Makefile.
I've been working on a program called RoboJournal and I recently finished the 0.4.1 release. I'm currently in the process of packaging it for Fedora but for some reason the program won't compile on that OS. The exact same code builds fine on Windows and any Debian-based Linux (Debian itself, Ubuntu, Mint, et al). I had no problems packaging this for Debian. Here's the the compiler output error message (running on Fedora 18 KDE version):
/usr/bin/ld: dblogin.o: undefined reference to symbol 'XkbGetIndicatorState'
/usr/bin/ld: note: 'XkbGetIndicatorState' is defined in DSO /lib64/libX11.so.6 so try adding it to the linker command line
/lib64/libX11.so.6: could not read symbols: Invalid operation
collect2: error: ld returned 1 exit status
The problem seems to be that the Linker can't find whatever is supposed to control the XkbGetIndicatorState signal (one of the X11 libs). This is used to determine whether caps lock is enabled while a certain dialog is active. Apparently, anything Debian-based includes this library out of the box while Fedora does not. I think this error is simply caused by a missing package but I'm not sure which one. Google gave me nothing useful. Any ideas?
Anyone who wants to test this for themselves can clone from git://github.com/pwizard2/robojournal.git. The app depends on the following packages (so far): qt, qt-assistant, qt-mysql, qt-devel, qt-webkit, qt-webkit-devel.
The problem is probably that you're not linking your program against libX11 so you need to add -lX11 to your link command and then everything will work.
The reason it works on some other linux distributions is that they allow symbols to be resolved using libraries that have only been pulled in indirectly - so if your program links against a library that is linked against libX11 then you will be able to call routines in libX11.
Fedora has not allowed this indirect linking (by default) for several years now (see UnderstandingDSOLinkChange) and several other distributions have also now followed suit.
I have an R package which is easily sped up by using OpenMP. If your compiler supports it then you get the win, if it doesn't then the pragmas are ignored and you get one core.
My problem is how to get the package build system to use the right compiler options and libraries. Currently I have:
PKG_CPPFLAGS=-fopenmp
PKG_LIBS=-fopenmp
hardcoded into src/Makevars on my machine, and this builds it with OpenMP support. But it produces a warning about non-standard compiler flags on check, and will probably fail hard on a machine with no openMP capabilities.
The solution seems to be to use configure and autoconf. There's some information around here:
http://cran.r-project.org/doc/manuals/R-exts.html#Using-Makevars
including a complex example to compile in odbc functionality. But I can't see how to begin tweaking that to check for openmp and libgomp.
None of the R packages I've looked at that talk about using openMP seem to have this set up either.
So does anyone have a walkthrough for setting up an R package with OpenMP?
[EDIT]
I may have cracked this now. I have a configure.ac script and a Makevars.in with #FOO# substitutions for the compiler options. But now I'm not sure of the workflow. Is it:
Run "autoconf configure.in > configure; chmod 755 configure" if I change the configure.in file.
Do a package build.
On package install, the system runs ./configure for me and creates Makevars from Makevars.in
But just to be clear, "autoconf configure.in > configure" doesn't run on package install - its purely a developer process to create the configure script that is distributed - amirite?
Methinks you have the library option wrong, please try
## -- compiling for OpenMP
PKG_CXXFLAGS=-fopenmp
##
## -- linking for OpenMP
PKG_LIBS= -fopenmp -lgomp
In other words, -lgomp gets you the OpenMP library linked. And I presume you know that this library is not part of the popular Rtools kit for Windows. On a modern Linux you should be fine.
In an unrelease testpackage I have here I also add the following to PKG_LIBS, but that is mostly due to my use of Rcpp:
$(shell $(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()") \
$(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
Lastly, I think the autoconf business is not really needed unless you feel you need to test for OpenMP via configure.
Edit: SpacedMan is correct. Per the beginning of the libgomp-4.4 manual:
1 Enabling OpenMP
To activate the OpenMP extensions for
C/C++ and Fortran, the compile-time
flag `-fopenmp' must be specified.
This enables the OpenMP directive
[...] The flag also
arranges for automatic linking of the
OpenMP runtime library.
So I stand corrected. Seems that it doesn't hurt to manually add what would get added anyway, just for clarity...
Just addressing your question regarding the usage of autoconf--no, you do not want to run autoconf with any arguments, nor should you redirect its output. You are correct that running autoconf to build the configure script is something that the package maintainer does, and the resulting configure script is distributed. Normally, to generate the configure script from configure.ac (older packages use the name configure.in, but that name has been discouraged for several years), the developer simply runs autoconf with no arguments. Before running autoconf, it is necessary to run aclocal, autoheader, libtoolize, etc... There is also a tool (autoreconf) which simplifies the process and invokes all the required programs in the correct order. It is now more typical to run autoreconf instead of autoconf.