




免费预览已结束,剩余23页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
目录目录 1简介简介 3 1 1准备工作 3 1 2MAKEFILE介绍 3 1 3规则简介 4 1 4MAKE工作原理 4 1 5使用变量 5 1 6简化命令 5 1 7另一种风格 6 1 8清理 6 2MAKEFILE 7 2 1MAKEFILE名字 7 2 2包含 7 2 3 MAKEFILE 变量 7 2 4如何重新生成MAKEFILE 7 2 5重载MAKEFILE 8 3规则规则 8 3 1例子 8 3 2规则的语法 9 3 3通配符 9 3 3 1通配符的缺陷 9 3 3 2wildcard函数 10 3 4目录搜索 10 3 4 1 VPATH 10 3 4 2选择性搜索 11 3 4 3使用自动变量 11 3 4 4目录搜索和隐含规则 12 3 5PHONY 目标 12 3 6FORCE 目标 13 3 7空目标 13 3 8内建的特殊目标 13 3 9一个规则多个目标 14 3 10一个目标多条规则 14 3 11静态模式规则 14 3 11 1语法 15 3 11 2静态模式规则和隐式规则 15 3 12双冒号规则 16 3 13自动生成依赖关系 16 4编写命令编写命令 17 4 1回显 17 4 2执行 17 4 3并行执行 17 4 4错误 18 4 5中断MAKE 18 4 6递归使用 18 4 6 1 MAKE 变量 19 4 6 2传递变量到子make 19 5命令行参数命令行参数 20 6参考参考 23 6 1指令 23 6 2函数 24 6 3自动变量 26 6 4特殊变量 27 GNU Make 使用使用 Make 程序最初设计是为了维护 C 程序文件防止不必要的重新编译 在使用命令行编 译器的时候 修改了一个工程中的头文件 如何确保包含这个头文件的所有文件都得到编 译 现在的版本生成是使用批处理程序 编译那些文件依赖于程序的维护者 在模块之间 相互引用头文件的情况下 要将所有需要重新编译的文件找出来是一件痛苦的事情 在找 到这些文件之后 修改批处理进行编译 实际上这些工作可以让 make 程序来自动完成 make 工具对于维护一些具有相互依赖关系的文件特别有用 它对文件和命令的联系 在文 件改变时调用来更新其它文件的程序 提供一套编码方法 Make 工具的基本概念类似于 Proglog 语言 你告诉 make 需要做什么 提供一些规则 make 来完成剩下的工作 1简介简介 make 工作自动确定工程的哪部分需要重新编译 执行命令去编译它们 虽然 make 多 用于 C 程序 然而只要提供命令行的编译器 你可以将其用于任何语言 实际上 make 工具的应用范围不仅于编程 你可以描述任和一些文件改变需要自动更新另一些文件的任 务来使用它 1 1准备工作准备工作 如果要使用 make 你必须写一个叫做 makefile 的文件 这个文件描述工程中文件之 间的关系 提供更新每个文件的命令 典型的工程是这样的 可执行文件靠目标文件来更 新 目标文件靠编译源文件来更新 Makefile 写好之后 每次更改了源文件后 只要执行 make 就足够了 所有必要的重新 编译将执行 Make 程序利用 makefile 中的数据库和文件的最后修改时间来确定那个文件需 要更新 对于需要更新的文件 make 执行数据库中记录的命令 可以提供命令行参数给 make 来控制那个文件需要重新编译 1 2Makefile 介绍介绍 Makefile 文件告诉 make 做什么 多数情况是怎样编译和链接一个程序 这里有一个简单的 makefile 描述如何编译链接由 8 个 C 文件和 3 个头文件组成的一 个编辑器 edit main o kbd o command o display o insert o serach o files o utils o cc o edit main o kbd o command o display o insert o search o files o utils o main o main c defs h cc c main c kdb o kbd c defs h command h cc c kbd c command o command c defs h command h cc c command c display o display c defs h buffer h cc c display c insert o insert c defs h buffer h cc c insert c search o search c defs h buffer h cc c search c files o files c defs h buffer h command h cc c files c utils o utils c defs h cc c utils c clean rm edit main o kbd o command o display o insert o search o files o utils o 将长行用 分开便于阅读 这和使用一个长行的作用是一样的 使用这个 makefile 创建 可执行文件 edit 时运行 make 就可以了 如果要将可执行文件和目标文件删除 执行 make clean make 重新编译这个编辑器时 每个更改的 C 文件必须重新编译 如果头文件更改了 每个包含头文件的 C 文件必须重新编译 每次编译产生一个对应于原文件的目标文件 最 终 目标文件链接在一起产生新的可执行文件 1 3规则简介规则简介 makefile 中的规则是这样的 TARGET DEPENDENCIES COMMAND 目标 TARGET 程序产生的文件 如可执行文件和目标文件 目标也可以是要执行 的动作 如 clean 依赖 DEPENDENCIES 是用来产生目标的输入文件 一个目标通常依赖于多个文件 命令 COMMAND 是 make 执行的动作 一个可以有多个命令 每个占一行 注意 每个命令行的起始字符必须为 TAB 字符 有依赖关系规则中的命令通常在依赖文件变化时负责产生 target 文件 make 执行这些 命令更新或产生 target 规则可以没有依赖关系 如包含 target clean 的规则 规则解释如何和何时重做该规则中的文件 make 根据依赖关系执行产生或更新目标 规则也说明如何和何时执行动作 有的规则看起来很复杂 但都符合上述模式 1 4make 工作原理工作原理 缺省 make 从第一个 target 开始 第一个非 开始的 target 这称作缺省目标 在上 述的 makefile 中 缺省目标是更新执行程序 edit 将这个目标置于最前面 当执行 make 的时候 make 程序从当前目录读入 makefile 开始处理第一个规则 在例子中 这个规则是 重新链接 edit 在 make 处理这个规则之前 必须处理 edit 所依赖的那些文件的规则 例 子中是目标文件 这些文件按照他们自己的规则处理 通过编译源文件来更新每个 o 文件 当依赖关系中的源文件或头文件比目标文件新 或目标文件不存在时 必须重新编译 其它的规则被处理是因为他们的 target 是目标的依赖 和目标没有依赖关系的规则不 会被处理 除非指定 make 处理 如 make clean 在重新编译目标文件之前 make 会试图更新它的依赖 源文件和头文件 例子中的 makefile 对源文件和头文件未指定任何操作 c 和 h 文件不是任何规则的目标 确认所有 的目标文件都是最新的之后 make 决定是否重新链接 edit 如果 edit 不存在 或者任何 一个目标文件都比它新 则链接工作将进行 这样 如果我们改变 insert c 运行 make make 会编译这个文件来更新 insert o 然后 链接 edit 如果修改了 command h 运行 make kbd o command o files o 会重新生成 链接 edit 1 5使用变量使用变量 在例子中 在规则 edit 中 目标文件被列出来两次 edit main o kbd o command o display o insert o search o files o utils o cc o edit main o kbd o command o display o insert o search o files o utils o 这样的重复容易出错 假设工程中加入了一个新的目标文件 可能只将其加入了一个 列表中 通过使用变量可以消除这种风险 变量允许一个预定义的字符串在多个地方被替 换 在 makefile 中 可以写这样一行来定义 object 变量 objects main o kbd o command o display o insert o search o files o utils o 于是在需要目标文件名列表的地方 使用 object 来代替变量的值 以下是使用了变 量以后的 makefile objects main o kbd o command o display o insert o search o files o utils o edit objects cc o edit objects main o main c defs h cc c main c kbd o kbd c defs h command h cc c kbd c command o command c defs h command h cc c command c display o display c defs h buffer h cc c display c insert o insert c defs h buffer h cc c insert c search o search c defs h buffer h cc c search c files o files c defs h buffer h command h cc c files c utils o utils c defs h cc c utils c clean rm edit objects 1 6简化命令简化命令 为每个文件写出编译命令不是必要的 因为 make 可以自己来做 以 c 文件更新 o 文 件有一个隐含的规则 使用 cc c 命令 Make 将利用 cc c main c o main o 来将 main c 编 译为 main o 因此在生成目标文件的规则中 可以省略命令 当 c 文件以这样的方式使用时 将自动加入到依赖关系中 由是在省略命令的前提下 可以将 c 文件从依赖关系中省略 以下是简化过的 makefile objects main o kbd o command o display o insert o search o files o utils o edit objects cc o edit objects main o defs h kbd o defs h command h command o defs h command h display o defs h buffer h insert o defs h buffer h search o defs h buffer h files o defs h buffer h command h utils o defs h PHONY clean clean rm edit objects 1 7另一种风格另一种风格 如果 makefile 中的目标都是以隐含规则生成 可以将规则按照依赖关系分组 objects main o kbd o command o display o insert o search o files o utils o edit objects cc o edit objects objects defs h kbd o command o files o command h display o insert o search o files o buffer h 这里 defs h 作为所有目标文件的依赖 这种风格是好是坏取决于个人喜好 它非常紧 凑 但是将每个目标的依赖信息放在一起看起来更清楚一些 1 8清理清理 编写规则不至于编译程序 Makefile 通常描述如何做其它事情 比如删除目录中的目 标文件和可执行文件来清理目录 例子中是这样写的 clean rm edit objects 实际情况是 我们需要处理一些意外事件 存在一个叫做 clean 的文件 如果 rm 出错 并不希望 make 过程停止下来 修改过的版本如下 PHONY clean clean rm edit objects 这样的规则当然不能放在 makefile 的开始 因为这并不是我们缺省要做的工作 由于 clean 并不是 edit 的依赖 在运行 make 时没有参数时 这条规则不会执行 要执行这个规 则 必须运行 make clean 2Makefile Makefile 中包含五种内容 显式规则 隐式规则 变量定义 指令 directive 和注释 显式规则描述如何生成规则的目标 它列出了目标依赖的文件 指定了产生或更 新目标的命令 隐式规则描述如何生成基于文件名的一类文件 说明目标可能依赖于和其文件名 类似的文件 指定了相应的命令 指令类似与编译器的伪指令 包含 指示 make 读入另一个 makefile 决定是否忽略 makefile 中的一部分 定义一个变量 一行中 开始是注释 直到行末 除非遇到续行符号 在 define 和命令中不能有 注释 其它情况下注释可出现在任何地方 2 1makefile 名字名字 缺省情况下 make 以下列名字查找 makefile GNUmakefile makefile 和 Makefile 注意大小写 通常你的 makefile 应叫做 makefile 或 Makefile GNUmakefile 不推荐 除非你的 makefile 是为 GNU 的 make 定制的 其它的 make 不认为该名字是一个 makefile 的名字 如果你使用非标准命名的 makefile 必须用命令开关 f 或 file 参数 f NAME 或 file NAME 告诉 make 读入 NAME 作为 makefile 如果使用多个该开关 所有的文件 将按顺序连接起来 如果使用该选项 标准的 makefile 名字不会自动检测 2 2包含包含 include 指令告诉 make 暂停处理余下的内容 读入其它 makefile 语法如下 include FILENAMES 这一行起始可以有空格 但 TAB 字符不允许 如果文件名包含变量或函数 这些将被 扩展 2 3 MAKEFILE 变量变量 如果环境变量 MAKEFILE 已定义 make 认为它的值是一系列空格隔开的文件名 这 些文件在处理其它 makefile 前被 make 程序读入 这类似于 include 指令 这些文件中的目 标不会影响缺省目标 而且如果文件未找到的话 make 并不认为是错误 这个变量的主要用途是递归引用 make 程序时通讯 2 4如何重新生成如何重新生成 makefile 有时候 makefile 是从其它文件生成的 比如 RCS 或 SCCS 文件 如果 makefile 是由其 它文件生成的 需要 make 读入最新版本的 makefile 在读入所有 makefile 之后 make 认为每个 makefile 是一个目标 试图去更新它 如果 makefile 中有一条如何更新它的规则 或者有适用的隐式规则 需要的更新会进行 所有 的 makefile 检查完之后 如果有的改变了 make 重新开始再读入 make 会试图再做更新 但通常不会再改变了 因为已经是最新的了 如果一个文件使用双冒号规则 提供了命令但没有依赖关系 文件始终会被更新 在 makefile 的情况下 如果 makefile 双冒号规则 提供了命令但没有依赖关系 这样 makefile 始终会重新生成 这会导致循环 make 只是在不断更新 makefile 却不干活 为避免这种 情况 make 不会重新生成那些只有命令没有依赖关系的双冒号规则的 makefile 如果没有使用 f 或 file 选项 make 会尝试缺省的 makefile 文件名 和指明 f 或 file 选项不同 make 不能确定这些文件是否应当存在 然而 如果缺省 makefile 不存在但 可以通过运行 make 规则生成 你可能希望这些规则被运行使得 makefile 可以使用 因此 如果没有缺省 makefile make 试图按照 makefile 名查找的顺序生成它 直到成 功或名字用完 注意如果 make 不能找到或生成 makefile 这并不是错误 makefile 不总是 必需的 当使用 t 或 touch 选项时 不希望使用过时的 makefile 来决定那个目标来 touch 所 以 t 选项对 makefile 更新不起作用 类似 q or question 和 n or just print 不阻止 makefile 的更新 因为过时的 makefile 会产生错误的输出 这样 make f mfile n foo 会更新 mfile 读入它 打印出更新 foo 需要执行的命令但不运行这些命令 与 foo 有 关的命令是更新过的 mfile 中的内容 但是有时不希望更新 makefile 可以将 makefile 作为命令行的目标 当 makefile 被显 式指定为目标时 t 选项也适用于它们 这样 make f mfile n mfile foo 会读入 mfile 打印出更新执行的命令 foo 的命令是 当前的 mfile 中的内容 2 5重载重载 makefile 可以使用 include 指令来包含其它 makefile 增加目标的变量定义 然而 make 不允 许同一个目标有不同的命令 有其它的途径可以达到目的 假设有 makefile 和 mfile makfile 要包含 mfile 但都有对于目标 foo 的规则 这是 可以在 makefile 中写一条匹配任意模式的规则 指明当 make 在 makefile 中未找到目标时 搜索 mfile foo frobnicate foo force MAKE f mfile force 当执行 make foo 时 make 找到 makefile 执行命令 frobnicate foo 执行 make bar 时 在 makefile 中未找到相应的规则 这时模式规则适用 执行命令 make f mfile bar makefile 中未提及的其它目标也是类似的 这种方法之所有工作是因为模式规则的模式是 可以匹配任何的目标 这条规则的 依赖是 force 保证即使目标存在命令也会执行 force 规则的命令为空防止 make 为其搜 索隐式规则 这样会导致依赖循环 3规则规则 makefile 中的规则描述如何生成特定的文件 即规则的目标 规则列出了目标的依赖 文件 指定生成或更新目标的命令 规则的次序是不重要的 除非是确定缺省目标 缺省目标是第一个 makefile 中的第一 个规则 如果第一个规则有多个目标 第一个目标是缺省的 有两个例外 以 开头的目 标不是缺省目标 模式规则对缺省目标没有影响 通常我们所写的地一个规则是编译整个或 makefile 中指定的所有程序 3 1例子例子 foo o foo c defs h module for twiddling the frobs cc c g foo c 它的目标是 foo o 依赖于 foo c 和 defs h 有一个命令 cc c g foo c 命令行以 TAB 字符开始标识它是一个命令 这条规则说明两件事 如何决定 foo o 是旧的 如果它不存在 或者 foo c 或者 defs h 比它新 如何更新 foo o 文件 通过运行 cc 程序 命令未提及 defs h 担可以猜想 foo c 包含了它 这是 defs h 被置于依赖关系中的理由 3 2规则的语法规则的语法 语法如下 TARGETS DEPENDENCIES COMMAND 或者 TARGETS DEPENDENCIES COMMAND COMMAND TARGETS 是以空格隔开的文件名 统配符可以使用 通常一个规则只有一个目标 偶尔也有多个 命令行以 TAB 键开始 第一条命令可在依赖关系的下一行 或者在同一行 在分号后 面 两种方式效果相同 因为 符号被用做变量引用 如果要在规则中使用 符号 必须写两个 可以 用 符号来分割一个长行 这不是必须的 因为 make 对行的长度没有限制 3 3通配符通配符 规则中的文件名可以包含统配符 如 文件名前的字符 有特殊的含义 单独使用 或跟随一个 代表用户的 home 目录 比如 bin 扩展为 home you bin 如果 跟随一个单词 表示单词指示的那个用户的 home 目录 如 john bin 扩展为 home john bin 通配符在目标 依赖关系 命令中自动扩展 其它情况下 统配符的扩展除非显式使 用 wildcard 函数 通配符的特殊意义可以使用 符号关闭 例子 clean rm f o 和 print c lpr p touch print 通配符在定义变量时并不扩展 例如 objects o 则 objects 的值是字符串 o 但是如果你将 objects 用于目标 依赖或命令中 扩展 会进行 要将 objects 设置成扩展过的内容 使用 objects wildcard o 3 3 1通配符的缺陷通配符的缺陷 这是一个使用通配符的例子 但结果不是你所期望的 假设可执行文件 foo 是从当前 目录中的所有 o 文件生成的 objects o foo objects cc o foo CFLAGS objects objects 变量的值是字符串 o 通配符扩展在规则 foo 中进行 于是所有存在的 o 文 件成为 foo 的依赖而且在需要时重新编译 但如果删除了所有的 o 文件呢 当通配符不匹配任何文件时 一切都保持原样 则 foo 依赖于一个叫做 o 的文件 由于这个文件不大可能存在 make 程序会报告一个无法 生成 o 文件的错误 这不是期待的结果 实际上可以用通配符获得期望结果 但是需要复杂的技术 包括 wildcard 函数和字符 串替换函数 3 3 2wildcard 函数函数 通配符自动在规则中进行 但是在变量赋值的和函数的参数中通配符不会扩展 如果 在这些情况下需要通配符扩展 必须使用 wildcard 函数 语法如下 wildcard PATTERN 这个在 makefile 任何地方出现的字符串 会被匹配任何一个文件名格式的以空格隔开 的现有文件列表替换 如果没有任何文件匹配一个模式 这个模式从 wildcard 的输出中忽 略 注意 这和上述的通配符的处理是不一样的 wildcard 函数的一个功能是找出目录中所有的 c 文件 wildcard c 可以通过替换后缀 c 为 o 从 C 文件列表得到目标文件的列表 patsubst c o wildcard c 这样 上节中的 makefile 改写为 objects patsubst c o wildcard c foo objects cc o foo objects 这个 makefile 利用了编译 C 程序的隐含规则 所以不需要对编译写出显式的规则 是 的一个变体 注意 PATTERN 是大小写敏感的 3 4目录目录搜索搜索 对于大的系统 通常将源文件和目标文件放在不同的目录中 目录搜索功能可以让 make 自动在多个目录中搜寻依赖文件 当你将文件重新分布是 不需要改变规则 更改搜 索路径即可 3 4 1 VPATH make 变量 VPATH 列出 make 应当搜索的目录列表 很多情况下 当前目录不包含依 赖文件 VPATH 描述一个对所有文件的搜索列表 包含那些是规则的目标的文件 如果一个目标或者依赖文件在当前目录没找到的话 make 在 VPATH 中列出的目录中 查找同名的文件 如果找到的话 那个文件成为依赖文件 规则可以象这些文件在当前目 录中一样来使用他们 在 VPATH 变量中 目录名以冒号或空格隔开 目录列出的顺序决定 make 查找的顺 序 注 在 pSOSystem 2 5 移植到 Win32 的 GNU make 目录名必须使用分号隔开 以下均 简称 Win32 GNU make 举例说明 VPATH src headers 则规则 foo o foo c 被解释为 foo o src foo c 假设 foo c 在当前目录不存在 在 src 目录中可以找到 3 4 2选择性搜索选择性搜索 与 VPATH 变量相似但更具选择性的是 vpath 指令 注意是小写 可以指定对于符合 特定模式文件的查找路径 这样可以为不同类型的文件指定不同的搜索路径 vpath 指令共有三中形式 vpath PATTERN DIRECTORIES 为匹配 PATTERN 的文件名指定搜索路径 DIRECTORIES 目录的分隔和 VPATH 的 相同 vpath PATTERN 清除为匹配 PATTERN 的文件名指定的搜索路径 vpath 清除所有以前用 vpath 指定的搜索路径 vpath 的模式是包含 的字符串 这个字符串必须匹配需要搜索的依赖文件名 字 符匹配 0 个或多个任意字符 例如 h 匹配任何以 h 结尾的文件 如果没有 则 PATTERN 必须和依赖文件完全一致 这种用法不太多 当当前目录中不存在依赖文件时 如果 vpath 中的 PATTERN 匹配依赖文件名 则指 令中 DIRECTORIES 列出的目录和 VPATH 中同样处理 举例 vpath h headers 告诉 make 在当前目录中未找到的 h 文件在 headers 目录中查找 如果多个 vapth 的模式匹配依赖文件名 make 将逐一处理 在所有指定的目录中搜索 Make 按照 vapth 在 makefile 中的次序 来处理它们 多个相同模式的 vapth 是相互独立的 vpath c foo vpath blish vpath c bar 将按照 foo blish bar 的次序查找 c 文件 而 vpath c foo bar vpath blish 按照 foo bar blish 的顺序搜索 3 4 3使用自动变量使用自动变量 目录搜索的结果并不改变规则中的命令 命令按原样被执行 因此 必须写出与目录 搜索功相适应的命令 这可以通过使用 这样的自动变量来完成 表示规则中的所有 依赖文件 包含它们所在的目录名 参见目录搜索 表示目标 例如 foo o foo c cc c CFLAGS o 通常情况下 依赖文件也包含头文件 但命令中并不提及这些文件 变量 表示第 一个依赖文件 VPATH src headers foo o foo c defs h hack h cc c CFLAGS 和 bigoutput text g generate text g big bigoutput littleoutput text g generate text g little littleoutput 等同 这里假设程序 generate 产生两种输出 一种使用 big 选项 一种使用 little 选项 如果想象使用 变化命令那样来变化依赖关系 不能通过多目标的普通规 则实现 但是可以通过模式规则来实现 3 10 一个目标多条规则一个目标多条规则 一个文件可以是多条规则的目标 所有规则的依赖关系被合并 如果目标比任一个依 赖文件旧 命令被执行 一个文件只能有一组命令执行 如果多个规则对于同一个文件都给出了命令 make 使 用最后一组并打印错误信息 特殊情况 如果文件名以 开始 并不打印错误信息 这一 点是为了和其它 make 兼容 没有任何理由需要将 makefile 写成这样 这是 make 给出错 误信息的理由 一条只有依赖关系的附加规则可以一次给出许多文件的附加依赖文件 例如 objects 变 量表示系统中编译器的所有输出 说明当 config h 更改时所有文件必须重做的简单方法如 下 objects foo o bar o foo o defs h bar o defs h test h objects config h 不用改变实际目标文件生成的规则 这条规则可以在需要增删附加的依赖关系时插入 或提出 另一个诀窍是附加的依赖关系可以用变量表示 在 make 执行时 可以给变量赋 值 extradeps objects extradeps 当命令 make extradeps foo h 执行时会认为 foo h 是每个目标文件的依赖文件 但简单 的 make 命令不是这样 3 11 静态模式规则静态模式规则 静态模式规则 static pattern rules 可以指定多个目标 并且使用目标名字来建议依赖 文件的名字 比普通多目标规则更通用因为不需要依赖关系是相同的 依赖关系必须类似 但不需要相同 3 11 1语法语法 TARGETS TARGET PATTERN DEP PATTERNS COMMANDS TARGETS 列表指出规则应用的目标 可以包含通配符 于普通规则的目标相同 TARGET PATTERN 和 DEP PATTERNS 来表明目标的依赖关系如何计算 匹配 TARGET PATTERN 的目标从名字中抽出一部分 叫做词干 stem 词干被替换到 DEP PATTERNS 来形成依赖文件名 每个模式通常包含一个 字符 当 TARGET PATTERN 匹配一个目标时 字符可 以匹配目标名中的任何部分 这部分即是词干 模式的其余部分必须完全匹配 例如 foo o 匹配 o foo 是词干 目标 foo c 和 foo out 并不匹配这个模式 目标的依赖文件名通过将 DEP PATTERNS 中的 替换为词干形成 如果依赖模式 为 c 在替换词干 foo 可以得到 foo c 依赖模式中不包含 也是合法的 此依赖文件 对所有的目标均有效 如果需要在模式规则中使用 字符 必须在其前面加 字符 如果 前的 字符是 有实际意义的 必须在其前面加 其它的 不必如此处理 如 the weird pattern 在 有效的 前是 the weird 其后是 pattern 最后的 保持原样是因为其并不影响 字 符 以下例子从相应的 c 文件编译 foo o 和 bar o objects foo o bar o objects o c CC c CFLAGS o 每个目标必须匹配目标模式 对于不匹配的目标会给出警告 如果列表中只有部分文 件匹配模式 可以使用 filter 函数移去不匹配的文件名 files foo elc bar o lose o filter o files o c CC c CFLAGS o filter elc files elc el emacs f batch byte compile 命令 generate 执行时 扩展为词干 big 或 little 3 11 2静态模式规则和隐式规则静态模式规则和隐式规则 静态模式规则和隐式规则在作为模式规则是具有很多共同点 都有目标模式和构造依 赖文件名的模式 不同之处在于 make 决定何时应用规则的方法 隐式规则可应用于匹配其模式的任何目标 但只限于没有指定命令的目标 如果有多 条可应用的隐式规则 只有一条被使用 取决于规则的顺序 反之 静态模式规则适用于规则中明确目标列表 不适用于其它目标且总是适用于指 定的每个目标 如果有两条冲突的规则 且都有命令 这是一个错误 静态模式规则比隐式规则优越之处如下 可为一些不能按句法分类 但可以显式列出的文件重载隐式规则 不能判定目录中的精确内容 一些无关的文件可能导致 make 适用错误的隐式规则 最终结果可能依赖于隐式规则的次序 适用静态模式规则时 这种不确定性是不存 在的 规则适用于明确指定的目标 3 12 双冒号规则双冒号规则 双冒号规则 Double colon rules 的目标后是 而不是 当一个目标出现在多条规 则中时 其处理和普通规则的处理不同 当一个目标出现在多条规则中时 所有规则必须是相同类型的 都是普通的或者都是 双冒号的 如果是双冒号 规则之间相互独立 如果目标需要更新 则规则的命令被执行 结果可能是没有执行 或者执行了其中一些 或者所有的规则都执行了 同一目标的双冒号规则事实是完全孤立的 每条规则被被单独处理 就象不同目标的 规则一样 规则按照在 makefile 中出现的次序被处理 此类规则真正有意义的是那些于命 令执行次序无关的 这种规则有时比较晦涩不是特别有用 它提供了一种机制 通过不同依赖文件的更新 来对目标进行不同的处理 这种情形很罕见 每个这种规则应当提供命令 如果没有 适 用的隐式规则将使用 3 13 自动生成依赖关系自动生成依赖关系 在 makefile 中 许多规则都是一些目标文件依赖于一些头文件 例如 main c 通过 include 使用 defs h 这样规则 main o defs h 告诉 make 在 defs h 变化时更新 main o 在程序比较大时 需要写许多这样的规则 而且当每次增删 include 时 必须小心的更新 makefile 许多现代的编译器可以帮你写这 些规则 通常这是通过编译器的 M 选项 例如命令 cc M main c 输出以下内容 main o main c defs h 这样就不必写这些规则 有编译器代劳了 注意这样的依赖关系中提及 main o 不会被隐式规则认为是中间文件 这意味这 make 在使用过它之后不会将其删除 使用老的 make 程序时 习惯做法是使用 make depend 命令利用编译器的功能产生依赖关系 该命令会产生一个 depend 文件包含所有自 动产生的依赖关系 然后在 makefile 中使用 include 将其读入 使用 GNU 的 make 时 重新生成 makefile 的功能使得这种做法变得过时 从不需要显 式请求更新依赖关系 因为它总是重新生成任何过时的 makefile 自动依赖关系生成推荐的做法是对每个源文件做一个 makefile 对每个源文件 NAME c 有一个 makefile NAME d 其中列出了目标文件 NAME o 依赖的所有文件 这样在源文件更新时 需要扫描来产生新的依赖关系 例子是一个从 NAME c 产生依赖关 系文件 NAME d 的模式规则 d c SHELL ec CC M CPPFLAGS e 选项是当 CC 命令失败时 exit 状态非 0 shell 立刻退出 通常 shell 的返回值是 管道中最后一条命令 sed 的返回值 这样 make 不会注意到编译器出错 使用 GNU 的 C 编译器时 gcc 可以用 MM 选项来代替 M 选项 这样省略系统头 文件的依赖关系 sed 命令的目的是将 main o main c defs h 转换为 main o main d main c defs h 这样使得每个 d 文件依赖于 o 文件相应源文件和头文件 make 则可以在原文间或头 文件变化时更新依赖关系文件 如果定义了生成 d 文件的规则 可以使用 include 指令来读入所有的文件 sources foo c bar c include sources c d 例中使用替换变量来将源文件列表 foo c bar c 转换为依赖关系文件的列表 因为 d 文件和其它文件一样 不需要更多工作 make 会在需要时重新生成它们 4编写命令编写命令 规则的命令是由一一执行的 shell 命令组成 除了以分号隔开写在依赖关系后的命令 每个命令行必须以 tab 字符开始空行和注释行可以出现在命令行中 处理时被忽略 注意 以 tab 字符开始的空行不是 空 行 是一条空命令 可以在命令中使用任何程序 但这些程序是由 SHELL 来执行的 4 1回显回显 通常 make 打印出要执行的命令 称之为回显 这和亲自敲命令的现象是一样的 当 行之前有 字符时 命令不再回显 字符 在传递给 shell 前丢弃 典型的用法是只对 打印命令有效 比如 echo 命令 echo About to make distribution files 当 make 使用 n 或 just print 选项时 显示要发生的一切 但不执行命令 只有在这 种情况下 即使命令以 开始 命令行仍然显示出来 这个选项对查看 make 实际要执行 的动作很有用 s 或 silent 选项阻止 make 所有回显 就象所有命令以 开始一样 一条没有依赖 关系的 SILENT 规则有相同的作用 但是 更加灵活 4 2执行执行 在需要执行命令更新目标时 make 为每一行创建一个子 shell 来执行 这意味着诸如 为进程设置局部变量的 shell 命令 cd 改变进程的当前目录 不会影响以后的命令 如果 需要 cd 影响下一个命令 将它们放在一行上用分号隔开 这样 make 认为是一条命令传递 给 shell 程序 注意 这需要 shell 支持 foo bar lose cd bar gobble lose foo 另一个形式使用续行符 foo bar lose cd bar gobble lose foo shell 程序的名字是通过 SHELL 变量来取得的 UNIX 不象大多数变量 SHELL 变量不是通过环境来设置的 即需要在 makefile 中设置 因为 SHELL 环境是个人选择的 如果不同人的选择会影响 makefile 的功能的话 这样很糟糕 4 3并行执行并行执行 GNU make 可以一次执行几条命令 通常 make 一次执行一条命令 等待其返回 再执 行下一条 使用 j 或 jobs 可以同时执行多条命令 如果 j 后梗一个正数 表示一次可 以执行的命令条数 如果 j 之后没有参数 则不限制可执行的命令数 缺省的数量是一 一个讨厌的问题是如果同时执行多条命令 它们的输出会混在一起 另一个问题是两 个进程不能从同一个设备获得输入 4 4错误错误 每条 shell 命令返回时 make 会检查其返回状态 如果命令执行成功 则下一条命令 被执行 最后一条命令执行完后 规则执行结束 如果有错误 返回非 0 状态 make 放弃当前规则 也可能是所有规则 有时候命令执行错误并不是问题 比如使用 mkdir 命令确保目录存在 如果目录一存 在 则 mkdir 会报告错误 但仍希望 make 继续 要忽略命令的错误 在命令之前使用 字符 字符在传递给 shell 之前被丢弃 clean rm f o 如果使用 i 或 ignore errors 选项 make 会忽略所有命令产生的错误 一条没有依 赖关系的 IGNORE 规则有相同的作用 但 更灵活 在忽略错误时 make 将错误也认为是成功 只是通知你命令的退出状态和和错误被忽 略 如果 make 并未告知忽略错误 在错误发生时 表明该目标不能成功更新 直接或间 接依赖于此的目标当然也不能成功 这些目标的命令不会被执行 因为其先决条件不满足 通常 make 会立即以非 0 状态退出 然而 如果给定 k 或 keep going 选项 make 在退出前会处理其它的依赖关系 进行必要的更新 例如 在编译一个目标文件遇到错误 make k 会继续编译其它的目标文件 通常认为你的目的是更新指定的目标 当 make 知道这是不可能时 会立即报告失败 k 选项指示真正目的是测试更新程序的更多可能性 在编译之前找出更多不相关的问题 如果命令失败了 假设它更新的目标文件 这个文件是不完整的不能使用 至少不是 完全更新的 但文件的最后修改时间表明停已经是最新的 下一次 make 运行时 不会再 更新这个文件 这种情况和命令被 kill 相同 则通常情况下在命令失败时将目标删除是正 确的 当 DELETE ON ERROR 是目标时 make 帮你做这件事 虽然你总是希望 make 这 么做 但这不是过去的习惯 所以必须显式要求 make 这样做 其它的 make 自动这样做 4 5中断中断 make 如果 make 执行命令时遇到错误 可能会删除命令更新的目标文件 make 检查文件 的修改时间是否变化 删除目标的目的是确保 make 下次执行时重新生成它 为什么这样 做 假设在编译器运行时按了 Ctrl c 此时编译器写生成目标文件 foo o Ctrl c kill 了编 译器 留下一个不完整的文件 但它的修改时间比源文件 foo c 新 此时 make 也受到 Ctrl c 信号删除这个不完整的文件 如果 make 不这样做 下次 make 运行时认为 foo o 不 需要更新 会在链接时出现奇怪的错误 可以使用 PRECIOUS 规则来防止目标文件被删除 在 make 更新目标时 会检测其 是否为 PRECIOUS 的依赖 决定在命令出错或中断时是否删除该目标 如果你希望目标 的更新是原子操作 或是用来记录修改时间 或必须一直存在防止其它类型的错误 这些 理由使得你必须这样做 4 6递归使用递归使用 递归使用 make 就是在 makefile 中使用 make 命令 这种技术在你将一个大系统分解为 几个子系统 为每个自系统提供一个 makefile 时有用处 比如有一个子目录 subdir 中有自 己的 makefile 希望 make 在自目录中运行 可以这样做 subsystem cd subdir MAKE 或者 subsystem MAKE C subdir 可以照抄这个 例子来递归使用 make 4 6 1 MAKE 变量变量 递归的 make 必须使用 MAKE 变量 不是显式的 make 命令 subsystem cd subdir MAKE 该变量的值是被调用的 make 的名字 在命令中使用 MAKE 有特殊的功能 它改变了 t touch n just print 和 q question 选项的含义 使用上例来考虑 make t 命令 t 选项将目标标记为最新但不运行命令 更加 t 选项的功能 该命令将创建一个 subsystem 文件 实际希望的操作是运行 cd subdir make t 但这会执行命令 与 t 的原 意不符 这个特殊功能做了期望的工作 当命令行包含变量 MAKE 时 选项 t n 和 q 并不 适用 不管这些导致不会执行命令的标志 包含 MAKE 变量
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 远程工作技能需求-洞察与解读
- 2025第二季度福建中共福州市马尾区委员会办公室招聘编外人员1人模拟试卷及答案详解(易错题)
- 2025广西崇左市人民检察院公开招聘机关文员4人考前自测高频考点模拟试题及答案详解(有一套)
- 2025辽宁鞍山市立山区教育局面向应届毕业生校园招聘2人模拟试卷及参考答案详解1套
- 2025贵州铜仁职业技术学院引进博士研究生15人模拟试卷及完整答案详解1套
- 2025年河北邯郸丛台区公开选聘农村党务(村务)工作者42名模拟试卷带答案详解
- 2025昆明市禄劝县人民法院司法协警招录(2人)考前自测高频考点模拟试题含答案详解
- 供应链透明度提升策略-第23篇-洞察与解读
- 2025广西平果市新安镇人民政府城镇公益性岗位人员招聘2人模拟试卷及答案详解(网校专用)
- 2025广东东莞市水务局招聘聘用人员2人考前自测高频考点模拟试题附答案详解(典型题)
- 墩柱安全教育培训课件
- 新版中华民族共同体概论课件第十五讲新时代与中华民族共同体建设(2012- )-2025年版
- 卫生监督协管五项制度范文(4篇)
- 2025中国低压电能质量市场白皮书
- 2025年全国《家庭教育指导师》考试模拟试题(附答案)
- 航空安全培训计划课件
- 电瓶搬运车安全培训课件
- 数据保护与安全知识培训课件
- 情报共享平台架构-洞察及研究
- 棉纱库存管理办法
- 量具借用管理办法
评论
0/150
提交评论