当前位置: 首页 > news >正文

[Linux] make自动化构建

目录

一.什么是make

二.Makefile结构

2.1 典型结构

2.2 变量

1. 普通变量(User-Defined Variables)

2. 自动变量(Automatic Variables)

3. 预定义变量(Built-in Variables) 

4. 函数变量(Functions) 

2.3 伪目标

三. 实战解析


一.什么是make

在 Linux 中,make是一个用于自动化构建和编译程序的命令工具,而 Makefile 是make的配置文件,用于定义编译规则、依赖关系和执行步骤。

  • 自动化编译:根据 Makefile 中定义的规则,自动完成编译、链接等操作。
  • 增量编译:根据文件的修改时间,仅重新编译被修改的文件及其依赖项,提高效率。
  • 管理复杂项目:处理多文件、多依赖的大型项目,避免手动编译的繁琐。

[注意事项]

  1. make默认仅生成第一个目标,而非所有目标。

  2. make通过依赖关系和时间戳自动判断是否需要重新生成。

  3. make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件,找到了解释这个文件

二.Makefile结构

2.1 典型结构

target: dependencies
        command
  • 目标(Target):要生成的文件或伪目标(如 clean)。
  • 依赖(Dependencies):生成目标所需的文件或目标。
  • 命令(Commands)必须以 Tab 开头的 Shell 命令。

Makefile一般包含以下五个核心元素

  1. 显式规则(显式定义目标及其依赖关系);

  2. 隐晦规则(隐式规则,由make内置推理规则支持);

  3. 变量定义(类似宏的字符串变量);

  4. 文件指示(如include包含其他文件);

  5. 注释(以#开头)。

2.2 变量

1. 普通变量(User-Defined Variables)

普通变量由用户自定义,用于存储字符串、路径、编译选项等信息。$符号用于引用已定义的变量,格式为 $(变量名)$带括号的变量名:

# 定义变量
CC = gcc
CFLAGS = -Wall -g

# 使用变量
all: main
main: main.o utils.o
    $(CC) $(CFLAGS) -o $@ $^

2. 自动变量(Automatic Variables)

$后跟特定字符表示自动变量,用于引用目标、依赖等信息:

变量含义
$@当前目标的完整名称。
$<当前规则中第一个依赖文件的名称。
$^当前规则中所有依赖文件的列表(去重,以空格分隔)。
$?当前规则中比目标更新的依赖文件的列表(以空格分隔)。
$*当前目标的“茎”(Stem),即去掉后缀的部分(如 foo.o 的 $* 是 foo)。
$(@D)目标文件的目录路径(如 dir/file.o 的 $(@D) 是 dir)。
$(@F)目标文件的文件名(不含目录路径)。
$(<D)第一个依赖文件的目录路径。
$(<F)第一个依赖文件的文件名(不含目录路径)。

3. 预定义变量(Built-in Variables) 

变量默认值用途
CCccC 编译器。
CXXg++C++ 编译器。
ARar归档程序(用于生成静态库)。
ASas汇编器。
CPP$(CC) -EC 预处理器。
CFLAGS空字符串C 编译器选项。
CXXFLAGS空字符串C++ 编译器选项。
LDFLAGS空字符串链接器选项。

4. 函数变量(Functions) 

$ 可用于调用 Makefile 内置函数或特殊语法

(1) 文件名称处理函数

SRCS = $(wildcard src/*.c)  # 获取 src/ 目录下所有 .c 文件

OBJS = $(patsubst %.c,%.o,$(SRCS))  # 将 .c 文件替换为 .o

BASE = $(basename test.c)  # BASE = test

EXT = $(suffix test.c)     # EXT = .c

(2) 控制函数

ifeq ($(OS),Windows_NT)
# Windows 特定配置
else
# 其他系统配置
endif

FILES = a b c
OBJ = $(foreach file,$(FILES),$(file).o)
# OBJ = a.o b.o c.o

2.3 伪目标

.PHONY: clean
clean:
        rm -f *.o main

伪目标的特性是,总是被执行的。

三. 实战解析

# 定义变量
BIN=proc.exe          # 定义最终生成的可执行文件名
CC=gcc                # 定义编译器(gcc)
SRC=$(wildcard *.c)   # 使用wildcard函数获取当前目录下所有.c文件的列表
# SRC=$(shell ls *.c) # 注释掉的另一种方法,通过shell命令获取.c文件(与wildcard功能相同)
OBJ=$(SRC:.c=.o)      # 将SRC中的所有.c文件名替换为对应的.o文件名(例如:main.c → main.o)
LFLAGS=-o             # 定义链接选项(-o用于指定输出文件名)
BFLAGS=-c              # 定义编译选项(-c表示仅编译不链接)
RM=rm -f              # 定义删除命令(rm -f强制删除)

# 定义生成可执行文件的规则
$(BIN): $(OBJ)        # 目标:$(BIN)依赖于所有.o文件
    $(CC) $^ $(LFLAGS) $@ # 隐式规则:链接所有.o文件生成$(BIN)
    @echo "linking ... $^ to $@" # 输出链接信息($^是所有依赖文件,$@是目标文件名)

# 定义生成.o文件的通用规则(隐式规则)
%.o: %.c              # 通配符规则:将每个.c文件编译为对应的.o文件
    @$(CC) $(BFLAGS) $< # 编译单个.c文件为.o文件($<是第一个依赖文件,即对应的.c文件)
    @echo "compiling ... $< to $@" # 输出编译信息($<是源文件,$@是目标文件)

# 定义伪目标(确保即使存在同名文件也会执行)
.PHONY: clean test    # 声明clean和test为伪目标

# 清理生成的文件
clean:
    $(RM) $(OBJ) $(BIN) # 删除所有.o文件和可执行文件

# 测试目标(显示变量内容)
test:
    @echo $(SRC)       # 输出所有.c文件列表
    @echo $(OBJ)       # 输出所有.o文件列表

相关文章:

  • 【多线程-第四天-SDWebImage介绍 Objective-C语言】
  • Ubuntu24.10编译Android12源码并运行于模拟器中
  • k8s中的组件
  • AI训练如何获取海量数据,论平台的重要性
  • 部署|Llama-Facory微调模型部署
  • element-plus中Dropdown下拉菜单组件的使用
  • word插入Mathtype公式居中和自动更新
  • PairRE: Knowledge Graph Embeddings via Paired Relation Vectors(论文笔记)
  • 八股学习-JUC java并发编程
  • svn-1.7.22安装
  • ESP8266通过AT指令配置双向透传
  • C++常用多线程模式
  • 【病毒分析】伪造微软官网+勒索加密+支付威胁,CTF中勒索病毒解密题目真实还原!
  • 机器学习面试重点第二部分(动画版)
  • 服务创造未来 东隆科技携多款产品亮相慕尼黑
  • Idea中使用Git插件_合并当前分支到master分支_冲突解决_很简单---Git工作笔记005
  • Debezium + Kafka-connect 实现Postgres实时同步Hologres
  • Spring Boot配置与注解的使用
  • Leetcode 1277. 统计全为 1 的正方形子矩阵 动态规划
  • 【C++】动态规划从入门到精通
  • 网站开发 简单留言板/现在有哪些免费推广平台
  • 甘肃做网站/百度关键词优化送网站
  • 北仑网站建设网站/建立免费个人网站
  • 保定网站制作网站/特大新闻凌晨刚刚发生
  • 免费学校网站模板html/软文写作经验是什么
  • 洛阳电商网站建设公司排名/北京自动seo