As with all good explanations of UNIX facilities, we will start
with Hello World, in C:
#include <stdio.h> int main (int argc, const char *argv[]) { printf ("Hello, World!\n"); return 0; }
Example 5.1: hello.c
-- an old favourite
In a directory that contains nothing but this one file, you can invoke
make
to make a program out of it, like so:
$ make hello gcc hello.c -o hello $ ./hello Hello, World!
The program hello
that Make has been asked to build is known as
the target. The files that are required in order to bring the
target up to date, or to refresh the target, are called the
target's dependencies1.
Make knows an awful lot about the compilation process, and the
relationships between file names of related suffixes (also known
as extensions). In the example above, when we asked
make
to refresh hello
for us, it was able to infer that
it should compile hello.c
, in part due to the presence of
hello.c
, but also due to the fact that files with a .c
suffix are normally passed to the C compiler. This inference depends on
the association between the target name, hello
, and the source
file name, hello.c
; Make did not merely pick hello.c
because it was the only file in the build directory. For example in the
same directory, it won't work if we try to make
a target with
no matching source file name:
$ make helloagain make: *** No rule to make target `helloagain'. Stop.
Internally, Make contains an extensive database of commands that are
normally used to transform between files with names that differ only in
suffix. As another example, Make knows that intermediate compilation
objects are held in files with a .o
suffix (voir The GNU Compiler Collection), and that the C compiler performs that
transformation:
$ make hello.o gcc -c -o hello.o hello.c