In the GNU-Make manual the How make Reads a Makefile https://www.gnu.org/software/make/manual/make.html#Reading-Makefiles sections says
GNU make does its work in two distinct phases. During the first phase it reads all the makefiles, included makefiles, etc. and internalizes all the variables and their values, implicit and explicit rules, and constructs a dependency graph of all the targets and their prerequisites. During the second phase, make uses these internal structures to determine what targets will need to be rebuilt and to invoke the rules necessary to do so.
I am not able to understand the difference b/w the two phases clearly. May be looking at an example will help understand. Are there any links or tutorials which clarifies what exactly happens in the first phase and second phase.
Take this trivial makefile:
var := some_other_file
some_file: $(var)
some_command $^ $@
After phase one the file will look like the following
var := some_other_file
some_file: some_other_file
some_command $^ $@
Notice how $^
and $@
haven't been expanded yet, recipes are only expanded and invoked as part of phase 2.
In phase 2, make will use the rules resulting from phase 1 and determine which targets need to be remade, you can see how make "thinks" by running make with the -d
flag (warning: lots of output).
During phase 2 of the above case, after having checked all of some_other_file
's dependencies and remade it if necessary, it then considers whether some_other_file
is newer then some_file
.
If this is the case then (and only then) are the recipes' variables expanded, and the contents of each line is passed to the shell, which here would be some_command some_other_file some_file
.
It follows that you can't use $@
etc. anywhere except as part of a recipe because automatic variables are only set during phase 2.
foo: $@bar
some_command $^
This will be expanded in phase 1 to:
foo: bar
some_command $^
Which during phase 2 will result in:
foo: bar
some_command bar
Probably not what you wanted.
Some makes have ways of working around this limitation. GNU make for instance has .SECONDEXPANSION
, and the following will work as expected:
.SECONDEXPANSION:
foo: $$@bar
some_command $^
Anything after .SECONDEXPANSION
will be expanded both during phase 1:
.SECONDEXPANSION:
foo: $@bar
some_command $^
and phase 2:
.SECONDEXPANSION:
foo: foobar
some_command foobar
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With