Linux学习笔记(make/Makefile)1.23

一、核心概念

  1. Make:Linux 下的命令工具,用于解释 Makefile 中的指令,执行自动化编译流程。

  2. Makefile:定义工程编译规则的文件,指定源文件的编译顺序、依赖关系、清理逻辑等,实现"一键编译"。

  3. 核心价值:解决大型工程中多文件编译的繁琐问题(无需手动输入多条 gcc 命令),提高开发效率,确保编译流程一致性。

二、Makefile 基本结构

(一)核心三要素

  1. 目标(Target):要生成的文件(可执行程序、目标文件)或执行的操作(如 clean)。

  2. 依赖(Prerequisites):生成目标所需的文件或条件(如源文件、其他目标文件)。

  3. 依赖方法(Recipe):生成目标的具体命令(需以 Tab 键开头,如 gcc 编译命令)。

(二)最简示例

1. 工程文件
  • 源文件:myproc.c(含 main 函数,打印 "hello Makefile!")
2. Makefile 内容
bash 复制代码
# 目标:myproc;依赖:myproc.c;依赖方法:编译命令
myproc: myproc.c
    gcc -o myproc myproc.c  # Tab 键开头

# 伪目标:clean;无依赖;依赖方法:删除目标文件
.PHONY: clean
clean:
    rm -f myproc

(三)关键说明

  1. 伪目标(.PHONY)

    1. 作用:标记目标为"操作型目标"(非文件),确保其始终被执行(不受同名文件影响)。

    2. 示例:clean 是伪目标,用于清理编译产物,执行命令 make clean 触发。

  2. 文件时间对比

    1. Make 会比较目标文件与依赖文件的修改时间(Modify 时间)。

    2. 若依赖文件比目标文件新(或目标文件不存在),则执行依赖方法重新编译;否则跳过。

三、Make 的工作流程

  1. 执行 make 命令后,Make 会在当前目录查找 Makefilemakefile 文件。

  2. 找到文件后,定位第一个目标(称为"终极目标",如上例的 myproc)。

  3. 检查终极目标的依赖文件:

    1. 若依赖文件不存在,查找是否有以该依赖为目标的规则,递归生成依赖文件(类似堆栈过程)。

    2. 若依赖文件存在,对比依赖文件与终极目标的修改时间,决定是否重新编译。

  4. 执行依赖方法,生成终极目标。

  5. 若过程中依赖文件缺失或命令执行失败,Make 直接退出并报错。

(一)完整推导示例(多阶段编译)

1. Makefile 内容
bash 复制代码
myproc: myproc.o
    gcc myproc.o -o myproc
myproc.o: myproc.s
    gcc -c myproc.s -o myproc.o
myproc.s: myproc.i
    gcc -S myproc.i -o myproc.s
myproc.i: myproc.c
    gcc -E myproc.c -o myproc.i

.PHONY: clean
clean:
    rm -f *.i *.s *.o myproc
2. 推导流程

make → 查找 myproc → 依赖 myproc.o(不存在)→ 查找 myproc.o → 依赖 myproc.s(不存在)→ 查找 myproc.s → 依赖 myproc.i(不存在)→ 查找 myproc.i → 依赖 myproc.c(存在)→ 执行 gcc -E 生成 myproc.i → 执行 gcc -S 生成 myproc.s → 执行 gcc -c 生成 myproc.o → 执行 gcc 生成 myproc

四、Makefile 进阶语法(实用特性)

(一)变量定义与使用

  • 作用:简化命令编写,统一修改(如更换编译器、修改选项)。

  • 语法:变量名=值,使用时用 $(变量名) 引用。

  • 示例:

bash 复制代码
# 定义变量
BIN=myproc          # 终极目标文件名
CC=gcc              # 编译器
SRC=$(wildcard *.c) # 获取当前目录所有 .c 文件(等价于 ls *.c)
OBJ=$(SRC:.c=.o)    # 将 SRC 中 .c 替换为 .o(生成目标文件列表)
RM=rm -f            # 删除命令

# 使用变量
$(BIN): $(OBJ)
    $(CC) -o $@ $^  # $@:目标文件名;$^:所有依赖文件列表
%.o: %.c            # 模式匹配:所有 .o 目标依赖对应的 .c 文件
    $(CC) -c $<     # $<:第一个依赖文件(即对应的 .c 文件)

.PHONY: clean test
clean:
    $(RM) $(OBJ) $(BIN)
test:                # 自定义测试目标
    @echo "源文件:$(SRC)"
    @echo "目标文件:$(OBJ)"
  • 常用自动变量:

    • $@:当前目标的名称。

    • $^:当前目标的所有依赖文件(去重)。

    • $<:当前目标的第一个依赖文件。

    • @:命令前加 @,执行时不回显命令(如 @echo 只输出内容)。

(二)模式匹配(%)

  • 作用:批量处理同类文件(如多个 .c 文件生成对应的 .o 文件),避免重复编写规则。

  • 示例:%.o: %.c 表示"所有以 .o 为后缀的目标,依赖对应的 .c 文件"。

(三)函数使用

  • wildcard:查找指定模式的文件,示例 $(wildcard *.c) 获取所有 .c 源文件。

  • 替换函数$(变量名:原后缀=新后缀),示例 $(SRC:.c=.o) 将源文件列表的 .c 替换为 .o。

五、注意事项

  1. 命令缩进:依赖方法必须以 Tab 键开头,不能用空格(否则 Make 报错)。

  2. 伪目标声明 :清理、测试等操作型目标必须用 .PHONY 标记,避免当前目录存在同名文件导致目标失效。

  3. 依赖完整性:确保所有生成目标的依赖都被明确声明(包括间接依赖),否则可能导致编译不完整。

  4. 变量引用 :变量名区分大小写,引用时必须加 $(变量名),否则视为普通字符串。

  5. 命令执行 :若命令执行失败(返回非 0 状态),Make 会立即停止编译,可在命令后加 ; true 忽略错误。

六、常用操作命令

|---------------|-------------------------------------------|
| 命令 | 功能描述 |
| make | 执行 Makefile,生成第一个目标(终极目标) |
| make 目标名 | 生成指定目标(如 make myproc.o 只生成目标文件) |
| make clean | 执行 clean 伪目标,清理编译产物 |
| make -n | 模拟执行,不实际编译,仅输出要执行的命令 |
| make -f 文件名 | 指定非默认名称的 Makefile(如 make -f MyMakefile) |

相关推荐
程序员侠客行6 小时前
Mybatis连接池实现及池化模式
java·后端·架构·mybatis
时艰.6 小时前
Java 并发编程 — 并发容器 + CPU 缓存 + Disruptor
java·开发语言·缓存
Harvey9036 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
工程师老罗6 小时前
YOLOv1 核心知识点笔记
笔记·yolo
丶小鱼丶7 小时前
并发编程之【优雅地结束线程的执行】
java
市场部需要一个软件开发岗位7 小时前
JAVA开发常见安全问题:Cookie 中明文存储用户名、密码
android·java·安全
lingggggaaaa7 小时前
安全工具篇&动态绕过&DumpLsass凭据&Certutil下载&变异替换&打乱源头特征
学习·安全·web安全·免杀对抗
忆~遂愿7 小时前
GE 引擎进阶:依赖图的原子性管理与异构算子协作调度
java·开发语言·人工智能
Days20507 小时前
简单处理接口返回400条数据本地数据分页加载
前端