[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Pattern rules with % matching empty string?
From: |
Kaz Kylheku (gmake) |
Subject: |
Re: Pattern rules with % matching empty string? |
Date: |
Fri, 24 Apr 2020 22:29:55 -0700 |
User-agent: |
Roundcube Webmail/0.9.2 |
On 2020-04-24 21:56, Kaz Kylheku (gmake) wrote:
And a fourth option: keep the host names inconsistent
(they are probably hard to change) but enumerate them
with consistently named stamp files (easy to control).
Use computed variable names to associate the two together:
remote-bin-host%: bin
scp $< $(host_$*):$<
touch $@
With computed variable names, you can fake out a data
structure in which it looks like keys are matched to records
that have fields.
Then you can specify a database of hosts records, such
that for each one you can give a stamp file name, host
name and any other property, like using a different SSH
key or whatever.
Please study this Makefile:
host_1.name := foo
host_1.stamp := foo.txt
host_2.name := bar
host_2.stamp := bar.txt
host_list := 1 2
define host_bin_template =
$$(host_$1.stamp): bin
echo scp $$< $$(host_$1.name):$$<
touch $$@
endef
$(foreach n,$(host_list),$(eval $(call host_bin_template,$n)))
If we run "make foo.txt", this happens:
echo scp bin foo:bin
scp bin foo:bin
touch foo.txt
Make has deduced through the structure we set up and the generated rules
that foo.txt is a stamp file associated with host foo.
This doesn't use pattern rules at all, but procedural rule expansion. We
have a list of hosts 1 2.
The foreach loop steps over this list, and substitutes it as parameter
$1 into the host_bin_template, which is evaluated via $(eval ...) as a
piece of Makefile syntax. That syntax creates a rule, exactly as if we
had typed this in:
$(host_1.stamp): bin
echo scp $< $(host_1.name):$<
touch $@
$(host_2.stamp): bin
echo scp $< $(host_2.name):$<
touch $@
Of course, these variables expand, and so the effect of the for loop and
eval is that this is generated:
foo.txt: bin
echo scp $< foo:$<
touch $@
bar.txt: bin
echo scp $< bar:$<
touch $@
To add, a third rule, we just create new variables:
host_3.name := saturn.localdomain
host_3.stamp := saturn.stamp
Update the list:
host_list = 1 2 3
Done. Now we have a third rule where saturn.stamp is a target,
and updating it copies the bin file to saturn.localdomain.
With a little more hacking, we can probably (and ironically)
re-create the "rdist" utility. :)
The advantage of pattern rules is that they avoid instantiation bloat.
A pattern rule can potentially match just, say, one of potentially
thousands of targets, which is more efficient than generating thousands
of rules with an eval. And it can match new things in the filesystem
that don't require any new definitions in the Makefile.
We lost some of the advantage of the pattern rule when we turned
to computed variables for assistance; manual definitions had to be made
to satisfy the computed variable references.