makefile summarize

Variable Assignment(变量赋值)

comparison of “=“, “:=“ , “?=“ and “+=

=

Variables defined with ‘=’ are recursively expanded variables. It means that value of this variable will be the last value gived by ‘=’ in makefile. For example:

1
2
3
a = foo
b = $(a) abc
a = oof

In this case, the value of b will be oof abc.

:=

Variables defined with ‘:=’ are simply expanded variables. Just like “=“ in other language(C/C++/C#/Java). For example:

1
2
3
a := foo
b := $(a) abc
a := oof

In this case, the value of b will be foo abc.

?=

We can use ‘?=’ to set a value to a variable only if this variable is not set yet. For example:

1
a ?= foo

It is similar to:

1
2
3
ifeq ($(origin a), undefined)
a = bar
endif

+=

‘+=’ is using for appending text. It will appending a space between two text.For example:

1
2
a = first
a += second

In this case, the value of a will be first second.

Useful Makefile Functions

In makefile, functions should be called like this:

1
var = $(functionname arg1,arg2,arg3...)

wildcard

wildcard will help you get specific file name list in a dir.For example:

1
2
SRC_DIR := src
SOURCES := $(wildcard $(SRC_DIR)/*.cpp)

In this case, SUORCES will be set like this(if *.cpp exists in SRC_DIR):

1
src/a.cpp src/b.cpp src/c.cpp 

addprefix

addprefix is using for add one value to the front of another value. For example:

1
a = $(addsuffix .o,foo bar)

a will be set as ‘foo.o bar.o

patsubst

$(patsubst pattern,replacement,text):Finds whitespace-separated words in text that match pattern and replaces them with replacement(gnu.org)
For example:

1
a = $(patsubst %.cpp,%.o,a.cpp b.h c.cpp)

a will be set as ‘a.o b.h c.o

notdir

$(notdir names…):remove dir in names.For example:

1
a = $(notdir src/foo.c src/bar.c)

a will be set as ‘foo.c bar.c

Using those functions to genreate *.o file and exec files in specific dir

1
2
3
4
5
SRC_DIR:=src
OBJ_DIR:=obj
OUT_DIR:=out
SOURCES:=$(wildcard $(SRC_DIR)/*.cpp)
OBJECTS:=$(addprefix $(OBJ_DIR)/,$(patsubst %.cpp,%.o,$(notdir $(SOURCES))))

Phony Targets(伪目标)

If we have a recipe :

1
2
clean:
rm -rf $(OBJ_DIR) $(OUT_DIR)

It will works well until one day you add one file called clean. In this case, you need add .PHONY:

1
2
3
.PHONY:clean
clean:
rm -rf $(OBJ_DIR) $(OUT_DIR)

If we do this, ‘make clean’ will run the recipe regardless of whether there is a file named clean.