概述
make 是一个命令工具,它用来解释 Makefile 中的规则。Makefile 中可以使用系统 shell 所提供的任何命令。但注意有些像 set,setenv 等是不行的。
Makefile 最大的优点是简单,只需要一句话的解释就可以让一个之前不懂的人可以用起来并发挥作用。但只有掌握了它的内涵才能真正得心应手。
编译的知识
Makefile 开始其实是为了 C/C++的编译而诞生的,所以它里面的很多隐藏规则都是针对 C/C++的。
在讲 Makefile 之前有必要对 C/C++的编译有一点了解
过程如下:
- 预处理器:将.c 文件转化成 .i 文件,使用的 gcc 命令是:gcc –E,对应于预处理命令 cpp;
- 编译器:将.c/.h 文件转换成.s 文件,使用的 gcc 命令是:gcc –S,对应于编译命令 cc –S;
- 汇编器:将.s 文件转化成 .o 文件, 使用的 gcc 命令是:gcc –c,对应于汇编命令是 as;
- 链接器:将.o 文件转化成可执行程序,使用的 gcc 命令是: gcc,对应于链接命令是 ld;
- 加载器:将可执行程序加载到内存并进行执行,loader 和 ld-linux.so。
例子
例1 分别创建一个加法的add.c 和 add.h ,一个减法 sub.c和 sub.h 最后main.c 来调用add 和 sub实现加减法。此时Makefile 会像这样
main: main.o add.o sub.o
main.o: main.c
gcc -c main.c -o main.o
add.o: add.c
gcc -c add.c -o add.o #加-c 指定生成为可重链接.o文件
sub.o: sub.c
gcc -c sub.c -o sub.o
.PHONY:clean
clean:
-rm -rf *.o
使用看看
从上面注意几个地方:
①当最终目标文件依赖多个.o时,将依赖的多个.o 一起写到main: 后面。然后依次以 目标:依赖文件 gcc... 的格式,罗列所有依赖关系
②由于在上面的过程中生成了多个中间.o文件(实际工程中肯定是比较多的),所以每次编译完成,后续基本还需要进行一定的清理工作,这时候就用上一个 "clean" (后面细说一下)来清理。
③ .PHONY意思表示clean是一个“伪目标”。也即是无论clean是否最新,一定执行它。rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但并不理睬。当然,clean的规则不要放在文件的开头,否则这就会变成make的默认目标,相信谁也不愿意这样。不成文的规矩是——“clean从来都是放在文件的最后”
例2 假设有一个简单的程序,包括两个源文件main.c和lib.c,他们都包含了头文件header1.h和header2.h,把编译后形成的可执行程序命名为prog,那么makefile可以写为:
all: prog
prog: main.o lib.o
gcc -o prog main.o lib.o
main.o : main.c header1.h header2.h
gcc -c main.c
lib.o : lib.c header1.h header2.h
gcc -c lib.c
现在你只要执行make就会自动执行相应的shell命令把程序编译好了。
当然这只是个说明makefile工作方式的简单例子,并不比直接输入编译命令快多少。但是makefile可以借助变量、函数等工具完成非常复杂的规则描述,对于要反复调试的程序显然非常方便快捷。