Make Functions to the Rescue!
The solution is to define a function (aka “macro”, aka “variable”) that generates the recipe for the locally cached files. There is no requirement that a multi-line variable uses parameters, but we’ll be taking advantage of that capability to implement our dual-source rule:
# parameter 1 is a local cache location $(CACHEDIR)
# parameter 2 is a bare file name
# parameter 3 is the source directory for the file named in $(2)
define single_prereq_rule
cache_files += $(1)/$(2)
$(1)/$(2) : $(3)/$(2) | $(1)
cp $$< $$@
endef
For the uninitiated, this is the definition for a Make “function”. It is referenced using Make’s built-in $(call func_name,arg1,arg2 ...)
function. Arguments may be passed during a call, and are referenced inside the definition with $(1)
, $(2)
,
etc. Make defers parameter evaluations in the definition until the
function is called with actual arguments. Other variable references are
expanded during reading of the definition. In particular, the automatic
variables in the cp
command would be expanded during read.
However, they have no value assigned to them until rule execution, so
their expansion must be delayed. We do this by escaping the dollar sign
($$
) in the definition. (See our post on escaping in Make
files.) Note that we’ve also included an “order only” prerequisite for
the local cache directory ($(1)
in the macro definition). We’ll need a rule to create the directory when it doesn’t already exist.