Makevars 文件,在Writing R Extensions: 1.2.1 Using Makevars 中指定,是Make 的一个变体,对于R 来说是唯一。您列出的许多变量都称为implicit variables。含义如下:
隐式规则告诉 make 如何使用惯用的技术,这样您在使用它们时就不必详细指定它们。
这些implicit variables
规定应该使用 what 编译器并且 what 选项可用。
在R中,我们关心以下默认编译器选项:
CC 编译C程序的程序;默认‘抄送’。
CXX 编译C++程序的程序;默认‘g++’。
CPP 用于运行 C 预处理器的程序,并将结果输出到标准输出;默认‘$(CC) -E’。
FC 用于编译或预处理 Fortran 和 Ratfor 程序的程序;默认为“f77”。
下一组值详细说明了编译器应该使用的什么选项。通常,所有这些选项的默认值都是空字符串。
CFLAGS 提供给 C 编译器的额外标志。
CXXFLAGS 提供给 C++ 编译器的额外标志。
CPPFLAGS 提供给 C 预处理器和使用它的程序(C 和 Fortran 编译器)的额外标志。
FFLAGS 提供给 Fortran 编译器的额外标志。
LDFLAGS 在编译器应该调用链接器时提供给编译器的额外标志,“ld”,例如 -L。应添加库 (-lfoo)
改为 LDLIBS 变量。
LDLIBS 当编译器应该调用链接器“ld”时为编译器提供的库标志或名称。 LOADLIBES 已被弃用(但
仍然支持)替代 LDLIBS。非库链接器标志,例如
作为 -L,应该放在 LDFLAGS 变量中。
现在,R 根据不同的 C++ ISO 标准定义了“额外的”变体。这些变体在R Administration: Section 2.7.2 C++ Support 和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
说了这么多,我们来解决第一个问题:
CXX和CXX98、CXX11和CXX14是什么关系?
CXX 是要使用的通用编译器选项。同时,R 定义了额外的CXX 选项以根据检测到的编译标准使用。也就是说,如果-std=c++98(CXX98 语言规范)由CXX_STD 设置,则使用与CXX98 关联的编译器。同样,对于CXX11 和CXX14,遵循相同的逻辑。详情请见Rcpp Gallery: Using Rcpp with C++11, C++14 and C++17。
如果已经隐含了 C++11,例如 CXX11STD = -std=c++11 的含义是什么?是在选择-std=c++11 和-std=gnu++11 之间吗?出于便携性原因,是否应该避免使用 -std=gnu++11?
CXX11STD的含义是确定适合C++11编译的语言标准。这个选项之所以存在只是因为如果R 选择的适当C++11 编译选项的版本对于编译器不正确,您可以更改它。存在这种情况的原因是因为每个编译器定义的 C++11 支持可能与 R Installation and Administration: 2.7.2 C++ Support 中所示的下一个编译器略有不同:
可能是 [脚注 13] 没有适合 C++11 支持的标志,在这种情况下,可以为 CXX11 及其相应标志选择不同的编译器。
脚注 13:
对于早期版本的 g++(例如 4.2.1)和 Solaris 编译器 CC 的常用版本也是如此。
有关 gcc 批准的语言标准的详细信息,请参阅GCC Manual: 3.4 Options Controlling C Dialect。此外,有关在包中使用带有 R 的 C++11 的详细信息,请参阅Writing R Extensions: Section 1.2.4 Using C++11 Code。
通常,我会避免显式设置此变量。如果您必须显式设置此变量,我建议您使用-std=c++11,因为大多数编译器都支持此声明。
CXXSTD 和 CXXFLAGS 的标志是否可以不只是添加到 CXX,这样前三行会减少到 CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer。明确指定CXXSTD 和CXXFLAGS 有什么好处?
有可能吗?是的。这样对吗?没有。
为什么我们可以只拥有一个三个变量?
三个变量工作流程的优势在于为不同的生产线提供了不同的角色。这允许快速理解编译选项的能力。因此,与将其塞入一行中的一个变量(终端宽度为 80)相比,它更容易理解。
例如
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 表示年份。
CXX_STD = CXX11 是如何工作的?这里的CXX11 与~/.R/Makevars 中的CXX11 有什么关系?
这会将语言的编译和链接设置为使用 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。但是,例程可能是/m4/R。
CXXFLAGS 和PKG_CXXFLAGS 之间是什么关系(我的示例中没有包含)?
这两个都指定了编译器的编译标志。它们在Makevars 中的写入顺序不同。特别是,我们有
CXXFLAGS placed after PKG_CXXFLAGS。 正确大多数选项总是使用。因此,CXXFLAGS 优先于 PKG_CXXFLAGS。
Writing R Extensions: Section 5.5 Creating shared objects 中有一个关于PKG_* 选项的简要说明。
附录
以下是@Dominik 在此回复的评论部分提出的问题。
~/.R/Makevars 中定义的变量是否全局适用于所有包的安装,而/src/Makevars 中的变量只适用于当前包?
是的。这是准确的。 ~/.R/Makevars 中的变量将应用于所有包,而每个包附带的/src/Makevars 只会影响该包的设置。 /src/Makevars 中的值将优先于 ~/.R/Makevars。
某些软件包可能附带/src/Makevars.win,它提供了一个专门用于Windows 环境的Makevars 文件。
现在用于包的编译标准是否仅通过CXX_STD 设置,而不再由PKG_CXXFLAGS 设置,如gallery.rcpp.org/articles/simple-lambda-func-c++11 所示?
这两个标志的使用时间略有不同。特别是,CXX_STD 只能在包环境中运行。同时,与其名称相反,PKG_CXXFLAGS 会影响所有编译选项。因此,当您引用上述 Rcpp 库帖子时,您正在观察正在运行的独立脚本。要快速启用正确的模式,需要设置 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"。)
使用CXX_STD=CXX11 是否意味着使用CXX、CXXSTD、CXXFLAGS 和CXX11PICFLAGS 给出的所有设置?
没有。这意味着使用通过以下方式设置的选项:
CXX11
CXX11STD
CXX11FLAGS
CXX11PICFLAGS