I'm wanting to use a makefile to update figure files generated by R code. The R code is in various files in the directory ../R
and all ending in .R
. The figure files are in the directory ../figs
and all ending in .pdf
or .png
. If an R file has a later date than any of the figure files, I want to process the R file with the command
R --no-save < file.R
I've looked a various example makefiles but couldn't find anything I could adapt.
My current effort (not working) is as follows:
PLOTDIR= ../figs
RDIR= ../R
RFILES= $(RDIR)/*.R
PLOTS= *.pdf *.png
FIGURES= $(PLOTDIR)/$(PLOTS)
$(FIGURES): $(RFILES)
R --no-save < $<
You can try the following.
The tricks are that you need to deduce output from inputs (.R file)
# 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 < $<
Edit to reflect my comment: Use 1 dependency output file per 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 $@
An interesting problem. It's logically simple, but goes right against the grain of what Make likes to do.
This seems to work. It relies on an obscure feature of pattern rules: if a pattern rule has more than one target, Make infers that it need be run only once to update all of its targets.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With