为什么要学习Makefile?

Linux环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该​不能算是一个合格的专业程序员​,至少不能称得上是Unix程序员。在Linux(unix)环境下使用GNU的make工具能够比较容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译、连接以至于最后的执行。不过这需要我们投入一些时间去完成一个或者多个称之为Makefile 文件的编写。

--引用某du

根据上面黄色标注的文字,你觉得需要学习Makefile吗?


《概念篇》


linux下,Makefile是啥??_目标文件Makefile的概念linux下,Makefile是啥??_目标文件

一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,Makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 Makefile就像一个Shell脚本一样,也可以执行操作系统的命令。


linux下,Makefile是啥??_文件名_03Makefile的命名规则linux下,Makefile是啥??_文件名_03  

默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、 “makefile”、“Makefile”的文件,在这三个文件名中,最好使用“Makefile”。因为,这个文件名第一个字符为大写,这样有一种显目的感觉。最好不要用“GNUmakefile”,是GNU的make识别的。有另外一些make只对全小写的“makefile”文件名敏感,大多数的make都支持“makefile”和“Makefile”这两种默认文件名。

Makefile也可以为其他名字,比如makefile.linux,但你需要使用make的参数(-f or --file)制定对应的文件,例如:

make -f makefile.linux


linux下,Makefile是啥??_文件名_05Makefile的规则linux下,Makefile是啥??_文件名_05

Makefile的规则:

target: prerequisites
command
  • target:​可以是一个object file(目标文件),也可以是一个执行文件,还可以是一个标签(label)。

  • prerequisites:​生成该target所依赖的文件和/或target

  • command:​该target要执行的命令


上面三者的关系:target​这一个或多个的目标文件依赖于​prerequisites​中的文件, 其生成规则定义在​command​中。

举个例子,比如我们平时要编译一个文件:

gcc main.c -o main

换成Makefile的书写格式:

main:main.c
gcc main.c -o main


linux下,Makefile是啥??_目标文件Makefile的工作流程linux下,Makefile是啥??_目标文件

  1. 执行make会在当前目录下找名字叫“Makefile” or “makefile”的文件。

  2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“main”这个 文件,并把这个文件作为最终的目标文件。

  3. 如果main文件不存在,或是main所依赖的后面的​.o​​文件的文件修改时间要比main​​这个 文件新​,那么,他就会执行后面所定义的命令来生成main这个文件。

  4. 如果main所依赖的​​.o​​​文件也不存在,那么make会在当前文件中找目标为 ​​.o​​​文件 的依赖性,如果找到则再根据那一个规则生成​​​.o​​文件。(这有点像一个堆栈的过程)

  5. 当然,你的C文件和H文件是存在的啦,于是make会生成​​.o​​​文件,然后再用​​.o​​​文件生 成make的终极任务,也就是执行文件​​​main​​了。


执行make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在执行过程中,如果出现错误,比如被依赖的文件找不到,那么make就会直接退出,并报错,而对于所 定义的命令的错误,或是编译不成功,make根本不理。make只管文件的依赖性。

在上述黄色自体中,可以明确的是,​make执行时,它会校验依赖文件的更性时间,如果目标文件跟依赖文件时间一致,则不会相应的命令。


linux下,Makefile是啥??_文件名_09Makefile包含什么内容linux下,Makefile是啥??_文件名_09

Makefile里主要包含了五个东西:​显式规则​、​隐晦规则​、​变量定义​、​文件指示​和​注释

  1. 显式规则。显式规则说明了如何生成一个或多个目标文件。这是由Makefile的书写者明显指出要生成的 文件、文件的依赖文件和生成的命令。

  2. 隐晦规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较简略地书写 Makefile,这是由make所支持的。

  3. 变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点像你C语言中的 宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。

  4. 文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中 的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一 样;还有就是定义一个多行的命令。

  5. 注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用​​#​​字符,这个就 像C/C++中的​​//​​一样。如果你要在你的Makefile中使用​​#​​字符,可以用反斜杠进行 转义,如:​​\#​​  。




linux下,Makefile是啥??_显式_11make的工作方式linux下,Makefile是啥??_显式_11

make的执行步骤如下:

  1. 读入所有的Makefile。

  2. 读入被include的其它Makefile。

  3. 初始化文件中的变量。

  4. 推导隐晦规则,并分析所有规则。

  5. 为所有的目标文件创建依赖关系链。

  6. 根据依赖关系,决定哪些目标要重新生成。

  7. 执行生成命令。


Makefile分为多个章节进行书写,有些概念描述参考与某些资料。linux下,Makefile是啥??_目标文件_13linux下,Makefile是啥??_显式_14linux下,Makefile是啥??_目标文件_15

我将持续更新文章和学习资料



饭仔DIY

微信号 : Rice_DIY

技术 | 开源 | 分享 

长按关注。。。

linux下,Makefile是啥??_目标文件_16