Makefile
0.什么是Makefile
是make命令的配置文件
make是一个智能化自动归纳的工程管理工具,他可以决定在一个工程里面
那些文件需要被编译,那些文件不需要被编译。还知道如何去编译这些文件
Makefile是make的一个配置 文本文件
make的正常工作是离不开Makefile
1.Makefile的文件格式
文件名:
Makefile / makefile
文件格式:
先看看makefile 的规则:
TARGET:依赖文件列表
<tab键> command1
<tab键> command2
<tab键> @command3
。。。。。。
注:
Makefile上在命令前面加一个@字符
表示只执行此命令,不会将命令字符打印出来
不加@则相反 执行命令的同时也会将命令字符串打印
TARGET:目标
通常是一个要生成的文件名
依赖文件列表:
要生成的那个target所需要的文件或者目标
当需要生成某个target ,第一步看当前目录下面是否存在依赖文件
如果没有依赖 就看Makefile中是否有以依赖文件为目标,如果有
就去生成依赖文件
---------------------------
运行make
make 目标名
make首先要在当前目录下去寻找Makefile 然后再找到Makefile中的
“目标名” ,再找它的依赖文件 最后执行达成目标的命令
make
make首先要在当前目录下去寻找Makefile 然后再找到Makefile中的
“第一个目标” ,再找它的依赖文件 最后执行达成目标的命令
make -f dir
make首先会到dir这个目录下面去找Makefile 然后再找到Makefile中的
“目标名” ,再找它的依赖文件 最后执行达成目标的命令
eg:
写一个简单的Makefile 里面包含一个目标
该目标打印 “hello world”
一个包含两个目标的Makefile 其中一个目标是另一个目标的依赖文件
假设需要编译a.c b.c c.c
TARGET:= main
$(TARGET):a.c b.c c.c
gcc a.c b.c c.c -o $(TARGET)
clean:
rm $(TARGET)
突然我现在加了一个 main.c Makefile 是不是也要修改
TARGET:= main
$(TARGET):a.c b.c c.c main.c
gcc main.c a.c b.c c.c -o $(TARGET)
clean:
rm $(TARGET)
这样的话很麻烦 所以Makefile 增加了许多特性 : 变量 函数 。。。。。。
3.最简单的Makefile
3.1 Makefile变量
Makefile 里面可以定义变量 但是Makefile的变量没有类型 都当字符串
而且变量名可以任意取(一般满足标识符规定),变量不需要提前定义
直接拿过来用就可以了
引用变量:引用变量的值
$(变量名)
如果变量名没有实现赋值 那么$(变量名) 的值为空
在Makefile 中有赋值语句:
(1)简单赋值 := "就地赋值" 不会向后展开
B:=$(A)
A:=12345
=> A 为 12345
B为空
A:=12345
B:=$(A)
C:=A
--------------------------------
$(A) 12345
$(B) 12345
$(C) A
(2)递归赋值 = “向后展开赋值”
C = $(D)
D = 12345
$(D) $(C) 都是12345
注意:
C = $(D)
D = $(C)
(3)追加赋值 +=
A:= 123
A+= 456
===> A:=$A456
$(A) 123456
(4)条件赋值 ?= 当变量没有定义或者是没有值的时候 我们才给他赋值
A?= hello
因为A事先没有定义 $(A) hello
A:=123
B:=456
B?=$(A)
$(B) 456
3.2 自动变量 别人早就给你定义好的变量
make 内置变量
$@ 目标文件的完整名
$+ 所有依赖文件 以空格隔开 也可能会包含重复的依赖文件
$^ 所有的不重复的依赖文件 以空格隔开
$< 第一个依赖的文件名字
main:a.c b.c
gcc $<
<=> gcc a.c
$? 所有时间比目标文件晚(更新的)的依赖文件 以空格隔开
eg:
当前路径下有: a.c b.c c.c
main: a.o b.o c.o
gcc $^ -o $@
a.o:a.c
gcc -c $< -o &@
b.o:b.c
gcc -c $< -o &@
c.o:c.c
gcc -c $< -o &@
上面这个 Makefile 在增加 .c 后 就要修改相应的 Makefile
main.c
main.o: main.c
gcc -c $< -o $@
发现:.c --> .o 创建的命令是相同的 能不能创建一个默认的规则
Makefile里面的通配规则:
% 表示一个任意的文件名(不包括扩展的文件名)
%.o 表示所有的以.o结尾的文件名
%.c 表示所有的以.c结尾的文件名
同名的.o 依赖同名的.c
%.o: %.c
gcc -c $< -o $@
3.3 makefile 的 内置函数
makefile 允许定义并且调用函数
调用内置函数的格式:
$(函数名 函数参数列表)
调用shell命令:
$(shell shell命令名 命令参数)
表达式:执行某个函数或者shell命令的输出结果
wildcard:
文件名展开函数 展开成一列所有的符合由其参数描述的文件名
文件名以空格隔开 返回展开后的文件列表
eg:
CSRCS:= $(wildcard *.c)
在当前目录下找所有以.c 结尾的文件名 然后赋值给 CSRCS
CSRCS+= $(wildcard mp3/*.c)
在mp3目录下找所有以.c 结尾的文件名 然后追加赋值给 CSRCS
patsubst:模式字符串替换函数
$(patsubst<from>,<to>,<text>)
把原始字符串<text> 中的 <from> 替换成<to>
eg:
CSRCS:= a.c b.c c.c
OBJS:= $(patsubst %.c,%.o,$(CSRCS))