在安装/构建自己的R软件包时,我试图了解~/.R/Makevars
和package_directory/src/Makevars
中设置的宏/变量的角色和关系。假设这些文件看起来像
〜/ .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
我们可以在构建R包时为C ++选择编译器,CXXSTD
我们选择标准,而CXXFLAGS
我们添加编译器标志。使用PKG_CPPFLAGS
我们为C ++预处理器和CXX_STD
添加标志,我们告诉我们的包使用C ++ 11。
我有以下问题:
CXX
与CXX98
,CXX11
和CXX14
之间的关系是什么?CXX11STD = -std=c++11
是什么意思?是在选择-std=c++11
和-std=gnu++11
之间吗?出于便携性原因,通常应该避免-std=gnu++11
吗?CXXSTD
和CXXFLAGS
的标记是否可以添加到CXX
,以便前三行减少到CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer
。明确指定CXXSTD
和CXXFLAGS
?CXX_STD = CXX11
如何运作? CXX11
如何与CXX11
中的~/.R/Makevars
相关联?CXXFLAGS
和PKG_CXXFLAGS
之间的关系是什么(我的示例中未包含)? 我知道Writing R Extensions和R Installation and Administration中包含的信息,但我无法提取超出目前理解水平的更多信息来回答上述问题。
我正在添加Rcpp
代码,因为我认为这些问题的答案与Rcpp
的用户最相关,但我知道这可能与{{1}没有直接关系},因此如果认为合适,标签可能会被移除。
答案 0 :(得分:72)
Writing R Extensions: 1.2.1 Using Makevars中指定的Makevars
文件是Make
的变体,唯一到R.您列出的许多变量都是叫implicit variables。含义如下:
隐式规则告诉您如何使用习惯技术,这样您就不必在使用它们时详细指定它们。
这些implicit variables 指示应该使用什么编译器以及可用的选项。
在 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的替代方案。非库链接器标志,例如 as -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)时,它更直接。
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
此外,如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