Makfile总结
在前面的三篇文章彻底掌握Makefile(一)、彻底掌握Makefile(二)和彻底掌握Makeifle(三)当中我们仔细介绍了Makefile各种使用方法,在本篇文章当中主要是对前面三篇关于makefile的文章做一个总结,方便大家快速查阅和检查。
Makefile基础以及小技巧
Make命令的工作流程
当我们在命令行当中输入make
的时候他的执行流程如下:
- make命令首先会在当前目录下面寻找makefile或者Makefile文件。
- 寻找到makefile文件之后,他会在文件当中寻找到一个编译目标,比如在上面的makefile文件当中他会找到
demo
这个编译目标,而不是clean
这个目标,因为clean
是第二个编译目标。
- 然后make会解析编译目标的依赖,如果这个依赖是其他的编译目标A的话,那么make会先完成它依赖的编译目标A的命令,如果它依赖的编译目标A也存在依赖B的话,make就会去执行依赖的B的编译命令,如此的递归下去,知道有所得依赖目标都存在了,才会完成第一个编译目标的编译,这个也很好理解,只有依赖文件都存在了我们才能够完成正确的编译过程。
Makefile当中的小技巧
| main: demo.o myprint.o |
| gcc demo.o myprint.o -o out |
| echo make 解析编译完成 |
| |
| demo.o: demo.c |
| gcc -c demo.c -o demo.o |
| |
| myprint.o: myprint.c |
| gcc -c myprint.c -o myprint.o |
| |
| clean: |
| rm myprint.o demo.o out |
| cflags=-c |
| main: demo.o myprint.o |
| gcc demo.o myprint.o -o out |
| |
| demo.o: demo.c |
| gcc $(cflags) demo.c -o demo.o |
| |
| myprint.o: myprint.c |
| gcc $(cflags) myprint.c -o myprint.o |
| |
| clean: |
| rm myprint.o demo.o out |
| include submakefile |
| |
| demo.o: demo.c |
| gcc $(cflags) demo.c -o demo.o |
| |
| myprint.o: myprint.c |
| gcc $(cflags) myprint.c -o myprint.o |
| |
| clean: |
| rm myprint.o demo.o out |
| cflags=-c |
| main: demo.o myprint.o |
| gcc demo.o myprint.o -o main |
| |
| demo.o: demo.c |
| gcc $(cflags) demo.c -o demo.o |
| |
| myprint.o: myprint.c |
| gcc $(cflags) myprint.c -o myprint.o |
| |
| clean: |
| rm myprint.o demo.o main |
| .PHONY: clean # 增加这一行 |
| cflags=-c |
| |
| main: demo.o myprint.o |
| gcc demo.o myprint.o -o main |
| |
| %.o: %.c |
| gcc $(cflags) $< |
| clean: |
| rm myprint.o demo.o main |
| .PHONY: clean |
| cflags=-c |
| |
| VPATH=./files |
| |
| main: demo.o myprint.o a.o b.o |
| gcc demo.o myprint.o a.o b.o -o main |
| |
| demo.o:demo.c |
| gcc $(cflags) demo.c |
| |
| myprint.o:myprint.c |
| gcc $(cflags) myprint.c |
| |
| a.o: a.c |
| gcc $(cflags) $< |
| b.o: b.c |
| gcc $(cflags) $< |
| |
| clean: |
| rm myprint.o demo.o main |
| .PHONY: clean |
有时候在makefile当中我们不想输出某些命令(如果不进行设置makefile会输出每一条我们执行过的命令),我们就可以使用@符号进行修饰。
| main: demo.c |
| @echo hello world |
- override覆盖命令行的赋值,让makefile文件当中的变量覆盖命令行当中的变量。
Makefile当中进行if判断
ifeq 和 ifneq
主要是用于判断字符是否相等。
| cc=g++ |
| |
| main: demo.c |
| echo $(cc) |
| |
| ifeq ($(cc), gcc) |
| echo $(cc) = 相等的语句执行了 |
| else |
| echo $(cc) != 不相等的语句执行了 |
| endif |
| cc=g++ |
| |
| main: demo.c |
| echo $(cc) |
| |
| ifneq ($(cc), gcc) |
| echo $(cc) != gcc |
| else |
| echo $(cc) = gcc |
| endif |
ifdef 和 ifndef
判断变量是否被定义或者为空
| foo = 1 |
| main: demo.c |
| echo demo |
| ifdef foo |
| echo define foo |
| else |
| echo not define foo |
| endif |
| main: demo.c |
| echo demo |
| ifdef foo |
| echo define foo |
| else |
| echo not define foo |
| endif |
Makefile当中的函数
在makefile当中除了能够使用条件表达式之外我们还可以使用函数,在makefile当中函数的使用规则如下:
| $(<函数名> <函数参数>) |
| 或者 |
| 将()替换为{} |
函数的调用规则如上图所示,函数参数用.隔开。
字符串函数
subst
| $(subst <from>,<to>,<text>) |
- 字符串替换函数。
- 表示文本,这个函数会将text当中是的字符串替换为。
| s = ii am learning makefile |
| ss = $(subst ii, you, $(s)) |
| |
| main: demo.c |
| echo demo |
| echo $(s) |
| echo $(ss) |
patsubst
| $(patsubst <pattern>,<replacement>,<text>) |
- pattern 表示第一个参数,用于表示如何对 text 进行匹配。
- replacement 表示第二个参数 表示如何对匹配的字符进行重写。
- patsubst在进行匹配替换的时候,会先将字符串text根据空格或者tab键或者回车换行符进行分割,然后一一的进行替换和匹配。
| s = a.c b.c d.c abc.c abo.c |
| ss = $(patsubst %.c, %.o, $(s)) |
| |
| main: demo.c |
| echo demo |
| echo $(s) |
| echo $(ss) |
Strip
主要功能去掉字符串 string 首尾的空格。
findstring
| $(findstring <find>,<text>) |
这个函数的作用是从字符串当中寻找字符串,如果找到了字符串就返回字符串,否则返回空。
filter
| $(filter <pattern...>,<text>) |
这是一个过滤函数,这个函数执行时,首先会根据空格或者tab键或者回车换行符进行分割,然后一一的进行filter函数的操作。然后遍历每一个被分割出来的字符,如果不满足pattern的规则的话对应的字符就会被过滤掉。
| s = a.c abo.c s.o s.y x.o x.y |
| ss = $(filter %.c %.o, $(s)) |
| |
| main: demo.c |
| echo $(ss) |
filter-out
这个函数和filter的用法是一样的只不过,作用刚好相反,filter是保存符合条件的字符串,filter-out是保存不符合条件的字符串。
| s = a.c abo.c s.o s.y x.o x.y |
| ss = $(filter-out %.c %.o, $(s)) |
| |
| main: demo.c |
| echo $(ss) |
sort
这个函数主要是用于帮助字符串排序的,同时还会取出分割之后相同的字符串。
| s = g a b c d e f a a a a |
| ss = $(sort $(s)) |
| |
| main: demo.c |
| echo $(ss) |
word
这个功能很简单,返回当中第个字符。
| s = g a b c d e f a a a a |
| ss = $(word 1, $(s)) |
| |
| main: demo.c |
| echo $(ss) |
wordlist
| $(wordlist <start>,<end>,<text>) |
这个也是从字符串当中取出字符,是取出第个字符一直到第个字符。
| s = g a b c d e f a a a a |
| ss = $(wordlist 1, 5, $(s)) |
| |
| main: demo.c |
| echo $(ss) |
words
统计单词的个数。
| s = 1 2 3 4 5 |
| ss = $(words $(s)) |
| |
| main: demo.c |
| echo $(ss) |
firstword
这个函数主要是用于返回第一个字符串的。
| s = 1 2 3 4 5 |
| ss = $(firstword $(s)) |
| |
| main: demo.c |
| echo $(ss) |
文件函数
dir与notdir函数
dir函数主要书获取文件路径当中的目录部分,而notdir函数主要是获取文件路径当中文件名的部分
| file = ./files/a.c |
| fdir = $(dir $(file)) |
| nfdir = $(notdir $(file)) |
| |
| main: demo.c |
| echo $(fdir) |
| echo $(nfdir) |
suffix函数
这个函数主要是用于获取文件的后缀名。
| file = ./files/a.c |
| fdir = $(dir $(file)) |
| nfdir = $(notdir $(file)) |
| name = $(suffix $(file)) |
| main: demo.c |
| echo $(fdir) |
| echo $(nfdir) |
| echo $(name) |
basename
这个函数用于获取文件路径当中除去后缀名的部分。
| file = ./files/a.c |
| base = $(basename $(file)) |
| main: demo.c |
| echo $(base) |
addsuffix
这个函数主要是给文件加上后缀的。
| file = ./files/a.c |
| base = $(addsuffix .c, $(file)) |
| main: demo.c |
| echo $(base) |
addprefix
这个函数的主要作用就是在字符串的前面加上一串字符。
| file = files/a.c |
| base = $(addprefix ./src/main/, $(file)) |
| main: demo.c |
| echo $(base) |
其他函数
循环函数foreach
foreach
函数的主要使用规则为:
| $(foreach <var>,<list>,<text>) |
我们直接使用一个例子来说明这个情况:
| files = a.c b.c c.c d.c |
| new_files = $(foreach n, $(files), $(n)pp) |
| main: demo.c |
| echo $(new_files) |
call函数
call函数在makefile当中可以用于调用我们自定义的一个表达式,他的语法个数如下面所示:
| $(call <expression>,<parm1>,<parm2>,...,<parmn>) |
- 表示定义的表达式的名字。
- 表示第n个参数,我们在当中可以使用
$(n)
进行引用。
| a=a.c |
| b=b.c |
| c=$(a)-------$(b) |
| main: demo.c |
| echo $(c) |
在makefile当中使用shell函数
我们在makefile的表达式当中可以使用shell的函数。
比如现在我们有一个文件叫做test.txt
,文件的内容如下所示:
| content=$(shell cat test.txt) |
| |
| main: demo.c |
| echo $(content) |
origin函数
origin这个函数主要是返回变量的定义方式,使用格式如下:
error函数
在makefile当中我们可以使用error函数让makefie停止执行。当我们有需求:让在某种条件下让makefile停止编译
| data=data |
| |
| ifeq ($(data), data) |
| $(error "data == data") |
| endif |
| |
| main: main.c |
| gcc main.c |
除此之外还有个warning函数使用方法和error一样!
总结
在本篇文章当中主要给大家总结了一些常见的makefile的使用方法,方便大家查阅复习!
以上就是本篇文章的所有内容了,我是LeHung,我们下期再见!!!更多精彩内容合集可访问项目:https://github.com/Chang-LeHung/CSCore
关注公众号:一无是处的研究僧,了解更多计算机(Java、Python、计算机系统基础、算法与数据结构)知识。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构