万能makefile写法详解

上传人:xiao****1972 文档编号:84186830 上传时间:2019-03-03 格式:DOC 页数:9 大小:77.64KB
返回 下载 相关 举报
万能makefile写法详解_第1页
第1页 / 共9页
万能makefile写法详解_第2页
第2页 / 共9页
万能makefile写法详解_第3页
第3页 / 共9页
万能makefile写法详解_第4页
第4页 / 共9页
万能makefile写法详解_第5页
第5页 / 共9页
点击查看更多>>
资源描述

《万能makefile写法详解》由会员分享,可在线阅读,更多相关《万能makefile写法详解(9页珍藏版)》请在金锄头文库上搜索。

1、“万能makefile”写法详解,一步一步写一个实用的makefile,详解 sed s,($*).o :*,1.o $ : ,g $; 一目的:编写一个实用的makefile,能自动编译当前目录下所有.c/.cpp源文件,支持二者混合编译。并且当某个.c/.cpp、.h或依赖的源文件被修改后,仅重编涉及到的源文件,未涉及的不编译。二要达到这个目的,用到的技术有:1-使用wildcard函数来获得当前目录下所有.c/.cpp文件的列表。2-make的多目标规则。3-make的模式规则。4-用gcc -MM命令得到一个.c/.cpp文件include了哪些文件。5-用sed命令对gcc -MM命

2、令的结果作修改。6-用include命令包含依赖描述文件.d。三 准备知识(一)多目标对makefile里下面2行,可看出多目标特征,执行make bigoutput或make littleoutput可看到结果:html view plaincopy1. bigoutput littleoutput: defs.h pub.h 2. echo $ $(subst output,OUTPUT,$) $ # $指这个规则里所有目标的集合,$指这个规则里所有依赖的集合。该行是把目标(bigoutput或littleoutput)里所有子串output替换成大写的OUTPUT (二)隐含规则对mak

3、efile里下面4行,可看出make的隐含规则,执行foo可看到结果:第3、4行表示由.c得到.o,第1、2行表示由.o得到可执行文件。如果把第3、4行注释的话,效果一样。即不写.o来自.c的规则,它会自动执行gcc -c -o foo.o foo.c这条命令,由.c编译出.o(其中-c表示只编译不链接),然后自动执行gcc -o foo foo.o链接为可执行文件。html view plaincopy1. foo:foo.o 2. gcc -o foo foo.o; ./foo 3. foo.o:foo.c #注释该行看效果 4. gcc -c foo.c -o foo.o #注释该行看效

4、果 (三)定义模式规则下面定义了一个模式规则,即如何由.c文件生成.d文件的规则。html view plaincopy1. foobar: foo.d bar.d 2. echo complete generate foo.d and bar.d 3. %.d: %.c #make会对当前目录下每个.c文件,依次做一次里面的命令,从而由每个.c文件生成对应.d文件。 4. echo from $ to $ 5. g+ -MM $ $ 假定当前目录下有2个.c文件:foo.c和bar.c(文件内容随意)。验证方法有2种,都可:1-运行make foo.d(或make bar.d),表示想要生成

5、foo.d这个目标。根据规则%.d: %.c,这时%匹配foo,这样%.c等于foo.c,即foo.d这个目标依赖于foo.c。此时会自动执行该规则里的命令gcc -MM foo.c foo.d,来生成foo.d这个目标。2-运行make foobar,因为foobar依赖于foo.d和bar.d这2个文件,即会一次性生成这2个文件。四下面详述如何自动生成依赖性,从而实现本例的makefile。(一)本例使用了makefile的模式规则,目的是对当前目录下每个.c文件,生成其对应的.d文件,例如由main.c生成的.d文件内容为:html view plaincopy1. main.o : m

6、ain.c command.h 这里指示了main.o目标依赖于哪几个源文件,我们只要把这一行的内容,通过make的include指令包含到makefile文件里,即可在其任意一个依赖文件被修改后,重新编译目标main.o。下面详解如何生成这个.d文件。(二)gcc/g+编译器有一个-MM选项,可以对某个.c/.cpp文件,分析其依赖的源文件,例如假定main.c的内容为:cpp view plaincopy1. #include /标准头文件(以方式包含的),被-MM选项忽略,被-M选项收集 2. #include stdlib.h/标准头文件(以方式包含的),被-MM选项忽略,被-M选项收

7、集 3. #include command.h 4. int main() 5. 6. printf(# Hello Makefile #n); 7. return 0; 8. 则执行gcc -MM main.c后,屏幕输出:html view plaincopy1. main.o: main.c command.h 执行gcc -M main.c后,屏幕输出:html view plaincopy1. main.o: main.c /usr/include/stdio.h /usr/include/features.h 2. /usr/include/bits/predefs.h /usr/

8、include/sys/cdefs.h 3. /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h 4. /usr/include/gnu/stubs-64.h 5. /usr/lib/gcc/x86_64-linux-gnu/4.4.3/include/stddef.h 6. /usr/include/bits/types.h /usr/include/bits/typesizes.h 7. /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h 8. /usr

9、/lib/gcc/x86_64-linux-gnu/4.4.3/include/stdarg.h 9. /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h 10. /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h 11. /usr/include/endian.h /usr/include/bits/endian.h 12. /usr/include/bits/byteswap.h /usr/include/sys/select.h 13.

10、 /usr/include/bits/select.h /usr/include/bits/sigset.h 14. /usr/include/bits/time.h /usr/include/sys/sysmacros.h 15. /usr/include/bits/pthreadtypes.h /usr/include/alloca.h command.h (三)可见,只要把这些行挪到makefile里,就能自动定义main.c的依赖是哪些文件了,做法是把命令的输出重定向到.d文件里:gcc -MM main.c main.d,再把这个.d文件include到makefile里。如何inc

11、lude当前目录每个.c生成的.d文件:html view plaincopy1. sources:=$(wildcard *.c) #使用$(wildcard *.cpp)来获取工作目录下的所有.c文件的列表。 2. dependence=$(sources:.c=.d) #这里,dependence是所有.d文件的列表.即把串sources串里的.c换成.d。 3. include $(dependence) #include 后面可以跟若干个文件名,用空格分开,支持通配符,例如include foo.make *.mk。这里是把所有.d文件一次性全部include 进来。注意该句要放在终

12、极目标all的规则之后,否则.d文件里的规则会被误当作终极规则了。 (四)现在main.c command.h这几个文件,任何一个改了都会重编main.o。但是这里还有一个问题,如果修改了command.h,在command.h中加入#include pub.h,这时:1-再make,由于command.h改了,这时会重编main.o,并且会使用新加的pub.h,看起来是正常的。2-这时打开main.d查看,发现main.d中未加入pub.h,因为根据模式规则%.d: %.c中的定义,只有依赖的.c文件变了,才会重新生成.d,而刚才改的是command.h,不会重新生成main.d、及在mai

13、n.d中加入对 pub.h的依赖关系,这会导致问题。3-修改新加的pub.h的内容,再make,果然问题出现了,make报告up to date,没有像期望那样重编译main.o。现在问题在于,main.d里的某个.h文件改了,没有重新生成main.d。进一步说,main.d里给出的每个依赖文件,任何一个改了,都要重新生成这个main.d。所以main.d也要作为一个目标来生成,它的依赖应该是main.d里的每个依赖文件,也就是说make里要有这样的定义:html view plaincopy1. main.d: main.c command.h 这时我们发现,main.d与main.o的依赖

14、是完全相同的,可以利用make的多目标规则,把main.d与main.o这两个目标的定义合并为一句:html view plaincopy1. main.o main.d: main.c command.h 现在,main.o: main.c command.h这一句我们已经有了,如何进一步得到main.o main.d: main.c command.h呢?(五)解决方法是行内字符串替换,对main.o,取出其中的子串main,加上.d后缀得到main.d,再插入到main.o后面。能实现这种替换功能的命令是sed。实现的时候,先用gcc -MM命令生成临时文件main.d.temp,再用sed命令从该临时文件中读出内容(用输出到最终文件main.d。命令可以这么写:html view plaincopy1. g+ -MM main.c main.d.temp 2. sed s,(main).o :*,1.o main.d : ,g main.d 其中: sed s,(main).o :*,1.o main.d : ,g,是sed命令。 main.d,把行内替换结果输出到最终文件main.d。(六)这条sed命令的结构是s/match/replace/g。有时为了

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 大杂烩/其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号