Search code examples
gnu-makevariable-expansion

GNU make: expansion of a deferred construct


On this site containing the documentation describing how make reads a Makefile, there is the following paragraph:

[...]

It’s important to understand this two-phase approach because it has a direct impact on how variable and function expansion happens; this is often a source of some confusion when writing makefiles. Here we will present a summary of the phases in which expansion happens for different constructs within the makefile. We say that expansion is immediate if it happens during the first phase: in this case make will expand any variables or functions in that section of a construct as the makefile is parsed. We say that expansion is deferred if expansion is not performed immediately. Expansion of a deferred construct is not performed until either the construct appears later in an immediate context, or until the second phase.

[...]

I do not know what the highlighted part means.

Does it try to say that if there is a variable reference first found in a deferred section it will not be expanded during the first phase, but if the same variable reference is then found (later in the Makefile) in an immediate context, that variable reference will be expanded? Why would it say this explicitly?

Or does it try to say that there are cases when the exact same line can be read within a different context?


Solution

  • I do not know what the highlighted part means.

    Does it try to say that if there is a variable reference first found in a deferred section it will not be expanded during the first phase, but if the same variable reference is then found (later in the Makefile) in an immediate context, that variable reference will be expanded?

    Something like this, but I hesitate to say "yes" because I'm not sure I fully understand you. Instead, I put it in my own words: the manual says that an expression with a deferred expansion is expanded immediately when it is evaluated as part of the value of an expression that is immediately expanded. Example:

    INTRO     := The messages are
    DEFERRED   = $(MESSAGE1) literal message
    IMMEDIATE := $(INTRO) $(DEFERRED)
    MESSAGE1   = deferred message,
    
    demo:
        @echo immediate: "$(IMMEDIATE)"
        @echo deferred: "$(INTRO) $(DEFERRED)"
    

    Demo:

    $ make demo
    immediate: The messages are  literal message
    deferred: The messages are deferred message, literal message
    $
    

    Note that variable DEFERRED is expanded immediately as part of the process of setting the value of immediately-expanded variable IMMEDIATE. You can see this from the difference in the output of the two echo commands. You can also see that this expansion does not stick to DEFERRED, which is one of the things that can be confusing.

    Why would it say this explicitly?

    Because one might suppose otherwise. Specifically, one might suppose that building the "demo" target in the example above would cause two identical lines to be printed. That would require a deferred expansion of DEFERRED being somehow symbolically encoded into the immediate expansion of IMMEDIATE, or else that DEFERRED be somehow converted into an immediately-expanded variable. Nothing along those lines happens.

    Note, too, that the two expansions of DEFERRED are different in this case, which is not necessarily a possibility that is immediately evident.

    Or does it try to say that there are cases when the exact same line can be read within a different context?

    Inasmuch as I differentiate between identical and exact same, the only way "the exact same" line can be evaluated in different contexts is if it is part of the expansion of a deferred-expansion expression. Then it can appear in both immediate and deferred context, as the text $(MESSAGE1) literal message in the example does. In that sense, yes, the manual is talking about that; it's not different from your other alternative.

    It is also possible for distinct but identical text to appear in different contexts, but this is not as interesting.