Printing the Value of a Makefile Variable

Summary:

If you've ever looked in a Makefile you'll realize that Makefile variables (often called macros) form the backbone of any Make process. The variables usually define which files will be compiled, what command-line parameters to pass to compilers, even where to find the compiler itself. And if you've ever tried to debug a Makefile you'll know that the number 1 question you ask yourself is “What is the value of variable X?.”

There aren't any debuggers for Make and Make doesn't provide the sort of interactivity you'd see from a scripting language like Perl or Python. So how do you figure out the value of a variable? Take a look at this simple Makefile (which does nothing but set various variables):

X=$(YS) hate $(ZS)

Y=dog
YS=$(Y)$(S)
Z=cat
ZS=$(Z)$(S)
S=s
all:

What's the value of X? The small size and simplicity of this Makefile means that tracing through all the variable assignments is feasible, leading to the conclusion the X is “dogs hate cats”. In a real multi-thousand line Makefile that unleashes the power of GNU Make's variables and functions figuring out the value of a variable can be a laborious task. But here's a little Make recipe that does all the work for you. Create a Makefile called helper.mak and place in it:

print-%:

@echo $* = $($*)
 

Now we can find the value of variable X with the following command:

gmake -f Makefile -f helper.mak print-X

The first -f Makefile tells GNU Make to load our original Makefile, and the second -f helper.mak loads in the receipe. The print-X directs make to “build” the target named print-X. Since there isn't an explicit rule to build print-X GNU Make looks for a pattern and finds print-% (the % acts as a wildcard) and runs the associated command.

The command uses $* (a special GNU Make variable that will have the value matched by the % in the rule) to print the name of the variable and then by doing $($*) gets the value of the variable named by $*. So experimenting with it we can see the following:

$ gmake -f Makefile -f helper.mak print-X
X = dogs hate cats
$ gmake -f Makefile -f helper.mak print-YS
YS = dogs
$ gmake -f Makefile -f helper.mak print-S
S = s
 

Sometimes it's useful to know how a variable was defined. GNU Make provides the $(origin) function that returns a string containing the type of the variable

(e.g. Whether it was defined in a Makefile, on the command-line, or in the environment). Modifying helper.mak prints out origin information as well.

print-%:
@echo $* = $($*)
@echo $*\'s origin is $(origin $*) 

Now we see that YS is defined in the Makefile.

$ gmake -f Makefile -f helper.mak print-YS

YS = dogs
YS's origin is file
 

If we override the value of YS on the GNU Make command-line we'll see:

$ gmake -f Makefile -f helper.mak print-YS YS=fleas

YS = fleas
YS's origin is command line
 

Next time I'll serve up a recipe for printing every variable in a Makefile.

About the author

John Graham-Cumming's picture
John Graham-Cumming

John Graham-Cumming is Co-Founder at Electric Cloud, Inc . Prior to joining Electric Cloud, John was a Venture Consultant with Accel Partners, VP of Internet Technology at Interwoven, Inc. (IWOV), VP of Engineering at Scriptics Corporation (acquired by Interwoven), and Chief Architect at Optimal Networks, Inc. John holds BA and MA degrees in Mathematics and Computation and a Doctorate in Computer Security from Oxford University. John is the creator of the highly acclaimed open source POPFile project. He also holds two patents in network analysis and has others pending.