makefile笔记.doc_第1页
makefile笔记.doc_第2页
makefile笔记.doc_第3页
makefile笔记.doc_第4页
makefile笔记.doc_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

什么是 make?当你写一个简单的程序,只有一到两个源文件的时候,输入% cc file1.c file2.c就没什么问题,但如果有很多源文件就会很烦人编译的时间也会很长。一个方法就是使用目标文件,只在源文件有改变的情况下才重新编译源文件。因此你可以这样做:% cc file1.o file2.o . file37.c .上次编译后,file37.c 发生了改变,但其他文件没有。这样做可以让编译过程快很多,但是也不能解决累人的输入问题。或者我们可以使用一个 shell script 来解决输入问题,但是也需要重新编译所有文件,在大型项目上很没有效率。如果有成百上千的源文件的话怎么办?如果我们在与很多人合作写程序,别人对源文件进行了修改,又没有告诉你,该怎么办?也许我们可以把以上两种方法结合,写一种像 shell script 一样的东西。这种文件包含某种技巧可以决定什么时候该对源文件进行编译。现在所有我们要的就是一个程序可以懂得这种技巧,因为要懂得这种技巧,shell 还没那么大的能耐。这个程序就叫 make。它读入一个文件,叫 makefile,这个文件决定了源文件之间的依赖关系。而且决定了源文件什么时候该编译什么时候不应该编译。例如,某个规则可以说 “ 如果 fromboz.o 比 fromboz.c 要旧,意思就是有人修改了 fromboz.c,因此我们需要重新编译这个文件。”这个 makefile 还有规则通知 make 该 怎么 重新编译源文件,因此 make 是一个强大得多的工具。makefile 通常和相关的源文件保存在同一个目录下,可以叫做 makefile,Makefile 或者 MAKEFILE。大多数程序员会使用 Makefile 这个名字,因为这样可以让这个文件被放在目录列 表的顶端,可以很容易得看见。使用 make 的例子这是一个非常简单的 make 文件:foo: foo.ccc -o foo foo.c包含两行,一行是依赖关系,一行是执行动作。依赖关系的那一行包含了程序的名字 (叫做 target),紧跟着一个冒号,然后是空格,最后是源文件的 名字。当 make读入这一行的时候,会检查 foo 是否存在;如果存在,就比较 foo 和 foo.c 最后的修改时间有什 么不同。如果 foo 不存在,或者比 foo.c 要旧,就检查执行动作那一行看看该怎么做。换句话 说,就是 foo.c 需要重新编译的时候该怎么办。执行动作那一行以一个 tab (按下 tab) 开始,然后是你在命令行下产生 foo 所执行的命令。如果 foo 过期了,或者不存在,make 就会 执行这个命令来产生 foo。换句话说,这就是重新编译 foo.c 的规则。因此,当你输入 make 时,它会确定 foo 和 foo.c 在修改时间上是否同步。这个原则可以在 Makefile 里扩展到成百上千的目标文件上实际上,在 FreeBSD 里,你只要在合适的目录下输入 make world 就可以编译整个操作系统!makefile 另一个有用的特点就是目标文件不一定就是程序。例如,我们可以 有这样的 make 文件。foo: foo.ccc -o foo foo.cinstall:cp foo /home/me我们可以输入如下的命令告诉 make 该执行哪个目标:% make targetmake 会只执行这个目标而忽略其他的目标。例如,如果我们输入 make foo,就只有 foo 被执行,必要的情况下重新编译 foo 而不会继续执行 install 这个目标。如果我们只是输入 make 这个命令,make 总会寻找第一个目标,并且在执行完以后就不管其他的目标了。例如,如果我们输入 make foo,make 就会转到 foo 这个目标,在必要的情况下重新编译 foo,而不会执行 install 目标, 然后就停止了。一定要注意,install 这个目标不依赖任何其他的东西!这意味着我们一旦输入 make install,这个目标下的所有命令都将被执行。这种情况下,foo 将被安装到用户的家目录下。应用程序的 makefile 正是这样写的,以便程序在正确编译后可以被安装到正确的目录。要尝试解释的话会比较容易让人混淆。如果你不太懂 make 是如何工作的,最好的办法就是先写一个简单的程序例如 “hello world” 以及和上面的例子相同的 make 文件再去实验。然后 再进一步,使用多个源文件,或者让你的源文件包含一个头文件。 touch 命令在这里就非常有用了它能让在不改变文件内容的情况下改变文件的日期。Make 和 include-文件C 源码的开头经常有一系列被包含的头文件,例如 stdio.h。有一些是系统级的头文件,有一些是你正在写的项目的头文件:#include #include foo.hint main(.要确定在你的 foo.h 被改变之后,这个文件也会被重新编译,就要在你的 Makefile 这样写:foo: foo.c foo.h当你的项目变得越来越大,你自己的头文件越来越多的时候,要追踪所有这些头文件和所有依赖它的文件会是一件痛苦的事情。如果你改变了其中一个头文件,却忘了重新编译所有依赖它的源文件,结果会是很失望的。gcc 有一个选项可以分析你的源文件然后产生一个头文件的列表和它的依赖关系: -MM。如果你把下面的内容加到你的 Makefile 里面:depend:gcc -E -MM *.c .depend然后运行 make depend,就会产生一个 .depend,里面包含了目标文件,C 文件和头文件的列表:foo.o: foo.c foo.h如果你改变了 foo.h,下一次运行 make 的时候,所有依赖 foo.h 的文件就会被重新编译。每一次你增加一个头文件的时候,别忘了运行一次 make depend。自动化编译一 makefile规则 makefile是一个make的规则描述脚本文件,包括四种类型行:目标行、命令行、宏定义行和make伪指令行(如“include”)。makefile文件中注释以“#”开头。当一行写不下时,可以用续行符“”转入下一行。 1.1 目标行 目标行告诉make建立什么。它由一个目标名表后面跟冒号“:”,再跟一个依赖性表组成。 例: example: depfile deptarget 该目标行指出目标example与depfile和deptarget有依赖关系,如果depfile或deptarget有修改,则重新生成目标。 example1 example2 example3: deptarget1 deptarget2 depfile 该目标行指出目标名表中的example1、example2、example3这三个各自独立的目标是用相同的依赖列表和规则生成的。 clean: 空的依赖列表说明目标clean没有其他依赖关系。 目标行后续的以Tab 开始的行是指出目标的生成规则,该Tab字符不能以空格代替。例如: example.o:example.c example.h cc c example.c 该例子指出目标example.o依赖于example.c和example.h。如果example.c或example.h其中之一改变了,就需要执行命令cc c example.c重新生成目标example.o。 可以用文件名模式匹配来自动为目标生成依赖表,如: prog: *.c 以下是一个简单的makefile的例子: 图 1 最简单的makefile例 make使用makefile文件时,从第一个目标开始扫描。上例中的第一个目标为all,所以目标clean不会自动被执行,可以通过命令make clean来生成目标。 1.2 命令行 命令行用来定义生成目标的动作。 在目标行中分号“;”后面的文件都认为是一个命令,或者一行以Tab制表符开始的也是命令。 如在上面的makefile例中,第三行以Tab字符开始的cc命令即是一个命令行,说明要生成hello应执行的命令。也可以写成:hello:hello.o;cc c hello L 一般情况下,命令行的命令会在标准输出中回显出来,如对上面的makefile执行make时,标准输出如下: cc -c hello.c cc -o hello -L/usr/X11R6/lib -L/usr/lib -lXm -lXt -lX11 hello.o cc -c hello1.c cc -o hello1 -L/usr/X11R6/lib -L/usr/lib -lXm -lXt -lX11 hello1.o 如果不希望命令本身回显,可在命令前加字符,如在上例中不希望回显cc c hello.c和cc c hello1.c,可修改makefile文件如下: 图 2 抑制回显的makefile例 对该makefile文件执行make时,标准输出如下: cc -o hello -L/usr/X11R6/lib -L/usr/lib -lXm -lXt -lX11 hello.o cc -o hello1 -L/usr/X11R6/lib -L/usr/lib -lXm -lXt -lX11 hello1.o 可以看出,命令行前有字符的不回显。 1.3 宏定义行 在makefile中,可以使用宏定义减少用户的输入,例如上例中对hello和hello1的编译选项均为“-L/usr/X11R6/lib -L/usr/lib -lXm -lXt -lX11”,此时可以用宏来代替,如: 图 3 使用宏定义的makefile例 宏定义的基本语法是: name=value 在定义宏时,次序不重要。宏不需要在使用前定义。如果一个宏定义多次,则使用最后一次的定义值。 可以使用“$”字符和“()”或“”来引用宏,例如: cc o hello.o $(CCFLAGS) hello.o 也可以将一个宏赋值给另一个宏,但这样的定义不能循环嵌套,如: A=value1 B=value2 C=$(A) $(B)等价于C=value1 value2 1.4 伪指令 makefile大部分由宏定义行、命令行和目标行组成。第四种类型是make伪指令行。make伪指令没有标准化,不同的make可能支持不同的伪指令集,使得makefile有一定的不兼容性。如果要考虑移植性问题,则要避免使用make伪指令。但有一些伪指令,如include,由于使用比较多,很多不同make都提供该伪指令。 1.4.1 伪指令include 该伪指令类似C语言中的#include,它允许一次编写常用的定义并包括它。include伪指令必须在一行中,第一个元素必须是include,并且跟一个要包含的文件名,如: include default.mk 1.4.2 伪指令“#” “#”字符也是make的伪指令,它指出“#”后面的文件是注释,如: PROGNAME=test # define macro #dont modify this 二 后缀规则 2.1 双后缀规则 在前面的makefile例中有许多重复内容,例如,生成hello和hello1的命令类似,生成hello.o和hello1.o的命令也类似,除了编译或链接的文件不一样外,其它均相同,这时,我们就可以使用后缀规则。首先看一个双后缀的例子: 图 4 使用双后缀规则的makefile例 后缀规则使用特殊的目标名“.SUFFIXES”。 第一行中.SUFFIXES的依赖表为空,用来清除原有的后缀规则,因为.SUFFIXES可以在makefile中多次使用,每一次都将新的后缀规则加入以前的后缀规则中。 第二行中指定后缀规则为“.c .o”,即表示将所有的.c文件转换为.o文件。 第三行指定将.c文件转换成.o文件的方法。$(CC)为make的预定义宏,其默认值为cc,$为特殊的宏,代替当前的源文件,即所有要编译的.c文件。 第六行指定目标hello和hello1的生成方法。$为特殊的宏,代替当前的目标名,即hello和hello1,$.o即为hello.o和hello1.o。 上例介绍的是双后缀规则,即它包含两个后缀,如.c.o,用来把一个C源文件编译为目标文件。双后缀规则描述如何由第一个后缀类型的文件生成第二个后缀类型的文件,例如:.c.o规则描述如何由.c文件生成.o文件。 2.2 单后缀规则 单后缀规则描述了怎样由指定后缀的文件生成由它基名为名字的文件。例如使用单后缀规则.c,可以由hello.c和hello1.c生成hello和hello1文件。例如将前面的makefile改为: 图 5 使用单后缀规则的makefile例 由于.c后缀规则为make标准后缀规则,make为其指定了相应的命令行,所以在makefile中可以不用再指定其目标生成的具体命令行。 下表是make提供的标准后缀规则。 表 1 make标准后缀规则 后缀规则 命令行 .c $(LINK.c) o $ $ $(LDLIBS) .c.ln $(LINK.c) $(POUTPUT OPTPUT OPTION) i $ .c.o $(COMPILE.c) $(OUTPUT OPTION) $ .c.a $(COMPILE.c) o $% $ $(AR) $(ARFLAGS) $ $% $(RM) $% 三 特殊目标 在后缀规则中使用了特殊目标.SUFFIXES,用来指定新增的后缀规则。make还提供了几个特殊目标来设置make的行为,下面为一些特殊的目标: l .IGNORE make在执行命令行时,如果返回的是错误码,make的缺省动作是停止并退出。增加该目标后,make将忽略命令行返回的错误码,并继续执行后续的操作。 l .SILENT 前面已经介绍过,make在执行命令行时会回显命令行内容,在命令行前增加“”字符将抑制该命令行的回显。 如果增加该目标,所有的命令行不再回显,相当于在每个命令行前均增加了“”字符。 l .PRECIOUS 当收到一个信号或从shell命令返回非零的错误码时,make删除它所有已建立的文件。但有些文件即使出了错误,用户也不想让make删除,这些文件可以作为.PRECIOUS目标的参数。它可以在一个makefile中出现多次,每一次都累积文件列表。 l .SUFFIXES 它为makefile指定新的后缀规则,新的后缀规则作为.SUFFIXES的依赖表给出。.SUFFIXES可以在一个makefile中多次使用,每一次都将新的后缀规则加入以前的后缀规则中,如果.SUFFIXES的依赖表为空,则设置后缀规则表为空。 四 特殊的宏 为简单使用规则,make提供了几个特殊的宏: l $ 整个当前目标名的值可以由宏“$”来代替。 l $ 当前的源文件由“$”来代替。例如,在前面

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论