Linux项目自动化构建工具 —— make/makefile
在此之前对于一个多文件的项目,它们之间的关系是 VS 帮我们维护处理的,而在 Linux 中需要我们自己来维护处理。
1、背景
- 会不会写 makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
- 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至进行更复杂的功能操作
- makefile 带来的好处就是 “自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率
- make 是一个命令工具,是一个解释 makefile 中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,如:Delphi 的 make,Visual C++ 的 nmake,Linux 下 GNU 的 make。可见,makefile 都成为了一种在工程方面的编译方法
- make 是一条命令,makefile 是一个文件,两个搭配使用,完成项目自动化构建
2、依赖关系
其次我们再了解一下什么是 make,什么是 makefile:
-
make 是一条命令,它可以帮我们自动化构建项目
-
makefile 是一个文件,自动化构建项目的过程是它完成的
这个文件里包含目标文件和原始文件的依赖关系和依赖方法。
3、依赖方法
如上
4、文件清理
- 文件除了被创建,也是需要被清理的
- 像 clean 这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要 make 执行。即命令 —— “make clean”,以此来清除所有的目标文件,以便重编译
- 但是一般我们这种 clean 的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的
5、理解
如下实例
6、实例代码
-
touch makefile/Makefile
注意 m 可以大写,但不能写错 -
vim Makefile 表明依赖关系和依赖方法后 wq
注意依赖方法也就是第二行是以 Tab 开头,并不能以 4 个空格
- make 直接编译代码
- vim Makefile 清理文件
一个项目不仅需要能生成文件,还要能清理文件
-
make clean 清理文件
-
vim Makefile 用符号简化
@ 表示目标文件 -
多文件项目的构建
注意生成的 mytest 需要依赖 mytest.c、main.c,而 mytest.h 则已经被它们包含了
📝说明
4 ❓
.PHONY 表示定义伪目标,它的意义是 make clean 时 clean 总是可执行的
这个 clean 没有依赖关系,但有依赖方法
什么叫总是可执行的 ?
其中 mytest 和 clean 都是目标文件,只不过 mytest 没有用 .PHONY 修饰,所以 clean 使用 .PHONY 修饰后就由总是不被执行的转换成总是可执行的。
验证 !
但是我们通常不会把目标可执行程序设置成总是可执行的,因为每次编译它都是有成本的,你只要保证程序是最新的,也就是说当你去 vim 原始文件后,它就可以再 make。
Makefile 里有两个目标文件,make mytest 执行 gcc,make clean 执行 rm,为什么 make 可以默认执行 gcc ?
因为 Makefile 在进行自上向下搜索目标文件时,默认生成第一个可执行程序后就不会往下搜索生成了,也就是说 Makefile 默认只生成一个目标文件。
验证 !
注意一般为了符合习惯,不那么写。
make/makefile 实现 一个 C 文件到可执行程序 ❓
验证 !
7、原理
make 是如何工作的,在默认方式下,也就是我们只输入 make 命令:
- make 会在当前目录下找名字叫 “Makefile” 或 “makefile” 的文件
- 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,它会找 “mytest” 文件,并把这个文件作为最终的目标文件
- 如果 “mytest” 文件不存在,或是它所依赖的的后面的 “mytest.o” 文件的修改时间要比 “mytest” 这个文件新(可以用 touch 测试),那么,它就会执行后面所定义的命令来生成 “mytest” 这个文件
- 如果 “mytest” 所依赖的 “mytest.o” 文件不存在,那么 make 会在当前文件中找目标为 “mytest.o” 文件的依赖性,如果找到则再根据那一个规则生成 “mytest.0” 文件(类似于堆栈的过程)
- 当然,你的文件是存在的,于是 make 会生成 mytest.o 文件,然后再用 mytest.o 文件声明,make 的终极任务也就是执行 mytest
- 这就是整个 make 的依赖性,make 会一层一层的去找文件的依赖关系,直到最终编译出第一个目标文件
- 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到了,那么 make 会直接退出,并报错,而对于所定义的命令的错误,或是编译失败,make 不会理睬
- make 只管文件的依赖性,即如果在我找到依赖关系之后,冒号后面的文件不存在,那么对不起,make 就不会工作了
- 点赞
- 收藏
- 关注作者
评论(0)