- Basics of pattern substitutions
- Use the
- Use the
Let's consider the example used in the previous two lessons. This involves
executing four R scripts---
in batch mode via the command
R CMD BATCH --no-save.
We've seen the naive option of writing a
Makefile like this:
.PHONY: all clean all: script1.Rout script2.Rout script3.Rout script4.Rout script1.Rout: script1.R R CMD BATCH --no-save script1.R script2.Rout: script2.R R CMD BATCH --no-save script2.R script3.Rout: script3.R R CMD BATCH --no-save script3.R script4.Rout: script4.R R CMD BATCH --no-save script4.R clean: rm -f *.Rout
A makefile like the one above is obviously not very efficient. Instead,
we can define a variable
rcmd that refers to the R command in each recipe.
Likewise, we can use a pattern rule for all the targets:
%.Rout: %.R $(rcmd) $<
All the previous elements can be combined in the following makefile:
rcmd = R CMD BATCH --no-save .PHONY: all clean all: script1.Rout script2.Rout script3.Rout script4.Rout %.Rout: %.R $(rcmd) $< clean: rm -f *.Rout
As you can tell, the only part that still has some repetition has to do
with the prerequisites of the target
all (i.e. all the
It would be nice if you could group all the
.Rout in one single variable.
Let's see how to do this.
Using the wildcard function
Remember Make's wildcard function? We can use it to define a variable with
the list of input
rfiles = $(wildcard *.R)
The good news is that we have a variable
rfiles that contains the names
of all the R script files. The problem now is how to take advantage of
You may be tempted to do something like this (with some tragic consequences):
rcmd = R CMD BATCH --no-save rfiles = $(wildcard *.R) $(rfiles)out: $(rfiles) $(rcmd) $(rfiles)
Using Pattern Substitution
To create a variable that contains the name of the
.Rout files, we are
going to use the function patsubst (for pattern substitution).
The idea is to take advantage of the variable
rfiles---which has the value:
script1.R script2.R script3.R script4.R---and define a pattern of characters
to be substituted.
patsubst has the following usage:
patsubst finds whitespace-separated words in
text that match the
pattern and replaces them with the specified
pattern may contain a
% which acts as a wildcard, matching any number
of any characters within a word. If
replacement also contains a
% is replaced by the text that matched the
Only the first
% in the pattern and replacement is treated this way;
% is unchanged.
In our example, we can use
patsubst to create the variable
rout like thi:
rfiles = $(wildcard *.R) rout = $(patsubst %.R,%.Rout,$(rfiles))
%.Ris the pattern to be match in the provided text
$(rfiles)is the provided text (i.e.
script1.R script2.R script3.R script4.R)
%.Routis the replacement
In other words,
patsubst will look for the pattern
and will replace the pattern with
.Rout. This implies that
be a text formed by:
script1.Rout script2.Rout script3.Rout script4.Rout.
Having obtained the variable
rout with the list of output files, we can
Makefile as follows:
rcmd = R CMD BATCH --no-save rfiles = $(wildcard *.R) rout = $(patsubst %.R,%.Rout,$(rfiles)) all: $(rout) %.Rout: %.R $(rcmd) $< clean: rm -f *.Rout
Note that the variable
rout is used as the prerequisite of the target
You don't need to write a long list of prequisites for