首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于Rmarkdown文件的条件渲染的Makefile

用于Rmarkdown文件的条件渲染的Makefile
EN

Stack Overflow用户
提问于 2017-11-09 19:56:55
回答 1查看 514关注 0票数 2

我是一个Makefile新手,我想用它来渲染Rmarkdown文件,当他们改变了时间戳,以产生相应的.pdf文件。将文件data_prep_1.Rmd呈现为.pdf,并另外生成输出文件all_sample_data.csv。当data_prep_1.Rmd被更改(或其时间戳被更改)时,应该重新呈现它,就像../bioinformatics/Reads_by_sample.Rmddistance_matrices.Rmd一样,因为它们依赖于.csv文件。如果../bioinformatics/Reads_by_sample.Rmd的时间戳相对于其.pdf发生更改,则只应重新呈现此.Rmd文件。

将all :和.pdf.csv文件放在第一行将导致这两个块在每次调用make时都运行。

我有:

代码语言:javascript
复制
../../data/all_sample_data.csv : data_prep_1.Rmd
    Rscript -e "rmarkdown::render('data_prep_1.Rmd')"
    Rscript -e "rmarkdown::render('../bioinformatics/Reads_by_sample.Rmd')"
    Rscript -e "rmarkdown::render('distance_matrices.Rmd')"

../bioinformatics/Reads_by_sample.pdf :  ../bioinformatics/Reads_by_sample.Rmd
    Rscript -e "rmarkdown::render('../bioinformatics/Reads_by_sample.Rmd')"

如果我执行touch data_prep_1.Rmd,然后执行make,那么第一个块就会按预期运行。

但是如果我做了touch ../bioinformatics/Reads_by_sample.Rmd,那么make

我得到了make: '../../data/all_sample_data.csv is up to date'

我知道这是对Makefile的笨拙使用,但是我如何在一个Makefile中获得我想要的行为呢?

EN

回答 1

Stack Overflow用户

发布于 2017-11-10 22:51:54

上面的注释令人困惑,但隐藏了答案。

make运行时,它不会尝试在makefile中构建每个单独的目标。相反,它只尝试在makefile中构建第一个目标。在您的makefile中,第一个目标是../../data/all_sample_data.csv,因此这是make将尝试构建的唯一目标。

您可以通过将其他目标添加到命令行来使用它来构建其他目标;例如make ../bioinformatics/Reads_by_sample.pdf

如果您总是想要一组特定的目标,那么您要做的就是创建一个新目标作为makefile中的第一个目标,它列出了您想要创建的所有其他目标作为先决条件。按照惯例,但仅限于惯例,该目标通常称为all。所以它看起来像这样:

代码语言:javascript
复制
all: ../../data/all_sample_data.csv ../bioinformatics/Reads_by_sample.pdf
.PHONY: all

../../data/all_sample_data.csv : data_prep_1.Rmd
        Rscript -e "rmarkdown::render('data_prep_1.Rmd')"
        Rscript -e "rmarkdown::render('../bioinformatics/Reads_by_sample.Rmd')"
        Rscript -e "rmarkdown::render('distance_matrices.Rmd')"

../bioinformatics/Reads_by_sample.pdf :  ../bioinformatics/Reads_by_sample.Rmd
        Rscript -e "rmarkdown::render('../bioinformatics/Reads_by_sample.Rmd')"

.PHONY不是必需的,但它很有用,它告诉make all不是一个真正的文件,而只是makefile中的一个虚拟目标。

您还应该考虑创建一些make变量并使用automatic variables来简化您的makefile,例如:

代码语言:javascript
复制
BIODIR := ../bioinformatics
DATADIR := ../../data

all: $(DATADIR)/all_sample_data.csv $(BIODIR)/Reads_by_sample.pdf
.PHONY: all

$(DATADIR)/all_sample_data.csv : data_prep_1.Rmd
        Rscript -e "rmarkdown::render('$<')"
        Rscript -e "rmarkdown::render('$(BIODIR)/Reads_by_sample.Rmd')"
        Rscript -e "rmarkdown::render('distance_matrices.Rmd')"

$(BIODIR)/Reads_by_sample.pdf :  $(BIODIR)/Reads_by_sample.Rmd
        Rscript -e "rmarkdown::render('$<')"

如果你有很多这样的文件,你可以更进一步,使用模式规则等等。

而且,您的第一个目标似乎不仅应该依赖于data_prep_1.Rmd,还应该依赖于distance_matrices.RmdReads_by_sample.Rmd;如果这些更改中的任何一个,您不想重新构建吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47201240

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档