Make

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 @ before echo.
  • make: builds the first target in makefile.
  • make target1: searches the rule for target1 and builds it.
  • make clean: usually clean is a phony target, which removes all temporary files.
  • Separate configuration from computation: use include config.mk at the top of the main makefile and put all configuration (LANGUAGE, SRC_FILE_NAME, etc) in config.mk.

Phony Targets

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 program.

.PHONY: cleanall cleanobj cleandiff

cleanall : cleanobj cleandiff
    rm program

cleanobj :
    rm *.o

cleandiff :
    rm *.diff

Automatic Variable

  • [email protected]: the target of the current rule.
  • $^: the dependencies of the current rule.
  • $<: the first dependency of the current rule.

Options

  • -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.

Pattern Rules

%.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].”

The Make % 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/Macros

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

Functions

Use 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

Self-Documenting Makefile

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.

References


comments powered by Disqus