13.1隐含规则搜索算法
有一个目标叫 T,下面是搜索目标 T 的规则的算法。在下面,没有提到后缀规则,原因是,所有的后缀规则在 Makefile 被载入内存时,会被转换成模式规则。果目标是"archive(member)"的函数库文件模式,那么这个算法会被运行两次,第一次是找目标 T,如果没有找到的话,那么进入第二次,第二次会把"member"当作 T 来搜索。
1、把 T 的目录部分分离出来。叫 D,而剩余部分叫 N。(如:如果 T 是"src/foo.o",那么,D 就是"src/",N就是"foo.o")
2、创建所有匹配于 T 或是 N 的模式规则列表。
3、如果在模式规则列表中有匹配所有文件的模式,如"%",那么从列表中移除其它的模式。
4、移除列表中没有命令的规则。
5、对于第一个在列表中的模式规则:
1)推导其"茎"S,S 应该是 T 或是 N 匹配于模式中"%"非空的部分。
2)计算依赖文件。把依赖文件中的"%"都替换成"茎"S。如果目标模式中没有包含斜框字符,而把 D 加在第一个依赖文件的开头。
3)测试是否所有的依赖文件都存在或是理当存在。(如果有一个文件被定义成另外一个规则的目标文件,或者是一个显式规则的依赖文件,那么这个文件就叫"理当存在")
4)如果所有的依赖文件存在或是理当存在,或是就没有依赖文件。那么这条规则将被采用,退出该算法。
6、如果经过第 5 步,没有模式规则被找到,那么就做更进一步的搜索。对于存在于列表中的第一个模式规
则:
1)如果规则是终止规则,那就忽略它,继续下一条模式规则。
2)计算依赖文件。(同第 5 步)
3)测试所有的依赖文件是否存在或是理当存在。
4)对于不存在的依赖文件,递归调用这个算法查找他是否可以被隐含规则找到。
5)如果所有的依赖文件存在或是理当存在,或是就根本没有依赖文件。那么这条规则被采用,退出该算法。
7、如果没有隐含规则可以使用,查看".DEFAULT"规则,如果有,采用,把".DEFAULT"的命令给 T 使用。一旦规则被找到,就会执行其相当的命令,而此时,我们的自动化变量的值才会生成。
13.2使用make更新函数库文件
13.2.1函数库文件的成员
一个函数库文件由多个文件组成。你可以以如下格式指定函数库文件及其组成:archive(member)
这个不是一个命令,而一个目标和依赖的定义。一般来说,这种用法基本上就是为了"ar"命令来服务的。如:
foolib(hack.o) : hack.o
ar cr foolib hack.o
如果要指定多个member,那就以空格分开,如:
foolib(hack.o kludge.o)
其等价于:
foolib(hack.o) foolib(kludge.o)
还可以使用Shell的文件通配符来定义,如:
foolib(*.o)
13.2.2 函数库成员的隐含规则
当 make 搜索一个目标的隐含规则时,一个特殊的特性是,如果这个目标是"a(m)"形式的,其会把目标变成"(m)"。于是,如果成员是"%.o"的模式定义,并且如果使用"makefoo.a(bar.o)"的形式调用 Makefile 时,隐含规则会去找"bar.o"的规则,如果没有定义 bar.o 的规则,那么内建隐含规则生效,make 会去找 bar.c 文件来生成 bar.o,如果找得到的话,make 执行的命令大致如下
cc -c bar.c -o bar.o
ar r foo.a bar.o
rm -f bar.o
注意的是"$%",这是专属函数库文件的自动化变量。
13.2.3 函数库文件的后缀规则
可以使用"后缀规则"和"隐含规则"来生成函数库打包文件,如:.c.a:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
$(AR) r $@ $*.o
$(RM) $*.o
等效于
(%.o):%.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
$(AR) r $@ $*.o
$(RM) $*.o
foolib(*.o)