轻松玩转makefile | 变量与模式
2023/3/3 21:20:58
本文主要是介绍轻松玩转makefile | 变量与模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
本文通过简单的几个示例,以及对同一个Makefile进行几个版本的迭代,帮助快速的理解变量和模式规则的使用。
1、回顾
在上一篇文章中,我们使用Makefile编译fun.c和main.c这两个文件,最终生成名为app的可执行文件。
fun.c的内容
#include <stdio.h> void fun() { printf("This is fun()!\n"); }
main.c的内容
extern void fun(); int main() { fun(); return 0; }
第一版Makefile
.PHONY:clean all: main.o fun.o gcc -o app main.o fun.o main.o : main.c gcc -o main.o -c main.c fun.o : fun.c gcc -o fun.o -c fun.c clean: rm app main.o fun.o
可以发现,Makefile里面有很多重复的内容,我们可以利用变量和模式规则对其进行优化。
2、自动变量
KaTeX parse error: Expected 'EOF', got ':' at position 2: @:̲用于表示一个规则中的目标。当有…@指的是其中任何导致规则命令被运行的自标。
$^:表示的是规则中的所有先决条件。
$<:表示的是规则中的第一个先决条件。
是不是看得有点晕?没关系,我们基于上面的Makefile,做一点点修改,把这些东西都打印出来看一下,就很清楚了。
.PHONY:clean all: main.o fun.o gcc -o app main.o fun.o @echo "\$$@ = $@" @echo "$$^ = $^" @echo "$$< = $<" main.o : main.c gcc -o main.o -c main.c fun.o : fun.c gcc -o fun.o -c fun.c clean: rm app main.o fun.o
运行make,终端打印如下内容
gcc -o app main.o fun.o $@ = all $^ = main.o fun.o $< = main.o
了解到这些之后,我们再次修改
第二版Makefile
.PHONY:clean all: main.o fun.o gcc -o app $^ main.o : main.c gcc -o $@ -c $^ fun.o : fun.c gcc -o $@ -c $^ clean: rm app main.o fun.o
3、变量的类别与赋值
变量的类别有递归扩展变量和简单扩展变量
3.1 递归扩展变量
这种只用一个“=”符号定义的变量被称为递归扩展变量
.PHONY:all goal = $(mid) mid = $(fun) fun = test all: @echo "goal = $(goal)"
运行make命令 ,打印如下
goal = test
3.2 简单扩展变量
用“:=”操作符来定义的,make只对其进行一次展开。
.PHONY:all goal_A = hello mid_A = $(goal_A) world goal_A = test goal_B := hello mid_B := $(goal_B) world goal_B := test all: @echo "mid_A = $(mid_A),mid_B= $(mid_B)"
运行make命令 ,打印如下
mid_A = test world,mid_B= hello world
3.3 变量条件赋值
用“?=”操作符来定义,如果变量没有被定义,将右边的值赋值给它,如果变量已经定义了,则不改变其原值。
.PHONY:all funA = original funA ?= replacement funB ?= replacement all: @echo "funA = $(funA),funB = $(funB)"
运行make命令 ,打印如下
funA = original,funB = replacement
3.4 变量追加赋值
通过“+=”实现追加赋值
.PHONY:all objects = main.o fun.o objects += append.o all: @echo "objects = $(objects)"
运行make命令 ,打印如下
objects = main.o fun.o append.o
3.5 高级变量引用功能
在赋值的同时,完成文件名后缀替换操作
.PHONY:all src = a.c b.c c.c objs := $(src:.c=.o) all: @echo "objs = $(objs)"
运行make命令 ,打印如下
objs = a.o b.o c.o
注意,src:.c=.o 冒号后面不能有空格,如果加了空格变成src: .c=.o ,运行make,打印的结果如下
objs = a.c b.c c.c
4、模式规则
一个模式规则的格式为:
%.o : %.c command...
我们利用模式规则对第二版的Makefile进行优化
第三版Makefile
#替换掉这部分 #main.o : main.c # gcc -o $@ -c $^ #fun.o : fun.c # gcc -o $@ -c $^ .PHONY:clean all: main.o fun.o gcc -o app $^ %.o : %.c gcc -o $@ -c $^ clean: rm app main.o fun.o
这里将两条构建目标文件的规则变成了一条
" % " 类似于通配符,%.c匹配所有以".c "结尾的文件,采用了模式以后,不管有多少个源文件,都可以用同一条规则,可以极大的简化Makefile
5、利用变量和模式规则优化Makefile
我们再对第三版的Makefile进行优化,将编译器,目标等都用变量替代,这样以后修改只需要改动变量部分就好了
第四版Makefile
.PHONY:clean CC = gcc RM = rm TARGET = app OBJS = main.o fun.o $(TARGET) : $(OBJS) $(CC) -o $@ $^ %.o : %.c $(CC) -o $@ -c $^ clean: $(RM) $(TARGET) $(OBJS)
到这里,Makefile已经得到了很大的改善,但是我们可以看到OBJS = xxxx 这里,如果文件数量多,得一个个书写,还是不够智能。
下一篇文章,将介绍Makefile函数的使用,利用函数可以轻松管理好源文件和目标文件。
码字不易,点个赞再走吧!
欢迎关注我的同名公众号,这里有更多好料等着你哦!
这篇关于轻松玩转makefile | 变量与模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-22程序员出海做 AI 工具:如何用 similarweb 找到最佳流量渠道?
- 2024-12-20自建AI入门:生成模型介绍——GAN和VAE浅析
- 2024-12-20游戏引擎的进化史——从手工编码到超真实画面和人工智能
- 2024-12-20利用大型语言模型构建文本中的知识图谱:从文本到结构化数据的转换指南
- 2024-12-20揭秘百年人工智能:从深度学习到可解释AI
- 2024-12-20复杂RAG(检索增强生成)的入门介绍
- 2024-12-20基于大型语言模型的积木堆叠任务研究
- 2024-12-20从原型到生产:提升大型语言模型准确性的实战经验
- 2024-12-20啥是大模型1
- 2024-12-20英特尔的 Lunar Lake 计划:一场未竟的承诺