make命令会在当前目录下按顺序找寻文件“makefile”、“Makefile”的文件,找到了执行make命令,否则退出。
1、基本规则 gcc -o main a.o b.o c.o ....
全部技巧都是为了把文件组织为 gcc -o xxxx 的形式
-E: 预处理生成xxx.i -S:编译,生成汇编代码xxx.s -c: 汇编,生成机器码xxx.o -o:链接,生成可执行文件
2、 三个特殊的符号 @,^, < : 代表gcc -o 后面的组成成分: 目标文件,所有依赖文件,第一个依赖文件,使用时加上$引用符号,$@: 代表目标文件; $^ 表示,所有依赖项 $<表示第一个依赖项 ; 所以 通用的 gcc -o 形式 变成了如下:
gcc -o $@ $^
3、目标文件与依赖文件的书写形式 目标:依赖1 依赖2. ....... 如
main1.o : main1.c main11.c main111.c
main2.o : main2.c main3.c main4.c
main : main1.o main2.o
4、依赖和规则的一般书写形式:前一行是依赖,后一行是规则
-------------------------------------------------------------------------------
main : main1.o main2.o
gcc -o $@ $^
main1.o : main1.c main11.c
gcc -o $@ -c $^ # -o 是输出文件 -c 是输入文件,需要区分清楚
main2.o : main2.c
gcc -o $@ $< # 这里-c可以省略不写,默认目标文件后面都是输入文件
clean:
rm *.o main
--------------------------------------------------------------------------------------
至此,已经可以正常使用makefile了
不过:每次新加文件都要在依赖项里面添加文件名,不够懒,我需要再智能一些,那么接着往下学
5、 %[ pattern ]表示匹配模式,如 %.o匹配.o结尾的文件 main1.o main2.o ..... %.c 匹配 .c结尾的文件,那么写法又智能了一些
--------------------------------------------------------------------------------
main : main1.o main2.o
gcc -o $@ $^
%.o : %.c
gcc -c $^ # -o $@也可以不写,默认跟 .c文件同名,以.o结尾
--------------------------------------------------------------------------------------
但是,多数时候 ,依赖文件并不是只有.c结尾,有可能cpp, hpp,cc等都行,而且我就是需要的罗列出来,有些不想要, 那么只能辛苦些了,每个目标和依赖项都列一下,但是开头的我们可以简化一些,接着往下走
6 、 = 可以创建一个变量, 如 objs = a.o b.o c.o ...., 使用变量用 $(objs)形式使用,另外 GUN在遇到第一个 gcc 之后,后面的gcc可以默认作为工具使用,所以写第一个就行了,后面就省略了。 makefile就如下所示了:
--------------------------------------------------------------------------------
OBJS = a.o b.o c.o d.o
main : $(OBJS)
gcc -o $@ $(OBJS)
a.o : a.c a.cc a.hpp a.cpp a.h
b.o : b.c b.cc b.h
c.o : c.c c.cc c.h
d.o : d.cpp d.h
clean:
-rm main $(OBJS) # 命令前面的小减号表示遇到错误继续往下执行
--------------------------------------------------------------------------------------
7、很多工程文件的时候,放在同一个makefile里面列出来好像很大很难看,我们可以用分而治之的办法,每个分支用一个makefile份文件,最后用include <filename>的形式统筹,假如有 a.mk b.mk c.mk d.mk e.mk
--------------------------------------------------------------------------------
OBJS = a.o b.o c.o
main : $(OBJS)
gcc -o $@ $(OBJS)
include a.mk b.mk c.mk
。。。
#注意include一定要放在目标main后面,make只会选择第一个:冒号的目标作为最终目标
#或者如果全部添加 可以写成 include *.mk ,甚至可以用$(var)形式:先用var = a.mk b.mk c.mk也是可以的
#a.o b.o %.o ....都在各自的mk文件里实现编译了
--------------------------------------------------------------------------------
如果这些mk都不在当前文件夹下,则需要加上路径
8、 执行make指令的时候 ,增加 --I (或“--include) 路径参数, 则在当前或者指定的路径查找所需要的mk文件
一般shell脚本执行时使用较多 如 : make -I ./somewhere 也可以直接在makefile文件里面指明路径(推荐)
VPATH 就是用来干这事的; 多个路径用 : 隔开
--------------------------------------------------------------------------------
VPATH = ./dir : ../include : ../lib : ../source ./code
# ./表示当前目录,可省略不写,dir跟./dir等同
OBJS = a.o b.o c.o
main : $(OBJS)
gcc -o $@ $(OBJS)
include a.mk b.mk c.mk
。。。。。。
结尾补充: # 表示注释 ; /表示换行,一行写不下用这个接第二行; .PHONY : clean 自行百度一下,一般套用即可,不用改变; -rm 前面有个减号表示遇到错误继续往下执行; makefle命令以TAB键开始 ; 环境变量中有个变量叫MAKEFILES , 它会影响所有的make命令,如果make发生奇怪的事情,建议清除这个变量; 小写的vpath是make的一个关键字,用于搜索匹配文件;make -n 只是显示命令,不执行make, make -s 不显示任何命令,执行make;