Makevars
文件是
编写R扩展:1.2.1使用Makevars中指定的一种
Make
变体,它是R所特有的。你列出的许多变量被称为
隐式变量。意义如下:
隐式规则告诉make如何使用惯用技术,以便在您想要使用它们时不必详细说明。
这些隐式变量决定了应该使用哪个编译器和哪些选项可用。
在R中,我们关心以下默认编译器选项:
CC:用于编译C程序的程序;默认值为“cc”。
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标准定义了“extra”变量。这些变量列在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
选项。也就是说,如果由 CXX_STD
设置为 -std=c++98
(CXX98
语言规范),则使用与 CXX98
相关联的编译器。同样地,对于 CXX11
和 CXX14
,也是按照同样的逻辑进行处理。有关更多详细信息,请参见 Rcpp Gallery: Using Rcpp with C++11, C++14 and C++17。
例如,CXX11STD = -std=c++11
的意义是确定C++11编译的适当语言标准。存在这个选项仅仅是因为如果R选择适当的C++11编译选项的版本不正确,则可以更改它。之所以存在这个选项是因为每个编译器对C++11的支持可能略有不同,如R Installation and Administration: 2.7.2 C++ Support所示:
可能没有适合C++11支持的标志,此时可以为CXX11选择不同的编译器及其相应的标志。
脚注13:
这适用于早期版本的g++(如4.2.1),以及常用的Solaris编译器CC版本。有关gcc批准的语言标准的详细信息,请参见
GCC手册:3.4控制C方言的选项。此外,有关在软件包中使用C ++ 11与R的详细信息,请参见
编写R扩展:第1.2.4节使用C ++ 11代码。通常,我会避免显式设置此变量。如果必须显式设置此变量,我建议选择
-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
此外,在打包时应选择
CXX_STD
而非
CXXSTD
,如
编写R扩展:1.2.4节 使用C++11代码所示。这是为了确保R将包注册为需要C++xy。另一种选择是在
DESCRIPTION
文件中编写属性
SystemRequirements: C++xy
,其中
xy
表示年份。请注意,需保留HTML标签。
这里的
CXX_STD
=
CXX11
是如何工作的?这里的
CXX11
与
~/.R/Makevars
中的
CXX11
有什么关系?
这将设置使用由
CXX11
指定的C++11编译器进行语言的编译和链接。通过指定
CXX11
,您正在指定一个
在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
中书写的顺序不同。特别地,我们有在 PKG_CXXFLAGS
后面放置了 CXXFLAGS
。总是使用最右边的选项。 因此,CXXFLAGS
优先于 PKG_CXXFLAGS
。
PKG_*
选项有一个简短的注释,在编写 R 扩展:第 5.5 节创建共享对象中有介绍。
补充说明
以下是 @Dominik 在此回答的评论部分提出的问题。
是这样的。在
~/.R/Makevars
中定义的变量会全局应用于所有包,而在
/src/Makevars
中定义的变量仅适用于当前包。在
/src/Makevars
中的值将优先于
~/.R/Makevars
。有些包可能会附带
/src/Makevars.win
,该文件专门针对Windows环境提供
Makevars
文件。
现在用于软件包编译标准的设置只能通过进行,并不再使用像gallery.rcpp.org/articles/simple-lambda-func-c++11中展示的。这两个标志的使用时有细微差别,特别是仅在软件包环境中操作。与其名称相反,会影响所有编译选项。因此,当引用上述Rcpp画廊文章时,您正在观察一个独立的脚本运行。为了快速进入正确模式,需要设置而不是定义。
现在,请原谅我稍微离题,讲一下关于独立编译选项的历史... 使用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"
)。
使用是否意味着使用、、和中给出的所有设置?
不是。这意味着使用以下选项设置:
~/.R/Makevars
中定义的变量是否适用于所有软件包安装,而/src/Makevars
中的变量仅适用于当前软件包? ii)现在,用于软件包的编译标准只通过CXX_STD
设置,不再使用PKG_CXXFALGS
,如http://gallery.rcpp.org/articles/simple-lambda-func-c++11/所示吗? iii)使用CXX_STD=CXX11
是否意味着使用CXX
,CXXSTD
,CXXFALGS
和CXX11PICFLAGS
给出的所有设置? - NoBackingDown~/.R/Makevars
是什么?我在Windows上。我正在使用sourceCpp()编译一个简单的模型。我想抑制-Wreorder警告。谢谢。 - Simon Woodwardtools::makevars_user()
找到Makevars
文件。我成功地通过添加PKG_CXXFLAGS = -Wno-reorder
来更改了sourceCpp()
的编译器选项。 - Simon WoodwardCC=gcc-7.3.1 CXX=g++7.3.1 CXX_STD=CXX CXX1X=g++-7.3.1 SHLIB_CXXLD=g++-7.3.1
,但当我尝试编译Rcpp时会出现错误。 - JerryN