[WPI] [cs2223] [cs2223 text] [News] [Notes]
As programs grow in complexity, management of the program becomes increasingly
difficult. Often large programs span several source and header files. Changing
any one of them requires recompilation and linking some portion of the program
modules. It is easy to forget which other parts of the program are affected
when an individual module is changed. This is particularly a problem when
several people are working on the same program.
The utiliy make
helps to manage the software development
process. Basically what it does is to keep track of which modules have been
modified and when. By comparing modification dates and a dependency list,
make
determines which modules need to be recompiled
and relinked when rebuilding your program after any module is changed. Let's
look at an example.
Suppose your program consists of five source files plus two header files,
each of which is used in some, but not all, of the source code files. If
you change one of the header files, some of the source code files need to
be recompiled and the resulting object code files need to be relinked to
produce a new executable version of your program. Instead of looking inside
each source file to decide which to recompile, and issuing a set of g++
commands with different source and object file names, a single command is
used -- something like this:
make my_prog
The utility make
will look for a file called "makefile
"
or "Makefile
" (no quotes, no extension) which contains
a dependency list and compilation instructions. Most systems require that
all but the first letter be lowercase; some systems will only take one version
of this name, so you may have to experiment. The list looks very similar
to the string of g++
commands you would normally type, except
they are all contained in a single file.
A typical make
file looks like this:
my_prog : main.C file1.o file2.o file3.o file4.o head1.h g++ -o my_prog main.C file1.o file2.o file3.o file4.o file1.o : file1.C #this is how to include a comment g++ -o file1.o file1.C -lm file2.o : file2.C head1.h #this is a dependency line g++ -o file2.o file2.C #this is a command line file3.o: file3.C file1.h file2.h g++ -o file3.o file3.C |
makefile
says that the object module my_prog
depends on four object
files and one header file. If any of those five files is changed, it is
necessary to recompile my_prog
. Note the use of the colon to
separate the object name my_prog from the list of files on which it depends.
makefile
says that the way to rebuild the object module my_prog
is to
use the g++
command to compile main.C
, link it
with four object files, and create an oject module called my_prog
.
These command lines are identical to the ones you would issue directly to
the UNIX shell, one at at time. You can't see it above, but each
command line begins with a tab character, not with spaces.
Using spaces instead of a tab is a common error when writing makefiles
.
Notice how one of the command lines above tells g++
to include
the math library.
'\t'
is considered to be
a command line. Any line not beginning with a tab is considered
to be aa dependency line. After the first character, you may use
tabs anywhere in a command or dependency line without effect. Similarly,
all extraa spaces in lines are ignored. Note, when you look at a make file,
it is sometimes hard to distinguish where the line begins with tab or space.
main.C
", "file.o
",
etc., need to be replaced by the actual path names, which can be considerably
longer.
'\''\r'
. Type a backslash followed immediately
by an return and then you can continue typing on the next line; make will
parse the text as if it had been typed on a single line.. This is quite
useful when including long path names or when you want to line up file
names to improve readability.
#
until the end of the
line is ignored. This is how comments are inserted into makefiles
.
Totally blank lines are also ignored.
You run make
by typing make
followed
by the name of the target or object module. For example, if you type
make file2.o
the make
utility checks to see whether file2.C
or head1.h
has been changed since the list time that file2.o
was created. If either or both have changed, then the commnd
g++ -o file1.o file1.C -lm
is used to create a new version of file2.o
. If neither file2.C
nor head1.h
has changed, then make
quits
without doing anything. Similarly, you can make
any of the
other targets in the makefile
-- anything to the left of a
colon on a dependencies line. If you type the command
make my_prog
then each of the dependency list objects will be checked too. If, for
example, head1.h
has been changed than the files file2.o
and file3.o
will be regenerated (using their respective command
lines from the makefile
) before my_prog
is regenerated
using its own command line.
Remember, you must be in the same directory as the makefile
and it has to be named exactly makefile
for this to work.
If you use the make facility, it is easier to keep track of large programs.
For example, as you work on individual files that are part of a large program,
you need only change the files and, if necessary, change the makefile. Then
instead of invoking g++
directly whenever you change anything,
you use the make
command to rebuild what you need when you
need it and all dependencies are automataically accounted for.
This is only a brief introduction to a few of make
's features.
You can learn more by using the command
man make
on your workstation. Also, the books mentioned in the Notes
page contain useful information.
[cs2223 text] [News] [Notes] |