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

时间:2017-04-24 20:59:49

标签: r rcpp

在安装/构建自己的R软件包时,我试图了解~/.R/Makevarspackage_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。

我有以下问题:

  • CXXCXX98CXX11CXX14之间的关系是什么?
  • 如果已经隐含了C ++ 11,那么CXX11STD = -std=c++11是什么意思?是在选择-std=c++11-std=gnu++11之间吗?出于便携性原因,通常应该避免-std=gnu++11吗?
  • CXXSTDCXXFLAGS的标记是否可以添加到CXX,以便前三行减少到CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer。明确指定CXXSTDCXXFLAGS
  • 有什么好处
  • CXX_STD = CXX11如何运作? CXX11如何与CXX11中的~/.R/Makevars相关联?
  • CXXFLAGSPKG_CXXFLAGS之间的关系是什么(我的示例中未包含)?

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

我正在添加Rcpp代码,因为我认为这些问题的答案与Rcpp的用户最相关,但我知道这可能与{{1}没有直接关系},因此如果认为合适,标签可能会被移除。

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

中给出
  

CXX98   CXX98STD   CXX98FLAGS   CXX98PICFLAGS

     

CXX11   CXX11STD   CXX11FLAGS   CXX11PICFLAGS

     

CXX14   CXX14STD   CXX14FLAGS   CXX14PICFLAGS

     

CXX17   CXX17STD   CXX17FLAGS   CXX17PICFLAGS

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

  

CXXCXX98CXX11CXX14之间的关系是什么?

CXX是要使用的常规编译器选项。同时, R 根据检测到的编译标准定义要使用的其他CXX选项。也就是说,如果由-std=c++98设置CXX98CXX_STD语言规范),则使用与CXX98关联的编译器。同样,对于CXX11CXX14,遵循相同的逻辑。有关详细信息,请参阅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,因为大多数编译器都支持此声明。

  

CXXSTDCXXFLAGS的标记是否可以添加到CXX,以便前三行减少到CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer。明确指定CXXSTDCXXFLAGS

有什么好处

有可能吗?是。这样对吗?否。

为什么三个变量每个都有自己的目标,而我们只能拥有一个?

三个变量工作流程的优势提供了不同的行,每个行都有不同的角色。这允许快速理解编译选项的能力。因此,当它被塞入一条线上的一个变量(终端宽度为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

  

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

没有。这意味着使用以下设置的选项:

  

CXX11   CXX11STD   CXX11FLAGS   CXX11PICFLAGS