CSC209H Worksheet: Makefiles
In this worksheet we will examine the Makefile for Assignment 2 for a previous offering of the course. Remember that the purpose of make is to automate the build process so that
• we don’t have to type a long compile command every time we want to compile our code, and
• dependencies between files are tracked and source files are only recompiled when necessary. 1. Before we look at the full Makefile, consider the following Makefile rule:
test_print: test_print.o ptree.o
gcc -Wall -g -std=gnu99 -o test_print test_print.o ptree.o
(a) Circle the target.
(b) Underline the prerequisites. What is another term for prerequisites?
(c) How many actions does this rule have?
(d) What does a file that ends in .o contain? How is it generated?
2. The remaining questions are about the Makefile on the other side of this page.
Suppose that the only files in the current working directory are the source files, the header files, and the Makefile.
In other words, this is the first time any compilation happens.
(a) If we were to run make test load data which rule is evaluated first?
(b) What new files would be created?
(c) What is the last action that is executed in the make command above?
(d) Which files will the pattern rule (%.o : %.c) match on?
(e) If we the modify dectree.c and run make test load data again, which rules are evaluated? Which actions are executed?
%.o : %.c
gcc ${FLAGS} -c $<
datasets : datasets.tgz
tar xzf datasets.tgz
.PHONY: clean all
clean:
rm classifier test_load_data *.o
CSC209H Worksheet: Makefiles
Here are two versions of the same Makefile: the first doesn’t use the special variables or pattern rule:
FLAGS = -Wall -g -std=gnu99
all: classifier test_load_data
classifier : dectree.o classifier.o
gcc ${FLAGS} -o classifier dectree.o classifier.o -lm
test_load_data : dectree.o test_load_data.o
gcc ${FLAGS} -o test_load_data dectree.o test_load_data.o -lm
classifier.o : classifier.c dectree.h
gcc ${FLAGS} -c classifier.c
test_load_data.o : test_load_data.c dectree.h
gcc ${FLAGS} -c test_load_data.c
dectree.o : dectree.c dectree.h
gcc ${FLAGS} -c dectree.c
datasets : datasets.tgz
tar xzf datasets.tgz
.PHONY: clean all
clean:
rm classifier test_load_data *.o
The second Makefile is shorter and arguably easier to add to and modify because it uses the variables.
FLAGS = -Wall -g -std=gnu99
all: classifier test_load_data
classifier : dectree.o classifier.o
gcc ${FLAGS} -o $@ $^ -lm
test_load_data : dectree.o test_load_data.o
gcc ${FLAGS} -o $@ $^ -lm
Makefile syntax
Variable
Meaning
$@
Target
$<
First prerequisite
$?
All out of date prerequisites
$ˆ
All prerequisites