Understanding the contents of the Makevars file in R (macros, variables, ~/.R/Makevars and pkg/src/Makevars)
I am trying to understand the role and relationship of the macros/variables set in ~/.R/Makevars
and package_directory/src/Makevars
when installing/building own R packages. Suppose these files look like
~/.R/Makevars
CXX = g++
CXXSTD = -std=c++11
CXXFLAGS = -fsanitize=undefined,address -fno-omit-frame-pointer
CXX98 = g++
CXX98STD = -std=c++98
CXX11 = g++
CXX11STD = -std=c++11
CXX14 = g++
CXX14STD = -std=c++14
package_directory/src/Makevars
PKG_CPPFLAGS = -I../inst/include
CXX_STD = CXX11
As I understand it, with CXX
we can select the compiler for C++ when building R packages, with CXXSTD
we chose the standard and with CXXFLAGS
we add compiler flags. With PKG_CPPFLAGS
we add flags for the C++ preprocessor and with CXX_STD
we tell that our packages uses C++11.
I have the following questions:
- What is the relationship between
CXX
andCXX98
,CXX11
andCXX14
? - What is the meaning of, e.g.,
CXX11STD = -std=c++11
if C++11 is already implied? Is it between choosing-std=c++11
and-std=gnu++11
? Should-std=gnu++11
generally be avoided for portability reasons? - Could the flags for
CXXSTD
andCXXFLAGS
not just be added toCXX
, such that the first three lines reduce toCXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer
. What is the advantage in explicity specifyingCXXSTD
andCXXFLAGS
? - How does
CXX_STD = CXX11
work? How isCXX11
here related toCXX11
in~/.R/Makevars
? - What is the relationship between
CXXFLAGS
andPKG_CXXFLAGS
(not included in my example)?
I am aware of the information contained in Writing R Extensions and R Installation and Administration, but I am not able to extract more information beyond my current level of understanding to answer the above questions.
I am adding a Rcpp
tag because I suppose that answers to these questions will be most relevant to users of Rcpp
, but I am aware that this is probably not directly related to Rcpp
, so the tag might be removed if deemed appropriate.
The Makevars
file, as specified in Writing R Extensions: 1.2.1 Using Makevars, is a variant of Make
that is unique to R. Many of the variables you have listed are called implicit variables. The meaning is given as:
Implicit rules tell make how to use customary techniques so that you do not have to specify them in detail when you want to use them.
These implicit variables dictate what compiler should be used and what options are available.
Within R, we care about the following default compiler options:
CC Program for compiling C programs; default ‘cc’.
CXX Program for compiling C++ programs; default ‘g++’.
CPP Program for running the C preprocessor, with results to standard output; default ‘$(CC) -E’.
FC Program for compiling or preprocessing Fortran and Ratfor programs; default ‘f77’.
The next set of values details what options should be used by the compiler. In general, the default values for all of these options is an empty string.
CFLAGS Extra flags to give to the C compiler.
CXXFLAGS Extra flags to give to the C++ compiler.
CPPFLAGS Extra flags to give to the C preprocessor and programs that use it (the C and Fortran compilers).
FFLAGS Extra flags to give to the Fortran compiler.
LDFLAGS Extra flags to give to compilers when they are supposed to invoke the linker, ‘ld’, such as -L. Libraries (-lfoo) should be added to the LDLIBS variable instead.
LDLIBS Library flags or names given to compilers when they are supposed to invoke the linker, ‘ld’. LOADLIBES is a deprecated (but still supported) alternative to LDLIBS. Non-library linker flags, such as -L, should go in the LDFLAGS variable.
Now, R defines "extra" variants in terms of different C++ ISO standards. These variants are given in the R Administration: Section 2.7.2 C++ Support and R Administration: Section B.7 Compile and load flags
CXX98 CXX98STD CXX98FLAGS CXX98PICFLAGS
CXX11 CXX11STD CXX11FLAGS CXX11PICFLAGS
CXX14 CXX14STD CXX14FLAGS CXX14PICFLAGS
CXX17 CXX17STD CXX17FLAGS CXX17PICFLAGS
Having said this, let's tackle the first question:
What is the relationship between
CXX
andCXX98
,CXX11
andCXX14
?
CXX
is the general compiler option to use. Meanwhile, R defines additional CXX
options to use depending on the detected compilation standard. That is, if -std=c++98
(CXX98
language spec) set by CXX_STD
, then the compiler associated with CXX98
is used. Similarly, for CXX11
and CXX14
, the same logic follows. See Rcpp Gallery: Using Rcpp with C++11, C++14 and C++17 for more details.
What is the meaning of, e.g.,
CXX11STD = -std=c++11
if C++11 is already implied? Is it between choosing-std=c++11
and-std=gnu++11
? Should-std=gnu++11
generally be avoided for portability reasons?
The meaning of CXX11STD
is to determine the appropriate language standard for C++11 compile. This option exists simply because if R's version of selecting the appropriate C++11 compile option is incorrect for the compiler, you can change it. The reason this exists is because each compiler may define C++11 support slightly differently than the next as indicate in R Installation and Administration: 2.7.2 C++ Support:
It may be [Footnote 13] that there is no suitable flag for C++11 support, in which case a different compiler could be selected for CXX11 and its corresponding flags.
Footnote 13:
This is true for earlier versions of g++ such as 4.2.1, and also for commonly-used versions of the Solaris compiler CC.
For details on the language standards approved by gcc see GCC Manual: 3.4 Options Controlling C Dialect. Also, for details on using C++11 with R in a package see Writing R Extensions: Section 1.2.4 Using C++11 Code.
Generally, I would avoid explicitly setting this variable. If you must explicitly set this variable, I would recommend going with -std=c++11
as a majority of compilers support this declaration.
Could the flags for
CXXSTD
andCXXFLAGS
not just be added toCXX
, such that the first three lines reduce toCXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer
. What is the advantage in explicitly specifyingCXXSTD
andCXXFLAGS
?
Is it possible? Yes. Is it right? No.
Why have three variables each with their own goal when we could simply just have one?
The advantages of a three variable workflow provide different lines each with a distinct role. This allows for the ability to quickly understand the compilation option. Thus, it is much more straight forward to grok when compared it being crammed into one variable on one line (with terminal width of 80).
e.g.
CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer
vs
CXX = g++
CXX11STD = -std=c++11
CXXFLAGS = -fsanitize=undefined,address -fno-omit-frame-pointer
Furthermore, you should opt for CXX_STD
over CXXSTD
when packaging as shown in Writing R Extensions: Section 1.2.4 Using C++11 Code. This is simply to ensure that R registered the package as requiring C++xy. The alternative is to write in the DESCRIPTION
file the attribute SystemRequirements: C++xy
, where xy
denotes the year.
How does
CXX_STD
=CXX11
work? How isCXX11
here related toCXX11
in ~/.R/Makevars?
This sets the compilation and linking for the language to be done with the C++11 compiler set by CXX11
. By specifying CXX11
, you are specifying a variable in Make
that will be used to compile the file under the recipe:
$(OBJCXX) $(ALL_CPPFLAGS) $(ALL_OBJCXXFLAGS) -c $< -o $@
where $(OBJCXX)
is CXX
, $(ALL_CPPFLAGS)
is given by $(R_XTRA_CPPFLAGS) $(PKG_CPPFLAGS) $(CLINK_CPPFLAGS) $(CPPFLAGS)
, and $(ALL_OBJCXXFLAGS)
has $(PKG_OBJCXXFLAGS) $(CXXPICFLAGS) $(SHLIB_CXXFLAGS) $(OBJCXXFLAGS)
.
The above follows /R/Makeconf.in
. However, the routine may be /m4/R
.
What is the relationship between
CXXFLAGS
andPKG_CXXFLAGS
(not included in my example)?
Both of these specify the compiler's compilation flags. The order in which they are written in the Makevars
is different. In particular, we have
CXXFLAGS
placed after PKG_CXXFLAGS
. The right most option is always used. So, CXXFLAGS
takes precedence over PKG_CXXFLAGS
.
There is a brief note on PKG_*
options in Writing R Extensions: Section 5.5 Creating shared objects.
Addendum
The following are questions that were asked by @Dominik in the comment section of this response.
Is it correct that variables defined in
~/.R/Makevars
apply globally to the installation of all packages, while variables in/src/Makevars
only apply to the present package?
Yes. This is accurate. Variables within ~/.R/Makevars
will apply to all packages while the /src/Makevars
that ships with each package will only influence settings for that package. The values in /src/Makevars
will take precedence over ~/.R/Makevars
.
Some packages may ship with /src/Makevars.win
, which provides a Makevars
file specifically for the Windows environment.
Is the compilation standard used for a packages nowadays only set via
CXX_STD
and not any more byPKG_CXXFLAGS
as shown in gallery.rcpp.org/articles/simple-lambda-func-c++11?
There is a slight difference between when these two flags should be used. In particular, CXX_STD
is only operational in a package environment. Meanwhile, contrary to its name, PKG_CXXFLAGS
, affects all compile options. Thus, when you quote the above Rcpp gallery post, you are observing a standalone script being run. To quickly engage the correct mode, that requires PKG_CXXFLAGS
to be set and not the CXX_STD
definition.
Now, forgive me for going on a brief tangent on the history of standalone use compilation options.... The use of PKG_CXXFLAGS
is a bit old school. In fact, the preferred approach in R 3.4 is to set the environment variable USE_CXX11 = "yes"
. Between R 3.1 and R 3.3, the standard was to set the environment variable USE_CXX1X = "yes"
. Prior to those instances, the use of PKG_CXXFLAGS ="-std=c++11"
was preferred. (Except on Windows, which needed PKG_CXXFLAGS ="-std=c++0x"
.)
Does using
CXX_STD=CXX11
then mean to use all the settings given byCXX
,CXXSTD
,CXXFLAGS
andCXX11PICFLAGS
?
No. This means to use options set by:
CXX11 CXX11STD CXX11FLAGS CXX11PICFLAGS