Makefiles contain a several types of elements: variable declarations, dependency rules, commands, and comments.
Variable declarations look like Bourne shell variable assignments. A variable usage starts with $ and has parentheses around the variable name. In the example below, the line CC = gcc sets the variable CC. The variable is later used as $(CC).
Dependency rules have the following structure:
<target> : <dependencies> <tab><command>The target is the name of the dependency rule. The target is followed by a colon, and a list of the files or targets that this rule depends on. The line following the target line begins with a tab, and contains the command to be run to evaluate the rule.
What does it mean for a rule to "depend on" a file or target?
The rule will be evaluated if any of the files or targets are
newer than the result of the rule evaluation. For example, the rule
beginning with the target main will be evaluated if any of
the object files are newer than the executable main. These
dependencies are recursively evaluated, so a rule associated with one
of the object files, will be evaluated if the source file is newer
than the object file. If "d.c" is newer than "d.o" then when we run
"make main", the recursive dependency analysis will cause the rule
that compiles "d.o" to be evaluated producing a new object file. Then
the "main" rule will be evaluated because "d.o" is newer than main.
One problem with the main rule as we have specified it, is that if we modify a ".h" file, the rule will not be evaluated because the ".h" files are not in the dependency list. We have two options to handle this. The first is to put the ".h" files into the dependency list. The second is to include a rule that will run the program "makedepend" on the sources. "makedepend" looks at all the source files and parses out the "include" files and produces a dependency list. After we run "makedepend", the target main will be evaluated if a ".h" file is newer than the executable.
CC = gcc CFLAGS = -g -Wall SRCS = main.c a.c b.c d.c HDRS = a.h b.h d.h OBJS = main.o a.o b.o d.o # The first rule is the one that is run when we type main # This rule contains the variable $@ which is the name of the target main : $(OBJS) $(CC) $(CFLAGS) -o $@ $(OBJS) # This is a special kind of rule that says how to turn .c files into .o files # The variable $< refers to the dependency rule that was matched by the # rule. (In this case the name of the source file.) .c.o : $(CC) -c $(CFLAGS) $< depend: makedepend $(SRCS) print: more $(HDRS) $(SRCS) | enscript -2r -p listing.ps # DO NOT DELETE (depend needs it)The source code files are
Another sample makefile, prepared by Professor Clarke and modified slightly by me, can be found here