学习理解 makefile
模拟个应用的例子:
有个工程包括头文件 001.h、002.h、003.h、004.h、005.h、006.h、007.h 共7个;程序文件 001.c、002.c、003.c、004.c、005.c、006.c、007.c、008.c、009.c、010.c 共10个文件。看着头大吧,先不关心具体内容。
现在来编译该工程。如下:
# cd example/
# gcc 001.c 002.c 003.c 004.c 005.c 006.c 007.c 008.c 009.c 010.c -o myresult
结果在编译完成后,一个奇思妙想猛然来袭,要是修改3个小文件,程序会有些改善。那就修改后重新编译。只是总共17个文件在仅仅修改了3个小文件的情况下需要统统地编译一次,这个不符合我们计算机领域的思维方式。由此我们选择另外的方式来编译这个工程。
我们首先编译生成目标文件,再连接成二进制文件。
# gcc -c 001.c
# gcc -c 002.c
# gcc -c 003.c
# gcc -c 004.c
# gcc -c 005.c
# gcc -c 006.c
# gcc -c 007.c
# gcc -c 008.c
# gcc -c 009.c
# gcc -c 010.c
# gcc 001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o -o myresult
如果修改了:001.c 002.c 003.c 三个文件。再次编译如下:
# gcc 001.c 002.c 003.c -c
# gcc 001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o -o myresult
可是如果涉及到头文件,影响就会更复杂,随着文件数量、编译时间的增加,对于源代码的修改,将会麻烦不尽。于是,对于编译一个工程,人们有些设想:对工程再次编译自动编译修改过的文件、涉及到头文件改动的文件。
编辑一个 makefile 文件。如下:
myresult:001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o
gcc -o myresult 001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o
001.o:001.c 003.h 004.h 007.h
gcc -c 001.c
002.o:002.c 001.h 002.h 003.h 006.h 007.h
gcc -c 002.c
003.o:003.c 002.h 004.h
gcc -c 003.c
004.o:004.c 006.h
gcc -o 004.c
005.o:005.c 006.h 007.h
gcc -o 005.c
006.o:006.c 004.h 005.h
gcc -c 006.c
007.o:007.c 001.h 002.h
gcc -c 007.c
008.o:008.c 001.h 002.h
gcc -c 008.c
009.o:009.c 001.h 002.h 006.h
gcc -c 009.c
010.o:010.c 001.h 002.h 005.h
gcc -c 010.c
clean:
rm *.o
rm myresult
把以上内容编辑在名字为“Makefile”的文件下,置于工程目录“example/”下。
# cd example/
# make
行首空白处为“tab制表符”,不能用空格;而且每次缩进都是“tab制表符”。
这个 Makefile 就解决了人们对于编译、再次编译的设想。带冒号的这里称作“条件行”,“tab键”缩进的这里称作“命令行”。当条件行里的文件发生改变的时候,就会执行相应下一行的命令行。第一次执行“make”、清除中间文件和目标文件后执行“make”命令后就会执行所有的命令行。在条件语句中,通过判断目标生成文件、条件文件的生成时间先后,决定要不要执行对应命令。
关于上面的 makefile 文件,我想大家要是一直在学习计算机(专指linux),就是不明白具体的执行内容、效果,也能看个差不多,对于这样的文档起码有个感觉,理解个大概。要是没有一点感觉的话,应该是不太适合这个事情的。对于学习这个语法仅仅是浏览一番,不必去记忆。有了感觉就自己加强一下,不强求。
在命令行和条件行会出现相同的内容(开始两行)。也就是说当工程里添加、删除某文件时,要在两行里添加相应的文件名;或者修改某个文件名称时,需要同时修改两行。这个时候人们想到了引入变量。
lastobject = 001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o
myresult:$(lastobject)
gcc -o myresult $(lastobject)
……
还可以参考:最简单的Makefile
GNU 的 make 很强大。可以自动推到文件以及文件依赖关系后面的命令。上面的 makefile 修改如下形式:
lastobject = 001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o
myresult:$(lastobject)
001.o:001.c 003.h 004.h 007.h
002.o:002.c 001.h 002.h 003.h 006.h 007.h
003.o:003.c 002.h 004.h
004.o:004.c 006.h
005.o:005.c 006.h 007.h
006.o:006.c 004.h 005.h
007.o:007.c 001.h 002.h
008.o:008.c 001.h 002.h
009.o:009.c 001.h 002.h 006.h
010.o:010.c 001.h 002.h 005.h
clean:
rm *.o
rm myresult
文件后面的“clean”是“编译程序”规则后,另外一个规则。前面的编译规则是个默认规则,因为在 “clean” 前面;那么最好不要把 “clean” 放在最前面。●在 makefile 中的 “#” 表示注视。
(到这里基本上就可以阅读文件了)