Makefile学习一

上次随着信号学习告一段落,也标志着linux系统编程相关的知识学完了,而学了这么多知识点,是需要用一个综合的项目来将其进行串起来的,这样学习的技术才会不那么空洞,所以接下来会以一个实际例子来综合运用下所学的知识,该知识点就是涉及到linux系统编程,在开始这个项目之前,还得补充一个知识点,因为会用到它,因为一个项目的源文件往往是由多个.c文件组成的,所以不可能一个个手动去用gcc去编译,所以这个高效工具就产生了-----Make工具

Makefile学习一_伪目标

简单的Makefile编写:

上面的理论先了解一下,下面会用实例来一步步阐述它的强大之处,首先先创建多个.c文件:

Makefile学习一_linux系统编程_02

然后在main.c中写一个主方法,由于只是为了演示make工具的使用,所以里面都是空实现,只要能编出可执行文件既可:

Makefile学习一_可执行文件_03

这时,在同一级文件夹下,新建一个Makefile文件,这里描述了其生成可执行文件的规则:

Makefile学习一_可执行文件_04

那规则如何编写呢?如下:

Makefile学习一_linux系统编程_05

这时, 我们开始编译:

Makefile学习一_可执行文件_06

从这结果可以很直观地感受到make命令的便捷之处,只要编写好Makefile之后,之后不管多少.c文件,编译起来都是比较简单的,和不使用make来编译文件,生成是比较麻烦的,所以,这就是为什么要学习它的原因,在实际项目开发中用它来做源代码编译是非常方便的。

其实从make的输出行中就可以发现,实际上就是按我们的规则去执行了一些编译命令,如下:

Makefile学习一_linux系统编程_07

如果这时我们再次make会怎样呢?

Makefile学习一_伪目标_08

那如果更改内容再来make呢?

Makefile学习一_linux系统编程_09

对于编译生成的中间.o文件,如果我们想全部删除该怎么办呢?可能大家都知道可以用rm命令,一个个去删除,但是如果每次编译之后删除都得手动去用rm命令去删是不是非常麻烦呢?所以可以采用make的伪目标,具体用法如下:

Makefile学习一_linux系统编程_10

这时来看一下效果:

Makefile学习一_可执行文件_11

如果我们只想生成某个文件的.o文件呢?可以这样办:

Makefile学习一_可执行文件_12

基于这个规则,我们就可以解释为什么我们敲入一个make既可生成一个main执行文件呢?因为make其实上是生成第一个目标,而我们编写的Makefile的第一个目标就是生成可执行文件,所以就生成了main可执行文件了。

对于伪目标,还有一个值得说明的地方,下面来看现象:

Makefile学习一_伪目标_13

这是由于它发现本地已经存在clean文件了,所以就不执行伪目标了,这时我们可以显示指定伪目标:

Makefile学习一_linux系统编程_14

这时再执行:

Makefile学习一_伪目标_15

从现在我们编写的Makefile文件中,可以发现一些问题,如:

Makefile学习一_可执行文件_16

所以,解决这个问题,在Makefile中使用变量则产生了。

Make自动化变量:

Makefile学习一_伪目标_17

下面用实际Makefile文件来说明上面的变量:

Makefile学习一_linux系统编程_18


Makefile学习一_linux系统编程_19


Makefile学习一_linux系统编程_20


下面,我们用上面自动化变量的方式,来改编一下Makefile,达到同样的效果:

Makefile学习一_linux系统编程_21

Makefile学习一_linux系统编程_22

思考这种方式用什么好处呢?

1、更加专业【感观上,呵呵】

2、代码量更加精简

3、更加灵活,因为自动化变量不是手动写死的


【说明】:

①、一般情况下Makefile文件中文件名首字母都是用大小的,但是用小写的m也未尝不可。

②、如是有多个Makefile存在同级目录下,可以指定用哪一个进行编译,如下:

Makefile学习一_伪目标_23\

③、可以在make时给出一些自己的提示,如下:

Makefile学习一_可执行文件_24


Makefile学习一_可执行文件_25


Makefile学习一_可执行文件_26


Makefile学习一_linux系统编程_27


Makefile编译多个可执行文件:如果一个目录下有多个.c文件都要生成多个可执行文件,那该怎么办呢?下面来研究这种情况,有两个.c文件,都有main函数,也就是都得要生成可执行文件:

Makefile学习一_linux系统编程_28

Makefile学习一_linux系统编程_29

Makefile学习一_伪目标_30

这作何解释呢?实际上,这里面隐含着一些推导规则:从Makefile文件中,可以看到all依赖于我们的bin,而all并非真正的目标,而是一个伪目标,实际上可以在Makefile中这样声明:

Makefile学习一_可执行文件_31

而要生成all,则需要生成bin,由于我们并没有指定生成all的规则,所以,Make就会生成BIN里面的文件,而我们又并没有给出01test、02test的生成规则,所以编译器将自动推导将同名的.c文件生成同名的可执行文件,所以就生成了01test和02test,当然我们也可以不用系统的这种推导规则,我们自己来写生成规则,具体如下:Makefile学习一_可执行文件_32

Makefile学习一_伪目标_33

如果上面.o的生成,我们不想用系统推导的,改用我们自己的呢?可以用一个比较通用的写法,规则如下:Makefile学习一_可执行文件_34

下面用来实践下:

Makefile学习一_linux系统编程_35

Makefile学习一_linux系统编程_36

另外,还可以用一个等价的规则,如下:

Makefile学习一_可执行文件_37

Makefile学习一_可执行文件_38

至此,通过这个Makefile就可以生成多个可执行文件了,但是,如果我们要做一个更加专业的Makefile,则还需稍加修改下,得加入一些自定义的变量,达到更加的灵活通用:

Makefile学习一_伪目标_39\

至此,一个很好用的Makefile就诞生了,怎么好用法呢?基于这个我们在新建一个新的.c文件,如果想让其快速生成可执行文件,用这个Makefile实在是太方便了,如下:

Makefile学习一_伪目标_40

这时,想要编译新增的文件,只需要在Makefile简单修改下既可:

Makefile学习一_linux系统编程_41

这时只要执行make既可:

Makefile学习一_伪目标_42

如果03test.c还依赖于其它的.c文件,也很方便,如:它依赖于pub.c文件,这时在Makefile上修改一下依赖文件既可:

Makefile学习一_可执行文件_43

Makefile学习一_linux系统编程_44

Makefile学习一_伪目标_45

实际上,对于可执行文件的生成,完成可以由系统去推导,这个之前我们有证明过,这里我们将我们写的可执行文件的依赖代码去掉就知道了:

Makefile学习一_linux系统编程_46

这时执行一下:

Makefile学习一_linux系统编程_47

根据这个规则,如果之后再加入一个04test.c,而它又没有依赖其它.c,那只要在Makefile中修改一处既可很方便的生成可执行文件了,如下:

Makefile学习一_伪目标_48

Makefile学习一_linux系统编程_49

Makefile学习一_伪目标_50

好了,今天就学到这,下节见~