快速到达Makefile介绍Makefile核心语法基本规则Makefile执行过程Makefile中的变量常用变量惯例Makefile中的变量三种变量类型对比Makefile中的函数wildcard函数获取匹配的文件列表patsubst函数模式替换函数Makefile介绍Makefile 是一个用于自动化构建和管理项目的文本文件由目标target、依赖prerequisites、命令commands构成这些元素共同组成“规则”make 工具负责读取并解析 Makefile 文件按照其中定义的规则执行项目构建操作作用自动化编译通过检测文件修改时间戳仅重新编译发生变化的文件及其依赖文件避免重复编译未改动部分提升编译效率依赖管理清晰定义文件间的依赖关系明确源文件、头文件和目标文件等之间的关联确保项目构建顺序正确流程规范统一项目的构建命令和流程使得项目构建过程标准化便于团队协作开发和项目维护需要Makefile原因手动输入编译命令不仅繁琐复杂容易出错而且当项目规模扩大源文件和头文件数量增多时手动管理编译程序和依赖关系会耗费大量时间和精力。而Makefile能够只能判断文件变化实现增量编译极大提高编译效率规范项目管理流程是项目构建更加有序。Makefile 与 make 工具的关系make 工具作为解释器读取和解析 Makefile 文件中的规则它根据文件的时间戳判断是否需要重新编译从而实现自动化构建。Makefile 则是定义项目构建规则和流程的脚本两者紧密配合完成项目的自动化构建任务。使用场景多文件项目开发当项目包含多个源文件.c、.cpp等、头文件.h和库文件时手动编译繁琐易错Makefile可通过依赖关系自动管理编译程序增量编译需求仅重新编译修改过的文件及其依赖文件大幅减少编译时间。跨平台构建通过条件判断适配不同操作系统的编译选项、头文件路径和链接库实现跨平台项目的统一构建复杂项目分层管理支持递归构建子目录如内核模块、第三方库配合伪目标实现统一的构建make all和清理make clean操作方便管理复杂项目的各个模块。Makefile核心语法基本规则格式目标(target):依赖(prerequisites)必须按下tab键命令(commands)说明目标可以是要生成的文件如可执行文件 app 或目标文件 main.o也可以是伪目标如clean伪目标不是真实的文件用于执行特定的操作如清理生成的文件声明伪目标时需通过 .PHONY 关键字显式标记避免因同名文件存在而导致目标失效依赖生成目标所需的文件列表可以是源文件、头文件或其他目标。目标的更新依赖于依赖文件的变化即当依赖文件的修改时间比目标文件新时目标需要重新生成命令生成目标的具体操作如编译命令gcc -c main.c每条命令单独一行且必须以 Tab 键缩进(不能用空格代替),在命令前添加 符号可禁止命令本身的回显仅显示执行结果用于提升输出可读性示例app:main.o utis.ogcc -o app main.o utis.o执行逻辑make 工具通过比较目标与依赖文件的修改时间戳仅当依赖文件比目标 “更新” 时才执行命令重新生成目标实现增量构建。例如如果 main.o 和 utils.o 的修改时间都比 app 旧那么 make工具不会执行链接命令若其中一个或两个依赖文件被修改app 将被重新链接生成。Makefile执行过程Makefile中的变量本质字符串用于存储编译器、编译选项、文件名等信息变量引用$(变量名)小括号不可丢定义方式 延迟赋值当使用此变量时才会对变量进行赋值操作格式变量名 变量的初始值:立即赋值定义时直接展开不支持引用未定义变量格式变量名 : 变量的初始值追加赋值在原有值后添加新字符串用空格分隔格式变量名 变量的初始值?条件赋值判断变量是否有初始值如果有值就不赋值如果没有初始值才会进行赋值的操作格式变量名 ? 变量的初始值常用变量惯例在Makefile中会将一些常用变量定义为大写例变量名说明CC指定C 编译器通常默认值为gcc可重赋值为其他C 编译器路径或名称CFLAGS用于指定C 编译器的编译选项如-Wall开启所有警告、-g生成调试信息等CPPFLAGSC 预处理器的选项例如包含头文件的路径等CXX指定C 编译器默认可能是g同样可修改为其他C 编译器CXXFLAGSC 编译器的编译选项与CFLAGS类似针对C 代码编译OBJS通常用于表示目标文件列表是由源文件编译生成的中间文件LDFLAGS链接器的选项例如指定库文件路径、链接特定的库等LIBS需要链接的库文件列表如-lm链接数学库、-lpthread链接线程库等AR归档器用于创建和维护静态库通常为arARFLAGS归档器的选项用于指定创建静态库的相关参数RM用于指定删除文件的命令通常默认值为rm -f-f选项表示强制删除不提示确认Makefile中的变量变量的类型自定义变量由用户自行定义可灵活设置和修改用于存储项目中的各类信息像源文件路径、目标文件路径、编译选项、链接选项等。在实际使用中通过常见的赋值方式、:、、? 来确定变量值。例如CC : gcc将编译器指定为gcc预定义变量是 Make 工具自身携带的变量具备默认值像CC通常默认指向gcc用于指定 C 编译器用户可以根据实际项目的要求对这些预定义变量进行覆盖以调整构建过程自动化变量(局部变量)在规则的命令中会依据上下文自动获取相应的值$代表当前目标对应的字符串即正在生成的目标文件的名称$^表示所有依赖对应的字符串即依赖的所有文件的列表(会自动去除重复的依赖文件)$指第一个依赖对应的字符串即当前目标的第一个依赖文件三种变量类型对比变量类型定义来源赋值特点作用域典型应用场景自定义变量用户自行定义可通过延迟赋值、:立即赋值、追加赋值、?条件赋值确定值灵活性高全局在Makefile文件中都可访问用于存储项目中自定义信息如源文件路径、自定义编译选项等预定义变量Make工具自带有默认值用户可按需覆盖默认值来调整构建过程全局涉及Make 工具默认行为的设置如指定编译器、链接器等自动化变量无特定用户定义在规则命令中起作用在规则的命令中依据上下文自动获取值仅在当前规则命令内有效仅在规则的命令中有效在规则命令中处理目标文件和依赖文件相关操作如编译、链接Makefile中的函数wildcard函数获取匹配的文件列表功能在当前目录及其子目录中按指定模式“PATTERN”查找并列出所有符合格式的文件名模式“PATTERN”采用 shell 通配符如“*”匹配多个字符等等语法$(wildcard PATTERN)其中PATTERN为文件匹配模式字符串例$(wildcard *.c)返回当前目录下所有.c源文件列表$(wildcard include/*.h)返回include目录下所以.h头文件列表返回值以空格分隔的符合模式 “PATTERN”的文件名列表无匹配文件时返回空字符串应用场景自动收集源文件自动发现目录下的所有源文件避免手动维护文件列表提高项目可扩展性查找条件构建逻辑根据文件是否存在决定构建行为实现灵活的条件编译等等注意事项仅匹配实际存在的文件wildcard 只返回文件系统中真实存在的文件路径无匹配文件时返回空值通配符路径精确性需明确指定搜索目录避免意外匹配其他路径变量与函数结合时需确保变量值正确使用$(info text)打印变量值验证匹配结果patsubst函数模式替换函数功能对指定字符串TEXT中的单词进行模式匹配替换将符合模式PATTERN的部分替换为指定的替换模板REPLACEMENT模式中的“%”代表任意字符序列替换模板中的 “%”会被自动替换为模式中 “%”所匹配的内容语法$(patsubst PATTERN,REPLACEMENT,TEXT)PATTERN包含“%”的匹配模式如%.cREPLACEMENT替换模板如%.oTEXT待处理的字符串通常为文件名列表例$(patsubst %.c,%.o,main.cfunc.c)将字符串 main.c func.c 里所有符合 %.c 模式的单词替换成以 .o 结尾的形式返回值替换后的新字符串原字符串中不符合模式的部分保持不变。若无可匹配项则返回原字符串应用场景源文件与目标文件自动映射将 .c 文件列表转换为 .o 目标文件列表避免手动维护重复的文件名批量修改文件路径或扩展名如将src/目录下的文件映射到build/目录等等注意事项“%”仅匹配完整单词模式替换基于空格分隔的单词而非字符串片段模式与替换模板需严格对应替换模板中的 % 必须与模式中的 % 对应相同内容字面量“%”的转义若需在模式或替换模板中使用字面量%需用 \% 转义