help-make
[Top][All Lists]
Advanced

[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.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]