WIN32汇编语言教程:第02章 准备编程环境 · 2.4 make工具的用法(2)

3. 显式规则

makefile中包含有一些规则,这些规则定义了文件之间的依赖关系和产生命令,一个规则的格式是这样的:

目标文件:依赖文件;命令           (方法1)

目标文件:依赖文件            (方法2)

       命令

在规则定义和命令行中,不能包含注释,例子中的第11和12行把宏定义展开后就是:

test.exe:x.obj y.obj x.res

   Link /subsystem:windows /out:test.exe x.obj y.obj x.res

这里的目标文件就是test.exe,它依赖于3个文件x.obj,y.obj和x.res,如果有必要,产生目标文件的命令就是下面的Link命令,整个规则可以用两种方法,用第二种方法的时候,命令可以从第二行开始,第一行的“;”省略,但是这时命令前面必须有一个Tab字符,否则nmake无法区分这究竟是命令还是别的定义。目标文件可以有多个,依赖文件也可以有多个,同时命令也可以由多个命令行组成,当然这时候就必须用第二种方法定义了。

我们也可以用test.exe生成的规则定义其他文件,如x.obj或x.res的生成方法,但nmake如何知道哪个是最终要make的文件呢?实际上nmake默认将整个描述文件的第一条规则中的目标文件认为是最终文件,如果我们把11,12行放到第13行后面,那么x.obj和y.obj的建立规则就成了第一条规则,nmake建立了x.obj和x.obj之后就不理会test.exe的建立了,所以我们必须把最终需要生成的文件放在第一条规则定义。当然,在nmake的命令行参数中可以指定要make的目标,如我们要生成x.res文件,那么不必修改makefile将x.res的描述规则移动到最前面,而是直接在命令行键入以下命令即可:

nmake x.res

参数中也可以同时带好几个目标文件名,nmake会一一处理,如果指定的目标文件没有对应的规则,nmake会返回一个出错信息:

fatal error U1073: don't know how to make 'xxx文件'

当用户要求nmake去建造一个目标时,make会去找到这个目标的依赖规则,这时第二行中的命令并不会立刻就执行,而是首先要做一些事情:nmake先去检查依赖文件是否是另一条规则的目标文件,如果是则先处理这一条规则,否则不是,nmake再检查各个依赖文件的时间,看这些文件有没有比目标文件更新的,如果没有,nmake会决定不再重新建造目标文件,并给出提示:'xxx文件' is up-to-date,如果依赖文件有比目标文件更新的,才执行命令。

所以一个顺序下来,所有的目标文件以及它们的依赖文件,以及依赖文件的依赖文件都会被检查并更新,总而言之,一个目标文件的建立包含了顺序正确的指令链接,这个链接结构是树状的,目标文件是根,一级级扩展到多个文件,我们要求的是nmake去建立链接中处于根部的那个文件,nmake会根据链接结构从目标开始向初始状态前进,最后慢慢回来,在这个过程中执行建立每个文件所必须的命令,一直到最终目标建立完成。

目标也可以没有依赖文件,而且目标也可以不是一个真正存在的文件,如例子第23行到第25行中的clean是一个目标,但我们并不是要生成一个clean文件,而是希望在文件调试完毕后用nmake来清除临时文件,当我们键入nmake clean的时候,工作目录下并没有clean这个文件,那么nmake就会去执行clean定义中的命令,因为nmake把每一个不存在的目标当做是一个过时的目标,如此一来,就会删除中间过程中的文件*.obj和*.res。

指出了目标文件全名的规则称为显式规则,但有些类别的文件的编译方法可以是雷同 的,如从asm文件产生obj文件的命令总是用ml,从rc文件产生res文件的命令总是用rc,对于每个文件都写一条规则有些多余,这时候就要用到隐含规则。

4. 隐含规则

隐含规则可以为某一类的文件指出建立的命令,它具体定义了如何将带一个特定扩展名的文件转换成具有另一种扩展名的文件,定义的格式是:

.源扩展名.目标扩展名:;命令       (方法1)

.源扩展名.目标扩展名:        (方法2)

   命令

隐含规则的语法和显式规则相似,也是用“:”隔开,在“;”下面书写命令,也可以不用“;”而将命令写在第二行,同理,这时命令之前要加一个Tab字符。

隐含规则不能有依赖文件,所以“:”下面没有内容,例子中的第17、18行定义了从asm文件建立obj文件的隐含规则,第19和20行定义了从rc文件建立res文件的隐含规则,隐含规则中无法指定确定的输入文件名,因为输入文件名是泛指的有相同扩展名的一整类文 件,这时候就要用到几个特殊的内定宏来指定文件名,这些宏是$@,$*,$?和$<,它们的含义如下:

● $@ —— 全路径的目标文件。

● $* —— 除去扩展名的全路径的目标文件。

● $? —— 所有源文件名。

● $< —— 源文件名(只能用在隐含规则中)。

所以第19、20行中的rc $< 用于x.rc的时候就是rc x.rc。

读者可以注意到一些显式规则没有命令行,如第13行的“$(OBJS): Common.inc”指出了所有的obj文件全部依赖于Common.inc文件,第14行的“y.obj: y.inc”则指出了y.obj同时也依赖于y.inc和第13行的规则合并,y.obj依赖于Common.inc也依赖于y.inc,但是这两条规则都没有指出产生这些obj文件的命令,所以nmake处理的时候会到隐含规则中去找命令行,最后会用第18行的“ml $(ML_FLAG) $<”命令去产生这些obj文件。

上页:第02章 准备编程环境 · 2.4 make工具的用法(1) 下页:第02章 准备编程环境 · 2.5 获取资料

第02章 准备编程环境

版权所有 © 中山市飞娥软件工作室 证书:粤ICP备09170368号