Makefile
variables1
It should be noted that the usage of site a variable in makefile is different from using it in shell.
In makefile, we use $()
to site a variable, which is means that command substitution in shll2
There are three ways to assign for a variable:
=
: It allows that the subsquent variable uses the following variable.:=
: It is same with the assignment symbol in programming language.?=
: If the varible has value, it will do nothing.
Wildcard
The wildcard in makefile is similar with macro in C/C++, it isn’t similar with wildcard in linux shell, so it doesn’t expend automatically.
|
|
Automatically generate dependencies
Utilizing the -M
and -MM
options to get the dependencies of source code from gcc/g++.
These options’ document can be found at Preprocessor-Options. (About why these option in the preprocessor options, it is easy to understand. In the state of preprocessor, the preprocessor will judge the header file, so it knows which files are dependented by current file.)
Hide commands themself
Place @
front of the command, e.g.
If you use echo "compiling..."
in makefile, you will get the output
|
|
If you use @echo "compiling..."
, you will get the output
|
|
Function
Automation variables
$@
: 匹配目标中模式定义的集合
|
|
上述的 $@
指代的即为 %.o
。不过从上述示例中,并不能看出“集合”这一含义,可以结合 $%
来看。
$%
: 仅当目标是函数库文件时,表示规则中的目标成员名
|
|
$%
将代表 a
,$@
将代表 fun
。从这个示例中就可以看出 $@
“集合“这一含义了。
不过 $%
的定义中提到“仅当目标是函数库文件“,如何理解这一点?
|
|
此时 $%
为空,由此即可理解这一变量的用法。
$<
: 第一个依赖文件的名字
例如,在 main.o: main.c defs.h 中,$< 就是 main.c。
$?
: 所有比目标新的依赖目标的集合
例如,如果 main.o 依赖于 main.c 和 defs.h,而 defs.h 比 main.o 更新,那么 $? 就是 defs.h。
$^
: 所有的依赖目标的集合
例如,在 main.o: main.c defs.h 中,$^ 就是 main.c defs.h
$+
: 这个变量很像 $^ ,也是所有依赖目标的集合。只是它不去除重复的依赖目标
例如,在 main.o: main.c defs.h main.c 中,$+ 就是 main.c defs.h main.c
Example
Advanced makefile usage example code
|
|
The above makefile can judge the source code which locates in src directory, and output the object file into the build directory. The following image shows the project file structure.
|
|
After compiling, we will get the following file structure.
|
|
There are some noteworthy points.
$^
and$<
Using the same file structure and editing the makefile, we can understand the difference between these two automation variables.
|
|
After we excute the make
command, we will get the result.
|
|
Based on the project file structure, we can understand the difference between them.
Pattern-specific Variable Values
The most obvious and easy example is distinguishing the difference between $<
and $^
in Automation variables.
i.e. the difference between $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
and $(OBJS): $(SRCS)
Although we know the $<
is the name of the first prerequisite and $^
is the names of all the prerequisites, if we don’t know the difference of the above expression of target: prerequisites
, we can’t understand the result of the g++ $(CFLAGS) -c $< -o $@
.
In short, if we still use the above file structure, when using $(OBJS): $(SRCS)
, the $(OBJS)
is the build/funcs.o build/main.o
, they are one expression, but using
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
, the $(BUILD_DIR)/%.o
is build/funcs.o
and build/main.o
, they are two expressions, it looks like a enumation, so we can use this to generate the corresponding .o object file and .c source file.