分类: 项目管理
2010-01-04 14:30:14
摘自《解读linux 0.11》——作者:赵炯
Make 工程管理器是一个“自动编译管理器” ,这里的“自动”是指它能够根据文件时间戳自动发现更新过的文件而减少编译的工作量,同时,它通过读入 Makefile 文件的内容来执行大量的编译工作。用户只需编写一次简单的编译语句就可以了。它大大提高了实际项目的工作效率,而且几乎所有 Linux 下的项目编程均会涉及它。
makefile 文件是 make 工具程序的配置文件。Make 工具程序的主要用途是能自动地决定一个含有很多源程序文件的大型程序中哪个文件需要被重新编译。 makefile 的使用比较复杂,详细说明请参考 GNU make 使用手册。为了使用 make 程序,你就需要 makefile 文件来告诉 make 要做些什么工作。通常,makefile 文件会告诉 make 如何编译和连接一个文件。当明确指出时,makefile 还可以告诉 make 运行各种命令(例如,作为清理操作而删除某些文件) 。
make 的执行过程分为两个不同的阶段。在第一个阶段,它读取所有的 makefile 文件以及包含的 makefile文件等,记录所有的变量及其值、隐式的或显式的规则,并构造出所有目标对象及其先决条件的一幅全景图。在第二阶段期间,make 就使用这些内部结构来确定哪个目标对象需要被重建,并且使用相应的规则来操作。
当 make 重新编译程序时,每个修改过的 C 代码文件必须被重新编译。如果一个头文件被修改过了,那么为了确保正确,每一个包含该头文件的 C 代码程序都将被重新编译。每次编译操作都产生一个与源程序对应的目标文件(object file)。最终,如果任何源代码文件被编译过了,那么所有的目标文件不管是刚编译完的还是以前就编译好的必须连接在一起以生成新的可执行文件。
简单的 makefile 文件含有一些规则,这些规则具有如下的形式:
目标(target)… : 先决条件(prerequisites)…
命令(command)
…
…
其中’目标’对象通常是程序生成的一个文件的名称; 例如是一个可执行文件或目标文件。 目标也可以是所要采取活动的名字,比如’清除’(‘clean’)。’先决条件’是一个或多个文件名,是用作产生目标的输入条件。通常一个目标依赖几个文件。而’命令’是 make 需要执行的操作。一个规则可以有多个命令,每一个命令自成一行。请注意,你需要在每个命令行之前键入一个制表符!这是粗心者常常忽略的地方。如果一个先决条件通过目录搜寻而在另外一个目录中被找到,这并不会改变规则的命令;它们将被如期执行。因此,你必须小心地设置命令,使得命令能够在 make 发现先决条件的目录中找到需要的先决条件。这就需要通过使用自动变量来做到。自动变量是一种在命令行上根据具体情况能被自动替换的变量。自动变量的值是基于目标对象及其先决条件而在命令执行前设置的。例如,’$^’的值表示规则的所有先决条件,包括它们所处目录的名称;’$<’的值表示规则中的第一个先决条件;’$@’表示目标对象;另外还有一些自动变量这里就不提了。有时,先决条件还常包含头文件,而这些头文件并不愿在命令中说明。此时自动变量’$<’正是第一个
先决条件。例如:
foo.o : foo.c defs.h hack.h
cc -c $(CFLAGS) $< -o $@
其中的’$<’就会被自动地替换成 foo.c,而$@则会被替换为 foo.o
为了让 make 能使用习惯用法来更新一个目标对象,你可以不指定命令,写一个不带命令的规则或者不写规则。此时 make 程序将会根据源程序文件的类型(程序的后缀)来判断要使用哪个隐式规则。
后缀规则是为 make 程序定义隐式规则的老式方法。 (现在这种规则已经不用了,取而代之的是使用更通用更清晰的模式匹配规则) 。下面例子就是一种双后缀规则。双后缀规则是用一对后缀定义的:源后缀和目标后缀。相应的隐式先决条件是通过使用文件名中的源后缀替换目标后缀后得到。因此,此时下面的’$<’值是*.c 文件名。而这条 make 规则的含义是将*.c 程序编译成*.s 代码。
.c.s:
$(CC) $(CFLAGS)
-nostdinc -Iinclude -S -o $*.s $<
通常命令是属于一个具有先决条件的规则,并在任何先决条件改变时用于生成一个目标(target)文件。然而,为目标而指定命令的规则也并不一定要有先决条件。例如,与目标’clean’相关的含有删除(delete)命令的规则并不需要有先决条件。此时,一个规则说明了如何以及何时来重新制作某些文件,而这些文件是特定规则的目标。make 根据先决条件来执行命令以创建或更新目标。一个规则也可以说明如何及何时执行一个操作。
一个 makefile 文件也可以含有除规则以外的其它文字,但一个简单的 makefile 文件只需要含有适当的规则。规则可能看上去要比上面示出的模板复杂得多,但基本上都是符合的。makefile 文件最后生成的依赖关系是用于让 make 来确定是否需要重建一个目标对象。比如当某个头文件被改动过后,make 就通过这些依赖关系,重新编译与该头文件有关的所有*.c 文件。