1、语法编译规则
targets : prerequisites
command
targets:规则的目标。可以是一个标签,也可以是要生成的可执行文件,还可以是 Object File(一般称它为中间文件);
prerequisites:依赖文件。要生成 targets 需要的文件或者是目标,可以没有,也可以是多个;
command:make 需要执行的命令(任意的 shell 命令)。可以有多条命令,每一条命令占一行。
【注】规则目标和依赖文件之间要使用冒号分隔开
【注】命令的开始一定要使用Tab键
2、变量定义
Makefile 文件中定义变量的基本语法如下, 变量的名称可以由大小写字母、阿拉伯数字和下划线构成。等号左右的空白符没有明确的要求,因为在执行 make 的时候多余的空白符会被自动的删除。至于值列表,既可以是零项,又可以是一项或者是多项。
变量的名称=值列表 #示例:VALUE_LIST = one two three
这些变量分为三大类:自定义变量、内置变量、自动变量,其中自定义变量和内置变量较为常用。
2.1 自定义变量
赋值方式 含义
简单赋值 ( := ) 只对当前语句的变量有效
递归赋值 ( = ) 赋值语句可能影响多个变量,所有目标变量相关的其他变量都受影响
条件赋值 ( ?= ) 如果变量未定义,则使用符号中的值定义变量。如果该变量已经赋值,则该赋值语句无效
追加赋值 ( += ) 原变量用空格隔开的方式追加一个新值
##########执行命令:make test###################
###############简单赋值#########################
x:=foo
y:=$(x)b
x:=new
test:
@echo "y=>$(y)" #执行结果:y=>foob
@echo "x=>$(x)" #执行结果:x=>new
###############递归赋值##########################
x=foo
y=$(x)b
x=new #该变量会覆盖之前的赋值(递归赋值尽量不要对相同变量使用)
test:
@echo "y=>$(y)" #执行结果:y=>newb
@echo "x=>$(x)" #执行结果:x=>new
###############条件赋值##########################
x:=foo
y:=$(x)b
x?=new #该变量上文已定义,故此处赋值无效
test:
@echo "y=>$(y)" #执行结果:y=>foob
@echo "x=>$(x)" #执行结果:x=>foo
###############追加赋值##########################
x:=foo
y:=$(x)b
x+=$(y) #在上文赋值基础上进行追加赋值,以单空格隔开
test:
@echo "y=>$(y)" #执行结果:y=>foob
@echo "x=>$(x)" #执行结果:x=>foo foob
2.2自动变量
自动化变量可以理解为由 Makefile 自动产生的变量。在模式规则(通过匹配模式找字符串)中,规则的目标和依赖的文件名代表了一类的文件。规则的命令是对所有这一类文件的描述。我们在 Makefile 中描述规则时,依赖文件和目标文件是变动的,显然在命令中不能出现具体的文件名称,否则模式规则将失去意义。
##########执行命令:make test###################
test:test.o test1.o test2.o
gcc -o $@ $^ # "$@" 代表的是目标文件test
test.o:test.c test.h
gcc -o $@ $< # “$^”代表的是所有依赖文件
test1.o:test1.c test1.h
gcc -o $@ $< # “$<”代表的是依赖文件中的第一个
test2.o:test2.c test2.h
gcc -o $@ $<
3、条件判断
############# ifeq #############
libs_for_gcc= -lgnu
normal_libs=
ifeq($(CC),gcc) # CC是系统环境变量
libs=$(libs_for_gcc)
else
libs=$(normal_libs)
endif
foo:$(objects)
$(CC) -o foo $(objects) $(libs)
############# ifdef #############
foo=
all:
ifdef foo
@echo yes
else
@echo no #打印的结果:no
endif
4、Makefile 特殊符号 - 、@、 +、 $ 、$$
4.1 - 符号 (连字符)
任何命令行的任何非零退出状态都被忽略,忽略当前命令行执行时所遇到的错误。
make 在执行命令的时候,如果遇到 error,会退出执行。加上减号的目的是即便此命令行执行出错,那么也不要管,继续执行 make。
通常删除或者创建文件时,遇到文件不存在或者已经创建。如果希望忽略掉错误,继续执行,就可以在命令行前面添加 -。
.PHONY : clean
clean :
-rm $(objects)
4.2 @ 符号 (at 符号)
通常 makefile 会将其执行的命令行在执行前输出到屏幕上。如果将 @ 添加到命令行前,这个命令将不被 make 回显出来,即不显示命令本身而只显示结果。
ifdef DEFINE_VAR
VAR = "!!!Hello World!!!"
endif
ifeq ($(OPT), define)
VAR ?= "!FIRST!"
endif
ifeq ($(OPT), add)
VAR += "!SECOND!"
endif
ifeq ($(OPT), recover)
VAR := "!THIRD!"
endif
x = cheng
y = $(x) yong
x = qiang
m := face
n := $(m) person
m := pedestrian
all :
@echo Compiling Kernel Module
echo Compiling Kernel Module
@echo $(VAR)
@echo $(x)
@echo $(y)
@echo $(m)
@echo $(n)
strong@foreverstrong:~/Desktop/makefile_work$ make DEFINE_VAR=true
Compiling Kernel Module
echo Compiling Kernel Module
Compiling Kernel Module
!!!Hello World!!!
qiang
qiang yong
pedestrian
face person
strong@foreverstrong:~/Desktop/makefile_work$
4.3 + 符号 (加号)
使用加号修饰符让命令始终执行。命令行执行时不受到 make 的 -n -t -q 三个参数的影响,忽略这三个参数。
如果 make 执行时,使用 -n 或 --just-print。该参数显示命令,不会执行命令。这个功能有利于调试 Makefile,方便查看执行的命令形式和顺序。
4.4 $ 符号 (美元符号)
美元符号 $,扩展打开 makefile 中定义的变量。
4.5 $$ 符号
$$ 符号,扩展打开 makefile 中定义的 shell 变量。