At 03:08 PM 7/13/98 -0400, you wrote:
>Hello,
> Now that I can semi-successfully program in C I wanted to move on
>to other things. Right now for my makefiles I am using a makefile I
>borrowed from somebody elses program and made work in mine. Could someone
>point me to some simple, easy to understand, downloadable for offline
>viewing guides on writing makefiles?
>
> Also I'd like to learn how to write configure scripts. (Using
>makefile.in, configure.out, etc) Anyone have pointers on this info? Thanks
>a bunch.
>
>Joseph
>
>-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>| Joseph Martin: | [EMAIL PROTECTED] |
>| Amateur C Programmer, | http://users.exis.net/~jam/ |
>| Web Designer, | |
>| All around tech nut | |
>-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
Introduction
The `make' utility automatically determines which pieces of a large
program need to be recompiled, and issues commands to recompile them.
Our examples show C programs, since they are most common, but you can use
`make' with any programming language whose compiler can be run with a shell
command. Indeed, `make' is not limited to programs. You can use it to
describe any task where some files must be updated
automatically from others whenever the others change.
Preparing and Running Make
To prepare to use `make', you must write a file called the "makefile"
that describes the relationships among files in your program and provides
commands for updating each file. In a program, typically, the executable
file is updated from object files, which are in turn made by compiling
source files.
Once a suitable makefile exists, each time you change some source files,
this simple shell command:
make
suffices to perform all necessary recompilations. The `make' program uses
the makefile data base and the last-modification times of the files to
decide which of the files need to be updated. For each of those files, it
issues the commands recorded in the data base.
You can provide command line arguments to `make' to control which files
should be recompiled, or how.
-
An Introduction to Makefiles
You need a file called a "makefile" to tell `make' what to do. Most
often, the makefile tells `make' how to compile and link a program.
We will discuss a simple makefile that describes how to compile and link
a text editor which consists of eight C source files and three header
files. The makefile can also tell `make' how to
run miscellaneous commands when explicitly asked (for example, to remove
certain files as a clean-up operation). When `make' recompiles the editor,
each changed C source file must be recompiled. If a header file has
changed, each C source file that includes the header file must be
recompiled to be safe. Each compilation produces an object file
corresponding to the source file. Finally, if any source file has been
recompiled, all the object files, whether newly made or saved from previous
compilations, must be linked together to produce the new executable editor.
What a Rule Looks Like
A simple makefile consists of "rules" with the following shape:
TARGET ... : DEPENDENCIES ...
COMMAND
...
...
A "target" is usually the name of a file that is generated by a program;
examples of targets are executable or object files. A target can also be
the name of an action to carry out, such as `clean' .
A "dependency" is a file that is used as input to create the target. A
target often depends on several files.
A "command" is an action that `make' carries out. A rule may have more
than one command, each on its own line. *Please note:* you need to put a
tab character at the beginning of every command line! This is an obscurity
that catches the unwary.
Usually a command is in a rule with dependencies and serves to create a
target file if any of the dependencies change. However, the rule that
specifies commands for the target need not have dependencies. For example,
the rule containing the delete command associated with the
target `clean' does not have dependencies.
A "rule", then, explains how and when to remake certain files which are
the targets of the particular rule. `make' carries out the commands on the
dependencies to create or update the target. A rule can also explain how
and when to carry out an action.
A makefile may contain other text besides rules, but a simple makefile
need only contain rules. Rules may look somewhat more complicated than
shown in this template, but all fit the pattern more
A Simple Makefile
Here is a straightforward makefile that describes the way an executable
file called `edit' depends on eight object files which, in turn, depend on
eight C source and three header files.
In this example, all the C files include `defs.h', but only those
defining editing commands include `command.h', and only low level files
that change the editor buffer include `buffer.h'.
edit : main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean : rm edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
We split each long line into two lines using backslash-newline; this is
like using one long line, but is easier to read.
To use this makefile to create the executable file called `edit', type:
make
To use this makefile to delete the executable file and all the object
files from the directory, type:
make clean
In the example makefile, the targets include the executable file `edit',
and the object files `main.o' and `kbd.o'. The dependencies are files such
as `main.c' and `defs.h'. In fact, each `.o' file is both a target and a
dependency. Commands include `cc -c main.c' and `cc -c kbd.c'.
When a target is a file, it needs to be recompiled or relinked if any of
its dependencies change. In addition, any dependencies that are themselves
automatically generated should be updated first. In this example, `edit'
depends on each of the eight object files; the object file `main.o' depends
on the source file `main.c' and on the header file `defs.h'.
A shell command follows each line that contains a target and
dependencies. These shell commands say how to update the target file. A
tab character must come at the beginning of every command line to
distinguish commands lines from other lines in the makefile. (Bear in
mind that `make' does not know anything about how the commands work. It is
up to you to supply commands that will update the target file properly.
All `make' does is execute the commands in the rule you have specified when
the target file needs to be updated.)
The target `clean' is not a file, but merely the name of an action.
Since you normally do not want to carry out the actions in this rule,
`clean' is not a dependency of any other rule. Consequently, `make' never
does anything with it unless you tell it specifically.
Note that this rule not only is not a dependency, it also does not have any
dependencies, so the only purpose of the rule is to run the specified
commands. Targets that do not refer to files but are just actions are
called "phony targets".
Variables Make Makefiles Simpler
In our example, we had to list all the object files twice in the rule
for `edit' (repeated here):
edit : main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
Such duplication is error-prone; if a new object file is added to the
system, we might add it to one list and forget the other. We can eliminate
the risk and simplify the makefile by using a variable. "Variables" allow a
text string to be defined once and substituted in multiple places later.
It is standard practice for every makefile to have a variable named
`objects', `OBJECTS', `objs', `OBJS', `obj', or `OBJ' which is a list of
all object file names. We would define such a variable `objects' with a
line like this in the makefile:
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
Then, each place we want to put a list of the object file names, we can
substitute the variable's value by writing `$(objects)'.
Here is how the complete simple makefile looks when you use a variable
for the object files:
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean : rm edit $(objects)
-Letting `make' Deduce the Commands
It is not necessary to spell out the commands for compiling the
individual C source files, because `make' can figure them out: it has an
"implicit rule" for updating a `.o' file from a correspondingly named `.c'
file using a `cc -c' command. For example, it will use the command `cc -c
main.c -o main.o' to compile `main.c' into `main.o'. We can therefore omit
the commands from the rules for the object files.
When a `.c' file is used automatically in this way, it is also
automatically added to the list of dependencies. We can therefore omit the
`.c' files from the dependencies, provided we omit the commands.
Here is the entire example, with both of these changes, and a variable
`objects' as suggested above:
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h
.PHONY : clean
clean : -rm edit $(objects)
This is how we would write the makefile in actual practice. (The
complications associated with `clean' are described elsewhere.
Because implicit rules are so convenient, they are important. You will see
them used frequently.
-Another Style of Makefile
When the objects of a makefile are created only by implicit rules, an
alternative style of makefile is possible. In this style of makefile, you
group entries by their dependencies instead of by their targets. Here is
what one looks like:
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h
Here `defs.h' is given as a dependency of all the object files; `command.h'
and `buffer.h' are dependencies of the specific object files listed for them.
Whether this is better is a matter of taste: it is more compact, but
some people dislike it because they find it clearer to put all the
information about each target in one place.
-
Rules for Cleaning the Directory
Compiling a program is not the only thing you might want to write rules
for. Makefiles commonly tell how to do a few other things besides
compiling a program: for example, how to delete all the object files and
executables so that the directory is `clean'.
Here is how we could write a `make' rule for cleaning our example editor:
clean:
rm edit $(objects)
In practice, we might want to write the rule in a somewhat more
complicated manner to handle unanticipated situations. We would do this:
.PHONY : clean
clean :
-rm edit $(objects)
This prevents `make' from getting confused by an actual file called `clean'
and causes it to continue in spite of errors from `rm'.
A rule such as this should not be placed at the beginning of the makefile,
because we do not want it to run by default! Thus, in the example
makefile, we want the rule for `edit', which recompiles the editor, to
remain the default goal.
Since `clean' is not a dependency of `edit', this rule will not run at
all if we give the command `make' with no arguments. In order to make the
rule run, we have to type `make clean'.
-
What Name to Give Your Makefile
By default, when `make' looks for the makefile, it tries the following
names, in order: `GNUmakefile', `makefile' and `Makefile'.
~ibrahim