跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C

Linux Makefile 自动化编译实战指南及进度条实现

Linux Makefile 自动化编译原理涉及依赖关系、伪目标及时间戳机制。文章通过实战演示了利用回调函数构建进度条的方法,解决了多文件编译繁琐问题,并优化了 Makefile 语法结构以提升开发效率。

2177283801发布于 2026/2/8更新于 2026/10/25103 浏览
Linux Makefile 自动化编译实战指南及进度条实现

一、前言

在之前的章节中我们提到,为了隐藏源码,可以将.c 文件编译后发送。但如果源文件过多,分发和使用都很麻烦。本章将解决该问题。

1.1 补充知识

一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中。Makefile 定义了系列的规则来指定哪些文件需要先编译,哪些需要后编译,哪些需要重新编译,甚至进行更复杂的功能操作。Makefile 带来的好处是'自动化编译',一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大地提高了软件开发的效率。

Make 是一个命令工具,是解释 Makefile 中指令的命令工具。Makefile 内部包含依赖关系和依赖方式。

二、理解

我们先创建一个 Makefile 文件(大小写均可)和 myproc.c 文件。

myproc.c

Makefile

然后运行 make,即可编译成功,再进行输出。

注意:项目是要被清理的,所以把 clean 的目标文件设置为伪目标(后续再讲)

上面的 Makefile 文件中:

  • 依赖关系:上面的文件 myproc,它依赖 myproc.c。
  • 依赖方式:gcc -o myproc myproc.c,就是与之对应的依赖关系。

2.1 引入小故事:加强理解

月底没生活费了,你打电话给家里人(你和家里人的关系就是依赖关系),问他们寻求支助生活费(这就是依赖方式)。

注:依赖关系与依赖方式必须对得上才有用(你不可能打电话问室友的爸爸要生活费)。

2.2 伪目标

项目工程是需要被 clean 的,一般我们这种 clean 的目标文件,我们将它设置为伪目标,用 .PHONY 修饰。伪目标的特性是总是被执行的。

即似乎 myproc 没有伪目标,就不会总是被执行。

[lcb@hcss-ecs-1cde 1]$ make gcc -o myproc myproc.c
[lcb@hcss-ecs-1cde 1]$ make
make: `myproc' is up to date.
[lcb@hcss-ecs-1cde 1]$ make clean
rm -f myproc
[lcb@hcss-ecs-1cde 1]$ make clean
rm -f myproc
[lcb@hcss-ecs-1cde 1]$ 

上面也确实如此。

注:编译器编译时是自上而下,也就是说如果把 clean 放在最前面,那 make 执行的就是 clean,而不是 myproc。

同样,如果我们为 myproc 加上.PHONY 呢,事实就是也可以无限次执行。

可以如此的原因是:编译器默认老代码不再编译。

2.3 Make 如果知道 bin 和.c 的新旧关系

Make 通过 Modify 知道 bin 和.c 的新旧关系。

此处就需要回顾前面提到的时间戳及文件组成:内容 + 属性。

  • Modify:内容变更,时间更新。
  • Change:属性变更,时间更新。
  • Access (特殊):常指的是文件最近一次被访问的时间。在 Linux 的早期版本中,每当文件被访问时,其 atime 都会更新。但这种机制会导致大量的 IO 操作。具体更新原则,不做过多解释。

注意,如果修改内容,属于也变更(修改内容很有可能会更新大小,大小属于属性)。

此时如果再进行 make 执行,由于 bin 的时间比.c 文件新,所以.c 为老代码,不再编译。

此时如果进行修改,改变.c 的时间戳,那么.c 文件与 myproc 相比,就为新了,可进行修改,那么就可以执行文件,进行编译。

2.4 继续手动编译过程:加强理解

在上一章我们已经详细讲述了编译过程,此处不再解释,只是给出代码。

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.5 适度扩展语法:解决仍存在的多文件繁琐问题

N=proc.exe
CC=gcc
SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
LFLAGS=-o
FLAGS=-c
RM=rm -rf

# 2. 链接规则
$(BIN):$(OBJ)
	@$(CC) $(LFLAGS) $@ $^
	@echo "linking ... $^ to $@"

# 3. 编译规则(.c → .o,批量编译)
%.o:%.c
	@$(CC) $(FLAGS) $< -o $@
	@echo "compiling ... $< to $@"

# 4. 清理伪目标(修正 RM 变量后可正常删除文件)
.PHONY:clean
clean:
	$(RM) $(OBJ) $(BIN)

# 5. 测试伪目标(修正执行命令,逻辑合理化)
.PHONY: test
test: $(BIN)
	@echo "=== Source files: $(SRC) ==="
	@echo "=== Object files: $(OBJ) ==="
	@./$(BIN)

注:上面的 SRC 也可改为 SRC=$(shell ls *.c)。

三、实战:利用 make Makefile 制作进度条

3.1 版本一

核心代码 main.c 和 process.c。

但上面代码有所缺陷,即 download 定义的太多死板,后面更新上传又要重新传参,因此我们可以使用 C 语言学习的知识,回调函数。

3.2 版本二

修改的核心代码:

#include <stdio.h>
#include "process.h"

typedef void (*callback)(double total, double current);

double total = 1024.0;
double speed = 1.0;

void Download(callback cb) {
    double current = 0.0;
    while(current < total) {
        cb(total, current);
        usleep(3000);
        current += speed;
    }
    printf("\ndownload%.2fMB done\n", current);
}

int main() {
    // 定义回调函数处理进度显示
    Download(print_progress);
    return 0;
}

上面的修改即可解决参数传递繁琐的问题。

目录

  1. 一、前言
  2. 1.1 补充知识
  3. 二、理解
  4. 2.1 引入小故事:加强理解
  5. 2.2 伪目标
  6. 2.3 Make 如果知道 bin 和.c 的新旧关系
  7. 2.4 继续手动编译过程:加强理解
  8. 2.5 适度扩展语法:解决仍存在的多文件繁琐问题
  9. 2. 链接规则
  10. 3. 编译规则(.c → .o,批量编译)
  11. 4. 清理伪目标(修正 RM 变量后可正常删除文件)
  12. 5. 测试伪目标(修正执行命令,逻辑合理化)
  13. 三、实战:利用 make Makefile 制作进度条
  14. 3.1 版本一
  15. 3.2 版本二

更多推荐文章

查看全部
  • Docker 容器内 Java 与 Python 代码运行示例
  • 滑动窗口算法详解:从入门到实战
  • JavaScript 中 this 的解析:从 call、bind 到箭头函数
  • Linux 远程连接 Windows 桌面配置指南
  • 基于 Dify 与 Qwen3-VL 的低代码视觉智能应用构建
  • LightGlue ONNX C++ 推理实践
  • VSCode 中如何正确创建并推送 Git Tag:避坑指南与最佳实践
  • Coze 智能体开发指南:从配置到工作流实战
  • Python 爬虫技术详解:核心难点、学习路径与实战规范
  • Spring AI 实战:基于 SSE 构建 MCP Server 与 Client
  • 10 款常用 Python 数据可视化工具推荐
  • MySQL 行级锁机制详解:Record、Gap 与 Next-Key Lock
  • CKS 核心命令速查指南
  • Ollama + Qwen 3.5 + OpenClawbot 本地部署教程
  • LIBERO 数据集:终身机器人学习基准测试平台
  • Agent-Browser:面向 AI 的浏览器自动化 CLI 工具指南
  • Stable Diffusion 显存优化与内存不足解决方案
  • OpenClaw 安装部署全流程:搭建自托管 AI 助手网关
  • 动态规划时间复杂度与空间复杂度计算方法
  • WebODM 无人机地图制作核心优势与应用解析

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online