如何使用带有R CMD构建的Makefile

bde*_*caf 8 makefile r

我正在开发一个R包.它基于仅使用Makefile的项目.大部分内容都很容易转换为R CMD build工作流程.然而,我需要创建的pdfs有点复杂,除非我修补,否则我没有把它们弄好 - 到目前为止,我想到了如何使用Makefile.

在R包文档中,我找到了使用Makefile作为源代码甚至是vignet的参考.

我不明白应该如何应用这些.从这些文档中我得到的印象Makefiles将在进程中被调用,R CMD build但是当我将Makefile放在所描述的目录中时,它们将被忽略.然而,R CMD check识别它们并输出通过测试.

我也看到了一些R CMD build内部调用的Makefile - 但我一直想知道这些在我使用时会如何执行install.packages.这似乎不对 - 我的意思是为什么R CMD check这些如果它不关心.R包中还有关于添加的这个页面SystemRequiremens: GNU make - 为什么这个文件你不使用?

那么现在最好的做法是什么?我可以看一下野外的例子吗?

更新

正如我被问到一个例子

我想构建一个与"编写包装晕影"中描述的相似的小插图.有一个主Latex文件,其中包含几个Rnw文件.具体的困境是:

  1. 如何构建pdf插图?
  2. 我如何强制执行依赖 - 显然rnws需要先渲染
  3. Rnw需要慢慢计算的数据,既不打算进入包,也不打算进入repo(它是几千兆字节) - 但它在构建过程中会重复使用几次.

到目前为止我用Makefile做了,一般模式是这样的:

tmp/test.pdf: tmp/test.tex tmp/rnw1.tex tmp/rnw2.tex
    latexmk -outdir=$(@D) $<

tmp/%.tex: r/%.rnw
    Rscript -e "knitr::knit('$<', output='$@')"

tmp/rnw1.tex tmp/rnw2.tex: tmp/slowdata.Rdata

tmp/slowdata.Rdata: r/ireallytakeforever.R
    Rscript $<
Run Code Online (Sandbox Code Playgroud)

Tec*_*e01 6

Bdecaf,

好的,回答版本2.0 - 轻笑.

您提到" 问题是Makefile和包构建工作流程应该如何结合在一起 ".在这种情况下,我建议您查看一组示例R包makefile:

knitrmakefile(在我看来)提供了如何构建护身符一个很好的例子.您需要查看makefile和目录结构,这将是我建议您查看和使用的模板.

我还建议你看看制造商,一个用于R包开发的Makefile.最重要的是,我将从Karl Broman指南开始- (这是我自己用作源参考的一段时间,现在已经被Hadley关于包装的书黯然失色但仍然有用(在我看来).

  • 最小化:Make的最小教程
  • R包底漆.

另一个建议是阅读Rob Hynman之前提到过的文章

在他们之间,你应该能够做你要求的.除此之外,您还可以参考基础R包手册.

我希望以上有所帮助.

T.


参考页面:

最小化制作一个最小的教程 - 作者Karl Broman

我认为,可重复研究最重要的工具不是Sweaveknitr,而是GNU make.

例如,考虑与手稿相关的所有文件.在最简单的情况下,我会为每个图形添加一个R脚本,并为主文本添加一个LaTeX文件.然后是参考文件的BibTeX文件.

编译最终的PDF有点工作:

  • 通过R运行每个R脚本以生成相关数字.
  • 再运行乳胶,然后用bibtex再乳胶几次.

并且R脚本需要在latex之前运行,并且只有在它们已经改变时才运行.

一个简单的例子

GNU make使这很容易.在您的手稿目录中,您将创建一个名为Makefile的文本文件,其外观如下所示(此处使用pdflatex).

mypaper.pdf: mypaper.bib mypaper.tex Figs/fig1.pdf Figs/fig2.pdf
    pdflatex mypaper
    bibtex mypaper
    pdflatex mypaper
    pdflatex mypaper

Figs/fig1.pdf: R/fig1.R
    cd R;R CMD BATCH fig1.R

Figs/fig2.pdf: R/fig2.R
    cd R;R CMD BATCH fig2.R
Run Code Online (Sandbox Code Playgroud)

每批行指示要创建的文件(目标),它依赖的文件(先决条件),然后是从依赖文件构造目标所需的一组命令.请注意,带有命令的行必须以制表符(而不是空格)开头.

另一个很棒的特性:在上面的例子中,当fig1.R改变时你只构建fig1.pdf.请注意,依赖关系会传播.如果你改变fig1.R,那么fig1.pdf将会改变,所以mypaper.pdf将被重建.

一个奇怪的是:如果您需要更改目录以运行命令,请在与相关命令相同的行上执行cd.以下不起作用:

### this doesn't work ###
Figs/fig1.pdf: R/fig1.R
    cd R
    R CMD BATCH fig1.R
You can, however, use \ for a continuation line, line so:

### this works ###
Figs/fig1.pdf: R/fig1.R
    cd R;\
    R CMD BATCH fig1.R
Run Code Online (Sandbox Code Playgroud)

请注意,您仍然需要使用分号(;).

使用GNU make

您可能已经在计算机上安装了GNU make.在终端/ shell中输入make --version来查看.(在Windows上,转到此处下载make.)

要使用make:

  • 进入项目目录.
  • 创建Makefile文件.
  • 每次要构建项目时,请键入make.
  • 在上面的示例中,如果要在不构建mypaper.pdf的情况下构建fig1.pdf,只需键入make fig1.pdf即可.

褶边

您可以使用上述简单的make文件,指定目标文件,它们的依赖项以及创建它们的命令.但是你可以添加许多装饰,以节省一些打字.

以下是我使用的一些选项.(有关详细信息,请参阅make文档.)

变量

如果您要多次重复同一段代码,则可能需要定义一个变量.

例如,您可能希望使用标志--vanilla运行R. 然后,您可以定义变量R_OPTS:

R_OPTS = - vanilla你将这个变量称为$(R_OPTS)(或$ {R_OPTS};允许使用括号或花括号),所以在R命令中你会使用像

cd R; R CMD BATCH $(R_OPTS)fig1.R这样做的一个优点是你只需要输入你想要的选项; 如果你改变主意想要使用的R选项,你只需要在一个地方更改它们.

例如,我实际上喜欢使用以下内容:

R_OPTS = - no-save --no-restore --no-init-file --no-site-file这就像--vanilla但没有--no-environ(我需要它,因为我使用.Renviron文件定义R_LIBS,说我在另一个目录中定义了R包).

自动变量

有一堆自动变量可以用来节省大量的输入.这是我最常用的:

$@    the file name of the target
$<    the name of the first prerequisite (i.e., dependency)
$^    the names of all prerequisites (i.e., dependencies)
$(@D)    the directory part of the target
$(@F)    the file part of the target
$(<D)    the directory part of the first prerequisite (i.e., dependency)
$(<F)    the file part of the first prerequisite (i.e., dependency)
Run Code Online (Sandbox Code Playgroud)

例如,在我们的简单示例中,我们可以简化线条

Figs/fig1.pdf: R/fig1.R
    cd R;R CMD BATCH fig1.R
Run Code Online (Sandbox Code Playgroud)

我们可以改写

Figs/fig1.pdf: R/fig1.R
    cd $(<D);R CMD BATCH $(<F)
Run Code Online (Sandbox Code Playgroud)

$(<D)在这种情况下,自动变量将采用第一个先决条件R的目录值.在这种情况下$(<F),将获取第一个先决条件的文件部分的值fig1.R.

好的,这不是真正的简化.这似乎没有多大优势,除非该目录可能是一个令人讨厌的长字符串,我们想避免必须输入两次.主要优势在于下一节.

模式规则

如果要以相同的方式构建多个文件,则可能需要使用模式规则.关键的想法是你可以使用符号%作为通配符,扩展为任何文本字符串.

例如,我们的两个数字基本上以相同的方式构建.我们可以通过包含一系列覆盖fig1.pdf和fig2.pdf的行来简化示例:

Figs/%.pdf: R/%.R
    cd $(<D);R CMD BATCH $(<F)
Run Code Online (Sandbox Code Playgroud)

这样可以节省输入并使文件更易于维护和扩展.如果要添加第三个数字,只需将其添加为mypaper.pdf的另一个依赖项(即先决条件).

我们的例子,有褶边

将所有这些添加到一起,这就是我们的示例Makefile的样子.

R_OPTS=--vanilla

mypaper.pdf: mypaper.bib mypaper.tex Figs/fig1.pdf Figs/fig2.pdf
    pdflatex mypaper
    bibtex mypaper
    pdflatex mypaper
    pdflatex mypaper

Figs/%.pdf: R/%.R
    cd $(<D);R CMD BATCH $(R_OPTS) $(<F)
Run Code Online (Sandbox Code Playgroud)

增加的装饰的优点是:减少打字,并且更容易扩展以包括额外的数字.缺点:对于不熟悉GNU Make的其他人来说,更难理解它正在做什么.

更复杂的例子

整个地方都有复杂的Makefile.捅github并研究它们.

以下是我自己的一些例子:

以下是Mike Bostock的一些例子:

也看看Makefile中一汇谢knitr[R .

同样令人感兴趣的是制造商,一个用于R包开发的Makefile.

资源


R包底漆

最小的教程

关于如何制作R包的最小教程.

R包是分发R代码和文档的最佳方式,尽管官方手册(Writing R Extensions)可能给出的印象,但它们的创建起来非常简单.

即使对于您不打算分发的代码,您也应该创建一个R包.如果它们在一个包中,你会发现更容易跟踪你自己的个人R功能.写文档很好,即使它只是为了你未来的自我.

Hadley Wickham了一本关于R包的书(免费在线;也可以从亚马逊以纸质形式获得 ).你可能会直接跳到那里.

希拉里·帕克写了一篇关于编写R包简短明了的教程.如果你想要一个速成课程,你应该从那里开始.很多人已经从她的指令中成功构建了R包.

但是拥有多样化的资源是有价值的,所以我想我会继续编写自己的最小教程.以下主题列表看起来令人生畏,但每个主题都简短明了(希望很清楚).如果你被主题列表所拖延,并且你还没有放弃我支持 Hadley的书,那你为什么不读 Hilary的教程呢?

如果有人还在我身边,以下几页介绍了制作R套餐的要点.

以下是重要但不重要的.

以下包含指向其他资源的链接:

如果这里的任何内容令人困惑(或错误!),或者如果我错过了重要的细节,请 提交一个问题,或者(甚至更好)为此网站分叉GitHub存储库,进行修改并提交拉取请求.


本教程的源代码在github上.

另请参阅我在git/github上的 教程, GNU make, knitr, 使用GitHub页面制作网站, 数据组织和可重复的研究.