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
usually synonymous.

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
hello.c.


Good things to know:

Printing in a makefile:

Automatic variables:

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:

$(shell ls)

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++.

Line separators:

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:




$ make
makefile:3: c:\WinAVR-20080430\bin\avr-gcc.exe
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.

$                                     
Observe that the two sections (lines 2-8 and 10-16) are identical except that 2-8 starts with spaces
(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. . .