Making makefiles work
Makefiles are one of the most challenging things to get working.
This article is intended for those with some level of experience that
want to understand common difficulties.
A simple makfile
The Makefile above has two parts: some code (lines 2-8) that are written using
makefile syntax, and targets in lines 10 and 12. The lines following a target are
expanded and then sent to the shell for interpretation.
The makefile code in lines 2-9 is interpreted by make alone. It is not sent to the
shell, so it must have spaces at the beginning of the line (notice the tiny dots in
lines 3-5, 7).
Lines 10 and 12 define targets. When a makefile runs, it executes the first target
encountered, called all by convention. This is why "make" and "make all" are
The all target is run in this makefile by default. It doesn't do anything, but it
does have a prerequisite that must be satisfied before it does nothing. That is,
the hello.a file must be built.
This is accomplished in line 12 that instructs make how to generate a .a file from
a .c file. The % signs must match, so in this case, a hello.a will be generated from
Good things to know:
Printing in a makefile:
- $(info Message) prints the message on the console and continues.
- $(warning Message) prints the makefile name and line number,
the message, and continues.
- $(error Message) prints the makefile name and line number,
the message, and aborts the make.
Variables like $@, $<, $(@D)
, et cetera
are called Automatic variables
It is a good idea to know these variables.
Calling out to a shell:
Calling to a shell is done like this:
This will run the ls command, take all of the lines from stdout, change
CRs to spaces, and return the value as a space-separated list of lines!
Remember, lists in Makefiles are generally space separated.
Conditional parts of a makefile:
The ifeq statement with the accompanying else and endif can be seen in the
example above. The conditional makefile commands are documented here
There are also conditional functions
. Remember, these run in the makefile
itself, not in a shell.
Know your whitespace
It is absolutely necessary to use an editor that can show what type of whitespace
is in your makefile. In particular, you must be able to distinguish tabs from spaces
and Unix line separators from DOS line separators.
There are several good freeware editors that can do this. Programmer's Notepad and
Notepad++ are two examples.
The screenshots below will be from Notepad++.
Unix uses LF (\n) characters to separate lines (this is what you want):
DOS uses CR+LF (\r\n) characters to separate lines (you don't
want these, convert them to Unix line separators!):
Indenting with tabs or spaces:
Lines that begin with tabs:
- Always have the make functions and variables expanded and then
are sent to a shell for interpretation.
- Must occur after targets.
Observe that the two sections (lines 2-8 and 10-16) are identical except that 2-8 starts with spaces
makefile:5: The AVR_HOME environment variable was NOT set, defaulting it to c:\WinAVR-20080430\bin\avr-gcc.exe.
makefile:15: *** commands commence before first target. Stop.
(see the dots) and 10-16 starts with tabs (see the arrows).
Starting a line with a tab is only legal after a target (see lines 11-12 in "A simple makefile" above).
Doing so in a non-target part of a makefile is what causes the "commands commence before
first target" error.
Lines that start with a tab must be used after a target. Using spaces at the beginning of a line
after a target causes a "Missing serparator" error.
More as time allows. . .