在安装/构建自己的R包时,我试图理解~/.R/Makevars包目录/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

包目录/src/Makevars

PKG_CPPFLAGS = -I../inst/include
CXX_STD = CXX11

正如我所理解的,用CXX,我们可以在编译R包时 Select C++编译器,CXXSTD Select 标准,CXXFLAGS加编译器标志.用PKG_CPPFLAGS,我们为C++预处理器添加标志,CXX_STD则告诉我们包使用C++ 11.

我有以下问题:

  • CXXCXX98CXX11CXX14之间的关系是什么?
  • 如果已经暗示了C++11,例如CXX11STD = -std=c++11的含义是什么?在-std=gnu++11-std=c++11之间 Select ?出于便携性的原因,通常应该避免使用-std=gnu++11吗?
  • CXXSTDCXXFLAGS的标志是否可以被添加到CXX,这样前三行就可以减少到CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer.明确指定CXXSTDCXXFLAGS的优势是什么?
  • CXX_STD = CXX11是怎么工作的?这里的CXX11~/.R/Makevars中的CXX11有什么关系?
  • CXXFLAGSPKG_CXXFLAGS之间的关系是什么(不包括在我的示例中)?

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

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

推荐答案

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++ SupportR Administration: Section B.7 Compile and load flags中给出

CXX98

CXX11

CXX14

CXX17


说到这里,我们来回答第一个问题:

CXXCXX98CXX11CXX14之间的关系是什么?

CXX是要使用的通用编译器选项.同时,R根据检测到的编译标准定义了额外的CXX个选项.也就是说,如果-std=c++98(CXX98语言规范)设置为CXX_STD,则使用与CXX98相关联的编译器.类似地,对于CXX11CXX14,同样的逻辑如下.更多细节见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,因为大多数编译器都支持此声明.


CXXSTDCXXFLAGS的标志是否可以被添加到CXX,这样前三行就可以减少到CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer.明确指定CXXSTDCXXFLAGS有什么好处?

可能吗?对对吗?不

为什么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.


CXXFLAGSPKG_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是否意味着使用CXXCXXSTDCXXFLAGSCXX11PICFLAGS给出的所有设置?

否.这意味着使用以下设置的选项:

CXX11

R相关问答推荐

按条件计算观察次数

在ubuntu 22.04上更新到R4.4后包安装出现编译错误

高质量地将R格式的图表从Word中输出

根据固定值范围在tible中添加新行

根据收件箱中的特定值提取列名

如何 bootstrap glm回归、估计95%置信区间并绘制它?

然后根据不同的列值有条件地执行函数

lightgbm发动机在tidymmodels中的L1正则化""

如何在Chart_Series()中更改轴值的 colored颜色 ?

在R中无法读入具有Readxl和lApply的数据集

如何使用列表中多个列表中的第一条记录创建数据框

打印XTS对象

`lazy_dt`不支持`dplyr/across`?

R:用GGPLATE,如何在两个独立的变量中制作不同形状的散点图?

按组计算列中1出现的间隔年数

如何在反曲线图中更改X标签

随机将数据帧中特定列上的某些行设置为NA

如何将EC50值绘制在R中的剂量-react 曲线上?

如何获取R chromote中的当前URL?

具有自定义仓位限制和计数的GGPLATE直方图