一、写makefile入门——规则、规则、规则

makefile是linux下常用的编程工具,功能非常强大,差不多相当于一门编程语言,能够定义变量、使用条件语句、编写函数、执行shell命令,一般主要用它组织项目中的代码文件,做到自动化编译。虽然功能强大,makefile的结构却很简单,最最基础的东西就是规则,定义好了规则,makefile就会按照我们的意愿做任何事。规则分为显示规则和隐式规则两种,显示规则就是我们在makefile中明明白白写出来的,指明了目标、依赖、命令的规则,而隐式规则就是makefile自己根据我们的显示规则推导出来的规则。

显示规则的格式很简单:
Target : Prerequisite1 Prerequisite2 ......
Command1
Command2
......
Target是规则的目标文件,只能有一个,Prerequisite是Target的依赖文件,可以有多个。比如编译一个helloworld.o文件,就依赖于helloworld.c、helloworld.h等。Command是规则的执行命令,如果经过各种判断后,发现Target需要更新,那么我们就会按部就班的一条条的执行规则里的命令。一定要注意写Command命令时要先缩进一个Tab字符,注意必须是Tab字符。

编译C语言helloworld.c的规则,就可以这么写:
helloworld.o : helloworld.c helloworld.h
gcc -c helloworld.c
保存为"makefile"文件,在终端输入make命令,就会编译出helloworld.o文件。

判断一条规则的目标是否需要更新,有三条原则:
  • 目标文件(Target)不存在
  • 目标文件的生成时间早于某些依赖文件的生成时间
  • 某些依赖文件需要更新.这些依赖文件是其他规则的目标文件,经过判断发现这些依赖文件需要更新.
前两条都很简单,就第三条复杂些.那么如何检测规则中的依赖文件是否需要更新呢?分两种情况.
第一种情况,在makefile中能够找到使用依赖文件作为目标的规则:
  • 如果依赖文件不存在,则需要更新
  • 如果依赖文件存在,则要根据更新原则判断是否需要更新
第二种情况,在makefile中不能找到使用依赖文件作为目标的规则:
  • 如果依赖文件不存在,报错
  • 如果依赖文件存在.则认为不需要更新


还是编译helloworld的例子:
helloworldapp : helloworld.o
gcc -o helloworldapp helloworld.o

helloworld.o : helloworld.c helloworld.h
gcc -c helloworld.c
修改一下helloworld.c文件,然后执行make命令.make在判断helloworldapp规则是否需要更新时,需要判断helloworld.o文件是否需要更新,在makefile中找了以helloworld.o为目标的规则,发现规则中helloworld.c文件比helloworld.o要新一些,就可以确认helloworld.o需要更新,那么helloworldapp也就需要更新了.make工具就会先执行helloworld.o规则中的命令,然后再执行helloworldapp中命令.

在定义规则时,规则的目标不一定是实实在在的文件,完全可以随意定一个名称作为规则的目标,这样目标称为伪目标.由于没有对应的文件,那这条规则就符合了"目标文件"不存在的原则,一直需要更新了.为了防止伪目标的名称与目录下的文件重名,可以在makefile中将目标明确声明为伪目标,格式如下:
.PHONY: 目标名称

我们定义一个删除*.o文件的规则,这个规则就使用了伪目标.
Clear :
rm *.o
.PHONY: Clear

在终端输入"make Clear"即可删除当前目录下的*.o文件.可以在make命令后输入目标名称作为参数.将Clear声明为伪目标后,即使当前目录下存在名称Clear的文件,Clear规则也会一直被执行.

makefile文件默认是从第一条规则开始检测的,第一条规则是makefile的默认规则.

转载于:https://my.oschina.net/u/1052241/blog/209630

你可能感兴趣的:(一、写makefile入门——规则、规则、规则)