1.用Makefile编译一个程序
1 hello: hello.c 2 gcc -o hello hello.c 3 clean: 4 rm -f hello
将上述4行存为Makefile文件(注意必须以Tab键缩进第2、4行,不能以空格键缩进)
make命令根据文件更新的时间戳来决定哪些文件需要重新编译,这使得可以避免编译已经编译过的、没有变化的程序,可以大大提高编译效率。
2.用Makefile编译多个程序
1 test : main.c sub.c 2 gcc -o test main.c sub.c
这样可以就可以编译多个源文件。但是有个缺点,如果修改.h头文件,那么Makefile不会执行,因为Makefile并没有检测文件更新。
1 test : main.c sub.c sub.h 2 gcc -o test main.c sub.c
这样就可以解决上述问题。但是如果修改一个源文件,那么所有得源文件都会被重新编译,如果源文件很多,效率会很低。
1 test : main.o sub.o 2 gcc -o test main.o sub.o 3 4 main.o : main.c 5 gcc -c -o main.o main.c 6 7 sub.o : sub.c 8 gcc -c -o sub.o sub.c 9 10 clean: 11 rm *.o test -f
这样修改一个源文件,只会重新编译修改得源文件。提高了编译效率。但是相似规则太多太啰嗦,不支持检测头文件。
1 test : main.o sub.o 2 gcc -o test main.o sub.o 3 4 %.o : %.c 5 gcc -c -o $@ $< 6 7 clean: 8 rm *.o test -f
这样看起来就比较整洁一点。但是还是不支持检测头文件。
1 test : main.o sub.o 2 gcc -o test main.o sub.o 3 4 %.o : %.c 5 gcc -c -o $@ $< 6 7 sub.o : sub.h 8 //这边一个TAB 9 //这边空行,没有TAB 10 clean: 11 rm *.o test -f
可以体检头文件,但是头文件需要手动添加。
1 objs := main.o sub.o 2 3 test : $(objs) 4 gcc -o test $^ 5 6 7 # 需要判断是否存在依赖文件 8 # .main.o.d .sub.o.d 9 dep_files := $(foreach f, $(objs), .$(f).d) 10 dep_files := $(wildcard $(dep_files)) 11 12 # 把依赖文件包含进来 13 ifneq ($(dep_files),) 14 include $(dep_files) 15 endif 16 17 18 %.o : %.c 19 gcc -Wp,-MD,.$@.d -c -o $@ $< 20 21 22 clean: 23 rm *.o test -f 24 25 distclean: 26 rm $(dep_files) *.o test -f
这样就可以自动检测头文件了。
Makefile函数介绍:
$(foreach var,list,text)
简单地说,就是 for each var in list, change it to text。
对list中的每一个元素,取出来赋给var,然后把var改为text所描述的形式。
例子:
1 objs := a.o b.o 2 dep_files := $(foreach f, $(objs), .$(f).d) // 最终 dep_files := .a.o.d .b.o.d
$(wildcard pattern)
pattern所列出的文件是否存在,把存在的文件都列出来。
例子:
src_files := $( wildcard *.c) // 最终 src_files中列出了当前目录下的所有.c文件