## Friday, April 10, 2015

### The one line you should add to every makefile

If you're using GNU make and you need help debugging a makefile then there's a single line your should add. And it's so useful that you should add it to every makefile you create.

It's:

print-%: ; @echo $*=$($*) It allows you to quickly get the value of any makefile variable. For example, suppose you want to know the value of a variable called SOURCE_FILES. You'd just type: make print-SOURCE_FILES If you are using GNU make 3.82 or above it's not even necessary to modify the makefile itself. Just do make --eval="print-%: ; @echo$*=$($*)" print-SOURCE_FILES

to get the value of SOURCE_FILES. It 'adds' the line above to the makefile by evaluating it. The --eval parameter is a handy way of adding to an existing makefile without modifying it.

### How that works

The line

print-%: ; @echo $*=$($*) defines a pattern-rule that matches any target in the form print-% (the % is the wildcard character). So when you run make print-SOURCE_FILES that rule will execute and the % will match SOURCE_FILES. The command executed by print-% is @echo$*=$($*). Here I've used a semicolon to separate the target name and the recipe (commands to be executed). That makes this into a one-liner. In more traditional make syntax (where a tab is used to introduce the recipe) that would be written.

print-%:
@echo $*=$($*) Using semicolon makes this easy to copy and paste. The automatic variable$* matches the % in print-% (so when executing print-SOURCE_FILES, $* will be SOURCE_FILES). So$* contains the name of the variable that we want to print out.

The $($*) uses gets the value of a variable whose name is stored in $*. For example,$* might expand to SOURCE_FILES and then GNU make would get the value of $(SOURCE_FILES). Getting a variable by storing its name in another variable turns out to be a useful technique in many makefiles. ### More? If that sort of thing interests you, you might enjoy my book: The GNU Make Book. If you enjoyed this blog post, you might enjoy my travel book for people interested in science and technology: The Geek Atlas. Signed copies of The Geek Atlas are available. #### 7 Comments: simont said... A small refinement, to avoid trouble if the value of the variable you're printing includes shell metacharacters: print-%: ; @echo '$(subst ','\'',$*=$($*))' The echoed string is now enclosed in single quotes, and every single quote appearing in the string has been replaced with the sequence '\'' which gets you a literal single quote. 2:50 PM D. Ongs said... If you're using BSD make, you can just use 'make -V SOURCE_FILES'. 3:07 PM Rainer Müller said... You can avoid editing the Makefile to add the rule with GNU make 3.81 or older, which does not support --eval. Create a new file in your home named ~/Makefile.debug with the contents: print-%: ; @echo$*=$($*)
include Makefile

Now you can use it the following way from any source directory:

$make -f ~/Makefile.debug print-SOURCE_FILES 3:25 PM Andrei Neculau said... added to my snippet collection https://github.com/andreineculau/util.mk 6:40 PM daniel said... It is sometimes also useful to know about the origin and flavor of the var: print-%: @echo '$(subst ','\'',$*=$($*)) (origin:$(origin $*), flavor:$(flavor $*))' 8:42 PM WallSt Prog said... I've been using this trick for years, with the following enhancements: # rule to print info about make variables, works only with make 3.81 and above # see http://blog.melski.net/2010/11/30/makefile-hacks-print-the-value-of-any-variable/ # for more info # to use invoke make with a target of print-VARNAME, e.g., # make print-CCFLAGS print-%: @echo '$*=$($*)'
@echo ' origin = $(origin$*)'
@echo ' flavor = $(flavor$*)'
@echo ' value = $(value$*)'

8:44 PM
Michael Le Barbier Grünewald said...

Users of bmake just say bmake -V VARIABLE and have the option to see the actual value of the variable before expansion, or the expanded value.

5:45 PM