关于makefile的规则
来源:互联网 发布:淘宝店铺类目 编辑:程序博客网 时间:2024/05/20 02:27
链接
链接器只管目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标文件打个包,在 Windows 下这种包叫“库文件”(Library File),也就是 .lib 文件,在 UNIX 下,是 Archive File,也就是 .a 文件。
- 如果这个工程没有编译过,那么所有 C 文件都要被编译和链接;
- 如果这个工程的某几个 C 文件被修改,那么只编译被修改的 C 文件,并链接目标程序;
- 如果这个工程的头文件被改变了,那么需要编译引用了这几个头文件的 C 文件,并链接目标程序。
target ... : prerequisites ... command ...
target是一个目标文件(可以是Object File,执行文件或者一个标签)
prerequisites:是要生成那个target所需要的文件或目标
command:需要执行的命令
这是一个文件的依赖关系,也就是说,target 这一个或多个的目标文件依赖于 prerequisites 中的文件,其生成规则定义在 command 中。说白一点就是说, prerequisites 中如果有一个以上的文件比 target 文件要
新的话,command 所定义的命令就会被执行。
示例
如果一个工程有 3 个头文件,和 8 个 C 文件,我们为了完成前面所述的那三个规则,我们的 Makefile 应该是下面的这个样子的。
edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.occ -o edit main.o kbd.o command.o display.o insert.o search.o files.o utils.omain.o : main.c defs.hcc -c main.ckbd.o : kbd.c defs.h command.hcc -c kbd.ccommand.o : command.c defs.h command.hcc -c command.cdisplay.o : display.c defs.h buffer.hcc -c display.cinsert.o : insert.c defs.h buffer.hcc -c insert.csearch.o : search.c defs.h buffer.hcc -c search.cfiles.o : files.c defs.h buffer.h command.hcc -c files.cutils.o : utils.c defs.hcc -c utils.cclean :rm edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o
在该目录下直接输入命令“make”就可以生成执行文件 edit。如果要删除执行文件和所有的中间目标文件, 那么, 只要简单地执行一下“make clean”就可以了。
在这个 makefile 中,目标文件(target)包含:执行文件 edit 和中间目标文件(*.o),依赖文件(prerequisites)就是冒号后面的那些 .c 文件和 .h 文件。每一个 .o 文件都有一组依赖文件,而这些 .o 文件又是执行文件 edit 的依赖文件。依赖关系的实质上就是说明了目标文件是由哪些文件生成的,换言之,目标文件是哪些文件更新的。
在定义好依赖关系后, 后续的那一行定义了如何生成目标文件的操作系统命令,一定要以一个 Tab 键作为开头。记住,make 并不管命令
是怎么工作的,他只管执行所定义的命令。make 会比较 targets 文件和 prerequisites 文件的修改日期,如果 prerequisites 文件的日期比targets 文件的日期新,或者 target 不存在的话,那么,make 就会执行后续定义的命令。
clean 不是一个文件,它只不过是一个动作名字,有点像 C 语言中的 lable 一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。要执行其后的命令,就要在 make 命令后明显得指出这个 lable的名字。这样的方法非常有用,我们可以在一个 makefile 中定义不用的编译或是和编译无关的命令,比如程序的打包,程序的备份,等等。
make的工作流程
输入make命令后的执行流程:
- make 会在当前目录下找名字叫 “Makefile” 或 “makefile” 的文件;
- 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到 “edit” 这个文件,并把这个文件作为最终的目标文件;
- 如果 edit 文件不存在,或是 edit 所依赖的后面的 .o 文件的文件修改时间要比 edit 这个文件新,那么,他就会执行后面所定义的命令来生成 edit 这个文件;
- 如果 edit 所依赖的.o 文件也存在,那么 make 会在当前文件中找目标为.o 文件的依赖性,如果找到则再根据那一个规则生成.o 文件。(这有点像一个堆栈的过程);
- 当然,你的 C 文件和 H 文件是存在的啦,于是 make 会生成 .o 文件,然后再用 .o 文件生命 make 的终极任务,也就是执行文件 edit了。
这就是整个 make 的依赖性, make 会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么 make 就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make 根本不理。make 只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
伪目标:并不对应于实际的文件,只规定了make应该执行的命令(因为没有依赖体,make 会认为目标体是最新的而不执行任何操作)
像 clean 这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要 make 执行。即命令——make clean
,以此来清除所有的目标文件,以便重编译。
makefile 的变量也就是一个字符串
#定义变量objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o #以“$(objects)”的方式来使用变量edit : $(objects)cc -o edit $(objects)main.o : main.c defs.hcc -c main.ckbd.o : kbd.c defs.h command.hcc -c kbd.ccommand.o : command.c defs.h command.hcc -c command.cdisplay.o : display.c defs.h buffer.hcc -c display.cinsert.o : insert.c defs.h buffer.hcc -c insert.csearch.o : search.c defs.h buffer.hcc -c search.cfiles.o : files.c defs.h buffer.h command.hcc -c files.cutils.o : utils.c defs.hcc -c utils.cclean :rm edit $(objects)
关于make的自动推导
GNU 的 make 可以自动推导文件以及文件依赖关系后面的命令。只要 make 看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,也就是说,如果 make 找到一个 whatever.o,那么 whatever.c 就会是 whatever.o 的依赖文件,并且 cc -c whatever.c
也会被推导出来。
objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.oedit : $(objects)cc -o edit $(objects)main.o : defs.hkbd.o : defs.h command.hcommand.o : defs.h command.hdisplay.o : defs.h buffer.hinsert.o : defs.h buffer.hsearch.o : defs.h buffer.hfiles.o : defs.h buffer.h command.hutils.o : defs.h.PHONY : cleanclean :rm edit $(objects)
上面文件内容中,.PHONY
表示,clean
是个伪目标文件。
上面的makefile中有一堆重复的.h文件,可以使用自动推导功能,把重复的.h文件收拢起来。
objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.oedit : $(objects)cc -o edit $(objects)$(objects) : defs.hkbd.o command.o files.o : command.hdisplay.o insert.o search.o files.o : buffer.h.PHONY : cleanclean :rm edit $(objects)
每个 Makefile 中都应该写一个清空目标文件(.o 和执行文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。
.PHONY : cleanclean :-rm edit $(objects)
.PHONY 意思表示 clean 是一个“伪目标”,而在 rm 命令前面加了一个小减号的意思就是, 也许某些文件出现问题, 但不要管,继续做后面的事。当然,clean 的规则不要放在文件的开头,不然,这就会变成 make 的默认目标,相信谁也不愿意这样。不成文的规矩是——“clean 从来都是放在文件的最后”。
Makefile 里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。
- 显式规则: 显式规则说明了,如何生成一个或多的的目标文件。
这是由 Makefile 的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。 - 隐晦规则: 由于我们的 make 有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写 Makefile,这是由 make 所支持的。
- 变量的定义:在 Makefile 中我们要定义一系列的变量,变量一般都是字符串,这个有点你 C 语言中的宏,当 Makefile 被执行时,其中的变量都会被扩展到相应的引用位置上。
- 文件指示:其包括了三个部分,一个是在一个 Makefile 中引用另一个 Makefile,就像 C 语言中的 include 一样;另一个是指根据某些情况指定 Makefile 中的有效部分,就像 C 语言中的预编译#if 一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。
- 注释:Makefile 中只有行注释,和 UNIX 的 Shell 脚本一样,其注释是用“#”字符,这个就像 C/C++中的“//”一样。如果你要在你的Makefile 中使用“#”字符,可以用反斜框进行转义,如:“#”。
PS:在 Makefile 中的命令,必须要以[Tab]键开始。
- 关于makefile的规则
- makefile的规则
- Makefile 的书写规则
- Makefile的规则
- makefile的规则
- Makefile 的规则
- Makefile文件的规则
- makefile的隐含规则
- Makefile的规则
- 一、Makefile的规则
- makefile的编译规则
- makefile的书写规则
- Makefile的规则
- Makefile的基本规则
- makefile目标的规则
- makefile的使用规则
- makefile-规则的命令
- Makefile的规则
- Sereja and Swaps
- rails + capistrano + nginx + puma部署
- Android 自定义统计趋势图
- Androd7.0-新特性
- sequelize荟萃
- 关于makefile的规则
- 金蝶EAS 后台事务监控
- ubuntu16.04LTS安装Qt Creator
- 创建 maven maven-archetype-quickstart 项目抱错问题解决方法
- hdu 1024 Max Sum Plus Plus
- Volley框架使用与源码解析(二)
- 群集环境不需重启,快速收集KSQL、RPC日志的方法
- [LeetCode] 110. Balanced Binary Tree
- centos6.5/centos7安装部署企业内部知识管理社区系统wecenter