Printing the Value of a Makefile Variable

[article]
Summary:

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? 

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.

AgileConnection is one of the growing communities of the TechWell network.

Featuring fresh, insightful stories, TechWell.com is the place to go for what is happening in software development and delivery.  Join the conversation now!

Upcoming Events

Nov 09
Nov 09
Apr 13
May 03