Writing and Testing Programs 69
This seems acceptable for two files, but becomes a serious problem for larger projects.
Recompiling every file can take minutes, or even hours.
Fortunately it is possible to compile individual files separately. When a source file is
compiled, an intermediate file is created. This intermediate file is called an object file and it
has the .o extension. Once an object file has been created for the corresponding source file,
gcc has a special procedure, called linking, for creating an executable file. The following
shows the commands.
$ gcc -g -Wall -Wshadow -c aredistinct.c
$ gcc -g -Wall -Wshadow -c main.c
$ gcc -g -Wall -Wshadow ardistinct.o main.o -o prog
The first gcc command compiles aredistinct.c and creates the object file whose name
is aredistinct.o. Adding -c after gcc tells gcc to create an object file. The object file has
the same name as the source file, except the extension is changed from .c to .o. Similarly,
the second command compiles main.c and creates main.o. The third command takes the
two object files and creates the executable file. This command links the two files because
the input files are object files and uses -o for the name of the executable output file. Please
notice that the last command has no -c.
To see how this saves time, note that aredistinct.o only needs to be updated if
aredistinct.c is changed. Similarly, main.o only needs to be updated if main.c changes.
If either of the object files change, then the link command (the third command above) needs
to be rerun to generate the updated executable. Avoiding the unnecessary compilation saves
time. This is called separate compilation. Even if the advantages of separate compilation
are compelling, typing the three commands is even more awkward and tedious than typing
one command. It certainly is inefficient to type
$ gcc -g -Wall -Wshadow -c main.c
$ gcc -g -Wall -Wshadow ardistinct.o main.o -o prog
whenever main.c is modified. These commands are too long to type over and over again.
Moreover, it is necessary to keep track of which files have been changed and need recom-
pilation. Fortunately, special build tools have been developed to take care of these issues.
The make program in Linux is one popular tool for this purpose.
5.1.4 make
The make program in Linux takes a special input file whose name is Makefile. The main
purpose of the Makefile is to decide which files need to be recompiled. The decisions are
based on the modification time of the object files and the relevant .c files. The object file
aredistinct.o depends on aredistinct.c. If aredistinct.c has a newer modification
date (or time) than aredistinct.o, then make recompiles aredistinct.c. This is expressed
below in the Makefile.
aredis tinct . o: aredist inct . c1
gcc -g - Wall - Wshadow -c aredi stinct .c2
The first line uses : to indicate dependence—aredistinct.o depends on aredistinct.c.
If aredistinct.o does not exist or aredistinct.c is newer than aredistinct.o, then
the command in the next line will be executed. This command uses gcc to recompile
aredistinct.c and to generate aredistinct.o. A Tab key is needed before gcc at the
second line. In make Tab cannot be replaced by spaces.
Note that Makefile is the name of a file that make looks for when it runs. You can tell
make to use any file by adding -f name: