了解 R 中 Makevars 文件的内容(宏、变量、~/.R/Makevars 和 pkg/src/Makevars)

Understanding the contents of the Makevars file in R (macros, variables, ~/.R/Makevars and pkg/src/Makevars)

我想了解 macros/variables 在 ~/.R/Makevarspackage_directory/src/Makevars 中设置的作用和关系,当 installing/building 拥有 R 包时。假设这些文件看起来像

~/.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

据我了解,使用 CXX 我们可以 select 在构建 R 包时使用 C++ 编译器,使用 CXXSTD 我们选择标准,使用 CXXFLAGS 我们添加编译器标志。使用 PKG_CPPFLAGS 我们为 C++ 预处理器添加标志,使用 CXX_STD 我们告诉我们的包使用 C++11。

我有以下问题:

我知道 Writing R Extensions and R Installation and Administration 中包含的信息,但我无法提取超出我目前理解水平的更多信息来回答上述问题。

我添加了一个 Rcpp 标签,因为我认为这些问题的答案与 Rcpp 的用户最相关,但我知道这可能与 [=] 没有直接关系41=],因此如果认为合适,可能会删除标签。

Makevars 文件,如 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 中所指定。给出的含义为:

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.

这些implicit variables 指示应该使用 what 编译器并且 what 选项可用。

R 中,我们关心以下默认编译器选项:

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

下一组值详细说明编译器应使用的选项。通常,所有这些选项的默认值都是空字符串。

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.

现在,R 根据不同的 C++ ISO 标准定义了 "extra" 变体。这些变体在 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


说到这里,我们来解决第一个问题:

What is the relationship between CXX and CXX98, CXX11 and CXX14?

CXX 是要使用的一般编译器选项。同时,R 根据检测到的编译标准定义了额外的 CXX 选项。也就是说,如果 -std=c++98CXX98 语言规范)由 CXX_STD 设置,则使用与 CXX98 关联的编译器。类似地,对于 CXX11CXX14,遵循相同的逻辑。有关详细信息,请参阅 Rcpp Gallery: Using Rcpp with C++11, C++14 and C++17


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?

CXX11STD的意思是确定适合C++11编译的语言标准。这个选项的存在只是因为如果R选择合适的C++11编译选项的版本对于编译器来说是不正确的,你可以改变它。存在这种情况的原因是因为每个编译器对 C++11 支持的定义可能与 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.

脚注 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.

有关 gcc 批准的语言标准的详细信息,请参阅 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

一般来说,我会避免显式设置这个变量。如果您必须显式设置此变量,我建议使用 -std=c++11,因为大多数编译器都支持此声明。


Could the flags for CXXSTD and CXXFLAGS not just be added to CXX, such that the first three lines reduce to CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer. What is the advantage in explicitly specifying CXXSTD and CXXFLAGS?

可能吗?是的。这样对吗?编号

为什么有 三个 个变量,每个变量都有自己的目标,而我们只能有一个?

三个 可变工作流的优点是提供不同的线路,每个线路都有不同的作用。这允许快速理解编译选项的能力。因此,与将它塞进一行中的一个变量(终端宽度为 80)相比,grok 更直接。

例如

CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer

CXX = g++ 
CXX11STD = -std=c++11
CXXFLAGS = -fsanitize=undefined,address -fno-omit-frame-pointer

此外,如Writing R Extensions: Section 1.2.4 Using C++11 Code所示打包时,您应该选择CXX_STD而不是CXXSTD。这只是为了确保 R 将包注册为需要 C++xy。另一种方法是在 DESCRIPTION 文件中写入属性 SystemRequirements: C++xy,其中 xy 表示年份。


How does CXX_STD = CXX11 work? How is CXX11 here related to CXX11 in ~/.R/Makevars?

这设置了要使用 CXX11 设置的 C++11 编译器完成的语言的编译和链接。通过指定 CXX11,您指定了一个 variable in Make,它将用于编译配方下的文件:

$(OBJCXX) $(ALL_CPPFLAGS) $(ALL_OBJCXXFLAGS) -c $< -o $@

其中 $(OBJCXX)CXX$(ALL_CPPFLAGS)$(R_XTRA_CPPFLAGS) $(PKG_CPPFLAGS) $(CLINK_CPPFLAGS) $(CPPFLAGS) 给出,而 $(ALL_OBJCXXFLAGS)$(PKG_OBJCXXFLAGS) $(CXXPICFLAGS) $(SHLIB_CXXFLAGS) $(OBJCXXFLAGS) .

以上为/R/Makeconf.in. However, the routine may be /m4/R.


What is the relationship between CXXFLAGS and PKG_CXXFLAGS (not included in my example)?

这两个都指定了编译器的编译标志。 Makevars 中的顺序不同。特别地,我们有 CXXFLAGS placed after PKG_CXXFLAGS正确大多数选项是总是使用。所以,CXXFLAGS优先于PKG_CXXFLAGS.

Writing R Extensions: Section 5.5 Creating shared objects 中有关于 PKG_* 选项的简短说明。

附录

以下是@Dominik 在此回复的评论部分提出的问题。


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?

是的。这是准确的。 ~/.R/Makevars 中的变量将应用于所有包,而每个包附带的 /src/Makevars 只会影响该包的设置。 /src/Makevars 中的值将优先于 ~/.R/Makevars.

一些软件包可能附带 /src/Makevars.win,它提供了专门用于 Windows 环境的 Makevars 文件。


Is the compilation standard used for a packages nowadays only set via CXX_STD and not any more by PKG_CXXFLAGS as shown in gallery.rcpp.org/articles/simple-lambda-func-c++11?

这两个标志的使用时间略有不同。特别是,CXX_STD 只能在包环境中运行。同时,与其名称相反,PKG_CXXFLAGS 影响所有编译选项。因此,当您引用上面的 Rcpp 库 post 时,您正在观察一个独立的脚本 运行。要快速进入正确的模式,需要设置 PKG_CXXFLAGS 而不是 CXX_STD 定义。

现在,请原谅我在独立使用编译选项的历史上进行简短的切线....PKG_CXXFLAGS的使用有点老派.事实上,R 3.4 中的首选方法是设置环境变量 USE_CXX11 = "yes"。在 R 3.1 和 R 3.3 之间,标准是设置环境变量 USE_CXX1X = "yes"。在这些情况之前,首选使用 PKG_CXXFLAGS ="-std=c++11"。 (Windows 除外,它需要 PKG_CXXFLAGS ="-std=c++0x"。)


Does using CXX_STD=CXX11 then mean to use all the settings given by CXX, CXXSTD, CXXFLAGS and CXX11PICFLAGS?

没有。这意味着使用由以下设置的选项:

CXX11 CXX11STD CXX11FLAGS CXX11PICFLAGS