help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Substitution references


From: Paul D. Smith
Subject: Re: Substitution references
Date: Tue, 30 Oct 2001 14:34:39 -0500

%% Phil Endecott <address@hidden> writes:

  pe> X=$(words Y)

  pe> test:
  pe>   echo $(X)
  pe>   echo $(X:Y=a b c)

  pe> I expected to get "1" and "3", but actually I got "1" and "1".
  pe> Is this the expected behaviour?  (GNU Make version 3.73).

Yes.

There is no such thing as "shallow evaluation" in make.  When make
evaluates a variable it _always_ evaluates it recursively and
completely, right there.

Since the $(V:X=Y) operator replaces X with Y in the _value_ of the
variable V, that variable must be evaluated.  The result of that will
not be "$(words Y)", since that would be a shallow, non-recursive
evaluation and make doesn't do that.  It would be the result of
evaluating $(words Y), which is "1".  So, you are replacing "Y" with "a
b c" in the value "1", where there is of course no "Y", so it doesn't do
anything and resolves to just "1".

  pe> What I was really trying to do was to use substitution references
  pe> to give a common interface to multiple programs that have the same
  pe> purpose but with different command-line formats.  My first idea
  pe> was (vaguely) like this:

  pe> if some-condition
  pe> DO_FOO=fooprog IN > OUT
  pe> else
  pe> DO_FOO=otherfoo -in IN -out OUT
  pe> endif

  pe> y: x
  pe>   $(DO_FOO:IN=x:OUT=y)

  pe> But of couse I can't do two substitututions in one go like this.  I could
  pe> go for this:
  pe>   $(subst IN,x,$(subst OUT,y,$(DO_FOO)))
  pe> but that's a bit long, so I tried this:

  pe> DO_FOO=fooprog $(word 1,IN_OUT) > $(word 2,IN_OUT)
  pe> or DO_FOO=otherfoo -in $(word 1,IN_OUT) -out $(word 2,IN_OUT)
  pe> and then
  pe>   $(DOO_FOO:IN_OUT=x y)
  pe> but this fails because the $(word...) functions seem to be applied before
  pe> IN_OUT is substituted.  It ends up doing "fooprog x y >" or
  pe> "otherfoo -in x y -out".

  pe> So, experts!, how would you do this?

Well, in this particular case in your example it's trivial because the
values you want to replace are provided as automatic variables.  So, you
can just do this:

 if some-condition
   DO_FOO = fooprog $< > $@
 else
   DO_FOO = otherfoo -in $< -out $@
 endif

 y: x
        $(DO_FOO)

As long as all the values you're using are targets or prerequisites or
are derivable from them, then you're fine with the above.

See the GNU make manual section "Automatic Variables".


If you need something more generic, then I would upgrade to a newer
version of GNU make (3.73!?!?  Ouch!), and use the $(call ...) function:

 if some-condition
   DO_FOO = fooprog $1 > $2
 else
   DO_FOO = otherfoo -in $1 -out $2
 endif

 y: x
        $(call DO_FOO, input, output)

Again, see the GNU make manual.

-- 
-------------------------------------------------------------------------------
 Paul D. Smith <address@hidden>          Find some GNU make tips at:
 http://www.gnu.org                      http://www.paulandlesley.org/gmake/
 "Please remain calm...I may be mad, but I am a professional." --Mad Scientist



reply via email to

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