Makefile с несколькими входами и выходами

Я хочу использовать make файл для обновления файлов цифр, генерируемых R-кодом. Код R находится в разных файлах в каталоге ../R и все заканчивается на .R. Файлы рисунков находятся в каталоге ../figs и все заканчиваются на .pdf или .png. Если файл R имеет более позднюю дату, чем любой из файлов рисунков, я хочу обработать файл R с помощью команды

R --no-save < file.R

Я просмотрел различные примеры make файлов, но не смог найти ничего, что мог бы адаптировать.

Мое текущее усилие (не работает) выглядит следующим образом:

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

Ответ 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 < $<

Изменить, чтобы отразить мой комментарий: используйте 1 выходной файл зависимости на R script

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 [email protected]

Ответ 2

Интересная проблема. Это логично просто, но идет прямо против зерна того, что 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