New website: https://rhythm16.github.io
My notes for the Makefile
file used by the make
utility.
The simplest =
will expand recursively when the LHS is used
:=
will expand and lock-in the resulting value when it assigns
?=
will assign only if the LHS is not assigned to anything
$@
: target$<
: the first prerequisite$^
: list of all prerequisite$*
: stem with which the implicit rule matches ("foo" in "foo.c")$(@D)
: target directorymeans every *.o
file seen in the make process is added a dependency *.c
, recipe is given in command
produces a list C_FILES
which contains all the *.c
files in $(SRC_DIR)
OBJ_FILES
is produced by mapping every item in C_FILES
from $(SRC_DIR/%.c
to $(BUILD_DIR)/%_c.o
Simply use include
or use -include
to not do anything if the file doesn't exist.
-M
options in gcc-M
: instead of outputing the preprocessed result, output a make
suiting dependency rule-MM
: ignore system header files-MD
: don't stop at the preprocessor, do the rest of the compilation process and generate the dependency as a side product-MMD
: -MD
and -MM
combined-MP
: create phony targets for each dependency other than the main file-MP
explanationSay the -MMD
option generated foo.d
:
Now if myheader.h
is no longer needed, we remove it from foo.c
, delete myheader.h
and rerun make
, because foo.d
hasn't changed make
will complain that myheader.h
is not found and report an error.
-MP
will create foo.d
like this:
Then myheader.h
will be seen as an empty target by make
in the case that myheader.h
is not present.
When using implicit rules and include
s, there might be multiple rules for one target, in that case all the dependencies are unioned into one big list. The recipe is executed when any of the dependency is younger than the target. There can only be one recipe to be executed for a file.