Linux 项目自动化构建工具 —— make/makefile

avatar
作者
猴君
阅读量:0

Linux 项目自动化构建工具 —— make/makefile

会不会写 makefile,从一个侧面说明了一个人是否具备完成大型工程的能力

一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作

makefile 带来的好处就是 —— “自动化编译” ,一旦写好,只需要一个 make 命令,整个工程完全 自动编译 ,极大的提高了软件开发的效率

make 是一个 命令工具 ,是一个解释 makefile 中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,比如: Delphi 的 make , Visual C++ 的 nmake ,Linux 下 GNU 的 make ;可见 makefile 都成为了一种在工程方面的 编译方法

入门使用

首先: make 是一条命令,makefile 是一个文件,两个搭配使用,完成项目自动化构建

现在在当前路径下有 code.c 代码,需要手动 touch 一个名为 makefileMakefile 的文件

在里面写上如下代码:

mycode:code.c 	gcc -o mycode code.c -std=c99 .PHONY:clean clean: 	rm -f mycode 
  • 构建可执行文件
    • mycode:code.cmycode 是指未来形成的 可执行程序code.c 是指此可执行程序依赖 code.c 文件
    • gcc -o mycode code.c -std=c99 这一行前面有一个 Tab 键,内容就是 编译 指令,不多说
  • 清理
    • 接下来的指令就都是清理所用

返回命令行,运行 make 指令,即可构建可执行程序 mycode ;运行 make clean 即可清理 mycode 文件

至此,你已经完成了入门使用 ^ ^

原理

自动化构建

先看下图:
在这里插入图片描述

这里的每一行都有其名称

  • 依赖关系
    • : 右边是 依赖文件列表 ,图中就只有 code.c 文件;可以为空,但若有多文件,以空格为分隔符,例: code1.c code2.c code3.c
    • : 左边是 目标文件 ,图中为 mycode 可执行程序
  • 依赖方法
    • 在单纯语法上,这一行 必须以 Tab 键开头,也不可是 4 个空格

当你在运行指令 make 后,会在当前目录下寻找 makefile 文件,根据 makefile 文件里的 依赖关系 ,遵循 依赖方法 ,为你完成 依赖方法 里的工作,生成 目标文件

递归式自动推导

当你知道目标文件如何生成时,再来看看类似 递归式的连锁生成
先来看看 makefile 文件:

mycode:code.o 	gcc code.o -o mycode code.o:code.s 	gcc -c code.s -o code.o code.s:code.i 	gcc -S code.i -o code.s -std=c99 code.i:code.c 	gcc -E code.c -o code.i 

这就是 gcc 编译的每一步明细,在这里不做详细解释(如不明白,请查阅过往 gcc 拙作)

  1. 我们知道最终的目标文件是 mycode 可执行程序,但 : 后面的依赖文件 code.o 在我们当前路径下并没有
  2. 于是 make 就会在 makefile 文件里寻找名为 code.o 的目标文件
  3. 找到之后会根据 : 后面的依赖文件,再根据依赖方法来生成 code.o 目标文件
  4. 但当前路径下 code.o 的依赖文件 code.s 也没有,那 make 就会继续在 makefile 文件里寻找名为 code.s 的目标文件
  5. 于是一直找到 code.i 目标文件,它的依赖文件是存在的,那么就会生成 code.i ,继而生成 code.scode.o 直至最后的 mycode 可执行程序

那么这就很类似 栈式结构的递归调用 ,而上述就是 自动推导 makefile 中的依赖关系 的过程,即使乱序也可构建执行

清理

先看看 makefile 里的 clean 部分

clean: 	rm -f code.i code.s code.o mycode 

是否感觉和你要自动化构建的可执行程序写法十分相似?

实际上 clean 就是 makefile 里的 目标文件,只是它没有 依赖文件 而已(依赖文件列表可以为空),而下面就是 依赖方法 ,完成 依赖方法 里的工作,即为清理完成

而你要执行清理,就是生成 clean 这个目标文件,命令行也就需要在 make 后面指定要生成的目标文件,所以是:

make clean 

注意

  • 当你直接 make 时,make 会默认生成 makefile 里的第一个目标文件
  • 如果你要生成 makefile 里的其他的目标文件,就在 make 后面带上你要生成的目标文件( clean 就是如此)
  • 当你第二次再运行 make 时,只要 源文件 没有被更新修改,就会告诉你要生成的 目标文件 是最新的,不让你继续 make ,因为没有必要,为了提高效率(实现方法就是对比 源文件目标文件 的最近修改时间)
  • 要想 目标文件总是被执行,需要在 目标文件 前添加 .PHONY 声明,相当于告诉 make 不要管什么时间问题;而此时的 目标文件 也被称为 伪目标

特殊符号

依赖关系 里存在 目标文件依赖文件列表

那么在 依赖方法 里,就可以利用 $@$^ 分别表示 目标文件 和整个 依赖文件列表

在我们成功 make 时,命令行会给我们回显自动化构建的步骤,如果不想回显,可在 依赖方法 最前面添加 @

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!