• Makefile


    Makefile

    1.什么是Makefile

    一个工程中的源文件不计其数,其按照类型、功能、模块分别存放在若干个不同的目录中。Makefile文件定义了一系列的 规则 来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至进行更为复杂的功能操作,因为 Makefile 就像一个脚本一样,也可以执行操作系统的命令。

    Makefile 的优点就是 “自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全自动编译,这样就极大的提高了软件开发的效率。

    make 是一个命令工具,是一个解释 Makefile文件中指令的命令工具。一般来说,大多数的 IDE 都有这个命令,比如 Delphi 的 make ,Visual C++ 的 nmake ,Linux 下的 GNU make

    2.Makefile文件命名和规则

    文件命名:

    • makefile 或者 Makefile

    Makefile 规则:

    • 一个 Makefile 文件中可以有 一个或者多个规则
    目标... : 依赖...
    	命令(shell命令)
    	...
    
    • 1
    • 2
    • 3
    • 目标:最终要生成的文件(伪目标除外);
    • 依赖:生成目标所需的文件或者目标;
    • 命令:通过执行命令对依赖操作生成目标(命令前必须以 Tab 缩进);

    Makefile 中其他的规则都是为第一条规则服务的。

    示例

    在这里插入图片描述
    在任意一个目录下,创建如下几个文件。

    add.c

    #include "head.h"
    
    int add(int a,int b){
        return a + b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    div.c

    #include "head.h"
    
    double div(int a,int b){
        return a * 1.0 / b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    head.h

    #include 
    
    int add(int a,int b);
    
    int sub(int a,int b);
    
    int mul(int a,int b);
    
    double div(int a,int b);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    main.c

    #include 
    
    #include "head.h"
    
    int main(){
        int a = 10 , b = 20;
        printf("a = %d , b = %d\n",a,b);
        printf("a + b = %d\n",add(a,b));
        printf("a - b = %d\n",sub(a,b));
        printf("a * b = %d\n",mul(a,b));
        printf("a / b = %.2lf\n",div(a,b));
        printf("xixixiixixixi\n");
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    mul.c

    #include "head.h"
    
    int mul(int a,int b){
        return a * b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    sub.c

    #include "head.h"
    
    int sub(int a,int b){
        return a - b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    makefile

    app:add.c sub.c mul.c div.c main.c
    	gcc add.c sub.c mul.c div.c main.c -o app
    
    • 1
    • 2

    然后执行 make 命令,再执行可执行文件。

    在这里插入图片描述

    3.工作原理

    命令在执行之前,需要先检查规则中的依赖是否存在。

    • 如果存在,则执行命令;
    • 如果不存在,就向下检查其他规则,检查是否存在一个规则是用来生成这个依赖的。如果找到了,就执行该规则中的命令;

    检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间。

    • 如果依赖的时间 比 目标的时间晚,需要重新生成目标;
    • 如果依赖的时间 比 目标的时间早,目标不需要更新,对应规则中的命令不需要执行;

    Makefile

    #app 依赖于 add.o sub.o mul.o div.o main.o 这些文件
    #由于这些文件还不存在,所以向下检查其他规则
    #比如首先检测到 add.o 发现它不存在,就向下找到生成 add.o 的规则 并执行命令
    #其他的也是类似,直到得到所有的依赖文件 最终生成目标文件 app
    app:add.o sub.o mul.o div.o main.o
    	gcc add.o sub.o mul.o div.o main.o -o app
    
    add.o:add.c 
    	gcc -c add.c -o add.o 
    
    sub.o:sub.c 
    	gcc -c sub.c -o sub.o 
    
    mul.o:mul.c 
    	gcc -c mul.c -o mul.o 
    
    div.o:div.c 
    	gcc -c div.c -o div.o 
    
    main.o:main.c 
    	gcc -c main.c -o main.o 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述
    我们推荐写成这样的形式

    因为这样写的话,如果我们修改了其中的部分文件,那么我们也只需要重新编译这些被修改过的文件,而不是所有文件。

    示例

    比如在 main 函数最后,添加一句输出 hello makefile 的语句,再编译。

    在这里插入图片描述
    再次执行 make 命令。

    在这里插入图片描述

    我们发现这次只重新编译了 main.c 文件,这样的形式就提高了编译的效率。之前的那种形式就算修改了一个文件,也会重新编译所有文件。

    4.变量

    自定义变量

    • 变量名=变量值,var=hello

    预定义变量

    • AR:归档维护程序的名称,默认值为 ar
    • CC:C编译器的名称,默认值为 cc
    • CXX:C++编译器的名称,默认值为 g++
    • $@:目标的完整名称;
    • $<:第一个依赖文件的名称;
    • $^:所有的依赖文件;

    获取变量的值

    • $(变量名)

    示例

    将工作原理中的示例,全部用变量替换。

    Makefile

    src=add.o sub.o mul.o div.o main.o
    target=app
    
    $(target):$(src)
    	$(cc) $(src) -o $(target)
    
    add.o:add.c 
    	$(cc) -c add.c -o add.o 
    
    sub.o:sub.c 
    	$(cc) -c sub.c -o sub.o 
    
    mul.o:mul.c 
    	$(cc) -c mul.c -o mul.o 
    
    div.o:div.c 
    	$(cc) -c div.c -o div.o 
    
    main.o:main.c 
    	$(cc) -c main.c -o main.o 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    5.模式匹配

    Makefile 中我们也可以使用 模式匹配

    %.o : %.c

    • %:通配符,匹配一个字符串;
    • 两个 % 匹配的是同一个字符串;

    例如:

    %.o:%.c
    	gcc -c $< -o $@
    
    • 1
    • 2

    示例

    把变量中的示例使用模式匹配。

    src=add.o sub.o mul.o div.o main.o
    target=app
    
    $(target):$(src)
    	$(CC) $(src) -o $(target)
    
    %.o:%.c 
    	$(CC) -c $< -o $@
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    6.函数

    $(wildcard PATTERN...)

    • 功能:获取指定目录下指定类型的文件列表;
    • 参数:PATTERN 指的是 某一个或者多个目录下的对应的某种类型的文件,如果有多个目录,一般使用 空格间隔
    • 返回:得到的若干个文件的文件列表,文件名之间使用 空格间隔

    例如:

    $(wildcard *.c ./sub/*.c)
    #返回 a.c b.c c.c d.c e.c ... 当前目录下 以及 当前目录的 sub 子目录下的 .c文件 
    
    • 1
    • 2

    $(patsubst , , )

    • 功能:查找 中的单词(单词以 空格,Tab 或者 回车 ,换行 分隔)是否符合模式 ,如果匹配的话则以 替换;
    • 可以包括通配符 % ,表示任意长度的字串。如果 中也包含 %,那么这个 % 将是 中那个 % 所代表的子串;
    • 返回:函数返回被替换后的字符串;

    例如:

    $(patsubst %.c , %.o , x.c bar.c)
    #返回为 x.o bar.o
    
    • 1
    • 2

    示例

    使用函数来实现。

    src=$(wildcard *.c)
    objs=$(patsubst %.c,%.o,$(src))
    
    target=app
    
    $(target):$(objs)
    	$(CC) $(objs) -o $(target)
    
    %.o:%.c
    	$(CC) -c $< -o $@
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    我们可以添加 clean ,使用 make clean 删除目标文件。

    clean:
    	rm $(objs) -f
    
    • 1
    • 2

    在这里插入图片描述

    需要注意的是,如果我们此时在 当前目录下创建一个 clean 文件,make clean 文件就会失效。

    在这里插入图片描述
    此时我们需要将 clean 设置生成伪文件。

    .PHONY:clean
    clean:
    	rm $(objs) -f
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    此时就执行成功了。

  • 相关阅读:
    Android 中手指从按钮 A 平移到 B,会发生什么?为什么?
    爬虫过程和反爬
    创意工具集
    Linux系统中让$前面显示完整的路径
    使用ansible-app2k8s管理和部署服务到 kubernetes
    ISP和IAP介绍
    Spring cloud alibaba实战
    面了个腾讯30k+出来的,他让我见识到什么是基础的天花板
    校园跑腿小程序还受欢迎不?
    react项目中遇到的几个问题(二)
  • 原文地址:https://blog.csdn.net/m0_74396439/article/details/134298632