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

目录

1.前言

 2.认识make

 3.编写一个简单的makefile

4.深入理解依赖关系和依赖方法

5.相同的源代码只能make一次

6.make的重新编译

文件的时间

7.makefile中的一些小细节


1.前言

  • 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
  • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  • make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
  • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

 2.认识make

make命令的功能是编译内核或源码文件。make是GNU工程化编译工具,用于编译众多相互关联的源代码文件。make命令也可以编译内核或模块功能,以工程化的工作方式提高开发效率。

初次运行make命令时,它会通过扫描Makefile文件找到目标及其依赖关系,并在建立依赖关系后依次编译所对应的源码程序。
原文链接:make命令 – 编译内核或源码文件 – Linux命令大全(手册)

 3.编写一个简单的makefile

我们编写一个简单的makefile并调用相关依赖关系,来理解make和makefile。

输入:make,表示调用当前目录下makefile中的第一条依赖关系的依赖方法。

输入:make 依赖者,表示调用当前目录下makefile文件中依赖者对应依赖关系的依赖方法。比如以下的“make clean"。

4.深入理解依赖关系和依赖方法

1.我们重新编写一个makefile,里面嵌套着预处理、编译、汇编、链接。

在makefile文件中,我们并没有按照源文件生成可执行文件的顺序编写依赖关系。

2.我们执行make指令,发现程序是按照预处理、编译、汇编、链接执行的,最终正常生成了可执行文件,没有报错。

3.我们编写清理指令clean,

 执行make clean,

 4.我们修改makefile中的内容,将汇编放在第一行,并执行make,

发现程序只执行到汇编阶段,没有进行链接生成可执行文件。 

这是为什么呢?

这是因为make会将依赖者作为最终目标文件,生成了最终目标文件,make就不会运行了。而我们输入make后没有指定依赖者,默认指定第一行中依赖关系的依赖者,此时make会将mytest.o作为最终目标文件。

5.继续clean,这里会少删一个文件mytest,因为上面的make没有生成可执行文件,但没有关系,少删是因为指定的文件在当前目录并不存在,相当于已经删除了。

6. 我们make mytest,

当当当当,make以mytest为最终目标文件,所以mytest.i,mytest.s,mytest.o,mytest都生成了。

综上,我们可以发现,make会通过依赖关系,自动调用对应的依赖方法,直到生成最终的目标文件。

5.相同的源代码只能make一次

对于一个源代码文件,make第一次生成可执行文件,再次make会失败,因为目标文件已存在。

对源代码文件进行修改,再次make会成功。

新的mytest会覆盖旧的mytest。 

为什么同一个源文件(不修改的前提下)我们通过make只能编译一次呢?

这是为了提高编译效率。 

6.make的重新编译

在5中,我们知道同一个源文件,不修改的情况下make只能编译一次(虽然make也是调用gcc,但gcc可以对一个源文件编译多次,并覆盖),其实这样说不准确,应该是在正常情况下不修改源文件,make只编译一次。原理是什么?

通过对比文件的时间(Modify),判断是否要编译。我们知道,源文件生成可执行文件,源文件在前,可执行文件在后,源文件最近修改的时间旧,可执行文件最近修改的时间新。也就是说,如果源文件最近修改的时间旧于其生成的可执行文件,就代表源文件在make编译后没有修改,反之,则代表修改了,make允许对其重新编译,并且编译后新的可执行文件会覆盖旧的可执行文件。

谈到文件的时间,我们有必要深入了解一下。

文件的时间

我们知道,文件 = 文件内容 + 文件属性。同样的,文件也可分为文件内容最近修改的时间,文件属性最近修改的时间。

我们可以用stat来查看文件的时间。

stat命令来自英文单词status的缩写,其功能是显示文件的状态信息。在Linux系统中,每个文件都有3个“历史时间”——最后访问时间(ATIME)、最后修改时间(MTIME)、最后更改时间(CTIME),用户可以使用stat命令查看到它们,进而判别有没有其他人修改过文件内容。 使用touch命令可以轻易修改文件的ATIME和MTIME,因此请勿单纯以文件历史时间作为判别系统有无被他人入侵的唯一标准。
原文链接:stat命令 – 显示文件的状态信息 – Linux命令大全(手册)

我们用statc查看mycode.c的时间,

其中,

Access表示最后访问时间(ATIME),一般情况下,只要打开了该文件,Access随之就要修改。

Modify表示文件内容最后的修改时间 (MTIME)。

Change表示文件权限最后的修改时间(CTIME)。

如果要手动更新文件的时间,我们可以用touch。

touch namefile会将文件的所有时间更新到计算机最新时间。 

touch命令的功能是创建空文件与修改时间戳。如果文件不存在,则会创建一个空内容的文本文件;如果文件已经存在,则会对文件的Atime(访问时间)和Ctime(修改时间)进行修改操作,管理员可以完成此项工作,而普通用户只能管理主机的文‍件。
原文链接:touch命令 – 创建空文件与修改时间戳 – Linux命令大全(手册) 

对文件的时间有一定了解后,我们容易理解,make是如何禁止对文件重复编译以及如何对文件进行重复编译了?

前者是通过将modify时间转换成时间戳,通过对比时间戳,判断源文件和可执行文件的最近修改内容修改时间。

只要刷新modify,就可以对源文件重新编译。但总是刷新时间,是不是太麻烦了呢?

还有一种方法,我们可以用“.PHONY”修饰依赖者,将依赖者设置为伪目标。

伪目标的特性是:总是被执行的。

 但一般我们只将作用是清理的依赖者设置成伪目标(用.PHONY修饰),很多情况下,我们希望先清理掉旧程序,再重新对源文件编译生成新的可执行程序。

7.makefile中的一些小细节

1.当我们写明依赖关系后,在对应的依赖方法中,我们可以用“$@”代表依赖者,“$^”代表被依赖者。

2.在我们用“make 依赖者”执行依赖关系后,总是会打印依赖关系对应的依赖方法。我们可以在makefile文件中,找到不想显示的依赖方法,在其行前加一个@符号,就不会打印依赖方法。

这样就不会打印依赖方法了。 

3.makefile注释

在要注释行的前面加#即可。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值