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

一、背景

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

二、make/Makefile的初步认识

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

1、举例

我们先创建一个源文件,源文件中写上我们需要编译运行的代码

再创建一个makefile文件,可以写成makefile或者Makefile都可以,创建后打开

我们在makefile文件中写一些程序,具体作用后文会慢慢解释

我们将一个可执行程序命名为mytest,生成源文件code.c的可执行程序名为mytest

clean部分 我在后面再做解释,现在你知道他是一个清理功能,命令为make clean 删除可执行程序mytest

我们直接使用make命令,创建可执行程序mytest并执行。

我们发现make命令后生成了可执行程序mytest,再使用命令make clean后将可执行程序mytest删除

这个举例就是对make/makefile的简单认识,了解它的作用,接下来我们深入讲解。

2、认清原理

一、依赖关系

我们先把在例子中,对makefile文件中的代码给大家做一下解释

mytest与code.c的依赖关系就是:源文件通过依赖方法生成可执行程序mytest。

make命令会根据makefile的内容,完成编译/清理工作

clean和他的依赖方法是一种特殊情况,因为它不需要依赖文件列表,rm表示清理

二、PHONY的了解

首先我们要弄清楚为什么我们使用make命令就会直接生成可执行文件mytest,而想清理的时候,就必须在make命令后加上clean呢?

因为make命令的执行推导规则是从上到下依次扫描,默认形成第一个目标文件。

那么第三行的.PHONY是什么呢?

当我们make生成可执行程序时,将同一个程序生成两次可以吗?

它会提醒我们目前存在的可执行程序是最新的,不可以再生成,会自动给你拦截

除非我们对源文件进行修改或者删除才可以继续make

那我们不想让他拦截,想一直生成的话怎么办呢?这就是.PHONY的作用

我们用.PHONY来修饰mytest,表示mytest要总是被执行

再重新make多次,这里make了三次也没有被拦截

具体使用方法如下: 

.PHONY:xxx
xxx对应的方法,要总是被执行

  我们之所以不在生成可执行程序这里使用,是因为没有这个必要,在大项目里,编译时间会很长,重复编译会浪费时间,不重复生成也提高了编译效率,在clean部分用是因为,我们可能会用到多次清理。

这里有两个问题需要理解:

1、为什么makefile对最新的可执行程序。默认不想重新生成呢?

我们之所以不在生成可执行程序这里使用,是因为没有这个必要,在大项目里,编译时间会很长,重复编译会浪费时间,不重复生成也提高了编译效率,在clean部分用是因为,我们可能会用到多次清理。

2、makefile是怎么做到的呢?

通过对时间的比较,只要源文件的修改时间比可执行程序文件的修改时间的话,就不会继续生成,而源文件的修改时间比可执行程序文件的修改时间的话,就可以再生成。

我们可以使用命令stat查看文件的修改时间

stat <文件名>

通过Modify的时间比较就可以确定是否要重新编译

我们也可以使用touch命令更新文件Modify的时间,touch命令本来是创建新文件,但是在这里用来更新Modify时间。

3、依赖关系的深入理解

  在我们makefile文件中我们是直接从code.c生成可执行程序mytest,但是我们在上文讲过程序的编译过程,整个流程应该是code.c→code.i→code.s→code.o→mytest,那我们在makefile文件中应该怎么写呢?

  我们已经知道,make的工作推导规则是从上到下,生成第一个目标文件,所以mytest还是应该在第一行,mytest的依赖文件列表是code.o,那么依赖方法就是gcc code.o -o code.exe。

  剩下的以此类推得:

  他们之间的依赖关系就是 mytest依赖code.o、code.o依赖code.s、code.s依赖code.i、code.i依赖code.c.

  这里大家可能会有疑问:我想生成目标文件mytest时,我并没有code.o文件啊

  我用一张图给大家作答:

  make/makefile会根据文件中的依赖关系,进行自动推导,帮助我们执行所有相关得依赖方法

  这个其实就是我们所知道得递归算法。

三、make/makefile的符号替换和变量

1、符号替换

$@代表的是依赖文件列表,$@代表的是目标文件,make之后会自动替换

2、变量

我们在c语言中定义变量是需要变量类型、初始化的。比如:int a=0;

我们在Liunx中的makefile中不是,我们直接:

变量=xxx

再与符号替换结合: 

之后我们修改目标文件或者依赖文件列表,直接修改变量就可以了,会方便很多。 

四、总结

1、make工作原理

  • 1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  • 2. 如果找到,它会找文件中的第一个目标文件(target)
  • 3. 如果mytest所依赖的code.o文件不存在,那么make会在当前文件中找目标为code.o文件的依赖性,如果找到则再根据那一个规则生成code.o文件。(这有点像一个堆栈的过程)
  • 4. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
  • 5. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错, 而对于所定义的命令的错误,或是编译不成功,make根本不理。
  • 6. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起, 我就不工作啦。

2、项目清理

  • 工程是需要被清理的
  • 像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行, 不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重新编译。
  • 但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的。

  • 27
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值