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


    1.背景

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

    2.实例代码

    1. 首先在Linux下创建两个文件,一个用来完成代码的编写,另一个是makefile(也可以是大写的Makefile)。
      在这里插入图片描述

    2. 在mycode.c中简单的编写一个hello world的代码
      在这里插入图片描述

    3. 在makefile编写依赖关系,和依赖方法
      在这里插入图片描述
      说明:makefile中的第一行表明依赖关系:mycode的可执行程序依赖mycode.c;第二行表明依赖方法:用gcc进行编译mycode.c生成mycode。后面三行是进行项目清理,下面会有介绍,现在可以忽略。

    4. 之后我们编译代码就再也不用用gcc mycode.c这样的指令,而是可以直接make,可执行程序mycode就会生成了。
      在这里插入图片描述

    5. 当然我们也可以运行这个可执行程序
      在这里插入图片描述

    6. 如果我们不想要mycode可执行程序,在命令行直接输入make clean即可。
      在这里插入图片描述
      注意: 通过make/Makefile管理的方式,就是Linux下的自动化构建工具。

    3.三个时间

    3.1 三个时间的引入

    通过上述例子,细心的同志就会发现如果你连续make生成可执行程序,就会生成一个报错mycode is up to date(mycode 是最新生成的),那么Linux是如何判断mycode是不是最新的呢?
    在这里插入图片描述
    毫无疑问,通过比较两个时间,mycode和mycode.c时间,那怎么查看文件的时间呢?stat + 文件名 用来查看时间。
    在这里插入图片描述
    这里通过比较两个文件Modify时间(后文具体介绍三个时间),来判断是否需要生成最新的mycode可执行程序
    在这里插入图片描述
    这里发现mycode的Modefy时间比mycode.c的文件新,所以不需要生成最新的可执行程序mycode,所以报错mycode is up to date也不难理解了。

    3.2 三个时间的具体介绍

    3.2.1 Access访问时间

    Access是最近访问文件的时间,但是由于用户访问文件的次数过多,而且用户对Access的时间需求不大。所以Linux系统优化了这Access的访问时间。可能是访问一定次数更改一次,也可能间隔一定的时间。如果需要准确了解,可能需要源码剖析,有兴趣的同志自行研究。

    在这里插入图片描述
    这里cat访问文件之后,Access的时间并没有进行修改。

    3.2.2 Change文件属性修改时间

    这个就很好理解了,当文件属性属性修改的时候,Change的时间也会修改。

    在这里插入图片描述

    3.2.3 Modify文件内容修改时间

    举例:把mycode.c中的printf赋值三遍
    在这里插入图片描述
    比较两个Modify时间
    在这里插入图片描述
    毫无疑问,modify的时间变了,但这里其实还有一个问题:
    问:为什么在Change的时间也更新的呢?
    答:当文件的大小发生改变,那大小算不算文件属性的一部分呢?

    4.makefile的推导规则

    我们在Makefile中编写这样的依赖关系和依赖方法
    在这里插入图片描述
    makefile的推导规则类似于stack结构,先进后出。
    mycode 依赖于mycode.o
    mycode.o 依赖于 mycode.s
    mycode.s 依赖于 mycode.i
    mycode.i 依赖于 mycode.c

    所以先执行那个依赖方法就很明显了后进去的先执行
    在这里插入图片描述

    5.原理

    那么make是如何工作的?

    1. make会在当前目录下找名字叫Makefile或者makefile的文件。
    2. 如果找到,它会找文件中的第一个目标文件(target),并把这个目标文件作为最终的文件。
    3. 如果mycode文件不存在,或者mycode所依赖的后面的mycode.o文件修改时间要比mycode要新。那么他会执行后面所定义的命令来生成这个mycode文件。
    4. 如果mycode依赖的文件mycode.o不存在,那么make会在当前文件夹找目标为mycode.o文件的依赖性,如果找到,再根据那个规则生成mycode.o文件。
    5. 这就是整个make的依赖性,make会一层一层去寻找文件的依赖关系,直到最终编译出第一个目标文件。当编译成功第一个目标文件后,make就不往下面进行编译了。
    6. 在寻找的过程中,如果发现错误,那么make会直接退出,并报错。而对于所定义的命令错误,或者编译不成功,make根本不理。
    7. make只管文件的依赖性。即,如果我找到依赖关系后,冒号后面的文件还是不在,那么make就直接罢工。

    6.项目清理

    • 还记的我们编写Makefile中的.PHONY:clean吗?它表明clean总是被执行。跳出时间比较,那如果我们进行.PHONY:mycode操作呢?
      在这里插入图片描述
      在这里插入图片描述
      结果显而易见,我们可以一直make了,在也不用比较两个Modify时间了
    • 像clean这种,没有被第一个目标文件直接或间接关联,那么他后面的所定义的命令不会被自动执行。所以如果我们需要执行它,需要显示执行,如make clean 来清除目标文件,以便重新编译。
      在这里插入图片描述
    • 但是一般我们这种clean目标文件,我们将它设置为伪目标。用.PHONY修饰。伪目标的特点:总是被执行。
  • 相关阅读:
    电工什么是电动势
    一篇文章让你搞懂Java中的静态代理和动态代理
    计算机毕业设计Java的音乐网站管理系统(源码+系统+mysql数据库+lw文档)
    Flamingo: a Visual Language Model for Few-Shot Learning
    嵌入式函数调用入栈与出栈
    P8352-[SDOI/SXOI2022]小N的独立集【dp套dp】
    pb:类定义查找函数
    shiny | 使用R创建一个网页应用(Web App)
    【数据结构】这些栈、队列的经典面试题你还不知道吗?
    Navicat:显示的行数与表中实际的行数不一致
  • 原文地址:https://blog.csdn.net/SASCII/article/details/127652698