### GNUMake 使用手册知识点详解 #### 一、Make概述 **1.1 怎样阅读本手册** - **目标读者**: 对Linux源代码感兴趣,希望通过深入理解Makefile来掌握Linux编程总体设计与思想的人士。 - **推荐背景**: 具备一定的C/C++编程基础,了解基本的构建流程。 **1.2 问题和BUG** - **反馈渠道**: 通过电子邮件与译者沟通(yfc70@public2.lyptt.ha.cn)。 - **目的**: 改进手册质量,确保翻译准确无误。 #### 二、Makefile文件介绍 **2.1 规则的格式** - **格式**: 指定目标、依赖项和命令。 - **示例**: `target : dependencies\n\tcommand` **2.2 一个简单的Makefile文件** - **基本结构**: 包含至少一个目标、其依赖项和相关的命令。 - **示例**: ``` all: main.o helper.o gcc -o myprogram main.o helper.o ``` **2.3 make处理makefile文件的过程** - **步骤**: 1. **读取**: make从指定文件读取规则。 2. **解析**: 解析makefile中的规则和变量。 3. **执行**: 根据目标文件的状态执行相应的命令。 **2.4 使用变量简化makefile文件** - **作用**: 通过定义变量来重复使用文件名、命令等。 - **示例**: ``` CC=gcc CFLAGS=-Wall all: main.o helper.o $(CC) $(CFLAGS) -o myprogram main.o helper.o ``` **2.5 让make推断命令** - **概念**: make能够根据依赖关系自动推断出所需的命令。 - **优点**: 减少makefile文件的复杂度。 **2.6 另一种风格的makefile文件** - **替代写法**: 使用模式规则和双冒号规则。 - **示例**: ``` .SUFFIXES: .c .o %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ ``` **2.7 在目录中删除文件的规则** - **用途**: 清除编译生成的文件。 - **示例**: ``` clean: rm -f *.o ``` #### 三、编写makefile文件 **3.1 makefile文件的内容** - **关键部分**: 目标、依赖和命令。 - **注意事项**: 文件应清晰地组织这些部分。 **3.2 makfile文件的命名** - **默认名称**: `Makefile` 或 `makefile`。 - **自定义**: 可以通过命令行参数指定其他名称。 **3.3 包含其它的makefile文件** - **方法**: 使用 `-I` 参数指定包含的文件。 - **示例**: `make -I common.mk` **3.4 变量MAKEFILES** - **用途**: 存储所有被包含的makefile文件的名称列表。 **3.5 makefile文件重新生成的过程** - **过程**: 当makefile文件本身也需要重新生成时,make将执行这个过程。 - **触发条件**: makefile文件比其中的某些目标文件旧。 **3.6 重载其它makefile文件** - **功能**: 使make能够在处理当前makefile文件之前先加载其他文件。 - **示例**: `make -f new.mk` **3.7 make读取makefile文件的过程** - **顺序**: 先读取命令行中指定的makefile文件,然后读取默认文件(`Makefile`/`makefile`),最后读取包含的文件。 #### 四、编写规则 **4.1 规则的语法** - **构成要素**: 目标、依赖项和命令。 - **示例**: `target: dependency\n\tcommand` **4.2 在文件名中使用通配符** - **作用**: 通配符允许匹配多个文件。 - **示例**: `*.o` 表示所有扩展名为 `.o` 的文件。 **4.3 在目录中搜寻依赖** - **概念**: make可以在指定目录下查找依赖项。 - **示例**: `VPATH = src include` **4.4 假想目标** - **定义**: 不存在于文件系统中的目标。 - **用途**: 用于标识特殊任务(如 `clean` 或 `install`)。 **4.5 没有命令或依赖的规则** - **概念**: 规则可以仅有目标,没有依赖项或命令。 - **示例**: `target:` 仅指定目标 `target`,但没有依赖项和命令。 **4.6 使用空目标文件记录事件** - **用途**: 创建空文件来记录完成的事件。 - **示例**: `touch done` **4.7 内建的特殊目标名** - **示例**: `all`, `clean`, `install` 等。 - **作用**: 定义了常见的构建任务。 **4.8 具有多个目标的规则** - **概念**: 单个规则可以同时生成多个目标文件。 - **示例**: `obj1.obj obj2.obj: src.c\n\t$(CC) $(CFLAGS) -c src.c -o obj1.obj -o obj2.obj` **4.9 具有多条规则的目标** - **定义**: 同一个目标可以出现在多个规则中。 - **示例**: `main.o: main.c\n\techo "compiling main.c"\nmain.o: main.cpp\n\techo "compiling main.cpp"` **4.10 静态格式规则** - **定义**: 提供了一种创建目标文件的方法,当目标文件名符合一定模式时。 - **示例**: `%.o: %.c\n\t$(CC) $(CFLAGS) -c $< -o $@` **4.11 双冒号规则** - **概念**: 定义一个目标可以有多个更新方法。 - **示例**: `target :: dependency1\n\tcommand1\ntarget :: dependency2\n\tcommand2` **4.12 自动生成依赖** - **概念**: 使用工具如 `gcc` 的 `-MM` 选项来自动生成依赖关系。 - **示例**: `$(shell gcc -MM file.c)` #### 五、在规则中使用命令 **5.1 命令回显** - **概念**: 显示即将执行的命令。 - **作用**: 便于调试和确认。 **5.2 执行命令** - **方法**: 通过 `\t` 开头的行执行。 - **示例**: `echo "Hello, World!"` **5.3 并行执行** - **概念**: 通过 `-j` 参数使make能够并行执行多个命令。 - **示例**: `make -j4` **5.4 命令错误** - **处理**: 当命令执行失败时,默认情况下make会停止后续操作。 - **忽略**: 使用 `-` 符号前缀命令以忽略错误继续执行。 **5.5 中断或关闭make** - **方法**: 使用 `break` 关键字或中断信号(Ctrl+C)。 - **示例**: `makefile: break` **5.6 递归调用make** - **概念**: 在一个makefile中调用另一个makefile。 - **示例**: `subdir: mkdir subdir\n\t(cd subdir && make)` **5.7 定义固定次序命令** - **概念**: 指定命令执行的顺序。 - **示例**: `PHONY := first second\nfirst: echo "first"\nsecond: echo "second"` **5.8 使用空命令** - **概念**: 规则可以不包含任何命令。 - **示例**: `target:` #### 六、使用变量 **6.1 变量引用基础** - **语法**: `$(variable)` 或 `${variable}`。 - **示例**: `CC=gcc\nCFLAGS=-Wall\nall: $(CC) $(CFLAGS) -o prog main.o` **6.2 变量的两个特色** - **展开**: 在makefile文件中展开变量。 - **引用**: 直接使用变量值。 **6.3 变量引用高级技术** - **条件**: 根据条件选择不同的变量值。 - **嵌套**: 在变量定义中引用其他变量。 **6.4 变量取值** - **概念**: 获取变量的当前值。 - **示例**: `$(value variable)` **6.5 设置变量** - **方式**: 直接赋值或使用 `:=`、`?=`、`+=` 运算符。 - **示例**: `CC=gcc\nCFLAGS ?= -Wall` **6.6 为变量值追加文本** - **概念**: 通过 `+=` 运算符向现有变量添加值。 - **示例**: `CFLAGS += -g` **6.7 override指令** - **概念**: 优先使用命令行参数设置的变量值。 - **示例**: `override CC=gcc` **6.8 定义多行变量** - **方法**: 使用反斜杠 `\` 来换行。 - **示例**: `CFLAGS = \n-Wall \n-Wextra` **6.9 环境变量** - **概念**: 从系统环境获取变量。 - **示例**: `$(shell echo $PATH)` **6.10 特定目标变量的值** - **概念**: 为特定目标设置变量值。 - **示例**: `main.o: CFLAGS += -O2` **6.11 特定格式变量的值** - **概念**: 根据目标的格式设置变量值。 - **示例**: `%.o: %.c\n\t$(CC) $(CFLAGS) -c $< -o $@` #### 七、makefile文件的条件语句 **7.1 条件语句的例子** - **示例**: ``` ifdef FOO CFLAGS += -DFOO endif ``` **7.2 条件语句的语法** - **基本结构**: `ifdef variable\n\tcommands\nendif` **7.3 测试标志的条件语句** - **概念**: 根据变量是否已定义来执行不同操作。 - **示例**: `ifeq ($(origin VPATH), undefined)\n\tVPATH = src\nendif` #### 八、文本转换函数 **8.1 函数调用语法** - **示例**: `$(filter-out .o, all.o main.o)` **8.2 字符串替换和分析函数** - **函数**: `subst`, `patsubst`, `findstring`, `strip` 等。 - **示例**: `$(subst -,_, $(notdir $(CURDIR)))` **8.3 文件名函数** - **函数**: `basename`, `dirname`, `notdir`, `suffix` 等。 - **示例**: `$(basename file.c)` **8.4 函数foreach** - **概念**: 对列表中的每个元素执行相同的操作。 - **示例**: `$(foreach var,$(LIST),$(patsubst %.c,%.o,$(var)))` **8.5 函数if** - **概念**: 根据条件执行不同的操作。 - **示例**: `$(if $(findstring x,$(VARIABLE)),true,false)` **8.6 函数call** - **概念**: 调用另一个函数。 - **示例**: `$(call concat,hello,world)` **8.7 函数origin** - **概念**: 返回变量值的来源。 - **示例**: `$(origin VPATH)` **8.8 函数shell** - **概念**: 在shell环境中执行命令。 - **示例**: `$(shell date)` **8.9 控制make的函数** - **函数**: `wildcard`, `error`, `warning`, `info` 等。 - **示例**: `$(wildcard *.c)` #### 九、运行make **9.1 指定makefile文件的参数** - **方法**: 使用 `-f` 或 `--file` 参数。 - **示例**: `make -f custom.mk` **9.2 指定最终目标的参数** - **方法**: 作为make命令的第一个参数。 - **示例**: `make install` **9.3 代替执行命令** - **概念**: 使用 `-s` 参数禁止显示命令。 - **示例**: `make -s` **9.4 避免重新编译文件** - **方法**: 使用 `-k` 参数继续执行即使有错误发生。 - **示例**: `make -k` **9.5 变量重载** - **概念**: 在命令行中重设变量值。 - **示例**: `make CFLAGS=-O3` **9.6 测试编译程序** - **概念**: 使用 `-n` 或 `--just-print` 参数只打印将要执行的命令。 - **示例**: `make -n` **9.7 选项概要** - **列表**: `-h`, `-q`, `-r`, `-w` 等。 - **示例**: `make --help` #### 十、使用隐含规则 **10.1 使用隐含规则** - **概念**: make可以根据文件扩展名自动识别构建规则。 - **示例**: `*.o: *.c` **10.2 隐含规则目录** - **概念**: make会在特定目录搜索隐含规则。 - **示例**: `VPATH = src include` **10.3 隐含规则使用的变量** - **示例**: `CC=gcc\nCXX=g++` **10.4 隐含规则链** - **概念**: 多个隐含规则可以链接起来。 - **示例**: `main: main.c main.h` **10.5 定义与重新定义格式规则** - **概念**: 可以自定义或重定义隐含规则。 - **示例**: `%.o: %.cpp\n\t$(CXX) $(CXXFLAGS) -c $< -o $@` **10.6 定义最新类型的缺省规则** - **概念**: 为新文件类型定义缺省规则。 - **示例**: `%.out: %.in\n\tcat $< > $@` **10.7 过时的后缀规则** - **概念**: 旧版本make使用的规则,不再推荐。 - **示例**: `.c.o:` **10.8 隐含规则搜寻算法** - **概念**: make如何找到并应用隐含规则。 - **示例**: `make -p` #### 十一、使用make更新档案文件 **11.1 档案成员目标** - **概念**: 使用make更新档案文件中的成员。 - **示例**: `archive(member): object\n\tar r archive member` **11.2 档案成员目标的隐含规则** - **概念**: make自动处理档案文件的更新。 - **示例**: `archive(member): object\n\tar r archive member` **11.3 使用档案的危险** - **警告**: 不正确的使用可能会导致意外覆盖文件。 - **建议**: 确保目标和依赖正确设置。 **11.4 档案文件的后缀规则** - **概念**: 针对档案文件的隐含规则。 - **示例**: `archive(member): object\n\tar r archive member` #### 十二、GNU make的特点 - **特性**: 包括并行构建、条件语句、文本转换函数等。 - **优势**: 更强大、灵活,支持高级特性。 #### 十三、不兼容性和失去的特点 - **变化**: 与早期版本相比,某些功能可能被移除或修改。 - **兼容性**: 注意查看版本间的差异。 #### 十四、makefile文件惯例 **14.1 makefile文件的通用惯例** - **建议**: 保持一致性和清晰性。 - **示例**: 使用大写字母命名变量。 **14.2 makefile文件的工具** - **工具**: `automake`, `autoconf`, `cmake` 等。 - **作用**: 生成makefile文件。 **14.3 指定命令的变量** - **示例**: `CC=gcc\nCXX=g++` **14.4 安装路径变量** - **示例**: `PREFIX=/usr/local\nBINDIR=$(PREFIX)/bin` **14.5 用户标准目标** - **概念**: 为用户提供常用的目标。 - **示例**: `all`, `clean`, `install` 等。 **14.6 安装命令分类** - **示例**: `install-data`, `install-exec`, `uninstall` 等。 #### 十五、快速参考 - **概念**: 提供make常用命令和选项的简要指南。 - **示例**: `make -h` #### 十六、make产生的错误 - **概念**: 解释make执行时可能出现的错误。 - **示例**: `make: *** No rule to make target 'file.o', needed by 'all'. Stop.` #### 十七、复杂的makfile文件例子 - **示例**: 包含多个目标、依赖、规则和函数的makefile文件。 - **作用**: 展示makefile文件的高级应用。 ### 结论 GNUMake 是一个强大的自动化构建工具,能够有效管理项目构建流程。通过深入学习本手册,读者不仅能够更好地理解和使用Makefile,还能够利用其高级特性来优化项目的构建过程。无论是对于Linux源代码的学习还是日常软件开发工作,掌握GNUMake都将带来极大的帮助。
- 粉丝: 8
- 资源: 15
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助