
枫亭湖区个人主页个人专栏《C知识分享》 《Linux 入门到实践零基础也能懂》 有善始者实繁能克终者盖寡索引与导读前言一、make是一条命令makefile是一个文件二、最初始的Makefile1Makefile的基本机构1.1 编译规则目标的生成逻辑1.2 伪目标管理清理逻辑2实际操作演示3核心用法三、深入理解Makefile1基本语法格式2深入理解依赖关系与推导入栈与出栈最佳实践3伪目标解释伪目标总是被执行思考make如何知道源文件是否被重新编译四、进阶用法变量与函数1变量定义与使用2常用函数简化文件列表2.1 wildcard获取指定模式的文件2.2 替换文件后缀3自动变量简化命令详细讲解工程化示例多源文件适配简化 Makefile/makefile1. 核心作用自动化编译与管理2. 代码逻辑大揭秘3. 你可以怎么使用它结尾— 核心连接协议前言在实际的Linux项目开发中随着源文件数量的增加手动使用gcc/g逐个编译不仅效率低下且极易出错 为了实现工程化的管理make工具与Makefile文件应运而生 它定义了一套完整的编译规则和依赖体系能够自动识别哪些文件已被修改从而实现“按需编译”极大提升了构建效率本文将深入浅出地拆解Makefile的核心语法、变量使用以及隐式规则带你从零搭建一套工业级的自动化构建系统彻底告别繁琐的重复劳动一、make是一条命令makefile是一个文件一个工程中的源文件不计数其按类型、功能、模块分别放在若干个目录中makefile定义了一系列的规则来指定哪些文件需要先编译哪些文件需要后编译哪些文件需要重新编译甚至于进行更复杂的功能操作makefile带来的好处就是——“自动化编译”一旦写好只需要一个make命令整个工程完全自动编译极大的提高了软件开发的效率 。所以会不会写makefile从一个侧面说明了一个人是否具备完成大型工程的能力makefile带来的好处就是——“自动化编译”一旦写好只需要一个make命令整个工程完全自动编译极大的提高了软件开发的效率make是一个命令工具是一个解释makefile中指令的命令工具一般来说大多数的IDE都有这个命令比如Delphi的makeVisual C的nmakeLinux下GNU的make可见makefile都成为了一种在工程方面的编译方法二、最初始的Makefile假设项目只有一个源文件hello.c要生成可执行文件并支持清理编译产物1Makefile的基本机构一个典型的Makefile由一系列规则组成每一条规则的基本格式如下1.1 编译规则目标的生成逻辑code: code.c gcc -o code code.c关键语法规则目标: 你想要生成的文件名通常是可执行文件或目标文件.o依赖: 生成目标所需要的源文件.c、.h等命令: 生成目标所需要执行的具体操作注意命令前必须有一个TAB键不能使用空格1.2 伪目标管理清理逻辑.PHONY: clean clean: rm -f code.PHONY: clean这是一个非常重要的指令它告诉makeclean只是一个任务名称标签而不是一个真实存在的文件名 如果不加这一行如果你的目录下恰好有一个名为clean的文件make clean就可能不会执行clean这是目标名称 当你运行make clean时就会触发这里的逻辑rm -f coderm是删除命令-f的作用是强制删除 即使code文件已经被删除了make clean也不会报错而是直接忽略2实际操作演示fthqfthq-virtual-machine:~/Linux_test$vimMakefile fthqfthq-virtual-machine:~/Linux_test$makegcc-ohello hello.c fthqfthq-virtual-machine:~/Linux_test$ ll 总计880drwxrwxr-x2fthq fthq40965月1921:29 ./ drwxr-x---18fthq fthq40965月1921:29../ -rwxrwxr-x1fthq fthq159605月1921:29 hello* -rw-rw-r--1fthq fthq695月1723:43 hello.c -rwxrwxr-x1fthq fthq159605月1822:20 hello_dynamic* -rwxrwxr-x1fthq fthq159605月1819:03 hello.exe* -rwxrwxr-x1fthq fthq159605月1819:05 hello.exe1* -rw-rw-r--1fthq fthq213015月1723:53 hello.i -rw-rw-r--1fthq fthq14975月1818:59 hello.o -rw-rw-r--1fthq fthq6665月1818:56 hello.s -rwxrwxr-x1fthq fthq7853605月1822:08 hello_static* -rw-rw-r--1fthq fthq695月1921:29 Makefile fthqfthq-virtual-machine:~/Linux_test$ ./hello Hello world fthqfthq-virtual-machine:~/Linux_test$makecleanrm-fhello fthqfthq-virtual-machine:~/Linux_test$ ll 总计864drwxrwxr-x2fthq fthq40965月1921:33 ./ drwxr-x---18fthq fthq40965月1921:29../ -rw-rw-r--1fthq fthq695月1723:43 hello.c -rwxrwxr-x1fthq fthq159605月1822:20 hello_dynamic* -rwxrwxr-x1fthq fthq159605月1819:03 hello.exe* -rwxrwxr-x1fthq fthq159605月1819:05 hello.exe1* -rw-rw-r--1fthq fthq213015月1723:53 hello.i -rw-rw-r--1fthq fthq14975月1818:59 hello.o -rw-rw-r--1fthq fthq6665月1818:56 hello.s -rwxrwxr-x1fthq fthq7853605月1822:08 hello_static* -rw-rw-r--1fthq fthq695月1921:29 Makefile3核心用法编译项目在Makefile所在目录执行make自动查找第一个目标code检查依赖是否更新执行编译命令清理项目执行make clean执行clean目标下的命令删除可执行文件增量编译修改code.c后再次执行make只会重新编译修改后的文件而非全部重编三、深入理解Makefile1基本语法格式目标:依赖 命令1 命令2...目标可以是可执行文件、目标文件.o、伪目标如clean依赖可以是源文件、目标文件、其他目标命令必须以Tab 键开头不能用空格否则make会报错注释以#开头单行有效2深入理解依赖关系与推导入栈与出栈makefile会默认形成第一个自己遇到的目标文件Makefilecode: code.o gcc code.o -o code code.o: code.s gcc -c code.s -o code.o code.s: code.i gcc -S code.i -o code.s code.i: code.c gcc -E code.c -o code.i入栈顺序出栈顺序最佳实践# 最终目标可执行文件code.exe依赖code.ocode.exe: code.o gcc code.o-ocode.exe# 目标文件code.o依赖code.ccode.o: code.c gcc-ccode.c-ocode.o# 伪目标clean.PHONY: clean clean:rm-fcode.exe code.o3伪目标伪目标不是实际文件而是一个 “命令标签”如clean作用: 避免项目中存在与伪目标同名的文件导致make误判为“目标已存在无需执行”语法:.PHONY: 伪目标名例如.PHONY: clean确保make clean总是执行命令解释伪目标总是被执行思考make如何知道源文件是否被重新编译这里给一个结论只要源文件的Modify时间比可执行文件时间新就可以重新编译接下来会解释原因文件 内容 属性属性改变了内容没变——创建时间就会改变内容改变了——变更时间改变创建时间也会改变因为文件内容的改变会影响文件的属性比如文件大小等注意当我们touch 文件名可以更新文件的所有时间四、进阶用法变量与函数随着项目源文件数量的增长手动配置依赖关系和编译指令的效率较低。利用Makefile的变量与函数功能可大幅简化配置并提升代码复用性1变量定义与使用变量本质上是文本替换。在 Makefile 中变量名通常使用大写字母语法变量名值使用时需要使用$(变量名) 或 ${变量名}# 定义变量编译器、可执行文件名、目标文件列表、清理命令CCgcc# 给编译器 gcc 起个名字叫 CCBINmyproc# 给生成的程序名字叫 myprocRMrm-f# 给删除文件的命令起个名字叫 RMCFLAGS-Wall-g# 编译参数-Wall显示所有警告-g生成调试信息# 最终目标依赖OBJ变量$(BIN):$(OBJ)$(CC)$(CFLAGS)-o$(BIN)$(OBJ)当make执行时$(CC)变成了gcc编译器名称$(CFLAGS)变成了-Wall -g编译选项-o是一个参数固定写法表示“输出到…”$(BIN)变成了myproc你最终想要的可执行文件名$(OBJ)变成了myproc.o你要参与链接的零件文件# 目标文件依赖源文件可省略make自动推导myproc.o: myproc.c# 清理伪目标.PHONY: clean clean:$(RM)$(BIN)$(OBJ)2常用函数简化文件列表Makefile提供内置函数可自动获取文件列表无需手动罗列2.1 wildcard获取指定模式的文件# 获取当前目录下所有.c文件存入SRC变量SRC$(wildcard *.c)2.2 替换文件后缀# 将SRC中的.c文件替换为.o文件存入OBJ变量Obj$(Src:.c.o)3自动变量简化命令Makefile提供自动变量替代命令中重复出现的目标和依赖简化书写自动变量含义示例$当前目标文件名$(CC) -o $$^所有不重复的依赖文件$(CC) -o $$第一个依赖文件名$(CC) -c $ -o $详细讲解# 定义编译器和基础参数CCgcc CFLAGS-Wall# 定义目标文件名TARGETmy_program# 定义依赖文件列表OBJSmain.o math_tools.o# 编译总规则$(TARGET):$(OBJS)$(CC)$^-o$# 编译单个文件的规则%.o: %.c$(CC)$(CFLAGS)-c$-o$A.$目标文件规则行$(TARGET): $(OBJS)具体动作gcc main.o math_tools.o -o my_program这里的$自动变成了my_program作用它确保了输出的文件名永远和你规则里定义的左侧目标名一致 如果你想把程序名改掉只需改TARGET一行下面的命令完全不用动B.$^所有依赖规则行$(CC) $^ -o $具体动作gcc main.o math_tools.o -o my_program这里的$^自动变成了main.o math_tools.o作用它把冒号右边的所有文件OBJS全部罗列出来传给gcc如果有10个依赖文件写$^比手动一个一个写要省事得多也绝不会漏掉文件C.$第一个依赖规则行$(CC) $(CFLAGS) -c $ -o $具体动作当make处理main.o时它会自动展开为gcc -Wall -c main.c -o main.o这里的$自动变成了main.c作用这是编译过程最精妙的地方 对于每个.o文件它只需要“第一个”对应的.c原材料$自动抓取当前任务对应的那个源文件让这一行通用的规则可以处理项目中成百上千个不同的.c文件工程化示例多源文件适配简化 Makefile/makefile假设项目有多个源文件Makefile可自动适配简化后的Makefile如下所示Bincode.exe# 定义变量#Src$(shell ls *.c) # 做法1 -- 采用shell命令行方式,获取当前所有.c文件名Src$(wildcard *.c)# 做法2 -- 使用 wildcard 函数,获取当前所有.c文件名Obj$(Src:.c.o)# 将Src的所有同名 .c 替换成 .o 形成目标文件列表EchoechoccgccRmrm-fFlags-c-Wall# 编译选项LD_Flags-o# 链接选项$(Bin):$(Obj)$(Echo)我要开始链接了...$(Obj)-$(Bin)# $: 代表目标文件名 $^: 代表依赖文件列表$(cc)$(LD_Flags)$$^ %.o:%.c# %.c: 展开当前目录下的所有.c %.o: 同时展开同名.o$(Echo)我要开始编译了...$ -$# : 不回显命令$(cc)$(Flags)$# %: 对展开的依赖.c文件一个个的交给gcc.PHONY:clean clean:$(Rm)$(Obj)$(Bin)# $(RM): 替换,用变量内容替换它.PHONY:debug debug: $(Echo)Bin:$(Bin)$(Echo)Obj:$(Obj)$(Echo)Src:$(Src)~这是一个非常标准且高质量的Makefile文件1. 核心作用自动化编译与管理这个Makefile的主要任务是自动发现文件它通过wildcard函数自动扫描目录下所有的.c文件无论你增加了多少个源文件它都能自动识别分步构建先编译将每个.c变成.o目标文件再链接将所有的.o文件组装成最终的可执行程序code.exe方便清理通过make clean指令一键删除所有产生的临时文件保持目录整洁2. 代码逻辑大揭秘模块代码片段逻辑解释定义变量Bin,Src,Obj给项目配置“起名字”方便修改 比如把gcc改成clang只要改cc变量链接动作$(Bin): $(Obj)这是最终目标 告诉计算机要生成code.exe必须先有所有的.o文件编译动作%.o: %.c这是自动化编译规则%是通配符表示无论你有多少个文件它都会一个个地处理清理伪目标.PHONY: clean这是一个安全机制 防止目录下正好有个真实文件叫clean而导致指令失效调试信息debug:这是一个自检工具 你执行make debug就能在屏幕上看到Makefile当前识别到的所有文件名非常适合排错3. 你可以怎么使用它假设这个文件名为Makefile把它放在你的代码目录下在终端里执行以下命令make直接开始编译它会自动识别所有的.c文件并生成code.exemake clean彻底清理目录删除所有生成的.o和code.exe让目录变回最初的状态make debug查看当前Makefile到底获取到了哪些文件名确认配置是否正确结尾— 核心连接协议警告正在接入底层技术矩阵。如果你已成功破解学习中的逻辑断层请执行以下指令序列以同步数据【】 建立深度链接关注本终端。在赛博丛林中深耕底层架构从原始代码到进阶协议同步见证每一次系统升级。【⚡】 能量过载分发执行点赞操作。通过高带宽分发让优质模组在信息流中高亮显示赋予知识跨维度的传播力。【】 离线缓存核心将本页加入收藏。把这些高频实战逻辑存入你的离线存储器在遭遇系统崩溃或需要离线检索时实现瞬时读取。【】 协议加密解密在评论区留下你的散列码。分享你曾遭遇的代码冲突或系统漏洞那些年踩过的坑通过交互式编译共同绕过技术陷阱。【️】 信号频率投票通过投票发射你的选择。你的每一次点击都在重新定义矩阵的进化方向决定下一个被全量拆解的技术节点。