Welcome to post 57 in the R4 series.
R packages with compiled codes can use the file
src/Makevars to set compilation flags. We often rely on
this to set libraries, include directories or compilation options. When
using external libraries, be it header-only or via headers and linking,
we are often experiencing ‘compilation noise’ when these libraries
tickle warnings under generally-recommended flags such as
-Wall -pedantic. Two packages I maintain are clearly repeat
offenders here: Eigen, and BH. Both cam generate pages and pages of
compiler output. This is generally not great as it may hide genuine
warnings from our own code.
What makes matters worse is that some of the available and specific
options for the compilers are treated by R CMD check as
‘non-portable’ leading to a nag on package checking. Examples are
-Wno-parentheses, -Wno-maybe-uninitialize or
-Wno-nunnull.
I have long resorted to adding these to my per-user
~/.R/Makevars. When added there, compilation is quieter,
but R CMD check still nags here where the option
is set but not at CRAN or
r-universe. A situation that is not ideal but what somewhat
‘stable’.
More recently, I realized there was an available check we can use to conditionally add extra compilation flags but leave them off by default. That makes local development quiet allowing us to focus on the quality of our additions here without noise from third-party libraries we may use. At the same time we do not need to do anything else to let CRAN do its work.
The check we now use is whether there is a .git/
directory present. If so, we are indeed building from local sources and
can add extra flags. If not, we are likely building from a tar.gz source
archive—which is the case for CRAN—and hence do not set these.
An example use is this recent additional to package qlcal where this bit of R
code is invoked from a minimal shell script configure and
replaces the stub @XTRAFLAGS@ in
src/Makevars.in (or src/Makevars.win.in)
if (dir.exists(".git")) {
## development from a .git directory can use these flags
xtraflags <- "-Wno-nonnull -Wno-deprecated-declarations"
} else {
## else build from tarball so stick with existing flags
xtraflags <- ""
}
win <- if (Sys.info()[["sysname"]] == "Windows") ".win" else ""
infile <- file.path("src", paste0("Makevars", win, ".in"))
outfile <- file.path("src", paste0("Makevars", win))
lines <- readLines(infile)
lines <- gsub("@XTRAFLAGS@", xtraflags, lines)
writeLines(lines, outfile)With this change, local compilation is quiet, yet CRAN has nothing to nag about (as seen at the qlcal results page).
Similarly, one can also check from an actual configure
file written in autoconf. Here is a similar example from RcppEigen
(showing some relevants parts of the whole file)
# PKG_CXXFLAGS initialized earlier ...
## Check if building locally
AC_MSG_CHECKING([whether .git/ exists])
if test -d "$srcdir/.git"; then
AC_MSG_RESULT([yes, adding extra flags])
AC_SUBST([PKG_CXXFLAGS],["${PKG_CXXFLAGS} -Wno-ignored-attributes -Wno-maybe-uninitialized"])
else
AC_MSG_RESULT([no, consider adding '-Wno-ignored-attributes -Wno-maybe-uninitialized' to ~/.R/Makevars])
fi
AC_SUBST([PKG_CXXFLAGS], ["${PKG_CXXFLAGS}"])
AC_CONFIG_FILES([src/Makevars])
AC_OUTPUTOnce again, with this change compilation is quiet locally, yet unaffected at CRAN. Just what we want. Give it a try in your packages.
This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can now sponsor me at GitHub.