zoukankan      html  css  js  c++  java
  • Makefile的介绍与使用(一)

     Makefile是Linux系统中必不可缺的一部分,Makefile可以简单理解为一份规则,也就是一个系统的执行指南,其规定了你所要执行的程序如何去做,需要什么文件参与等等。这部分就简单了解一下子目录下的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的格式并没有固定,例如也是可行的,但是hello.o必须在hello的前面,即错误的。(可以看成‘ -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。

     打开终端进行make。

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

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

     可以看出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就会退出并报错。例如的执行就会找不到文件,从而报错。

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

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

    三、在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,会发现此时和原来没有改变的时候是一样的。

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

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

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

    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

     

  • 相关阅读:
    《面向对象程序设计》课程作业 (三)
    《面向对象程序设计》课程作业 (二)
    webpack插件配置(二)- HtmlWebpackPlugin
    webpack插件配置(一) webpack-dev-server 路径配置
    创建react项目
    Idea中配置Tomcat
    在Idea创建Spring Boot + MyBatis的web项目
    Jenkins参数化构建(三)之 Jenkins从文件中读取运行参数
    Jenkins参数化构建(二)之 Maven command line使用Jenkins参数
    Jenkins参数化构建(一)之 Maven Command Line传递TestNG构建参数
  • 原文地址:https://www.cnblogs.com/heng-xing/p/13477204.html
Copyright © 2011-2022 走看看