【问题标题】:Makefile with multiple inputs and outputs具有多个输入和输出的 Makefile
【发布时间】:2012-10-19 05:35:19
【问题描述】:

我想使用 makefile 来更新由 R 代码生成的图形文件。 R 代码位于../R 目录中的各种文件中,并且都以.R 结尾。图形文件位于目录../figs 中,并且都以.pdf.png 结尾。如果 R 文件的日期晚于任何图形文件,我想使用命令处理 R 文件

R --no-save < file.R

我查看了各种示例 makefile,但找不到任何可以修改的内容。

我目前的努力(不工作)如下:

PLOTDIR= ../figs
RDIR= ../R
RFILES= $(RDIR)/*.R
PLOTS= *.pdf *.png
FIGURES= $(PLOTDIR)/$(PLOTS)
$(FIGURES): $(RFILES)
    R --no-save < $<

【问题讨论】:

  • 为什么不用Rscript file.R 而不是R --no-save &lt; file.R
  • R文件名和图形文件名有什么联系吗?
  • @rinni。没有什么特别的原因。那也行。
  • @Beta。不会。一个 R 文件可以创建许多不同名称的图形文件。
  • 如果 Make 让您烦恼,请尝试 Scons scons.org - 您将从头开始,但它是 Make 的更“常规”替代品。

标签: r makefile


【解决方案1】:

您可以尝试以下方法。

诀窍是您需要从输入(.R 文件)中推断出输出

# Makefile
# Beware of indentation when copying use TABS

PLOTDIR = ../figs
RDIR = ../R

# list R files
RFILES = $(wildcard $(RDIR)/*.R)

# compute output file names
PDF_FIGS = $(RFILES:.R=.pdf)
PNG_FIGS = $(RFILES:.R=.png)

# relocate files in output folder
OUT_FILES = $(subst $(RDIR), $(PLOTDIR), $(PDF_FIGS) $(PNG_FIGS))

# first target is the default: simply do 'make'
all: $(OUT_FILES)

clean:
    rm $(OUT_FILES)

.PHONY: all clean

# need to split PNG from PDF rules
$(PLOTDIR)/%.png: $(RDIR)/%.R
    R --no-save < $<

$(PLOTDIR)/%.pdf $(PLOTDIR)/%.png: $(RDIR)/%.R
    R --no-save < $<

编辑以反映我的评论:每个 R 脚本使用 1 个依赖项输出文件

PLOTDIR= ../figs
RDIR= ../R

# list R files
RFILES := $(wildcard $(RDIR)/*.R)

# relocate files in output folder
OUT_FILES=$(subst $(RDIR), $(PLOTDIR), $(RFILES:.R=.out))
#$(warning $(OUT_FILES))

# first target is the default: simply do 'make'
all: $(OUT_FILES)

clean:
    rm $(OUT_FILES)

.PHONY: all clean

$(PLOTDIR)/%.out: $(RDIR)/%.R
    R --no-save < $< && touch $@

【讨论】:

  • 我认为这行不通。 OUT_FILES 的名称不正确,因此通常每次都会运行每个 R 文件。
  • @Beat:我修正了规则。唯一存在的问题是我们不知道是否发布了 PDF 或 PNG(或两者)。一种解决方案是使用“touch”从一个 R 脚本中仅创建一个输出文件(即 ../figs/%.out)(当然,还要真正生成图形文件)。
  • 谢谢。您的第二个文件正是我所需要的,即使它不是我所要求的!
【解决方案2】:

一个有趣的问题。这在逻辑上很简单,但与 Make 喜欢做的事情背道而驰。

这似乎有效。它依赖于模式规则的一个模糊特性:如果模式规则有多个目标,Make 会推断它只需要运行一次即可更新其所有目标。

PLOTDIR = ../figs
RDIR = ../R
RFILES = $(wildcard $(RDIR)/*.R)
FIGURES = $(wildcard $(PLOTDIR)/*.pdf $(PLOTDIR)/*.png)

all: $(FIGURES)

$(PLOTDIR)/%.pdf $(PLOTDIR)/%.png: $(RFILES)
        @for x in $?; do R --no-save \< $$x; done

【讨论】:

  • 这就是我想要的(将 \
  • @Beta:如果没有数字已经存在怎么办?数字是空的,什么也没做。
  • @RobHyndman 要更精细地控制哪些 .R 文件生成哪些数字,您可以将 prereqs 声明与配方声明分开。为此,请使用通用配方(即,从此处的配方中删除 $(RFILES))来完成这项工作,并且每个目标(图)的先决条件可以在没有配方的声明行上。嗯;不确定这是否适用于 $?自动变量;它可能。
  • @levif,你说得对,我没有想到这一点。有一些方法可以纠正它,但看起来问题本身已经过时了。
猜你喜欢
  • 2021-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-06
  • 1970-01-01
  • 1970-01-01
  • 2016-07-08
  • 2021-08-20
相关资源
最近更新 更多