理解R中Makevars文件的内容(宏,变量,〜/ .R/Makevars和pkg/src/Makevars)

NoB*_*own 48 r rcpp

我想了解在设置宏/变量的作用和关系,~/.R/Makevars以及package_directory/src/Makevars安装时/构建自己的R包.假设这些文件看起来像

〜/ .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
Run Code Online (Sandbox Code Playgroud)

package_directory/SRC/Makevars

PKG_CPPFLAGS = -I../inst/include
CXX_STD = CXX11
Run Code Online (Sandbox Code Playgroud)

据我所知,CXX我们可以在构建R包时为C++选择编译器,CXXSTD我们选择标准并CXXFLAGS添加编译器标志.随着PKG_CPPFLAGS我们为C++预处理器添加标志,CXX_STD我们告诉我们的包使用C++ 11.

我有以下问题:

  • 什么是之间的关系CXXCXX98,CXX11CXX14
  • 例如,CXX11STD = -std=c++11如果已经隐含了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.明确指定CXXSTDCXXFLAGS?的优点是什么?
  • CXX_STD = CXX11工作怎么样?如何CXX11在这里涉及到CXX11~/.R/Makevars
  • CXXFLAGS和之间的关系是什么PKG_CXXFLAGS(不包括在我的例子中)?

我知道编写R扩展R安装和管理中包含的信息,但我无法提取超出目前理解水平的更多信息来回答上述问题.

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

coa*_*ess 80

Makevars文件,在指定的写作R附加:1.2.1使用Makevars,是的变体Make独特的,以R.许多已上市被称为变量的隐含变量.含义如下:

隐式规则告诉如何使用习惯技术,以便在您想要使用它们时不必详细指定它们.

这些隐含变量 决定什么样的编译器应使用哪些选项.

R中,我们关注以下默认编译器选项:

用于编制C计划的CC计划; 默认'cc'.

用于编译C++程序的CXX程序; 默认'g ++'.

用于运行C预处理器的CPP程序,其结果为标准输出; 默认'$(CC)-E'.

用于编译或预处理Fortran和Ratfor程序的FC程序; 默认'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管理中给出:第2.7.2节C++支持R管理:第B.7节编译和加载标志

CXX98 CXX98STD CXX98FLAGS CXX98PICFLAGS

CXX11 CXX11STD CXX11FLAGS CXX11PICFLAGS

CXX14 CXX14STD CXX14FLAGS CXX14PICFLAGS

CXX17 CXX17STD CXX17FLAGS CXX17PICFLAGS


说完这个,让我们解决第一个问题:

什么是之间的关系CXXCXX98,CXX11CXX14

CXX是要使用的常规编译器选项.同时,RCXX根据检测到的编译标准定义了要使用的其他选项.也就是说,如果 -std=c++98(CXX98语言规范)设置为CXX_STD,则使用与之关联的编译器CXX98.同样,对于CXX11CXX14,同样的逻辑如下.有关更多详细信息,请参阅Rcpp Gallery:将Rcpp与C++ 11,C++ 14和C++ 17一起使用.


例如,CXX11STD = -std=c++11如果已经隐含了C++ 11,那意味着什么?是在选择-std=c++11-std=gnu++11?应该-std=gnu++11通常避免针对便携性的原因?

其含义CXX11STD是确定C++ 11编译的相应语言标准.此选项的存在只是因为如果R选择适当的C++ 11编译选项的版本对于编译器不正确,则可以更改它.这种情况的原因是因为每个编译器可能会定义C++ 11支持与下一个不同,如R安装和管理中所示:2.7.2 C++支持:

可能是[脚注13]没有适合C++ 11支持的标志,在这种情况下,可以为CXX11及​​其相应的标志选择不同的编译器.

脚注13:

对于早期版本的g ++(例如4.2.1)以及常用版本的Solaris编译器CC都是如此.

有关gcc批准的语言标准的详细信息,请参阅GCC手册:3.4控制C语言的选项.另外,有关在包中使用带有R的 C++ 11的详细信息,请参阅编写R扩展:第1.2.4节使用C++ 11代码.

通常,我会避免显式设置此变量.如果你必须明确设置这个变量,我建议你去,-std=c++11因为大多数编译器支持这个声明.


是否可以添加标志CXXSTD,CXXFLAGS而不只是添加CXX,以便前三行减少到CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer.明确指定CXXSTDCXXFLAGS?的优点是什么?

可能吗?是.这样对吗?没有.

当我们只有一个变量时,为什么有三个变量各自有自己的目标?

变量工作流程的优点是提供不同的行,每行都有不同的作用.这允许快速理解编译选项的能力.因此,当它被塞入一条线上的一个变量(终端宽度为80)时,它更直接.

例如

CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer
Run Code Online (Sandbox Code Playgroud)

VS

CXX = g++ 
CXX11STD = -std=c++11
CXXFLAGS = -fsanitize=undefined,address -fno-omit-frame-pointer
Run Code Online (Sandbox Code Playgroud)

此外,您应该在打包时选择CXX_STD结束CXXSTD,如编写R扩展:第1.2.4节"使用C++ 11代码"所示.这只是为了确保R将包注册为需要C++ xy.另一种方法是在DESCRIPTION文件中写入属性SystemRequirements: C++xy,其中xy表示年份.


怎么样CXX_STD= CXX11工作?CXX11在这里如何与CXX11〜/ .R/Makevars相关?

这将设置要使用C++ 11编译器设置的语言的编译和链接CXX11.通过指定CXX11,您将指定一个变量,Make用于在配方下编译文件:

$(OBJCXX) $(ALL_CPPFLAGS) $(ALL_OBJCXXFLAGS) -c $< -o $@
Run Code Online (Sandbox Code Playgroud)

这里$(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放置 PKG_CXXFLAGS.大多数选项始终使用.所以,CXXFLAGS优先于PKG_CXXFLAGS.

关于编写R扩展中的PKG_*选项的简要说明:第5.5节创建共享对象.

附录

以下是@Dominik在本回复的评论部分中提出的问题.


是否正确定义的变量~/.R/Makevars全局应用于所有包的安装,而变量/src/Makevars仅适用于当前包?

是.这是准确的.其中的变量~/.R/Makevars将适用于所有包,而/src/Makevars每个包附带的变量只会影响该包的设置.值/src/Makevars将优先于~/.R/Makevars.

某些软件包可能附带/src/Makevars.win,它提供Makevars专门用于Windows环境的文件.


现在用于包的编译标准是否仅通过gallery.rcpp.org/articles/simple-lambda-func-c++11中的设置CXX_STD而不是设置PKG_CXXFLAGS

应该使用这两个标志之间存在细微差别.特别是,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,CXXFLAGSCXX11PICFLAGS

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

CXX11 CXX11STD CXX11FLAGS CXX11PICFLAGS