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.
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.
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 lineprint-%: ; @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.
Comments
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.
print-%: ; @echo $*=$($*)
include Makefile
Now you can use it the following way from any source directory:
$ make -f ~/Makefile.debug print-SOURCE_FILES
print-%:
@echo '$(subst ','\'',$*=$($*)) (origin: $(origin $*), flavor: $(flavor $*))'
# 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 $*)'
print-%: ; @echo $*=$($*) | tr '= ' '\n'
Example:
>make print-CFLAGS
CFLAGS
-fprofile-arcs
-ftest-coverage
-include
./Third_Party/cpputest/include/CppUTest/MemoryLeakDetectorMallocMacros.h