• Linux之make/Makefile联系



    前言

    Linux的学习之路是异常地艰难。有关Linux的知识点多而复杂,学习要有耐心并且要花费相对长的时间,下定决心去搞定一个知识点。在介绍make/Makefile的联系前,我想先告诉你们的是,make是一个命令,Makefile是一个文件。另外注意,Makefile的m可大写,可小写,本文为做更好地区分,Makefile中的m一贯保持大写。


    正文开始

    一、make/Makefile的演示

    如果是朋友想直接使用make命令,那么可以仿照下面的代码块。

    第一步,写想要编译的源文件。本文将用c语言来编写。

    #include
    int main()
    {
            printf("hello world");
            printf("hello world");
            printf("hello world");
            return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    第二步,创建与test.c文件对应的Makefile文件,并且进行相应的编译。

    在这里插入图片描述

    mytest:test.c
            gcc -o mytest test.c
    .PHONY:clean
    clean:
            rm -f mytest
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    第三步 使用make指令编译第一步所编写的源文件

    在这里插入图片描述

    第四步 清理所编译生成的可执行文件

    在这里插入图片描述

    二、与Makefile文件内容有关的原理

    1.Makefile文件存在的意义

    Makefile文件存在的意义是为了构建项目的。(要做一件事情)
    通俗地讲,Makefile文件是为了更简便地执行程序。以以上的程序作为一个例子,当编写与test.c对应的Makefile文件后,在编译是只需要写make命令,而不是一长串地输入gcc -o mytest test.c指令,操作更加简便。

    2.依赖关系

    目标文件与源文件的关系

    比如,以上程序中
    在这里插入图片描述
    就是要把test.c编译成一个可执行文件,并且起名为mytest。
    mytest:test.c就是表明一个依赖关系,mytest是在test.c基础上进行某种依赖方法而得到的文件。

    另外可以拿生活中的社会关系举例,比如父子关系
    小张:老张
    小张是老张的儿子,小张可以视为是依赖于老张的

    3.依赖方法

    目标文件在源文件的基础进行的操作
    gcc -o mytest test.c 这条指令就可以称得上是mytest和test.c的依赖关系

    上个例子,小张怎样依赖于老张的,他们的依赖关系是什么?
    小张是个大学生,他依赖于老张给的生活费而生存。所以据此要编写这个Makefile文件。

    小张:老张
    			老张给小张生活费
    
    • 1
    • 2

    4.依赖性

    编写Makefile文件如下

    test.out:test.o
            gcc -o test.out test.o
    test.o:test.s
            gcc -c -o test.o test.s 
    test.s:test.i
            gcc -S -o test.s test.i 
    test.i:test.c
            gcc -E -o test.i test.c 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    执行make指令
    在这里插入图片描述
    输入make命令,操作系统会自动在当前目录下寻找名称为makefile或者Makefile的文件,并且默认第一个目标文件为最终的目标文件。该文件以实现第一个目标文件的依赖关系为主,如果该目标文件所依赖的文件并不存在,那么操作系统会在Makefile文件向下寻找,通过完成其他的依赖关系找到此文件,如果并没有依赖关系生成此文件或者是该文件并不存在就会报错。
    比如,以上程序中test.out依赖的文件test.o并不存在,操作系统就会在文件中向下去寻找有无可生成test.o的依赖关系,发现第二个依赖关系可以生成,但是test.o依赖的test.s并不存在,则在去循环前几步。该make的命令则通过实现 gcc -E -o test.i test.c生成test.i,再通过实现 gcc -S -o test.s test.i生成test.s,再通过实现 gcc -c -o test.o test.s 生成test.o,最后通过实现gcc -o test.out test.o生成test.out。
    make命令的依赖性就像是剥洋葱,一层一层地实现依赖关系,编译获得最终的目标文件。

    5.项目清理

    在项目中往往存在生成某个可执行文件,在某个时机需要删除该可执行文件,便会用到clean命令。
    在使用时要输入make clean才能完成clean命令。

    三.对Makefile的初步理解

    1.stat命令的补充

    stat命令显示文件或目录的详细属性信息包括文件系统状态,比ls命令输出的信息更详细。
    在这里插入图片描述

    其中,三个表示时间的名称分别表示的含义:

    1.Modify(修改时间):文件内容被修改的时间
    2.Change(改动时间):文件属性(不只rwx的执行,还有文件内容大小)被修改的时间
    往往在修改文件内容时Modify和Change都会修改
    3.Access(访问时间):访问文件的时间
    特别地,只有读取够一定次数才修改Access的时间

    为什么只有读取一定次数才能修改Accsess的时间,而不是访问一次就修改呢?

    因为文件操作时是访问的次数多。每次修改文件的属性就会进行一次IO操作。如果每次访问文件就修改文件属性,过多的IO操作会给系统增加负担,影响效率。

    2.make为什么只能有效使用一次

    在这里插入图片描述
    在使用make命令时,发现make命令只有效生成一次。make命令防止源文件被多次重复编译,节省了项目编译的时间,提高效率。
    可make命令是怎么防止源文件被多次重复编译的呢?
    在查阅相关资料后,不难发现make命令是依据源文件Modify的时间是否早于目标文件Modify时间来更新来编译的。前提是编译过的文件存在,如果源文件Modify的时间晚于Modify的便可以编译。如果未编译过该文件则可以编译。通俗地讲,就是在有效编译一次后,如果源文件被修改,才可以被再次编译。

    源文件未被编译过可以进行编译
    在这里插入图片描述

    源文件被编译过
    在这里插入图片描述
    a.修改源文件内容,可以编译
    在这里插入图片描述

    b.修改源文件Access属性,可以编译
    其中,touch命令:touch file:如果 file 已存在,则更新 file 的所有时间
    在这里插入图片描述

    3.对.PHONY修饰的伪目标的理解(为什么make clean可以总是执行)

    在上文对make命令为什么只能有效使用一次的详细解释后,就可以很轻松地理解该部分内容

    关键字.PHONY修饰的是目标是伪目标,可以总是被执行。
    什么是伪目标?为什么能总是被执行?

    • 伪目标是这样一个目标:它不代表一个真正的文件名,在执行make时可以指定这个目标来执行其所在规则定义的命令,有时我们也可以将一个伪目标称为标签
    • 因为伪目标执行的原理于源文件、目标文件访问时间的先后无关,所以可以总是被执行。
  • 相关阅读:
    AutoConfigurationPackages.Registrar.class源码阅读
    K8S知识点(四)
    华为机试真题实战应用【赛题代码篇】-数组组成的最小数字(附Java和Python代码)
    cubemx stm32 陶晶驰 串口屏 基于YXY通信原理的串口屏驱动代码
    [多媒体] 多媒体封装格式 —— MP4 vs MKV
    Python中的类和对象
    金融业信贷风控算法3-数据分析简介
    设计模式:原型模式
    又一恶意软件:1000多名受害者均在韩国,不排除其他地区被攻击的可能
    解决跨域问题
  • 原文地址:https://blog.csdn.net/shizhongruyi0606/article/details/127700574