1.Makefile 概要
1.1 Makefile 规则
- make的基本格式
- 目标文件可以是个标签或者伪目标
target... : prerequlsites...
command
目标文件 :依赖文件
make要执行的命令
1.2 一个示例
- 试把下列的 .c .h 文件合并输出一个目标文件
- make : 生成目标文件edit
- make clean :清除执行文件和所有的中间目标文件
edit:main.o kbd.o command.o display.o\
insert.o search.o files.o utils.o
gcc -o edit main.o kdb.o command.o display.o\
insert.o search.o files.o utils.o
#下面是所需.o 文件的 生成过程
main.o:main.c defs.h
gcc -c main.c
kdb.o:kdb.c defs.h command.h
gcc -c kdb.c
command.o:command.c defs.h command.h
gcc -c command.c
display.o:display.c defs.h buffer.h
gcc -c insert.c
insert.o:insert.c defs.h buffer.h
gcc -c insert.c
search.o:search.c defs.h buffer.h
gcc -c search.c
files.o:files.c defs.h buffer.h command.h
gcc -c files.c
utils.o:utils.c defs.h
gcc -c utils.c
clean:
rm edit main.o kbd.o command.o display.o\
insert.o search.o files.o utils.o
1.3 make是如何工作的
- make 的依赖性
1. 键入 make 后-->执行当前目录的 "Makefile" 或"makefile"文件
2. 若找到makefile文件,首先会找第一个目标文件(target),如上面例子的 edit
3. 若 edit 不存在或者 edit 依赖后面的 .o 文件 修改时间比当前的 目标文件edit 新,则会执行下面定义的
命令生成 新的 edit 文件
4. 若 edit 依赖的 .o 文件 没有生成,要靠生成 .o 文件的依赖性找到最开始的 源文件 来生成 所需的 .o文件
- make 会一层一层地找文件的依赖关系,直至最终编译出第一个目标文件
- 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错
- 但是对于所定义的命令的错误,或是编译不成功,make根本不理,make只管文件的依赖性
- 像上面例子 如果改变了 command.h ,与其相关联的 kdb.o command.o files.o 都会被重新编译,edit 也会被重链接
1.4 makefile 中使用变量
- 可理解相当于 C 语言中的宏定义
- 变量名可任意起,最好是代表所加文件的总性质
- 定义一个 objects 的变量
#定义一个objects的变量
objects = main.o kbd.o command.o display.o\
insert.o search.o files.o utils.o
edit: $(objects) #引用变量
gcc -o edit $(objects)
#下面是所需.o 文件的 生成过程
main.o:main.c defs.h
gcc -c main.c
kdb.o:kdb.c defs.h command.h
gcc -c kdb.c
command.o:command.c defs.h command.h
gcc -c command.c
display.o:display.c defs.h buffer.h
gcc -c insert.c
insert.o:insert.c defs.h buffer.h
gcc -c insert.c
search.o:search.c defs.h buffer.h
gcc -c search.c
files.o:files.c defs.h buffer.h command.h
gcc -c files.c
utils.o:utils.c defs.h
gcc -c utils.c
clean:
rm edit $(objects) #清除所有生成的文件
1.5 让make自动推导
- 使用make 的隐晦规则
- make 会自动推导 目标文件 所要依赖的文件
#定义一个objects的变量
objects = main.o kbd.o command.o display.o\
insert.o search.o files.o utils.o
edit: $(objects) #引用变量
gcc -o edit $(objects)
#下面是所需.o 文件的 生成过程
#与.o 文件名字相同的 .c文件可省略 ,如下面的main.c 可省略
#main.o:main.c defs.h ,gcc -c main.c, make会自动推导
main.o: defs.h
kdb.o: defs.h command.h
command.o: defs.h command.h
display.o: defs.h buffer.h
insert.o: defs.h buffer.h
search.o: defs.h buffer.h
files.o: defs.h buffer.h command.h
utils.o: defs.h
# .PHONY 表示 clean是一个伪目标
.PHONY : clean
clean:
rm edit $(objects) #清除所有生成的文件
# "-" 小减号意思为某些文件出现文件不管,继续执行操作
# clean不要放在开头,否则为make的 默认目标
-rm edit $(objects)
2.Makefile总述
2.1 Makefile 主要包含5个规则
- 1.显式规则
生成的文件,文件的依赖文件,生成的命令
- 2.隐晦规则
make可自动推导
- 3.变量的定义
类似 C 语言的宏
- 4.文件指示
- 一个Makefile 中引用 另一个 Makefile ,类似 include
- 根据某些情况制定Makefile 中的有效部分 ,类似 预编译 #if
- 定义多行的命令
- 5.注释
采用 “#” 注释
2.2 Makefile 的文件名
-
自定义Makefile文件名 :Make.xxx
-
指定特定的Makefile
make -f Make.XXX 或 make --file Make.XXX
2.3 引用其他的Makefile
-
使用 include 把别的Makefile包含
-
不可在include前面用 [TAB]开头
-
格式:
include<filename> filename 可以是当前操作系统Shell的文件模式 可以是包含路径和通配符
-
例子
foo.make a.mk b.mk c.mk $(bar)=e.mk f.mk 写成 : include foo.make *.mk $(bar) 等价于:include foo.make a.mk b.mk c.mk e.mk f.mk
-
make 时,有 “-I” 或 “–include-dir” 参数,make会到参数指定目录下去寻找
-
目录 /include(一般是:/usr/local/bin或/usr/include)存在的话,make也找
-
找不到时,make 会生成一条警告信息,但不会出现致命错误
-
makefile完成读取,make会再重试之前没找到或没读取的文件,若还是不行,则产生一条致命错误
-
使 make 不理那些无法读取的文件而继续执行
-include<filename> -表示include无论出现什么错误,不报错继续执行
2.4环境变量MAKEFILES
-
环境变量MAKEFILES,make 会把这个变量的值做一个类似于 include 的动作
-
环境变量MAKEFILES的值是其他的 Makefile
-
与include的不同:
1.从这个环境变量中引入的Makefile 的“目标”不会起作用 2.环境变量中定义的文件发现错误,make不会理
2.5make的工作方式
- 第一阶段:定义的变量被使用了,make会把其展开在使用的位置,但make不会完全马上展开
- 变量出现在依赖关系的规则中,仅当这条依赖被决定要使用了,变量才会在其内部展开
第一阶段 1-5 第二阶段 6-7
1.读入所有的Makefile
2.读入被include的其他Makefile
3.初始化文件中的变量
4.推导隐晦规则,并分析所有规则
5.为所有的目标文件创建依赖关系链
6.根据依赖关系,决定哪些目标要重新生成
7.执行生成的命令