Writing R Extensions: 1.2.1 Using Makevars中指定的Makevars
文件是Make
的一个变体,即unique到R.您列出的许多变量称为implicit variables.其含义如下:
隐式规则告诉make如何使用惯用技术,这样当你想使用它们时,就不必详细指定它们.
这implicit variables
在R范围内,我们关心以下默认编译器选项:
CC个用于编译C程序的程序;默认为"cc".
CXX编译C++程序的程序;默认值为"g++".
CPP个用于运行C预处理器的程序,结果为标准输出;默认值"$(CC)-E".
FC个用于编译或预处理Fortran和Ratfor程序的程序;默认值为"f77".
编译器应该使用下一组值details what选项.通常,所有这些选项的默认值都是空字符串.
给C编译器额外的CFLAGS个标志.
CXXFLAGS个额外的标志给C++编译器.
为C预处理器和使用它的程序(C和Fortran编译器)提供CPPFLAGS个额外的标志.
为Fortran编译器提供FFLAGS个额外标志.
当编译器应该调用链接器"ld"时,应该添加LDFLAGS个额外的标志,例如-L.库(-lfoo)
当编译器应该调用链接器"ld"时,为其提供LDLIBS个库标志或名称.LOADLIBES是一个不推荐使用的(但是
现在,R定义了"不同"的C++不同的ISO标准.这些变体在R Administration: Section 2.7.2 C++ Support和R Administration: Section B.7 Compile and load flags中给出
CXX98
CXX11
CXX14
CXX17
说到这里,我们来回答第一个问题:
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=gnu++11
和-std=c++11
之间 Select ?出于便携性的原因,通常应该避免使用-std=gnu++11
吗?
CXX11STD
的意思是为C++11编译确定合适的语言标准.这个选项之所以存在,只是因为如果R版本的 Select 适当的C++11编译选项对编译器不正确,您可以更改它.之所以存在这种情况,是因 for each 编译器定义的C++11支持可能与R Installation and Administration: 2.7.2 C++ Support中的下一个略有不同:
可能是[Footnote 13]没有适合C++11支持的标志,在这种情况下,可以为CXX11及其相应的标志 Select 不同的编译器.
脚注13:
对于g++的早期版本,如4.2.1,以及Solaris编译器CC的常用版本,都是如此.
有关gcc批准的语言标准的详细信息,请参见GCC Manual: 3.4 Options Controlling C Dialect.此外,有关在包中使用C++11和R的详细信息,请参见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
有什么好处?
可能吗?对对吗?不
为什么three个变量都有自己的目标,而我们只需要一个?
three个变量的工作流的优点是为不同的行提供了不同的角色.这样就可以快速理解编译选项.因此,当它被塞进一行上的一个变量(终端宽度为80)时,grok要简单得多.
例如
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
此外,当包装如图Writing R Extensions: Section 1.2.4 Using C++11 Code所示时,你应该 Select CXX_STD
而不是CXXSTD
.这只是为了确保R将包注册为需要C++xy.另一种方法是在DESCRIPTION
文件中写入属性SystemRequirements: C++xy
,其中xy
表示年份.
CXX_STD
=CXX11
是如何工作的?这里的CXX11
和~/中的CXX11
有什么关系.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
.然而,例行程序可能是/m4/R
.
CXXFLAGS
和PKG_CXXFLAGS
之间的关系是什么(不包括在我的示例中)?
这两者都指定编译器的编译标志.它们在Makevars
中的书写顺序是不同的.特别是,我们有
这里有一个关于Writing R Extensions: Section 5.5 Creating shared objects个选项中PKG_*
个选项的简要说明.
补遗
以下是@Dominik在本回复的 comments 部分提出的问题.
~/.R/Makevars
中定义的变量全局适用于所有软件包的安装,而/src/Makevars
中的变量仅适用于当前软件包,这是否正确?
对这是准确的.~/.R/Makevars
以内的变量将应用于所有软件包,而每个软件包附带的/src/Makevars
只会影响该软件包的设置./src/Makevars
中的值优先于~/.R/Makevars
.
有些软件包可能附带/src/Makevars.win
,它专门为Windows环境提供Makevars
文件.
是目前用于软件包的编译标准,仅通过CXX_STD
设置,不再通过PKG_CXXFLAGS
设置,如图库所示.rcpp.org/articles/simple-lambda-func-c++11?
使用这两个标志的时间略有不同.特别是,CXX_STD
仅在软件包环境中运行.同时,与它的名字PKG_CXXFLAGS
相反,PKG_CXXFLAGS
影响所有编译选项.因此,当您引用上述Rcpp gallery帖子时,您看到的是一个正在运行的独立脚本.要快速进入正确的模式,需要设置PKG_CXXFLAGS
,并使用CXX_STD
定义.
现在,请原谅我简单介绍一下standalone use个编译选项的历史....PKG_CXXFLAGS
的用法有点老套.事实上,R3.4中的首选方法是设置环境变量USE_CXX11 = "yes"
.在R3.1和R3.3之间,标准是设置环境变量USE_CXX1X = "yes"
.在这些实例之前,优选使用PKG_CXXFLAGS ="-std=c++11"
.(Windows除外,它需要PKG_CXXFLAGS ="-std=c++0x"
个.)
那么,使用CXX_STD=CXX11
是否意味着使用CXX
、CXXSTD
、CXXFLAGS
和CXX11PICFLAGS
给出的所有设置?
否.这意味着使用以下设置的选项:
CXX11