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


    Linux项目自动化构建工具-make/Makefile

    在这里插入图片描述


    每博一文案

    人生路漫漫,越长大,越明白,每个人的路都是漫长而又艰辛的

    无论我们有多累,我们都无路可退。就像马丁说的那样,每一个强大的人都曾咬牙

    度过一段,没人帮忙,没人支持,没人嘘寒问暖的自己。过去了,这就是你的成人礼,过不去

    求饶了,这就是你的无底洞,我们都要熬过一段灰暗,孤独,无人能懂的岁月里,别无他法,谁也无法逃避。

    蔡康永曾说,人生前期越是嫌麻烦,越是懒得学习,后来就越可能错过让你,心动的人和事。

    错过新风景,生活有太多的磨难和挫折,但那些打不倒我们的,将会让我们变得更加强大,尝遍人生百味的我们,将会更加生动而干劲。

    ​ —————— 一禅心灵庙语



    make/Makefike 介绍

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


    使用make命令,一键编译

    首先我们创建一个C程序项目:

    [linux@localhost dir]$ touch main.c
    [linux@localhost dir]$ touch mytest.c
    [linux@localhost dir]$ touch mytest.h
    
    • 1
    • 2
    • 3

    main.c 文件内容

    #include"mytest.h"
    
    int main()
    {
     
      show();   
      return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    mytest.h 文件的内容

    pragma once    
        
    #include                                                                     
    extern void show();    
        
    
    • 1
    • 2
    • 3
    • 4
    • 5

    mytest.c 文件内容

    #include"mytest.h"    
        
    void show()    
    {    
        
      int i  = 0;                                                                                                                  
      for(;i < 10; i++)    
      {    
        printf("hello %d\n",i);    
        
      }    
        
    }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    创建 Makefile文件 : 在该项目,文件夹中创建 makefile 或者是 Makefile 文件名的大小写无关,因为 Linux 是不区分大小写的

    [linux@localhost dir]$ touch Makefile
    
    • 1

    在这里插入图片描述


    编写Makefile文件内容

    mybin:mytest.c main.c
    	gcc mytest.c main.c -o mybin
    
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    编写好 Makefile 内容后,就可以直接使用 make命令 ,就会自动一键,编译生成可执行程序了

    [linux@localhost dir]$ make
    
    • 1

    从下图中我们可以看到,当我们使用 make命令 ,就自动执行了,我们在 Makefile 文件中所写的 脚本内容:gcc mytest.c main.c -o mybin ,生成了,可执行程序 mybin ,对于该脚本的作用以及详细信息,大家可以移步到:

    🔜🔜🔜 Linux编译器-gcc的使用

    在这里插入图片描述

    运行看看

    [linux@localhost dir]$ ./mybin
    
    • 1

    在这里插入图片描述


    项目清理

    工程是需要被清理的,我们还可以编写一个清理项目的
    clean 这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不
    过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。脚本内容,打开 Makefile 写入如下:内容

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

    在这里插入图片描述


    编写好后,就可以使用命令 make clean 清除项目了

    [linux@localhost dir]$ make clean
    
    • 1

    从图下,我们可以看到当我们,使用 make clean 命令的时候,执行了 我们在 Makefile 中编写的脚本:rm -f mybin 强制删除 mybin 文件,

    在这里插入图片描述


    ”依赖关系“与 “依赖方法”

    Makefile 主要是由 “依赖关系"“依赖方法” 所对应的,缺一不可, 编写:Makefile ,本质上是在编写依赖关系和依赖方法

    在这里插入图片描述


    mybin:mytest.c main.c    
      gcc mytest.c main.c -o mybin    
    .PHONY:clean    
    clean:    
      rm -f mybin  
     
    //
    解析:
    mybin 是为目标文件 :冒号后面的为 依赖关系 main.c mytest.c ,就是mybin目标文件(可执行程序)的产生需要对应的源文件,不然没有源文件,又如何生成 mybin目标文件(可执行程序)	,注意语法细节:要顶格写入
    	gcc mytest.c main.c -o mybin  为依赖方法,就是如何通过依赖关系中的(main.c mytest.c)文件,生成,产生,目标文件mybin, 注意语法细节:要以Tab键开头,不可以是空格这是语法规定,依赖关系与依法方法之间不可以有空行的存在,必须相互紧挨着
    .PHONY: 可以理解成是 Makefile的关键字,凡是被.PHONY:clean(伪目标),总是会被执行的,达到无障碍运行,记住一点就是 (伪目标)可以无障碍运行,
    clean 是目标文件
          rm -f mybin 依赖方法,强制删除文件(mybin)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述


    这里解释一下:.PHONY:的总是被执行

    当我们已经产生了目标文件 比如这里的 mybin ,可我们还是继续使用 make 命令想要继续产出的时候,不会执行了,报出 make: `mybin’ is up to date. 以是最新的了,该make 命令被迫,不执行了,

    在这里插入图片描述


    而我们多次使用被 .PHONY 修饰的 clean(伪目标) 命令就不会被停止,可以一直使用,就算我们删除的文件不存在了,也还是会执行的,如下图:

    在这里插入图片描述


    我们的 mybin 也是可以被 .PHONY修饰的,从而达到 make的无障碍运行的 操作如下:

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

    在这里插入图片描述


    在这里插入图片描述


    问题 : 为什么 不要让 make 被修饰 .PHONY 成伪目标

    因为,对于项目而言,一般都是比较大的,完整编译一次,可能需要消耗 1~3 个小时,大一点的话,可能更多,成本太大了,太消耗时间了,所以不建议 被 .PHONY ,修饰,而清除项目,就不需要了,这么多时间成本,而且可能一次没有清除干净,需要多次清除。


    问题: 为什么 编译使用 make命令 就可以了,不需要带选项标签,而清除项目,却需要make clean 带上标签

    因为命令 默认是从上往下执行的,默认make 执行第一个语句的,所以不需要带上标签,而我们的清除项目,clean 命令,不是位于第一个语句,所以需要使用到 标签,跳转到相对应的位置 make clean


    优化

    大家发现没有,如果使用上述的方式,编写的Makefile 依赖关系和依赖方法,太过于死板了,如果项目中的依赖关系的文件,太多了的话,我们需要一个一个的输入,难免会输错,而且一旦在项目中我们添加了,对应的依赖关系中的文件,我们又要对 Makefile 内容上做修改,太麻烦了,有没有什么,一劳永逸的方法,当然,是用的,我们可以使用上 通配符以及一些特殊的符号,代替大量重复类似的文件上的操作

    mybin:main.o mytest.o    
      gcc $^ -o $@    
    %.o:%.c    
      gcc -c $<    
    .PHONY:clean    
    clean:    
      rm -f *.o mybin 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述


    试试看

    [linux@localhost dir]$ make 
    
    • 1

    在这里插入图片描述


    [linux@localhost dir]$ ./mybin
    
    • 1

    在这里插入图片描述


    [linux@localhost dir]$ make clean
    
    • 1

    在这里插入图片描述


    解析

    mybin:main.o mytest.o    
      gcc $^ -o $@    
    %.o:%.c    
      gcc -c $<    
    .PHONY:clean    
    clean:    
      rm -f *.o mybin
    mybin 目标文件
    main.o mytest.o 依赖关系,生成目标文件(mybin)所依赖的源文件 main.o mytest.o
    	$^ 表示依赖文件列表中的:冒号右侧的源文件(main.o mytest.o)
    	$@ 表示代指目标文件(mybin)
    	gcc $^ -o $@ 依赖方法,生成目标文件(mybin),在这里就等于是 gcc main.o mytest.o -o mybin
    	%.c  依赖关系表示当前目录下的所有后缀为.c文件
    	%.o 目标文件表示当前目录下的所有后缀为.o 文件,就是依赖关系中的.c 文件产生的.o 目标文件
    	$< 表示在依赖关系中的%.c的源文件,用 gcc 进行汇编成同名的.o 文件
    	gcc -c $< 依赖方法表示使用 gcc 依赖关系中的%.c的源文件对进行汇编生成同名的.o文件(%.o目标文件),因为 gcc -c 没有重定向默认是创建同名的.o二进制目标文件,在这里等于是 gcc -c main.c mytest.c
    	.PHONY:clean(伪目标) 表示无障碍运行
    	clean 表示目标文件
    	*.o 通配符,表示当前目录下的所有以.o 为后缀的文件
    	rm-f *.o mybin  表示强制删除当前目录下的以.o为后缀的文件以及名为mybin的文件 
    	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述


    原理:

    make是如何工作的,在默认的方式下,也就是我们只输入 make 命令。那么

    make 会在当前目录下找名字叫 “Makefile" 或**“makefile”** 的文件,如果找到了,它会找文件中的第一个目标文件(target), 在上面的例子中,它会找到 ”mybin" 这个文件,并把这个文件作为最终的目标文件,

    如果 “mybin" 文件不存在,或是 ”mybin" 所依赖的后面的 main.c mybin.c 文件的文件修改时间比 ”mybin“ 这个文件新(可以用touch测试),那么 ,它就会执行后面所定义的命令来生成 mybin 这个目标文件。

    如果**”mybin"** 所依赖的**“main.c mybin.c"** 文件不存在,那么 make 会在当前文件中找目标为 main.c mybin.c 文件的依赖性,如果找到了,则再根据那一个规则生成 ”main.c mybin.c 文件(这有点像一个堆栈的过程)

    当然,如果你的C文件,和H文件都是存在的,于是make 会生成main.o mybin.o 文件,然后再用 maIn.o mybin.o 文件声明make 的终极任务,也就是执行文件 mybIn

    这就是整个 make 的依赖性,make 会一层一层地去找文件之间的依赖关系,直到最终编译出第一个目标文件,在找寻的过程中,如果出现错误,比如:最后被依赖的文件找不到,那么make 就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make 根本不会理会

    make 只管文件的依赖性,即使如果在我找了依赖关系之后,冒火后面的文件还是否存在,那么对不起,我就不工作了。


    其中大家如果不理解的 gcc 的使用,大家可以移步到:🔜🔜🔜 Linux编译器-gcc的使用

    最后:

    限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见!


  • 相关阅读:
    顾客:花钱还要受气?消费体验令人下头,根因与解药何在?
    Java基础-JVM:垃圾回收算法与垃圾收集器
    .NET 7 SDK 开始 支持构建容器化应用程序
    轮式联合收割机液压系统设计
    全链路自研:腾讯混元大模型释放企业全新可能性
    java技术专家面试指南80问【java学习+面试宝典】(七)
    Vue项目中使用AntV G6绘制自适应图谱
    利用XtraDiagram.DiagramControl进行流程图形的绘制和控制
    向量检索库Milvus架构及数据处理流程
    Eyeshot Ultimate参数化建模升级
  • 原文地址:https://blog.csdn.net/weixin_61635597/article/details/125899087