Makefile的介绍与使用(一) 一、最简单的Makefile  二、make的工作情况 三、在Makefile中使用变量

 Makefile是Linux系统中必不可缺的一部分,Makefile可以简单理解为一份规则,也就是一个系统的执行指南,其规定了你所要执行的程序如何去做,需要什么文件参与等等。这部分就简单了解一下子目录下的Makefile。

最简单的Makefile所需要的只有三个:target(目标文件)、prerequisites(所依赖的文件)、command(此目标文件所需要执行的命令);

举一个例子:

hello : hello.o
    gcc hello.o -o hello

 上例中,左上角的hello便是目标文件(target),在其:后面的hello.o便是所依赖的.o文件(prerequisites),而下一行的gcc hello.o -o hello便是此目标文件所需执行的命令(command)。

gcc的格式并没有固定,例如Makefile的介绍与使用(一)
一、最简单的Makefile
 二、make的工作情况
三、在Makefile中使用变量也是可行的,但是hello.o必须在hello的前面,即Makefile的介绍与使用(一)
一、最简单的Makefile
 二、make的工作情况
三、在Makefile中使用变量错误的。(可以看成‘ -o hello ’必须以前移动)

接下来举一个完整的例子:

hello : hello.o
    gcc -o hello hello.o

hello.o : hello.c
    gcc -c hello.c

clean :
    rm *.o hello

 简单说明一下上面代码的意思:  1、生成一个hello程序,此程序依赖于hello.o文件,gcc...为其执行命令的方法。

                 2、hello.o文件依赖于hello.c文件。(一开始,hello.o文件是不存在的,因为gcc -c hello.c这个命令才会生成)

                 3、清除命令:清除(rm)所有的.o文件(*.o)以及hello程序。

需要注意的是: 1、gcc...前面的一大片空白是Tab键,Makefile的编写时非常严肃的,多一个空格都会出错,这里是Tab键就不要用空格隔开,否则就会出错。

        2、依赖关系是每一组文件都会有的,而依赖关系的实质即说明了目标文件是由哪些文件生成的,亦或者是由哪些文件更新的。

        3、clean不是一个文件而是一个动作,其冒号后什么都没有的时候,make就不会去找其依赖,也就不会执行其命令。

        4、make会对target和prerequisite的修改日期进行比较,如果prerequisite文件的日期比target文件的日期要新,亦或者target文件不存在,那么make才会执行后续的命令。

接下来,我们执行一下此Makefile。

我们需要先编写一个.c文件,要求其在终端显示“hello!!”

1 #include <stdio.h>
2 
3 int main(void)
4 {
5     printf("hello!!
");
6     return 0;
7 }

此时我们这个文件夹内便有了hello.c和Makefile。

Makefile的介绍与使用(一)
一、最简单的Makefile
 二、make的工作情况
三、在Makefile中使用变量

 打开终端进行make。

Makefile的介绍与使用(一)
一、最简单的Makefile
 二、make的工作情况
三、在Makefile中使用变量

 可以看出终端执行了两条command命令,同时在此文件夹中生成了一个hello程序及hello.o文件。

接下来我们跑一下所生成的hello程序。

Makefile的介绍与使用(一)
一、最简单的Makefile
 二、make的工作情况
三、在Makefile中使用变量

 可以看出hello程序其实就是hello.c的执行。

 二、make的工作情况

上面演示时用了make执行,所以这里简单说明一下make的工作情况,看看make是如何工作的。

可以看出,我们在执行make时,出现了gcc -c hello.c以及gcc -o hello hello.o两行代码,而这两行是和我们所输入command是一模一样的。而我们所属入的command是target找到prerequisite的路径。由此也就可以看出make的工作情况为:通过command找到prerequisite,并以此生成target。 如果在寻找依赖的过程中出现了问题(例如依赖找不到),那么make就会退出并报错。例如Makefile的介绍与使用(一)
一、最简单的Makefile
 二、make的工作情况
三、在Makefile中使用变量的执行就会找不到文件,从而报错。

Makefile的介绍与使用(一)
一、最简单的Makefile
 二、make的工作情况
三、在Makefile中使用变量

而在make过程中,它会对prerequisite和target二者的日期进行比较,并以二者时间判断是否进行重新链接。假如我们对.c文件进行了更改,那么.c文件的时间就会在.o文件之后,你再次make的时候它就会重新链接.c生成新的.o文件,以此类推所生成的程序也就会更新。

通过“一”中的例子可以看出,clean并没有被执行,因为其冒号后面是没有东西的。而我们使用make也可以强制执行它,只要在终端输入make clean就可以强制执行clean命令,使得生成的hello.o文件和hello程序全部清除。

Makefile的介绍与使用(一)
一、最简单的Makefile
 二、make的工作情况
三、在Makefile中使用变量

Makefile的介绍与使用(一)
一、最简单的Makefile
 二、make的工作情况
三、在Makefile中使用变量

三、在Makefile中使用变量

在我们编写小程序的时候我们可以直接这样将target、prerequisite以及command写上去,没什么问题,也容易排查错误。但是在我们编写一些比较大的程序的时候,我们这样直接编写,就会看起来很乱,并且容易敲错,到时候再回来找错就会非常困难。所以我们一般都会使用变量来将系统的一些定义,以后再次使用这个值的时候就会方便很多,而且也不易出错。

Makefile中的变量有四种:自定义变量,自动变量,预定义变量,环境变量。

而我们一般情况下使用的都是自定义变量和自动变量,我也就对这两种变量进行分析。

自定义变量:定义变量使用的变量名 := 变量值       使用变量  $(变量名)

仍然以hello为例:

HEL := hello.o
hel := hello

$(hel) : $(HEL)
    gcc -o $(hel) $(HEL)

hello.o : hello.c
    gcc -c hello.c

clean :
    rm *.o hello

 可以看到这时我将HEL设为hello.o的变量名;将hel设为hello的变量名,然后将下面对应的hello和hello.o部分全部修改为$(变量名)的形态。 (可以看见,我有部分.o文件改动,有部分维持原样)

尝试make,会发现此时和原来没有改变的时候是一样的。

Makefile的介绍与使用(一)
一、最简单的Makefile
 二、make的工作情况
三、在Makefile中使用变量

自动变量:特殊宏‘$@’,‘$^’,‘$<’等等

 $@:规则的目标文件名      $^:规则的所有依赖文件列表            $<:规则的第一个依赖文件名      (如果想知道更多的特殊宏的作用可以自行百度)

所谓的自动变量便是系统已经定义好的一种使用规则,它并不会单独特指某一变量,而是根据情况使用。

HEL := hello.o
hel := hello

$(hel) : $(HEL)
    gcc -o $@ $^

hello.o : hello.c
    gcc -c $^

clean :
    rm *.o hello

这样写的情况下,make的情况和上面是一样的,是gcc -o hello.c和gcc -o hello hello.o

 Makefile的介绍与使用(一)
一、最简单的Makefile
 二、make的工作情况
三、在Makefile中使用变量