### 跟我一起写Makefile #### 概述与背景 Makefile 是 Linux 和 Unix 系统中用于管理软件构建过程的一种脚本文件。它通过定义一系列规则来描述如何生成程序的不同部分,并且能够自动处理文件之间的依赖关系,极大地简化了软件项目的编译和链接流程。 #### 关于程序的编译和链接 编译和链接是软件开发过程中不可或缺的两个步骤。编译是指将源代码转换为机器可理解的目标代码的过程;而链接则是将多个目标文件连接成一个可执行文件的过程。在复杂项目中,手动管理这些步骤会变得异常困难。Makefile 的出现就是为了自动化这一系列任务,使开发者能够专注于代码本身而非繁琐的构建过程。 #### Makefile介绍 **一、Makefile的规则** Makefile 规则通常由目标(target)、依赖(dependencies)和命令(commands)组成。目标是指要构建的对象,依赖是指构建目标所需要的其他对象,而命令则是用来说明如何构建目标的具体步骤。 **二、一个示例** 一个简单的 Makefile 示例可能如下所示: ```makefile # 编译和链接程序 my_program: main.o helper.o gcc -o my_program main.o helper.o # 编译单独的源文件 %.o: %.c gcc -c -o $@ $< ``` **三、make是如何工作的** 当 make 被调用时,它会读取 Makefile 文件中的规则并解析依赖关系。接着,make 会根据依赖关系确定哪些文件需要被重新构建,并按照 Makefile 中定义的命令执行相应的构建操作。 **四、makefile中使用变量** 变量可以用来存储常用的路径、文件名或其他值,使得 Makefile 更加灵活和易于维护。 ```makefile CC = gcc CFLAGS = -Wall -g PROGRAM = my_program SOURCES = $(wildcard *.c) OBJECTS = $(SOURCES:.c=.o) $(PROGRAM): $(OBJECTS) $(CC) $(CFLAGS) -o $@ $^ ``` **五、让make自动推导** 通过使用通配符和模式规则,make 可以自动推导出大部分的构建命令,从而减少显式命令的需求。 **六、另类风格的makefile** 有些项目可能采用不同的 Makefile 风格,例如使用递归调用或者自定义函数等高级特性。 **七、清空目标文件的规则** 清理规则用于删除构建过程中产生的临时文件。 ```makefile .PHONY: clean clean: rm -f $(OBJECTS) $(PROGRAM) ``` #### Makefile总述 **一、Makefile里有什么?** 1. **显式规则**:明确地定义了目标和依赖。 2. **隐晦规则**:也称为隐含规则,make 自动识别并应用的规则。 3. **变量的定义**:存储常用值以简化 Makefile。 4. **文件指示**:用于包含其他文件。 5. **注释**:以 `#` 开头的行,用于添加注释。 **二、Makefile的文件名** 默认情况下,make 会寻找名为 `Makefile` 或 `makefile` 的文件。可以通过 `-f` 参数指定其他文件名。 **三、引用其它的Makefile** 可以使用 `include` 指令来引入其他 Makefile 文件。 **四、环境变量MAKEFILES** 环境变量 MAKEFILES 用于指定 Makefile 的位置。 **五、make的工作方式** make 会读取 Makefile 文件,分析依赖关系,并执行相应的命令来构建目标。 #### 书写规则 **一、规则举例** 规则是 Makefile 的核心组成部分,用于描述构建过程中的各个步骤。 **二、规则的语法** 每个规则都由目标、依赖项列表和一组命令组成。 **三、在规则中使用通配符** 通配符如 `*` 和 `?` 可以帮助简化规则。 **四、文件搜寻** 当目标文件未找到时,make 会在当前目录和其他指定目录中搜索。 **五、伪目标** 伪目标(如 `clean` 和 `all`)没有实际对应的文件,但可以触发特定的操作。 **六、多目标** 可以为单个目标定义多个规则。 **七、静态模式** 静态模式规则允许使用模式匹配来自动推导命令。 **八、自动生成依赖性** 某些工具(如 GCC)可以生成依赖性信息,这有助于 make 自动更新依赖关系。 #### 书写命令 **一、显示命令** 显示命令可以让用户看到正在执行的操作。 **二、命令执行** 命令通过 shell 执行。 **三、命令出错** 当命令执行失败时,make 会停止执行后续命令。 **四、嵌套执行make** 可以在 Makefile 中调用 make 来处理子目录中的构建过程。 **五、定义命令包** 可以将一组相关的命令封装在一个函数中,以便重复使用。 #### 使用变量 **一、变量的基础** 变量可以存储文本字符串、文件名、路径等信息。 **二、变量中的变量** 可以在变量定义中引用其他变量。 **三、变量高级用法** 包括变量覆盖、多行变量等。 **四、追加变量值** 可以在变量的末尾添加额外的值。 **五、override指示符** 用于在命令行上覆盖 Makefile 中的变量值。 **六、多行变量** 变量可以跨越多行定义。 **七、环境变量** 可以使用外部环境变量来影响 Makefile 的行为。 **八、目标变量** 特定于目标的变量,可以为不同的目标设置不同的值。 **九、模式变量** 基于目标名称的模式匹配来设置变量值。 #### 使用条件判断 **一、示例** 使用 `ifeq`、`ifdef` 等指令进行条件判断。 **二、语法** 条件结构的语法类似于其他编程语言。 #### 使用函数 **一、函数的调用语法** make 支持多种内置函数,用于处理字符串、文件名等。 **二、字符串处理函数** - `subst`:替换字符串。 - `patsubst`:模式替换。 - `strip`:去除空白字符。 - `findstring`:查找子字符串。 - `filter`:筛选符合特定模式的元素。 - `filter-out`:排除不符合特定模式的元素。 - `sort`:排序字符串列表。 - `word`:获取列表中的单词。 - `wordlist`:获取列表中的一部分单词。 - `words`:计算单词数量。 - `firstword`:获取列表中的第一个单词。 **三、文件名操作函数** - `dir`:获取目录名。 - `notdir`:获取非目录名。 - `suffix`:获取文件扩展名。 - `basename`:获取文件的基本名。 - `addsuffix`:向字符串添加后缀。 - `addprefix`:向字符串添加前缀。 - `join`:合并两个字符串列表。 **四、foreach函数** 用于遍历列表。 **五、if函数** 用于条件判断。 **六、call函数** 用于调用其他函数。 **七、origin函数** 查询变量的来源。 **八、shell函数** 在 make 中执行 shell 命令。 **九、控制make的函数** - `error`:打印错误消息并终止 make 运行。 - `warning`:打印警告消息但继续 make 运行。 #### make的运行 **一、make的退出码** make 的退出码用于指示执行状态。 **二、指定Makefile** 可以通过 `-f` 参数指定 Makefile 文件。 **三、指定目标** 可以指定特定的目标来构建。 **四、检查规则** 检查规则的有效性。 **五、make的参数** 传递给 make 的参数会影响其行为。 #### 隐含规则 **一、使用隐含规则** make 支持一系列默认的隐含规则,可以自动处理常见文件类型的构建。 **二、隐含规则一览** 包括 C/C++、Pascal、Fortran 等语言的编译规则。 **三、隐含规则使用的变量** 用于控制隐含规则行为的变量。 **四、隐含规则链** 隐含规则可以按顺序链接在一起,形成复杂的构建过程。 **五、定义模式规则** 模式规则允许更细粒度的控制。 **六、老式风格的"后缀规则"** 后缀规则是一种旧式的隐含规则风格。 **七、隐含规则搜索算法** make 在构建过程中如何选择适当的隐含规则。 #### 使用make更新函数库文件 **一、函数库文件的成员** 函数库文件通常包含多个目标文件。 **二、函数库成员的隐含规则** make 支持自动构建函数库文件的成员。 **三、函数库文件** 如何使用 make 构建和管理函数库文件。 以上内容涵盖了从 Makefile 的基本概念到高级功能,旨在帮助开发者更好地理解和使用 Makefile,提高软件构建的效率和自动化程度。
剩余77页未读,继续阅读
- 粉丝: 1
- 资源: 31
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
评论0