L9: Makefile utility
When
programs are built using several source files, which must be linked together,
the author(s) have a serious problem in ensuring that the program finally built
is up-to-date with all source files.
(Making sure that the source files, which may be changed by anyone on
the team, are consistent is another problem, one not solved by Make.) The “make” or “gmake” program can be used to
ensure that the object program is up-to-date.
Make
processes a special file in the current directory. This file, which must be named “makefile” or “Makefile” explains
how to run utility commands (like gcc, and others) which compile and process
source files, and combine them into a final running version of the program. Make examines the “last modification time”
of each source and object file, to decide which object files are out-of-date
(some source file changed more recently than the object file), and need to be
re-made. The makefile includes lists of
commands which can be used to re-make each object file. Make then executes those lists of commands
that it determines are required to construct the final objects.
A
basic makefile rule consists of a pair of filename lists, separated by a “:”
(colon), and optionally followed by a sequence of commands to run when the rule
“fires”:
objectfiles : sourcefiles
commands
The
lists of filenames are space-separated.
The commands are indented (using a tab), and consist of a sequence of
UNIX command lines. The list of
commands ends with a blank line. The
rule header indicates that each objectfile “depends” on every file in “sourcefiles”. When any file in objectfiles has an earlier “last
changed” date than any file in “sourcefiles”, the commands are executed. These commands should be designed to re-make
all the files in “objectfiles”.
Example: Suppose you want a rule to create a file
named “process” from “process.c” and “parse.c”. You could use the rule:
process
: process.c parse.c
gcc –g –o process process.c parse.c
Now,
whenever you type “make”, the Make program checks the modification times of all
3 files, and, if it decides that “process” is “older” than either “process.c”
or “parse.c”, Make executes the gcc command.
Make
by default checks the rule for the first object in the makefile. You can over-ride this by typing “make object”. This causes Make to check the rule for object
in the makefile.
Make
examines the selected first object, and then recursively examines each file
that object depends on, so Make can execute a whole series of rules
automatically.
Example 2: Suppose files process.c and parse.c take a
long time to compile. Furthermore, you
know that they aren’t likely to both change at once. You can use gcc options, together with a makefile, to compile
them each only when needed. First the
option “-c” on a gcc command line will compile file xxx.c into a special
unlinked form, an object file, and automatically give it the name xxx.o, by
substituting the .o for the .c in the source filename. You can then use 3 rules in the makefile to
keep the object files for the 2 source programs up-to-date, and a final rule
for constructing “process”, the running version:
process
: parse.o process.o
gcc –g –o process process.o parse.o
process.o
: process.c process.h parse.h
gcc –g –c process.c
parse.o
: parse.c parse.h
gcc –g –c parse.c
Here,
I’ve also specified that process.o depends on two “header files”, parse.h and
process.h, while parse.o depends on only one of them. Any change to parse.h will cause all 3 files to be re-made. Any change to either *.c file will cause
only the corresponding &.o file, and “process” to be re-made.
Make
thus automates the compilation process, allowing some very complex sequences of
steps to be executed as needed, and consistently. Make even quits when one of the commands returns non-zero “status”
(the value returned from main().
Finally, there are various “generic” rules you can build, which replace
specific file names with “wildcards”, and allow reference to the source and
object files within the commands. In
addition, Make allows you to define variables, whose values are usually lists
of files. The variables can be used to
abbreviate long lists in rules.
On
acpub, you can type “info make” to get complete documentation about the GNU
make facility.