[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Pattern rules with % matching empty string?
From: |
Glen Huang |
Subject: |
Re: Pattern rules with % matching empty string? |
Date: |
Sat, 25 Apr 2020 13:53:38 +0800 |
Thanks for the detailed examples.
Using variables to instantiate all hosts sounds overkill. I just want the
pattern rule to also apply when the stem would be empty, and all but one host
has a number suffix in their names.
I end up making all hosts contain the number suffix. Given the solutions
provided, it feels like the cleanest one.
> On Apr 25, 2020, at 1:29 PM, Kaz Kylheku (gmake) <address@hidden> wrote:
>
> 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.
>
>