Linux项目自动化构建工具-make/Makefile

简介: Linux项目自动化构建工具-make/Makefile

1.背景


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

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

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

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

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

如果在vs中写程序的时候,有100个源文件,那么我们是要把每个.c文件或者.cpp文件经过预处理,编译,汇编编译成.o文件 ,然后再把这些.o文件链接起来,生成1个或者多个可执行程序。那么这些事情是编译器帮我们做的,那么在linux中就需要我们手动去做了,在linux中自动化构建项目的工具就是make/makefile。


2.理解

那么make是什么呢?makefile又是什么呢?


make是一个命令,makefile是一个文件。make是系统为我们提供的一个命令,而makefile是需要用户在当前工作目录下自己写的一个文件。makefile是保存依赖关系和目标的一个东西。


3.依赖关系

如果我们要编译一个mytest.c的文件,首先我们要创建一个名为makefile的文件,名字必须是Makefile/makefile,那么第一行需要我们写上我们需要创建的可执行程序的名称以及这个目标文件所需要的依赖文件名称,在下面这个例子中我们想创建一个名为mytest的可执行程序,那么我需要一个名叫mytest.c的源文件,这就是依赖关系。


4.依赖方法

第二行就是依赖方法,使用gcc编译mytest.c这个源文件,生成一个名叫mytest.c的目标文件,这一步骤可以参考我的这一篇博客http://t.csdnimg.cn/yAdih


那么这两步就是依赖关系和依赖方法。


e5dc79769345451dad503b1c7097f9ae.png 然后我们退出之后,在命令行使用make这个命令,会自动进行编译,生成mytest这个可执行程序。

b2cbc3f489384c30a779205f69a28307.png

05e9eef25bb540078e4936916d22efd0.png


5.原理

make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,


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

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

3. 如果 hello 文件不存在,或是 hello 所依赖的后面的 hello.o 文件的文件修改时间要比 hello 这个文件新(可 以用 touch 测试),那么,他就会执行后面所定义的命令来生成 hello 这个文件。

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

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

6. 这就是整个 make 的依赖性, make 会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文 件。

7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么 make 就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make 根本不理。

8. make 只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。

6.项目清理

此时我将这个程序运行起来,就可以直接运行了,因为这是一个编译好的可执行程序,但是这是一个临时文件,这就意味着我们也需要一个方法能够清理掉这个文件。

5bbc1015f02e45718189bd6a0e3c0cdc.png

那么我们就需要在makefile里面定义一个clean,它的依赖关系为空,因为不需要依赖任何文件,依赖方法如下,也就是删除mytest这个临时文件,-f的意思是强制删除,就不会询问了。


像 clean 这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行, 不过,我们可以显示要make 执行。即命令 ——“make clean” ,以此来清除所有的目标文件,以便重编译。

但是一般我们这种 clean 的目标文件,我们将它设置为伪目标 , 用 .PHONY 修饰 , 伪目标的特性是,总是被 执行的。

8d2a9ec53e374adea0019bb958469125.png

在命令行中使用make clean这个命令就可以删掉了.

4e6243e8c7484f35bb667231a7c15d6c.png

需要注意的是在写完makefile之后,使用make这个命令默认执行的是第一行的代码,因为是从上到下扫描makefile这个文件的,如果我们把clean写在第一行,那么make就是删除命令,想执行gcc编译命令,那么就需要make mytest才行。并且make命令默认只执行一个依赖方法。


大家注意看,当我们已经形成可执行程序mytest后,如果再次使用make命令,那么系统会提示我们当前文件已经是最新的了。那么make/makefile是如何直到可执行程序是最新的呢?其实是通过对比时间来确定的,只要可执行程序的最新修改时间比源文件的修改时间新,就说明它是最新的。

0307fff2ac4b4a0887280e79149a76dc.png

7.文件时间

使用stat这个指令就能看到一个文件的三个时间,modify是修改的时间,change是改变的时间,当我们再次在mytest.c这个文件中写入内容是,我们会发现,modify和change都会改变,这是为什么呢?此时我们要知道的是文件=内容+属性,modify是内容的修改时间,change是属性的修改时间,那么属性包括文件的大小,拥有者,所属组.....其实ll这条指令查看到的所有内容都是文件的属性,那么为什么改变内容会导致change发生改变呢?因为内容的改变会导致文件的大小发生变化,那么就意味着属性发生了改变。


结论:通常内容和属性是一起改变的,而属性是单独改变的。


那么access是文件的访问时间,当我们使用cat命令的时候,就会修改access的时间,但是当我们短时间内多次的访问一个文件的话,它的access是不会一直改变的。

38f4a719c8364fcbb3317895bdb14173.png

那么想知道一个可执行程序是否是最新的,对比源文件和可执行程序的时间是哪个时间呢?对比的时间其实是modify的时间,因为主要是内容的更新。


今天的分享到这里就结束了,感谢大家的阅读!  

相关文章
|
6天前
|
小程序 Linux 开发工具
【Linux】Linux 开发工具(vim、gcc/g++、make/Makefile)+【小程序:进度条】-- 详解
【Linux】Linux 开发工具(vim、gcc/g++、make/Makefile)+【小程序:进度条】-- 详解
|
7天前
|
IDE Linux 测试技术
Linux项目自动化构建工具-make/Makefile
Linux项目自动化构建工具-make/Makefile
|
8天前
|
Linux Shell C语言
linux下configure,make(makefile),cmake命令详解-makefile和CMakeList
linux下configure,make(makefile),cmake命令详解-makefile和CMakeList
|
13天前
|
Linux 程序员 计算机视觉
【linux 学习】在Linux中经常用到的cmake、make、make install等命令解析
【linux 学习】在Linux中经常用到的cmake、make、make install等命令解析
24 0
|
13天前
|
Linux Shell C语言
Linux:自动化构建 - make
Linux:自动化构建 - make
17 1
|
6天前
|
Shell Linux 程序员
【Linux】Shell 命令以及运行原理
【Linux】Shell 命令以及运行原理
|
2天前
|
存储 Linux 网络安全
在 Linux 中通过 SSH 执行远程命令时,无法自动加载环境变量(已解决)
SSH远程执行命令时遇到“命令未找到”问题,原因是Linux登录方式不同导致环境变量加载差异。解决方案:将环境变量写入`/etc/profile.d/`下的文件,或手动在命令前加载环境变量,如`source /etc/profile`。
|
4天前
|
关系型数据库 MySQL Java
1.Linux常用命令
1.Linux常用命令
15 1