Ever wondered what the funny-looking vars in the GNU Makefiles are? These two are the most common ones: $@
and @<
there are some other are special vars as well.
Here’s what these two mean, and you can look up the rest on the GNU Makefile “Automatic Variables” help page:
$@ -
is the name of the target currently being processed.
$< -
is the name of the first dependency.
1. So if you have a makefile target that looks like this:
all: clean libs app
@echo 'Building target: $@. First dependency is: $<
...
Then when you invoke ‘make all’ you will see the message:
Building target: all. First dependency is: clean.'
2. It becomes more interesting when the first dependency is a list of several values, e.g.:
OBJS := lib1/src1.c lib1/src2.c lib2/src2.c lib2/src3.c
...
myapp: $(OBJS) $(USER_OBJS)
@echo 'Building target: $@. First dep: $<'
$(CC) $(USER_FLAGS) -o $@ $(OBJS) $(LIBS)
@echo 'Finished building target: $@'
In this case the first dependency which is the variable OBJS is evaluated. It resolves to a list of values and the first value ‘lib1/src1.c’ will be assigned to the ‘$<‘ variable.
So when making ‘myapp’ you will see the message:
Building target: myapp. First dependency is: lib1/src1.c.'
One more thing to look for, particularly if you are using echo messages to debug your make process:
Your first dependency may often be another target in the make file! In the first example (all: clean libs app) the dependencies are ‘clean’, ‘libs’ and ‘app’ and by the looks of it these are most likely other targets. Now, what I wanted point out is that if one of these targets prints a message… Then the sequence of the messages you see may not be what you expected! Or worse yet – if one of these pre-requisite targets breaks the build (!) then you may never see your message! Just keep these in mind when debugging your makefiles…
It’s easy to debug a makefile in the target sections, just add a echo somewhere within your target section :
some-target:
@echo Value of VAR1=$VAR1
But sometimes you really need to check some value before your targets. What can you do? You can’t use echo in the definitions section…
This will do the trick! 😉
$(error VAR1 = $(VAR1).)
It will do the job of printing the value of the variable from within your makefile’s definitions section… Of course it WILL also break the build… but I am assuming that if you’re at the stage of debugging environment variables in your makefiles then this is probably not be your major concern at this very moment… 🙂
And even better yet – use $(warning …) instead of $(error …).
This method is described in detail in O’Reilly’s book “Managing Projects with GNU Make” and the chapter “Debugging Makefiles” is free and available on O’Reilly’s site as a PDF download:
http://www.oreilly.com/openbook/make3/book/index.csp
… and as HTML page:
https://www.oreilly.com/library/view/managing-projects-with/0596006101/ch12.html