Why my prerequisites automatic variable is empty?

27 Views Asked by At

Use case: I use many Makefiles that share some logic but differ notably in prerequisites, so I include a Common.mk file and use a PREREQ variable in all of them.

Problem: $(PREREQ) is correctly set but $^ is mysteriously empty

Reproduction:

Here is an example Common.mk

all: $(PREREQ)
        echo $^
        echo $(PREREQ)

A B:

and here is the Makefile

include Common.mk

PREREQ ?= A

Now here is the result of typing make at the prompt:

echo

echo A
A

I expected to have the same output but it's not the case. Amusingly, if you type make PREREQ=B or if you switch the two lines in the Makefile, it works as expected and $^ is correctly set.

I use GNU Make 4.3.

Why $^ is empty in this case ?

2

There are 2 best solutions below

0
Croisen On

This is just a guess but maybe with the ?= operator is the culprit. As it only assigns it after it checks that the variable PREREQ is empty.

Now when using

> make PREREQ=B

the variable is already assigned to PREREQ and does not require some sort of downtime I say to get the $^ auto variable.

Try running the example makefile with (granted I have version 4.4.1, and do not know if this option is available to you)

> make --warn-undefined-variables

To me it output this:

> make --warn-undefined-variables
some.mk:1: warning: undefined variable 'PREREQ'
echo 

echo A
A

Hope this helps

0
MadScientist On

Please see this discussion of when variables are expanded.

There you will see that prerequisites are expanded when make reads the makefile and parses the line, while variables inside the recipe are expanded when the recipe is going to be invoked.

Your makefile:

include Common.mk

PREREQ ?= A

Is the same thing to make as if you'd written it all in one file, so it looks like this:

all: $(PREREQ)
        echo $^
        echo $(PREREQ)

A B:

PREREQ ?= A

You can see that at the time the all rule definition is parsed, PREREQ is not set yet. This means that the all rule expands to this:

all:
        echo $^
        echo $(PREREQ)

And so the $^ variable is empty. If you change your makefile to this:

PREREQ ?= A

include Common.mk

it will work as you expect.