What’s Wrong With GNU make?
HOWTO: Intro to GNU make variables
target: normal-prerequisites | order-only-prerequisites
recipe
Debugging
$ make -d
==> print out the parser results
$ make -p
==> execute make but prints the database
(buildins + Makefile) at the end
.SUFFIXES
Considering target file 'obj/osa541x_sim/advaNtpd/ntpd/ntp_parser.o'.
File 'obj/osa541x_sim/advaNtpd/ntpd/ntp_parser.o' does not exist.
Considering target file 'src/ntpd/ntp_parser.c'.
Looking for an implicit rule for 'src/ntpd/ntp_parser.c'.
Trying pattern rule with stem 'ntp_parser'.
Trying implicit prerequisite 'src/ntpd/ntp_parser.y'.
Found an implicit rule for 'src/ntpd/ntp_parser.c'.
Considering target file 'src/ntpd/ntp_parser.y'.
Looking for an implicit rule for 'src/ntpd/ntp_parser.y'.
Trying pattern rule with stem 'ntp_parser.y'.
Found an implicit rule for 'src/ntpd/ntp_parser.y'.
Finished prerequisites of target file 'src/ntpd/ntp_parser.y'.
No need to remake target 'src/ntpd/ntp_parser.y'.
Finished prerequisites of target file 'src/ntpd/ntp_parser.c'.
Prerequisite 'src/ntpd/ntp_parser.y' is newer than target 'src/ntpd/ntp_parser.c'.
Must remake target 'src/ntpd/ntp_parser.c'.
yacc src/ntpd/ntp_parser.y
Putting child 0xe159d0 (src/ntpd/ntp_parser.c) PID 5528 on the chain.
Live child 0xe159d0 (src/ntpd/ntp_parser.c) PID 5528
make: yacc: Command not found
Reaping losing child 0xe159d0 PID 5528
<builtin>: recipe for target 'src/ntpd/ntp_parser.c' failed
make: *** [src/ntpd/ntp_parser.c] Error 127
Removing child 0xe159d0 PID 5528 from chain.
# default
SUFFIXES := .out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo .w .ch .web .sh .elc .el
[...]
%.c: %.y
# recipe to execute (built-in):
$(YACC.y) $<
mv -f y.tab.c $@
.SUFFIXES:
Considering target file 'obj/osa541x_sim/advaNtpd/ntpd/ntp_parser.o'.
File 'obj/osa541x_sim/advaNtpd/ntpd/ntp_parser.o' does not exist.
Considering target file 'src/ntpd/ntp_parser.c'.
Looking for an implicit rule for 'src/ntpd/ntp_parser.c'.
Trying pattern rule with stem 'ntp_parser'.
Trying implicit prerequisite 'src/ntpd/ntp_parser.w'.
Trying pattern rule with stem 'ntp_parser.c'.
Found an implicit rule for 'src/ntpd/ntp_parser.c'.
Finished prerequisites of target file 'src/ntpd/ntp_parser.c'.
No need to remake target 'src/ntpd/ntp_parser.c'.
Finished prerequisites of target file 'obj/osa541x_sim/advaNtpd/ntpd/ntp_parser.o'.
Must remake target 'obj/osa541x_sim/advaNtpd/ntpd/ntp_parser.o'.
Putting child 0x1dcaaa0 (obj/osa541x_sim/advaNtpd/ntpd/ntp_parser.o) PID 5755 on the chain.
Live child 0x1dcaaa0 (obj/osa541x_sim/advaNtpd/ntpd/ntp_parser.o) PID 5755
[CC] src/ntpd/ntp_parser.c
Tagged Commands / Command Prefix
What do @, – and + do as prefixes to recipe lines in Make?
Command lines can have one or more of the following three prefixes:
- a hyphen-minus (-), specifying that errors are ignored
- an at sign (@), specifying that the command is not printed to standard output before it is executed
- a plus sign (+), the command is executed even if Make is invoked in a “do not execute” mode
- @ suppresses the normal ‘echo’ of the command that is executed.
- – means ignore the exit status of the command that is executed (normally, a non-zero exit status would stop that part of the build).
- + means ‘execute this command under make -n’ (when commands are not normally executed).
Substitution
Substitution References
SOURCE = main.c test.c bla.cpp blu.cpp bli.c
OBJECT = $(SOURCES:%.c=%.o)
Result:
main.o test.o bla.cpp blu.cpp bli.o
Functions
Functions for String Substitution and Analysis
SOURCE = main.c test.c bla.cpp blu.cpp bli.c
C_OBJECT = $(filter %.c,$(SOURCE): %.c=%.o)
CXX_OBJECT = $(filter %.cpp,$(SOURCE): %.cpp=%.o)
Result:
main.o test.o bla.cpp blu.cpp bli.o
Setting Variables = := ?= !=
Setting Variables
The Two Flavors of Variables
Computing Makefile variable on assignment
= Recursively expanded variable
:= Simply expanded variables
?= Only set variable if it’s not already set
!= execute program and set variable to its output
FOO ?= bar
equal to
ifeq ($(origin FOO), undefined)
FOO = bar
endif
hash != printf '\043'
file_list != find . -name '*.c'
equal to
hash := $(shell printf '\043')
var := $(shell find . -name "*.c")
Double-Colon Rules
Double-Colon Rules
What are double-colon rules in a Makefile for?
Makefiles – Make and the Double colon
ibxxx.a : sub1.o sub2.o
ar rv libxxx.a sub1.o
ar rv libxxx.a sub2.o
====
libxxx.a :: sub1.o
ar rv libxxx.a sub1.o
libxxx.a :: sub2.o
ar rv libxxx.a sub2.o
Empty Recipes (Semicolon)
Using Empty Recipes
What does it mean when a semicolon occurs in a makefile target’s prerequisites?
Match-Anything Pattern Rules
target: ;
% :: ;
Order-Only-Prerequisites
Types of Prerequisites
What does $$@ and the pipe symbol in Makefile stand for?
Makefile execute phonytargets of a file only if file does not exists
targets: normal-prerequisites | order-only-prerequisites
recipe
Pattern Rules
You define an implicit rule by writing a pattern rule. A pattern rule looks like an ordinary rule, except that its target contains the character ‘%’ (exactly one of them). The target is considered a pattern for matching file names; the ‘%’ can match any nonempty substring, while other characters match only themselves. The prerequisites likewise use ‘%’ to show how their names relate to the target name.
Defining and Redefining Pattern Rules
Pattern Rule Examples
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
Automatic Variables
Automatic Variables
$@
|
The file name of the target of the rule. |
$%
|
The target member name, when the target is an archive member. |
$<
|
The name of the first prerequisite. |
$?
|
The names of all the prerequisites that are newer than the target, with spaces between them. |
$^
|
The names of all the prerequisites, with spaces between them. |
$+
|
This is like ‘$^’, but prerequisites listed more than once are duplicated in the order they were listed in the makefile. |
$|
|
The names of all the order-only prerequisites, with spaces between them. |
$*
|
The stem with which an implicit rule matches. |
Built-in Target Names
Special Built-in Target Names
.PHONY
|
The prerequisites of the special target .PHONY are considered to be phony targets. When it is time to consider such a target, make will run its recipe unconditionally, regardless of whether a file with that name exists or what its last-modification time is. |
.SUFFIXES
|
The prerequisites of the special target .SUFFIXES are the list of suffixes to be used in checking for suffix rules. |
.DEFAULT
|
. |
.PRECIOUS
|
. |
.INTERMEDIATE
|
. |
.SECONDARY
|
. |
.SECONDEXPANSION
|
. |
.DELETE_ON_ERROR
|
. |
.IGNORE
|
. |
.LOW_RESOLUTION_TIME
|
. |
.SILENT
|
. |
.EXPORT_ALL_VARIABLES
|
. |
.NOTPARALLEL
|
. |
.ONESHELL
|
. |
.POSIX
|
. |
Canned Recipes / Functions/ Templates
Defining Canned Recipes
Makefiles: can 'canned recipes' have parameters?
define run-yacc =
yacc $(firstword $^)
mv y.tab.c $@
endef
define DIRECTORY_template
$(1):
@echo "[MKDIR] $$@"
@mkdir -p $(1)
endef
$(eval $(call DIRECTORY_template,testdir))
foo.c : foo.y testdir
$(run-yacc)
Makefile as a functional language program
The following article describes a real practical application: avoiding the explosion of makefile rules in a project that executes many test cases on many platforms. Each test target is built from its own set of source code files. Each (Scheme) platform has its own particular way of assembling source code files into a project; some source code files might need be omitted from the build for a particular platform. Because GNU make turns out to be a functional programming system, we can reduce the number of rules from * to just + .
The language of GNU make is indeed functional, complete with combinators (map and filter), applications and anonymous abstractions. GNU make does support lambda-abstractions. The following is one example from the Makefile in question: it is a rule to build a test target for the SCM Scheme system. The list of source code files and the name of the target/root-test-file are passed as two arguments of the rule:
make-scmi= scm -b -l $(LIBDIR)/myenv-scm.scm \
$(foreach file,$(1),-l $(LIBDIR)/$(file)) \
-l $(2).scm
The rule returns an OS command to interpret or compile the target. The rule can be invoked as
$(call make-scmi,util.scm catch-error.scm,vmyenv)
. As in TeX, the arguments of a function are numbered (it is possible to assign them meaningful symbolic names, too). Makefile's foreach corresponds to Scheme's map. The comparison with the corresponding Scheme code is striking:
(define make-scmi
(lambda (arg1 arg2)
`(scm -b -l ,(mks LIBDIR '/ 'myenv-scm.scm)
,@(map (lambda (file) `(-l ,(mks LIBDIR '/ file))) arg1)
-l ,(mks arg2 '.scm))))
Timestamp on files and directories
Makefile re-generates some object-files, but I didn't know why:
$ cat Makefile
[...]
obj/pi/main.o: obj/pi src/main.f90
@echo "[FC] src/main.f90"
@gfortran -o $@ -c src/main.f90
obj/pi/pi.o: obj/pi src/pi.f90
@echo "[FC] src/pi.f90"
@gfortran -o $@ -c src/pi.f90
[...]
$ make clean && make
$ make -d
[...]
Prerequisite 'obj/pi' is newer than target 'obj/pi/main.o'.
Prerequisite 'src/main.f90' is older than target 'obj/pi/main.o'.
Must remake target 'obj/pi/main.o'.
[...]
target: dependencies/prerequisites
<Tab> system command(s)/recipe
It imposes a dependency relationship: if any prerequisite is newer than the target, then the target is considered out-of-date and must be rebuilt.
The directory timestamp is updated, when a file in this directory is updated!!
$ stat obj/pi --printf '%n\nmtime: %y\nctime: %z\natime: %x\ncrtime:%w\n'
obj/pi
mtime: 2016-01-08 18:48:17.841692523 +0100
ctime: 2016-01-08 18:48:17.841692523 +0100
atime: 2016-01-08 18:49:34.724417557 +0100
$ touch obj/pi/test
$ stat obj/pi --printf '%n\nmtime: %y\nctime: %z\natime: %x\ncrtime:%w\n'
obj/pi
mtime: 2016-01-08 18:49:46.300225133 +0100
ctime: 2016-01-08 18:49:46.300225133 +0100
atime: 2016-01-08 18:49:34.724417557 +0100
$ stat obj/pi/test --printf '%n\nmtime: %y\nctime: %z\natime: %x\ncrtime:%w\n'
obj/pi/test
mtime: 2016-01-08 18:49:46.300225133 +0100
ctime: 2016-01-08 18:49:46.300225133 +0100
atime: 2016-01-08 18:49:46.300225133 +0100
I changed the directory creation on target 'all' so that the object files doesn't directly depend on the directories anymore:
define DIRECTORY_template
DIRECTORIES += obj/$(1)
obj/$(1):
@echo "[MKDIR] $$@"
@mkdir -p obj/$(1)
endef
[...]
DIRECTORIES =
all: mkdirs $(PROGRAMS)
$(foreach prog,$(PROGRAMS),$(eval $(call VARIABLE_template,$(prog))))
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
mkdirs: $(DIRECTORIES)
Difference between Build Tools
Build Tools: Make, Rake, Ant, MSBuild
RAKE – Ruby Make
Multi-Architecture Builds
Multi-Architecture Builds
How Not to Use VPATH
Rules of Makefiles
BSD make
Programming in Makefiles for NetBSD
GNU make
GNU make with Java
Java: Gnu Make Makefile Examples
make++
Makepp
Makepp Rules
Kleines Beispiel
SOURCES = main.c \
draw.c \
camera.c \
utils.c \
createTexture.c \
text.c
CFLAGS = `sdl-config --cflags` -D_REENTRANT -Wall
LDFLAGS = `sdl-config --libs` -lopengl32 -lglu32 -lSDL_ttf
OBJECTS = $(SOURCES:%.c=%.o)
.PHONY: all clean
all : Aufgabe4
Aufgabe4 : $(OBJECTS)
g++ -o $@ $(OBJECTS) $(LDFLAGS)
%.o : %.c
g++ $(CFLAGS) -c $<
clean :
rm *.o
build : clean all
PHONY:
Links dazu:
Automatic Variables für $< oder $@
How Patterns Match für %.o oder %.c
Phony Targets für .PHONY: clean
GNU Make and the foreach() function
Display the results of foreach / eval / call expansion
How can I use macros to generate multiple Makefile targets/rules inside foreach?
In GNU Make, how do I convert a variable to lower case?
8.4 Functions for Conditionals
GNU make conditional function $(if …) inside a user-defined function always evaluates to true
GNU make: Please give an example for the 'if' function
statt:
$(foreach prog, $(PROGRAMS), $(eval $(call VARIABLE_template,$(prog))))
nun:
$(foreach prog, $(PROGRAMS), $(info $(call VARIABLE_template,$(prog))))