help-make
[Top][All Lists]
Advanced

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

RE: clarification of deferred function expansion


From: Asperheim, Eric
Subject: RE: clarification of deferred function expansion
Date: Thu, 4 Apr 2002 19:01:48 -0800

Paul,

Thanks for the explanation and alternate solution to what I want. 

Your explanation was very helpful in helping me to better understand what is
done and when things are done during the "second phase" of gmake. This also
brings up a point which you may have heard. The gmake doc doesn't use
examples in some cases to clarify it's functionality - this being a perfect
example. I've read about 1st/2nd phase of gmake. But, I still wasn't sure
when the $(shell function expansion would occur - when I thought or what you
described. Anyway, I think my example below would be a great one to add to
the "3.7 How make reads a Makefile" section.

Thanks Again,

Eric


-----Original Message-----
From: Paul D. Smith [mailto:address@hidden
Sent: Thursday, April 04, 2002 5:12 PM
To: Asperheim, Eric
Cc: 'address@hidden'
Subject: Re: clarification of deferred function expansion


%% "Asperheim, Eric" <address@hidden> writes:

  ae> I've read the gmake v3.79.1 doc (p. 14) about deferred "Expansion
  ae> of deferred construct is not performed until either the construct
  ae> appears later in an immediate context, or until the second phase"
  ae> of gmake's operation.  Given that the shell command

  ae> $(shell echo $$ENV_VAR)

  ae> expansion was deferred since it's part of a define directive, I
  ae> was expecting this to work. I'm setting an environment var ENV_VAR
  ae> (using bash shell) and then trying to use that env var in the next
  ae> command. But, this doesn't work. Note, I tried to use the gmake
  ae> var $(ENV_VAR). But, this doesn't work either since the value of
  ae> $(ENV_VAR) is the value of the env var at gmake invocation - which
  ae> is not what I want.

  ae> Initially - ENV_VAR is set to "0"

  ae> define cmd
  ae>   ENV_VAR=1; \
  ae>   export ENV_VAR; \
  ae>   set TCL_VAR {$(shell echo $$ENV_VAR)};
  ae> endef

  ae> default : 
  ae>   @ $(cmd)

  ae> fhc2349:easperhe gmake -n
  ae> ENV_VAR=1; export ENV_VAR; set TCL_VAR {0};

This is correct behavior.  When working with make you always must,
_must_ keep in mind the distinction between things that make does and
things that the shell does.

The shell is a subprocess, and as such any modification of its
environment is completely its own; make cannot be impacted by it.

Likewise, no environment change from one shell that is invoked by make
(or elsewhere) can impact any sibling shell (shell also invoked by make,
before or after it).

Consider what happens above: make sees the define, and it stores the
value as a string and does not expand it.  So the value of $(cmd) is the
string:

   ENV_VAR=1; \
   export ENV_VAR; \
   set TCL_VAR {$(shell echo $$ENV_VAR)};

(BTW there's no need to use define/endef here; you could use a simple
variable assignment.  Also, what is the syntax of the last line?  It
looks like C shell to me...?).

Next, make reads the target and remembers that the command script to
build it is the string "@ $(cmd)" (again, not expanded).

Now it's done reading, so it proceeds to phase two and wants to build
the default rule.

Before it can build the rule, it has to expand all make variables and
functions in the script of course, so it proceeds like this:

  $(cmd)
    => ENV_VAR=1; export ENV_VAR; set TCL_VAR {$(shell echo $$ENV_VAR)};

Now make sees that there is a function, shell, so it _invokes a shell
and runs the commandline, in this case "echo $ENV_VAR" (after escaping).
Note it is _not_ running the entire command script, only the shell
function is being expanded here.  Obviously, the value of is $ENV_VAR is
0 since we are running this directory from make, before any of the
command script has been executed.

Once that shell command is done its value is substituted into the
command script, and a shell is invoked and given the command script:

  ENV_VAR=1; export ENV_VAR; set TCL_VAR {0}

  ae> Is this the expected behavior? Or, is there a bug in gmake. If
  ae> this is the intended behavior, is there anyway to do what I want
  ae> to do?

Sure.  You have to get the _shell_ to do it, as part of the command
script, not ask make to do it, before the command script is invoked.

This should do what you want:

  cmd = ENV_VAR=1; export ENV_VAR; set TCL_VAR {`echo $$ENV_VAR`}

See how we use the shell's backtick commands to perform the echo, rather
than having make do it which must happen before the command is invoked,
and thus before ENV_VAR is set to 1.

-- 
----------------------------------------------------------------------------
---
 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]