规则: 1.make会在当前目录下找名字叫“Makefile”或“makefile”的文件。 2.如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。 3.如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。 4.如果edit所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程) 5.当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件生成make的终极任务,也就是执行文件edit了。 一、Makefile是什么? Makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。 二、Makefile的好处是什么? 自动化编译,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。 三、怎么用? /********************************* 编译基础 :编译四步骤,预编译->编译->汇编->链接 1) 预编译 将.c 文件转化成 .i文件 使用的gcc命令是:gcc –E 2) 编译 将.c/.h文件转换成.s文件 使用的gcc命令是:gcc –S 3) 汇编 将.s 文件转化成 .o文件 使用的gcc 命令是:gcc –c 4) 链接 将.o文件转化成可执行程序 使用的gcc 命令是: gcc *************************************/ 规则 target ... : prerequisites ... //一条规则,以依赖项来生成最终目标 command //(重点)说白一点就是说,prerequisites中如果有一个以上的文件比 target 文件要新的话,command 所定义的命令就会被执行 示例 edit : main.o kbd.o command.o display.o \ //edit依赖以下二进制文件 insert.o search.o files.o utils.o cc -o edit main.o kbd.o command.o display.o \ //将以下汇编文件链接成edit这个可执行文件 insert.o search.o files.o utils.o main.o : main.c defs.h //main.o文件依赖以下文件 cc -c main.c //将main.c文件按依赖项汇编成main.o文件 kbd.o : kbd.c defs.h command.h cc -c kbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : insert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.h cc -c files.c utils.o : utils.c defs.h cc -c utils.c clean : rm edit main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o makefile 中使用变量 如: objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o 就可以使用“$(objects)”的方式来使用这个变量了 让 make 自动推导 只要 make 看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果 make 找到一个 whatever.o,那么 whatever.c,就会是 whatever.o 的依赖文件。并且 cc -c whatever.c 也会被推导出来 于是可以写成这样 objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) main.o : defs.h kbd.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) 进一步还可以写成以下这样 objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) $(objects) : defs.h kbd.o command.o files.o : command.h display.o insert.o search.o files.o : buffer.h .PHONY : clean clean : rm edit $(objects) 清空目标文件的规则 一般的风格都是: clean: rm edit $(objects) 更为稳健的做法是: .PHONY : clean clean : -rm edit $(objects) //在 rm 命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事 赋值符: =  延时变量,只有被使用时才展开定义 //真实值为最后定义的 := 立即变量,定义时的赋值立即有效 //真实值为立即定义的 ?= 条件变量,当变量为空时才赋值 += 追加赋值 示例: VAR_A=abc VAR_B=$(VAR_A) 222 VAR_C:=$(VAR_A) VAR_A=def #VAR_B的值会改变为def 222,而VAR_C的值还是为abc VAR_A:=$(VAR_B)222 VAR_B=$(VAR_A) #由于一开始VAR_B没有值,所以VAR_A的值为222,VAR_B的值为222 VAR_D=111 VAR_D?=000 #VAR_D的值仍为111 VAR_E=file1.c VAR_E+= file2.c #VAR_E最后的值为file1.c file2.c #等价于: VAR_E=$(VAR_E) file2.c 模式规则 通配符“%”和“*” 当“%”出现在目标中的时候,目标中“%”所代表的值决定了依赖中的“%”值,使用方 法如下:%.o : %.c 自动化变量 示例 test:test.o test1.o test2.o gcc -o $@ $^ test.o:test.c test.h gcc -o $@ $< test1.o:test1.c test1.h gcc -o $@ $< test2.o:test2.c test2.h gcc -o $@ $<