Summary
The lab assumes that you are familiar with compiling and linking C code and
focuses on how to automate the process through the use of make
and Makefiles.
The lab covers
-
What are Makefiles and how to invoke
make
-
What are Makefile rules, targets, prerequisites and recipes.
-
Makefile variables
For more detailed information on make
consult the documentation that
came with your OS and online.
What are Makefiles and how to invoke make
Makefiles are text files that reside on your drive. By convention the
file is also called Makefile
. Here is an example
hello:
gcc hello.c -o hello
To run this Makefile type
make
in the same directory as the file. Alternatively you can specify the name of the Makefile
to make
by using the -f
option, e.g.,
make -f Makefile
What are Makefile rules, targets, prerequisites and recipes.
Makefiles contain rules . A rule has the following schema
target : prerequisite ...
TAB recipe
...
-
You can think of
target
as the name of the file that this rule will generate. -
After the colon
:
we have a space separated list of files/targets that areprerequisite
s. The list of prerequisite can be empty. If the prerequisite is a file,make
will look for this files in your current folder. If a prerequisite is a targetmake
will jump to that target and create it first before coming back to this rule. -
The next line must start with a TAB special character. It must be a TAB and not spaces.
-
Following the TAB character we have the commands that
make
will perform in order to create the target.
So looking at our simple Makefile from the previous section, we have
-
one target called
hello
-
the target
hello
has no prerequisites -
the recipe is the command
gcc hello.c -o hello
By default make
will run the first target in the Makefile. In the case that we want
to run some other target we can pass the target name as an argument to
make
, e.g., make hello
.
Makefiles also accommodate targets that are not files. These are called phony targets. Think of phony targets as names for tasks.
all: hello (1)
hello: (2)
gcc hello.c -o hello
.PHONY: all (3)
We can tell make
which target(s) are phony by using the special
target name .PHONY
and listing all the phony targets as
prerequisites.
1 | specifies that all has one prerequisites hello and there are no
recipes for target all . This means that make will have to build the target
hello first in order to satisfy the target All . |
2 | is a new target that we added called hello , it has no prerequisites and the
recipe builds hello.c |
3 | specifies all as a phony target. |
If we do not specify all
as a phony target and it happens that there is a file
with the name all
, make
will take into account the file’s timestamp when
calculating what needs to be build. This might have side effects you do not expect.
Another typical phony target is clean
. This is the target typically used to
remove temporary and generated files.
all: hello
hello:
gcc hello.c -o hello
clean: (1)
-rm hello *.o (2)
.PHONY: all clean
1 | defines our new rule named clean . |
2 | the recipe runs the command rm hello *.o to remove the executable hello and
files with the suffix .o . Notice the starting hyphen - . The starting hyphen
instructs make that it should not fail in case that the command fails, e.g., calling
make clean when there is no hello file or any \*.o file will fail the
execution of rm but the target clean will succeed. |
Here is the output from running make clean
when there is no hello
file or *.o
files present
make -f Makefile.3 clean rm hello *.o rm: cannot remove ‘hello’: No such file or directory rm: cannot remove ‘*.o’: No such file or directory make: [clean] Error 1 (ignored)
Let’s also update our rule for hello
. There is a prerequisites that we should have
for that target, hello.c
. When the file changes we would like make to rebuild
the target hello
and any other target that depends (has hello
as a prerequisite)
on hello
.
all: hello
hello: hello.c
gcc hello.c -o hello
clean:
-rm hello *.o
.PHONY: all clean
Makefile variables
make
allows for the definition and use of variables. Consider a Makefile that
builds 3 source files hello.c
, announce.c
and yell.c
. Here is our first
version of the Makefile without the use of variables.
# begins a comment till the end of the line
#
# makefile for siri
all: hello.o announce.o yell.o
gcc -o siri hello.o announce.o yell.o
hello.o: hello.c
gcc -c -Wall hello.c
announce.o: announce.c
gcc -c -Wall announce.c
yell.o: yell.c
gcc -c -Wall yell.c
clean:
-rm *.o
.PHONY: all clean
We create variables with the syntax VAR_NAME=VAR_VALUE
and we use a variable with the
syntax $(VAR_NAME)
. Here is our Makefile refactored with variables.
#
# makefile for siri
# use `#` to begin a comment till the end of the line
CC = gcc
CFLAGS = -c -Wall
all: hello.o announce.o yell.o
$(CC) -o siri hello.o announce.o yell.o
hello.o: hello.c
$(CC) $(CFLAGS) hello.c
announce.o: announce.c
$(CC) $(CFLAGS) announce.c
yell.o: yell.c
$(CC) $(CFLAGS) yell.c
clean:
-rm *.o
.PHONY: all clean
The information in this lab should help you to get started with Makefiles. There are a lot
more features to make
and Makefiles, consult the make
documentation that is part
of your OS or online.