欢迎光临
我们一直在努力

Makefile

文章目录

  • 1.前置知识
    • 1.什么是make工具
    • 2.什么是Makefile?
  • 2.设置vim首行缩进
  • 3.Makefile基本语法
    • 1.语法格式
    • 2.伪目标
      • 1.概述
      • 2.伪目标格式
    • 3.Makefile变量和变量赋值
    • 4.自动化变量
  • 4.Makefile函数
    • 1.wildcard 函数
    • 2.notdir 函数
    • 3.dir 函数
    • 4.patsubst 函数
    • 5.foreach 函数

1.前置知识

1.什么是make工具

  • make工具,编译辅助工具
  • 解决什么问题:解决使用命令编译工程非常繁琐的问题,在大型项目中,如果修改了其中一个源文件,不需要重新编译整个项目的几十万个文件。Make会智能地只重新编译那些被修改过的文件及其依赖的文件,极大地节省编译时间。
  • 工作原理:它通过比较文件修改时间来决定是否执行编译命令。如果“目标文件”不存在,或者“依赖文件”比“目标文件”新,Make就会执行对应的命令。
  • 运行方式:在终端输入 make 命令即可运行。

2.什么是Makefile?

  • Makefile 是给 Make 工具看的文本配置文件,它描述了整个工程编译链接等规则的文件,定义了项目中的依赖关系和编译命令。
  • makefile的命令必须是makefile或Makefile

2.设置vim首行缩进

vi /etc/vim/vimrc (rc结尾的一般为配置 文件) 输入 set tabstop=4,保存后退出即可。此时vim打开后的缩进变成了4个空格 在这里插入图片描述 前后对比设置前 在这里插入图片描述 设置后 在这里插入图片描述

3.Makefile基本语法

1.语法格式

语法格式:
目标:依赖
(tab)命令

在这里插入图片描述

补充说明:这里是tab键,而非空格,如果这里缩进不是四格,参考上述所讲设置vim首行缩进

目标:all 依赖:空 命令:gcc hello.c -o hello

效果示例: 在这里插入图片描述 也可以写成 在这里插入图片描述

因为 all 依赖 hello.o 文件,所以要先执行 gcc -c hello.c 得到 hello.o 文件,然后才可以执行 gcc hello.c -o hello。所以输入 make 命令后执行顺序如下

在这里插入图片描述 补充说明

在编译的时候,用 make 目标来编译,如果不指定目标的话,默认执行的是第一个目标所对应的规则。也就是说 make 和 make all 是一样的。

2.伪目标

1.概述

问题:当前目标不能和Makefile目标名一样的文件,例如,当前目录下有个文件名是clean,同时Makefile存在目标名clean,那么执行make clean命令就会报错,因此引入伪目标,当使用伪目标来声明clean就可以解决这一问题,避免与当前目录下的同名文件发生冲突 在这里插入图片描述

2.伪目标格式

.PHONY:目标

示例 在这里插入图片描述 执行 make clean 命令。尽管当前目录下有 clean 同名文件,make clean 命令也可以执行成功 在这里插入图片描述

3.Makefile变量和变量赋值

  • 定义:变量名 = 值(等号两边有没有空格都可以,但推荐不加空格,如 CC=gcc)
  • 引用:必须写成 $(变量名) 或 ${变量名}

四种赋值方式

赋值符名称核心特点
= 递归展开赋值 “用到时再展开”(延迟展开),如果后面变量值变了,前面的引用也会跟着变。
:= 简单展开赋值 “定义时立即展开”,赋值瞬间就把右边的值算好固定下来
?= 条件赋值 “仅当变量为空时才赋值”,如果前面已经赋过值,这一行就不生效
+= 追加赋值 “在原有值后面追加内容”,自动加空格连接
  • 示例1,=来赋值 在这里插入图片描述 运行效果 在这里插入图片描述

使用=来给变量赋值,用到时再展开,延时赋值,变量的值为最后被赋值的值,即为3,所以这里最后为32

  • 示例2,:=来赋值 在这里插入图片描述 运行效果 在这里插入图片描述

使用:=来给变量赋值,定义时立即展开,是立即赋值,在执行a:=1时变量值就已经确定,所以最后打印伪12,而非32

  • 示例3,使用?=来赋值 情景1 在这里插入图片描述 运行效果 在这里插入图片描述 情景2 在这里插入图片描述 运行效果 在这里插入图片描述

使用?=来给变量赋值,仅当变量为空时才赋值,如果 变量前面没有被赋值,那么就给它赋值,如果前面已经赋值了,就使用前面的值,所以情景1为12,情景2为42

  • 示例4,使用+=来赋值

在这里插入图片描述 运行效果 在这里插入图片描述

使用+=来赋值,追加赋值 ,原有值后面追加内容自动加空格连接

如果赋值很长,也可以使用换行符 / 在这里插入图片描述 运行效果 在这里插入图片描述

4.自动化变量

自动化变量含义(一句话记忆)具体解释
$@ 目标(Target) 代表当前规则中冒号左边的目标文件名
$< 第一个依赖如果依赖模式是%,那么它就表示一系列文件。(%为通配符,类似 linux 上的*) 代表当前规则中冒号右边的第一个依赖文件
$^ 全部依赖 代表当前规则中冒号右边的所有依赖文件列表

使用自动化变量简化前 在这里插入图片描述 使用自动化变量简化后 在这里插入图片描述 自动化变量的作用就是:让 Makefile 中的“命令部分”彻底脱离具体文件名,使得规则变得通用、动态、零重复且不易出错。从之前写死的 gcc hello.c -o hello,升级到 gcc $< -o $@

4.Makefile函数

1.wildcard 函数

wildcard 函数在 Makefile 中的作用,一句话概括就是:帮你“自动在目录里扫描文件”,让你彻底告别手动列出源文件名的笨拙做法。

你现在写的 hello: hello.o main.o 是写死的。如果明天你新增了 utils.c,你必须手动改成 hello: hello.o main.o utils.o。而有了 wildcard,它会自动把目录下所有匹配的文件都找出来。

  • 基本语法
  • $(wildcard 匹配模式)

    • 匹配模式:支持 *(任意字符串)和 ?(单个字符)通配符。

    示例:

    var = $(wildcard *.c)

    • 如果当前目录下有 hello.c、main.c、utils.c,那么 var 的值自动变成 hello.c main.c utils.c的路径,如./hello.c
    • 如果只有 hello.c,那么 var 就是 hello.c的文件路径,如./hello.c

    2.notdir 函数

    notdir 函数的作用一句话概括就是:把文件路径前面的“文件夹部分”砍掉,只留下纯粹的文件名(含后缀)

    基本语法

    $(notdir 带路径的文件名列表)

    • 它会逐个处理列表中的名字,去掉最后一个 / 之前(含 /)的所有字符。

    效果示例(输入 → 输出)

    假设你通过 wildcard 扫描得到了一堆带路径的文件名:

    输入(带路径)经过 $(notdir …)输出(纯文件名)
    ./src/hello.c →hello.c
    ./src/main.c →main.c
    ./lib/utils/helper.c →helper.c
    ./hello.c →hello.c
    ../project/main.c →main.c

    SRCS := $(wildcard src/*.c) # 得到 "./src/hello.c src/main.c"

    此时,如果想用 %.o: %.c 的通用规则编译,并生成 .o 文件放在当前目录下,你需要把./src/去掉,否则会出乱子。

    3.dir 函数

    dir 函数的作用与 notdir 正好相反,一句话概括:提取文件路径中的“文件夹部分”,保留最后的斜杠 /

    基本语法

    $(dir 带路径的文件名列表)

    • 它会逐个处理列表中的名字,截取最后一个/之前(含 /)的所有字符

    效果示例(输入 → 输出)

    输入(文件路径)经过 $(dir …)输出(目录部分)
    ./src/hello.c→./src/
    ./src/main.c→./src/
    ./lib/utils/helper.c→./lib/utils/
    ./hello.c→./
    ./hello.c→./
    ../project/main.c→../project/

    4.patsubst 函数

    patsubst 函数的作用一句话概括:它可以根据你定义的“模式”,批量把文件名列表中的后缀换掉, 最常见的用途就是把 .c 列表变成 .o 列表

    基本语法

    $(patsubst 原始模式, 目标模式, 待替换的文本列表)

    • 原始模式:通常包含通配符 %,代表任意长度的字符串。
    • 目标模式:通常包含同样的 %,代表把匹配到的内容原样保留。
    • 匹配规则:% 匹配任意字符串,替换时会把 % 匹配到的内容“搬运”到目标模式中

    效果示例(输入 → 输出)

    待替换的文本原始模式目标模式输出结果
    hello.c%.c %.ohello.o
    src/main.c%.c %.osrc/main.o
    hello.c main.c%.c %.ohello.o main.o
    src/hello.c src/%.cbuild/%.obuild/hello.o

    替换我们可以使用这个函数,也可以使用$( 待替换的文本列表:旧后缀=新后缀)这个格式来替换,效果相同,例如$(hello.c:%.c=%.o),输出结果为hello.o

    5.foreach 函数

    foreach 函数是 Makefile 中的循环函数,它的作用就是“遍历列表,逐个处理”

    基本语法

    $(foreach 变量名, 待遍历的列表, 要执行的操作文本)

    • 变量名:临时变量,每次循环时,它会依次取得列表中的一个元素值。
    • 待遍历的列表:用空格分隔的单词列表。
    • 要执行的操作文本:每次循环时要执行的表达式,通常会引用临时变量(加 $)。
    • 返回值:所有循环执行结果的集合(用空格分隔)。

    效果示例(输入 → 输出) 示例 1:在每个文件名后加后缀

    FILES := hello main utils
    RESULT := $(foreach file,$(FILES),src/$(file).c)

    执行过程:

    • 第 1 次:file=hello,操作 → src/hello.c
    • 第 2 次:file=main,操作 → src/main.c
    • 第 3 次:file=utils,操作 → src/utils.c
    • 最终返回值:src/hello.c src/main.c src/utils.c
    赞(0)
    未经允许不得转载:171主机测评 » Makefile
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址