Make is a build tool, which reads rules from a makefile. A rule looks like this:
target: prerequisites recipe
If the prerequisite files are newer than the target, make will run the recipe to rebuild the target.
- There is a TAB before the recipe.
- The prerequisite files can be both data and code.
- If the target is a directory, the timestamp is not automatically updated when files are copied into it. Thus the last step is usually
touch [email protected].
- Make prints actions as it executes them. Using
@at the start of an action tells Make not to print this action. Therefore usually there is a
make: builds the first target in makefile.
make target1: searches the rule for
target1and builds it.
make clean: usually
cleanis a phony target, which removes all temporary files.
- Separate configuration from computation: use
include config.mkat the top of the main makefile and put all configuration (LANGUAGE, SRC_FILE_NAME, etc) in
make clean will run the recipe regardless of whether there is a file named clean.
.PHONY: clean clean: rm *.o temp
make to remake all three programs, or specify as arguments the ones to remake (as in ‘make prog1 prog3’).
all : prog1 prog2 prog3 .PHONY : all prog1 : prog1.o utils.o cc -o prog1 prog1.o utils.o prog2 : prog2.o cc -o prog2 prog2.o prog3 : prog3.o sort.o utils.o cc -o prog3 prog3.o sort.o utils.o
When one phony target is a prerequisite of another, it serves as a subroutine of the other. For example,
make cleanall will delete the object files, the difference files, and the file
.PHONY: cleanall cleanobj cleandiff cleanall : cleanobj cleandiff rm program cleanobj : rm *.o cleandiff : rm *.diff
[email protected]: the target of the current rule.
$^: the dependencies of the current rule.
$<: the first dependency of the current rule.
-f: read from other files than makefile, e.g.
make -f common.mk.
-n: dry run - show the commands it will execute without actually running them.
-C: change the directory and then run make.
%.dat : books/%.txt countwords.py python countwords.py $< $*.dat # can also use [email protected] here
This rule can be interpreted as: “In order to build a file named [something].dat (the target) find a file named books/[that same something].txt (the dependency) and run countwords.py [the dependency] [the target].”
% wildcard can only be used in a target and in its dependencies. It cannot be used in actions. In actions, you may however use
$*, which will be replaced by the stem with which the rule matched.
Variables can make the makefile more readable. For example:
CC = gcc # variable assignment CCFLAGS = -Wall -Wextra -Werror -std=c99 -pedantic -g main: main.o moreCode.o $(CC) $(CCFLAGS) -o main main.o moreCode.o # variable reference
wildcard function to get lists of files matching a pattern. Use
patsubst function to rewrite file names.
TXT_FILES=$(wildcard books/*.txt) DAT_FILES=$(patsubst books/%.txt, %.dat, $(TXT_FILES)) # output TXT_FILES: books/abyss.txt books/isles.txt books/last.txt books/sierra.txt DAT_FILES: abyss.dat isles.dat last.dat sierra.dat
Add a comment that begins with
## before each block and add a help block:
# makefile ## clean : Remove auto-generated files. .PHONY : clean clean : rm -f $(DAT_FILES) rm -f results.txt .PHONY : help help : Makefile @sed -n 's/^##//p' $< $ make help clean : Remove auto-generated files.