【Linux】自动化编译工具——make/makefile

一.前言

前文讲到Linux的基本指令和权限,但是在我们常见的项目编译中肯定会有很多代码文件 ,指挥使用指令是不够的,所以本篇章着重来讲解一下如何使用Make/Makefile来实现项目的自动化构建

在Linux中编译C语言代码,a.out是从

  • test.c 经过预编译 到**test.i**
  • test.i 经过编译 到**test.s**
  • test.s 经过汇编 到**test.o**
  • test.o 经过链接 到**a.out**

我们平常做做练习还可以接受,但是到了大型工程,可是有上千条上万条代码, 若是一次编译完成之后又修改了源代码,接着又想进行编译,此时便需要重新敲入指令,那会使得工作量变得很大。可是在VS中,我们可以无限地修改自己的代码,然后随时编译运行,不需要考虑这些复杂的原理

Linux 中有没有这样的一站式操作呢,那就是【make/Makefile】

二.make/makefile介绍

🥝Makefile是干什么的?

  • Makefile 是一个**文件**。它是一个工程文件的编译规则,它记录了原始码如何编译的详细信息、描述了整个工程的编译链接等规则。
  • Makefile 带来的好处就是------"自动化编译"。一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率🚀
复制代码
  target(目标文件):文件1 文件2(依赖文件列表)		//依赖关系
   
  <Tab>gcc -o 欲建立的执行文件 目标文件1 目标文件2		///依赖方法
  	 command
  	 ...
  	 ...
  • target就是我们想要建立的信息,一般称作**目标文件** 。而后面的**依赖文件列表** 就是具有相关性的 object files,也就是目标文件所依赖的文件(可以是一个或多个,也可以没有)
cpp 复制代码
目标:你想要生成的文件名(比如最终的可执行文件,或者中间的 .o 目标文件)。也可以是一个执行动作(如 clean)。

依赖:生成这个目标所需要的原材料(源文件或其他中间文件)。

命令:如何将"依赖"变成"目标"的具体操作(通常是 gcc/g++ 命令)。

⚠️ 致命易错点:命令前面必须是一个纯正的 Tab 键缩进,绝对不能是用空格代替,否则 make 会报错!

三.makefile操作

假设我们有一个简单的项目,包含三个文件:

cpp 复制代码
main.c (主函数)

math.c (数学功能实现)

math.h (头文件)

传统编译方式: gcc main.c math.c -o myapp

使用 makefile 的方式: 在源码同级目录下创建一个名为 Makefilemakefile 的文件,内容如下:

cpp 复制代码
# 最终目标 myapp 依赖于 main.o 和 math.o
myapp : main.o math.o
	gcc main.o math.o -o myapp

# main.o 依赖于 main.c
main.o : main.c
	gcc -c main.c -o main.o

# math.o 依赖于 math.c
math.o : math.c
	gcc -c math.c -o math.o

工作原理(依赖推导树): 当你输入 make 回车时:

  • make 会在当前目录找 makefile,并默认把找到的第一个目标 (也就是 myapp)作为最终目标。

  • 它发现要生成 myapp 依赖 main.omath.o

  • 如果当前目录下没有这两个 .o 文件,它会挂起当前任务,继续向下寻找生成 main.omath.o 的规则。

  • 找到底层的 .c 生成 .o 的规则后,按从下往上 的顺序,先执行 gcc -c 生成目标文件,最后再执行链接生成可执行程序 myapp。这就是所谓的自动推导

四.进阶操作

上面的写法有太多重复的内容(比如文件名被写了好多次),我们可以使用变量来简化它。

常用自动化变量:

  • $@:表示规则中的目标文件

  • $^:表示规则中的所有依赖文件(以空格分隔)。

  • $<:表示规则中的第一个依赖文件

cpp 复制代码
# 定义基础变量
CC = gcc
TARGET = myapp
OBJS = main.o math.o

# 链接生成最终可执行文件
$(TARGET) : $(OBJS)
	$(CC) $^ -o $@   # 等价于 gcc main.o math.o -o myapp

# 编译生成中间目标文件
# % 是通配符,表示所有的 .o 文件都由对应的 .c 文件生成
%.o : %.c
	$(CC) -c $< -o $@

五.项目清理:.PHONY伪目标

编译过程中会产生很多中间文件(如 .o),当你想清理工作区,准备重新全量编译或打包源码时,需要删除它们。我们通常会在 makefile 底部加上清理命令:

cpp 复制代码
.PHONY:clean
clean:
        rm-f $(OBJS) $(TARGET)

为什么要有.PHONY关键字

假设你的当前目录刚好有一个名为clean的实体文件 ,当你执行 make clean时,make发现目标文件clean已经存在,并且它没有任何以来,make就会认为它是最新的,从而提示make:'clean' is up to date,拒绝执行下面的rm命令。 .PHONY的作用就是告诉make,clean是一个伪目标,不代表具体的文件,无论当前目录有没有叫clean的文件,每次执行 make clean时无条件执行它下面的命令

六.核心优势:增量编译

这也是 makefile 最大的价值所在:只编译修改过的文件

如果你的项目有100个 .c文件,你修改其中一个。当你再次输入make时,make工具会对比源文件(.c)和目标文件(.o)的最后修改时间。

如果发现 xxx.c 的修改时间比 xxx.o 晚,它就知道源文件被改动过了,于是只重新编译这一个文件,然后重新链接。大大节省了大型项目的编译时间!

相关推荐
小马同学-8 分钟前
OpenStack 使用实战:Web 界面与 CLI 命令行实验
运维·云计算·openstack
GeW11 分钟前
RHCE备考别瞎学!按这个计划走,30天提高通过率,快速拿证
linux
Escalating_xu32 分钟前
【System V 信号量】从 P/V 原语到 Builder 封装:写出可控、可清理的进程互斥组件
java·linux·开发语言·jvm
傲世仙尊37 分钟前
System V 进程间通信详解:共享内存、消息队列与信号量(CSDN博客)
linux·开发语言·c++
码农小韩1 小时前
Linux应用开发(六)——进程间通信
linux·linux驱动·嵌入式软件开发·嵌入式操作系统·linux应用
网安老伯1 小时前
都2026年了,还在问网络安全怎么入门?看完这一篇你就懂了
运维·计算机网络·web安全·网络安全·wireshark·密码学·网络攻击模型
www.021 小时前
Codex额度用完怎么办?Windows定时自动继续VS Code Codex任务实战
人工智能·windows·vscode·自动化·openai·codex·autohotkey
星禾元亨1 小时前
生成式 AI 时代的架构演进与 GEO 优化:实体企业 AI 落地避坑指南
大数据·人工智能·架构·自动化·创业创新
小祺先生2 小时前
mt7921 debian系统 如何安装驱动
运维·网络·debian
笨笨饿2 小时前
#138_解决Codex要五次回复的问题
linux·stm32·单片机·嵌入式硬件·mcu·物联网·嵌入式实时数据库