• 浅讲make/makefile【linux】


    一. 什么是make/makefile?

    make/makefile这两个可以说是搭档,缺一不可
    make和makefile可以说是做大型项目不可缺少的功能
    就本质来讲
    make是系统自带的一条指令
    makefile则是一个文件

    使用make后:
    编译器会自己去寻找目录下的makefile文件并执行

    可以说make的指令作用:就是执行本目录下的makefile文件
    当目录下没有makefile文件的时候就会报错
    在这里插入图片描述

    所以我们在学习make/makefile的功能,主要专注在makefile内部

    二. makefile

    想用make/makefile功能,直接自己在本目录下创建个makefile文件即可

    touch makefile
    
    • 1

    在这里插入图片描述
    vim编辑器进行修改。
    在这里插入图片描述
    发现文件内是全空的,所以我们想要写出能用的makefile文件,需要先了解依赖关系与依赖方法

    2.1 依赖关系与依赖方法

    在这里插入图片描述
    这里一条最普通的编译test的makefile指令

    让我们看看这两行分别是什么

    在这里插入图片描述
    这里我们能看到一个指令的组成有两个部分

    1.依赖关系
    2.依赖方法

    接下来我们分别来看一下这两个部分:

    依赖关系:
    在这里插入图片描述
    左边可以说是指令名。
    使用的时候就是
    make test 来执行

    test.cpp是test指令依赖的文件。

    依赖方法
    在这里插入图片描述
    依赖方法可以说是
    编程语言中函数体内的函数内容。
    就是执行的指令

    2.2 浅用make

    了解了具体了以后我们就可以试着来编写两个makefile的文件了

    2.2.1 make test

    在这里插入图片描述
    这个就是我们上面的例子,接下来我们来使用一下。
    在这里插入图片描述
    这里随便写了一个test.cpp的文件
    在这里插入图片描述
    这里输入

    make test
    
    • 1

    可以发现这里已经执行了。
    在这里插入图片描述
    发现已经多了个可执行程序,makefile指令已经执行完毕了

    2.2.2 clean

    相同的,我们也可以写个像C++中的析构函数那样的清理可执行程序的clean指令

    clean:
            rm -rf test
    
    • 1
    • 2

    依赖关系冒号后面没有跟文件,代表这个指令没有依赖文件

    这里来执行一下

    make clean
    
    • 1

    在这里插入图片描述
    发现test可执行程序被删除了

    2.2 make一次执行多步

    讲这个内容时会涉及到语言的执行过程,如果看不太懂,可以去翻我以前的博客
    C语言程序的编译过程

    在这里插入图片描述

    这里的test.i ,test.s,test.o
    都是之前程序编译和汇编以及链接的生成文件。

    这里如果直接用make test.i会怎么样?
    这不是很简单嘛
    直接执行

    g++ test.cpp -o test.i -E
    
    • 1

    就结束了。

    但是如果我们执行 make test会怎么样?

    在这里插入图片描述

    我们会发现一下执行了全部的指令。

    这里让我们来刨析一下过程。

    在这里插入图片描述
    第一步执行test时,发现依赖关系时test.o文件,但是系统查找不到
    这是时候就会去寻找具有test.o的命令
    在这里插入图片描述

    这个时候找到 test.o指令,但是发现执行需要test.s,这个时候又会去寻找test.s文件

    在这里插入图片描述

    就这样不停寻找,找到了test.i能进行创建了
    在这里插入图片描述

    这个时候在返回到上一条需要test.i的指令,并执行
    就这样一条一条执行并返回,就类似于递归一样的思路

    那我们如果随便换个顺序也是结果会怎么样
    在这里插入图片描述

    在这里插入图片描述

    发现结果不会变,因为顺序不会影响执行
    系统是会寻找可以执行的指令,自动去执行,如果没有就报错
    就C语言中的函数一样,引用函数不需要注重顺序,只要能被系统找到就可以了

    2.3 部分修饰符号

    接下来是几个比较基础的修饰符号

    2.3.1 .PHONY(伪目标)

    在执行makefile时,如果可执行文件已经产生,为了防止重复无意义的执行生成可执行文件指令
    会自动判断可执行文件的源文件是否发生变动,从而判断是否要执行编译

    例:在这里插入图片描述
    这里进行了第一次编译。
    在这里插入图片描述
    第二次执行的时候就会发现,系统会阻止你重复make

    那这么高大上的功能是怎么实现的呢?
    
    • 1

    其实就是通过对比时间而已

    我们可以通过

    stat 【文件名】
    
    • 1

    查看文件属性
    在这里插入图片描述
    access:访问时间
    对文件内容进行修改:modify
    对文件属性进行改变:change

    这里要注意:对文件属性进行修改,文件内容的时间一般也会修改
    因为文件内容有一个size的属性

    按道理来说,对文件执行指令,access时间都要进行改变
    但是因为access变化实在是太过于频繁,文件处于磁盘中,多个用户访问文件都要改变access,导致服务器十分卡顿
    所以较新版中,只有对文件进行一定量的操作后才能会进行改变access时间

    所以make文件对源文件进行依赖关系的操作的时候
    会将可执行程序的时间转化为时间戳,将.cpp文件的修改时间转化为时间戳
    进行比较,判断是否要执行指令

    这里如果想要取消时间戳对比
    就可以添加.PHONY修饰(伪目标)
    但是不推荐将生成可执行文件用伪目标进行修饰
    在这里插入图片描述
    在这里插入图片描述
    这里就可以随便进行执行了,不用进行时间戳的对比。

    2.3.2 @

    我们在输入了make后
    make会自动弹出makefile中执行指令的依赖方法
    在这里插入图片描述

    在这里插入图片描述


    加了@后,就可以防止弹出依赖方法

    2.3.3 $@ $^

    这两个修饰符主要用在依赖关系上

    在这里插入图片描述
    这两个分别代表了依赖关系的两边

    那具体有什么用呢?

    在这里插入图片描述
    写依赖方法的时候就可以用符号代替文件名了

    在这里插入图片描述
    这里能发现文件正常执行了。

  • 相关阅读:
    运维的利器–监控–zabbix–第二步:建设–部署zabbix agent--windows server系统
    phpexcel设置背景色
    Web3 大众化必须解决的 5 个问题
    【QML】QML中的动画总结
    AMI MDS安装
    从Series到DataFrame:Python数据操作的转换技巧
    【算法刷题】—7.13哈希表的应用
    awk,gawk基本用法笔记221107
    智慧公厕:科技赋予公共卫生新生命,提升城市管理品质
    创建一个SpringCloud项目
  • 原文地址:https://blog.csdn.net/Ruaaa_iiiiiiiii/article/details/133826107