153 lines
5.6 KiB
Makefile
153 lines
5.6 KiB
Makefile
|
规则:
|
|||
|
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 $@ $<
|