一、实际写出来一个makefile
比较重要的一个是需要一个,生成a.o文件的时候不仅会依赖a.c还会依赖啊啊a.h,b.h,c.h
那么下面这个makefile文件就会出问题,因为没有依赖上.h文件。
test:a.o b.o c.o
gcc -o test $^
%.o:%.c
gcc -c -o $@ $<
clean:
rm *.o test
.PHONY: clean
因为啥呢,当修改.h文件的时候,这个makefile,并不知道修改了.h这个依赖文件,所以要对,makefile文件进行修改。
test:a.o b.o c.o
gcc -o test $^
b.o:b.c b.h
%.o:%.c
gcc -c -o $@ $<
clean:
rm *.o test
.PHONY: clean
把生成b.o文件的依赖都给加上 b.o:b.c b.h,,这样加上,当我们修改b.h的时候,就需要重新生成目标b.o了,.c也就重新被编译了,那修改的.h文件也就被找到编译了。
可是上面的写法还是有问题的,啥没问题呢,当这个b.c文件依赖的头文件比较多,不如说依赖成千上万个.h文件咋整,就一个一个写嘛,真实费劲。
所以还有其它办法。
就是有几个gcc命令很有意思,就是可以查找依赖,而且呢也可以把一个文件的所有依赖都写成一个文件。
比如说:
1、gcc -M b.c
root@wandzhang-virtual-machine:/home/book/makefile_test1# gcc -M b.c
b.o: b.c /usr/include/stdc-predef.h /usr/include/stdio.h \
/usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
/usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \
/usr/include/x86_64-linux-gnu/bits/wordsize.h \
/usr/include/x86_64-linux-gnu/bits/long-double.h \
/usr/include/x86_64-linux-gnu/gnu/stubs.h \
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
/usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h \
/usr/include/x86_64-linux-gnu/bits/types.h \
/usr/include/x86_64-linux-gnu/bits/typesizes.h \
/usr/include/x86_64-linux-gnu/bits/types/__FILE.h \
/usr/include/x86_64-linux-gnu/bits/types/FILE.h \
/usr/include/x86_64-linux-gnu/bits/libio.h \
/usr/include/x86_64-linux-gnu/bits/_G_config.h \
/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h \
/usr/lib/gcc/x86_64-linux-gnu/7/include/stdarg.h \
/usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
/usr/include/x86_64-linux-gnu/bits/sys_errlist.h b.h
打印出b.c的所有依赖文件
2、 gcc -M -MF b.d b.c
root@wandzhang-virtual-machine:/home/book/makefile_test1# gcc -M -MF b.d b.c
把依赖写成b.d文件
3、gcc -c -o c.o c.c -MD -MF c.d
root@wandzhang-virtual-machine:/home/book/makefile_test1# gcc -c -o b.o b.c -MD -MF b.d
编译b.c文件生成b.o文件,并把所有依赖写进b.d文件中
现在可以用上述命令写makefile文件了
二、开始写makefile
上面工作做完了,就是如何写个makefile了,而且呢,这个makefile可以自己添加依赖。开始上难度了。
步邹:
1、简单的生成依赖命令
test:a.o b.o c.o
gcc -o test $^
b.o:b.c b.h
%.o:%.c
gcc -c -o $@ $< -MD -MF .$@.d
clean:
rm *.o test
.PHONY: clean
root@wandzhang-virtual-machine:/home/book/makefile_test1# ls
a.c a.o b.c b.d b.h b.o c.c c.d c.o Makefile test
可以看出来,的确可以生成依赖文件,而且呢,这些依赖文件的命名还是有讲究的,$@可就是目标文件的意思,可能%这个通配符代表的啥,那么这个$@应该就是个啥名字。
2、makefile函数的作用
生成的这些依赖是有用的,makefile函数的作用就体现出来了
这些.d文件因该就是一些依赖的位置,应该就是头文件的位置
上一步,是生成了.d依赖文件,可是呢,这些依赖啥时候去用呢
objs = a.o b.o c.o
dep_files := $(patsubst %,.%.d,$(objs))
dep_files := $(wildcard $(dep_files))
test:a.o b.o c.o
gcc -o test $^
ifneq ($(dep_files),)
include $(dep_files)
endif
%.o:%.c
gcc -c -o $@ $< -MD -MF .$@.d
clean:
rm *.o test
distclean:
rm $(dep_files)
.PHONY: clean
这就很有意思了。
依赖是自己生成的文件,而且生成的依赖也不需要自己添加进去了,通过函数自动匹配加入。
dep_files := $(patsubst %,.%.d,$(objs)) #生成所有依赖的文件名
dep_files := $(wildcard $(dep_files)) #对文件名和生成的依赖进行匹配
ifneq ($(dep_files),)
include $(dep_files)
endif
#如果匹配的不是空依赖,就把依赖添加到。。。。。?,想不起来添加到哪了,就是makefile能找到,能用的地方。
3、CFLAGS编译参数
可以说就是拿来报错的,也是拿来指定.h文件路径的
CFLAGS = -Werror
objs = a.o b.o c.o
dep_files := $(patsubst %,.%.d,$(objs))
dep_files := $(wildcard $(dep_files))
CFLAGS = -Werror
test:$(objs)
gcc -o test $^
ifneq ($(dep_files),)
include $(dep_files)
endif
%.o:%.c
gcc -c -o $@ $< -MD -MF .$@.d
clean:
rm *.o test
distclean:
rm $(dep_files)
.PHONY: clean