Suppose we want to build an executable program from two source
files called myprog.c
and
math.c
.
First, exactly one of the files must contain the main program.
In C, this is the function called main()
.
To build the executable, we must first compile each source file
to an object file using the
-c
flag. When compiling with -c
,
a file is compiled (translated to an object file containing
machine code), but not linked with other object files or libraries
to create a complete executable. Object files are not executable,
since they only contain part of the machine language of
the program. The object files have a ".o" extension.
After building all the object files, they are linked
together along with additional object files from libraries to
produce the complete executable.
Using the Makefile below, make starts at the first rule it finds,
indicating that myprog
depends on
myprog.o
and math.o
.
But before running the link command, make
searches the rest of the Makefile and
sees that myprog.o
depends on
myprog.c
and that math.o
depends on math.c
. If either of the
".c" files is newer than the corresponding ".o" file, then
those rules are executed before the link rule that uses them as
sources.
// math.h int square(int c);
// math.c int square(int c) { return c * c; }
// myprog.c #include <stdio.h> #include <sysexits.h> #include <stdlib.h> #include "math.h" int main(int argc,char *argv[]) { int c; for (c = -10; c < 10; ++c) printf("%d ^ 2 = %d\n", c, square(c)); return EX_OK; }
# Makefile # Link myprog.o, math.o and standard library functions to create myprog. myprog: myprog.o math.o cc -o myprog myprog.o math.o -lm # Compile myprog.c to an object file called myprog.o myprog.o: myprog.c cc -c myprog.c # Compile math.c to an object file called math.o math.o: math.c cc -c math.c
Do not explicitly set the compiler to clang or gcc. Doing so renders the Makefile non-portable. Every Unix system has a cc command which is usually the same as clang or gcc, depending on the specific operating system.
Addendum: The book contains some examples using gcc explicitly. At the time the book was written, it was a common practice to install gcc on commercial Unix systems and use it instead of the native cc compiler. This is no longer common.
Running make with this Makefile for the first time, we will see the following output:
shell-prompt: make cc -c myprog.c cc -c math.c cc -o myprog myprog.o math.o
If we then edit math.c
, then it will be
newer than math.o
. When we run
make again, we will see the following:
shell-prompt: make cc -c math.c cc -o myprog myprog.o math.o
Show the compiler commands needed to build an executable called
calc
from source files calc.c
and functions.c
.
What C compiler command should usually be used by default in a makefile? Why?
How does make know when a source file needs to be recompiled?