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

Linux操作系统从入门到实战(九)Linux开发工具(中)自动化构建-make/Makefile知识讲解

Linux操作系统从入门到实战(九)Linux开发工具(中)自动化构建-make/Makefile

  • 前言
  • 一、 make/Makefile是什么?
    • 1. 我们先想个问题:手动编译代码有多麻烦?
    • 2. 为了解决麻烦,才有了自动化工具
    • 3. 什么是 Makefile ?
    • 4. 什么是 make ?
  • 二、如何使用 make/Makefile
    • 1. 如何创建第一个Makefile?
      • (1) 创建源文件
      • (2) 创建Makefile文件
      • (3) 编写Makefile规则
      • (4) 执行make命令
    • 2. 依赖关系与命令
      • (1) 依赖关系
      • (2) make的执行逻辑
      • (3) 为什么需要依赖关系?
    • 3. 如何清理编译结果?
      • (1) 添加clean目标
      • (2) 执行清理命令
      • (3) .PHONY 标签的作用
    • 4. Makefile的执行规则
      • (1) 默认执行第一个目标
      • (2) 如何执行其他目标?
      • (3) 多个目标的执行顺序
    • 5. 常见错误与注意事项
      • (1) 命令行必须以Tab键开头
      • (2) 文件名大小写敏感
  • 三、伪目标是什么,为什么伪目标总被执行?
    • 1. make如何判断是否需要重新编译?
    • 2. 什么是伪目标(.PHONY)?
      • (1)定义:
      • (2) 常见用途:
    • 3. 为什么伪目标总是被执行?
      • (1)核心原因:
      • (2) 对比实验:
    • 4. 为什么需要伪目标?
      • (1) 避免与文件冲突
      • (2) 强制执行命令
    • 5. 常见伪目标示例
      • 1. clean目标(最常见)
      • 2. all目标(批量编译多个程序)
      • 3. install目标(安装程序到系统)


前言

  • 前面的博客里我们讲解了vim编译,g++/gcc编译的步骤和动静态链接与库的相关知识
  • 接下来我们继续讲解Linux开发工具自动化构建-make/Makefile

我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Linux知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482


一、 make/Makefile是什么?

1. 我们先想个问题:手动编译代码有多麻烦?

  • 假设你写了一个小项目,里面有好几个 .c 源文件(比如 a.cb.cmain.c)。
  • 要让它们变成能运行的程序,得用 gcc 编译,比如:
    gcc a.c b.c main.c -o myprogram

这看起来简单,但如果项目变大呢?

  • 假设有 100 个源文件,每次都手动敲这串命令,累不说,还容易输错;
    在这里插入图片描述

  • 如果只改了 a.c,手动编译时还得重新编译所有文件,浪费时间

  • 不同文件有依赖关系(比如 main.c 要用 a.c 的结果),手动编译得记清顺序,错一步就失败

2. 为了解决麻烦,才有了自动化工具

就像做复杂的菜时,你需要一份「步骤清单」(先切菜、再炒肉、最后炖),再找个「帮手」按清单一步步做。

在编程里,「步骤清单」就是 Makefile,「帮手」就是 make

3. 什么是 Makefile ?

Makefile 是一个我们自己创建的文件(名字就叫 Makefile,没有后缀),里面写的是「编译规则」

比如在一个 Makefile 里,你可以在里面写下:

现在看一下代码,后面会详细讲

# 规则1:最终要生成的程序叫 myprogram,它依赖 a.o、b.o、main.o
myprogram: a.o b.o main.ogcc a.o b.o main.o -o myprogram  # 生成 myprogram 的命令# 规则2:a.o 依赖 a.c
a.o: a.cgcc -c a.c  # 把 a.c 编译成 a.o(中间文件)# 规则3:b.o 依赖 b.c
b.o: b.cgcc -c b.c# 规则4:main.o 依赖 main.c
main.o: main.cgcc -c main.c

简单说,Makefile 就像一份「菜谱」:

  • 明确最终要做什么(比如 myprogram 这个程序);
  • 明确需要哪些「原材料」(比如 a.o 这些中间文件);
  • 明确每一步怎么做(比如用什么命令编译,先编译哪个、后编译哪个)。

4. 什么是 make ?

make 是 Linux 自带的一个命令工具(就像 lscd 一样,输入 make 就能运行)。

  • 它的作用很单纯:Makefile 里的规则,然后自动执行命令

比如刚才写好了 Makefile,你在终端敲一句 make,它就会:

  1. 先看最终要生成 myprogram,发现需要 a.ob.omain.o
  2. 检查这些 .o 文件有没有,如果没有,就按规则编译 a.c 生成 a.o,以此类推;
  3. 最后把所有 .o 文件拼起来,生成 myprogram

如果之后我们只改了 a.c,再敲 make 时,它会聪明地只重新编译 a.omyprogram,其他没改的文件不碰——省时间!

二、如何使用 make/Makefile

1. 如何创建第一个Makefile?

(1) 创建源文件

首先,创建一个简单的C语言程序code.c
在这里插入图片描述

// code.c
#include <stdio.h>
int main() {printf("Hello, Makefile!\n");return 0;
}

在这里插入图片描述

(2) 创建Makefile文件

在相同目录下创建Makefile文件(注意大小写和文件名):

touch Makefile
vim Makefile

在这里插入图片描述

(3) 编写Makefile规则

Makefile中写入以下内容:

# 目标: 依赖文件
code: code.cgcc -o code code.c  # 注意这行必须以Tab键开头

在这里插入图片描述

(4) 执行make命令

在终端输入make,它会自动读取Makefile并执行编译:

在这里插入图片描述

$ make
gcc -o code code.c

此时,当前目录下会生成可执行文件code,运行它:

$ ./code

在这里插入图片描述

2. 依赖关系与命令

(1) 依赖关系

在Makefile中,每行规则的基本格式是:

目标文件: 依赖文件列表命令1命令2...
  • 目标文件:要生成的文件(如code
  • 依赖文件:生成目标所需要的文件(如code.c
  • 命令:生成目标的具体操作(如gcc -o code code.c

(2) make的执行逻辑

当你执行make时,它会:

  1. 检查目标文件是否存在
  2. 如果不存在,或依赖文件比目标文件更新(即依赖文件被修改过)
  3. 则执行对应的命令来生成/更新目标文件

(3) 为什么需要依赖关系?

假设你修改了code.c,再次执行make时:

$ make
make: 'code' is up to date.

make会自动判断:由于code已存在且code.c未修改,因此无需重新编译——这就是Makefile智能编译能力,大大节省时间!

在这里插入图片描述

3. 如何清理编译结果?

(1) 添加clean目标

Makefile中新增一个clean目标:

code: code.cgcc -o code code.c.PHONY: clean
clean:rm -f code  # 删除生成的可执行文件

在这里插入图片描述

(2) 执行清理命令

当需要删除编译结果时,执行:

$ make clean
rm -f code

在这里插入图片描述

(3) .PHONY 标签的作用

.PHONY用于声明clean是一个伪目标(即它不是真正的文件名),防止目录中真的存在名为clean的文件导致冲突。

4. Makefile的执行规则

(1) 默认执行第一个目标

当你直接输入make时,它会执行Makefile中的第一个目标(如上面的code)。

(2) 如何执行其他目标?

通过指定目标名来执行特定规则,例如:

$ make clean    # 只执行clean目标下的命令
$ make code     # 只执行code目标下的命令(等同于直接make)

(3) 多个目标的执行顺序

Makefile会按照依赖关系自动处理执行顺序。例如:

all: program1 program2program1: file1.cgcc -o program1 file1.cprogram2: file2.cgcc -o program2 file2.c

执行make all时,会先编译program1,再编译program2

5. 常见错误与注意事项

(1) 命令行必须以Tab键开头

在Makefile中,命令行必须以Tab键开头,否则会报错:

# 错误示例(使用空格缩进)
code: code.cgcc -o code code.c  # 错误!会提示"*** missing separator.  Stop."# 正确示例(使用Tab键缩进)
code: code.cgcc -o code code.c

(2) 文件名大小写敏感

Makefilemakefile是不同的文件,GNU make默认优先读取GNUmakefile,然后是makefile,最后是Makefile。建议统一使用Makefile

三、伪目标是什么,为什么伪目标总被执行?

1. make如何判断是否需要重新编译?

当我们执行make时,它会检查两件事:

  • 目标文件(如code)是否存在
  • 依赖文件(如code.c)的修改时间是否比目标文件更新

如果目标文件不存在,或依赖文件被修改过(修改时间比目标文件晚),make就会执行命令重新生成目标文件。

举个例子

# Makefile
code: code.cgcc -o code code.c
  • 第一次执行make:生成code文件
  • 第二次执行makemake发现code已存在,且code.c没修改,==“code”已是最新 ==
    在这里插入图片描述
$ make
gcc -o code code.c  # 第一次执行,生成code
$ make
make: “code”已是最新  

2. 什么是伪目标(.PHONY)?

(1)定义:

伪目标是用.PHONY声明的目标,它不代表一个真实的文件,而是一个动作名称

(2) 常见用途:

  • 清理编译结果(如clean目标)
  • 执行测试(如test目标)
  • 批量操作(如all目标)

示例:

.PHONY: clean  # 声明clean是伪目标
clean:rm -f code  # 删除生成的可执行文件

3. 为什么伪目标总是被执行?

(1)核心原因:

伪目标不对应真实文件,因此make无法检查它的修改时间
当你执行make 伪目标名时,make会直接执行对应的命令,而不做任何检查。

(2) 对比实验:

情况1:普通目标(无.PHONY)

hello:echo "Hello, World!"

执行效果:

$ make hello
echo "Hello, World!"
Hello, World!
$ make hello
make: 'hello' is up to date.  # 第二次不会执行,因为默认认为hello是文件且已存在

情况2:伪目标(有.PHONY)

.PHONY: hello
hello:echo "Hello, World!"

执行效果:

$ make hello
echo "Hello, World!"
Hello, World!
$ make hello
echo "Hello, World!"  # 每次都会执行!因为hello是伪目标
Hello, World!

4. 为什么需要伪目标?

(1) 避免与文件冲突

如果目录中真的有一个名为clean的文件,会发生什么?

# 错误示例:没有.PHONY的clean目标
clean:rm -f code

此时执行make cleanmake会认为:“clean文件已存在,无需执行任何命令”——这显然不是你想要的!

(2) 强制执行命令

对于cleantest这类目标,你总是希望它们无条件执行而不是根据文件时间判断

5. 常见伪目标示例

1. clean目标(最常见)

.PHONY: clean
clean:rm -f *.o       # 删除所有.o文件rm -f executable  # 删除可执行文件

2. all目标(批量编译多个程序)

.PHONY: all
all: program1 program2  # 先编译program1,再编译program2program1: file1.cgcc -o program1 file1.cprogram2: file2.cgcc -o program2 file2.c

3. install目标(安装程序到系统)

.PHONY: install
install:cp program /usr/bin/  # 复制程序到系统目录

以上就是这篇博客的全部内容,下一篇我们将继续探索Linux的更多精彩内容。

我的个人主页
欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Linux知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482

非常感谢您的阅读,喜欢的话记得三连哦

在这里插入图片描述

http://www.dtcms.com/a/280485.html

相关文章:

  • ubuntu部署kvm
  • AI-Compass LLM训练框架生态:整合ms-swift、Unsloth、Megatron-LM等核心框架,涵盖全参数/PEFT训练与分布式优化
  • 正则表达式深度解析:从LeetCode 3136题说起
  • 028_分布式部署架构
  • OpenCV图像自动缩放(Autoscaling)函数autoscaling()
  • 2025.7.15总结
  • 用Python构建机器学习模型预测股票趋势:从数据到部署的实战指南
  • 希尔排序:突破传统排序的边界
  • 【Java】【企业级应用】学生信息管理系统项目介绍
  • Mybatis05-动态sql
  • 深度解析 AI 提示词工程(Prompt Engineering)
  • 2025世界机器人大赛ICode专属训练平台图形化小学组答案
  • 光伏设计全方位指南
  • B/S 架构通信原理详解
  • sqli-labs靶场通关笔记:第17关 POST请求的密码重置
  • 如何配置maven
  • 【Linux手册】重定向是如何实现的?Linux下为什么一切皆文件?
  • flutter下的webview适配rem问题
  • 【NBA】75 Greatest NBA Players of All Time
  • 春秋云镜 initial
  • Uniapp动态切换主题与老年模式详解
  • 12.6 Google黑科技GShard:6000亿参数MoE模型如何突破显存限制?
  • Zen:一款简洁高效、注重隐私的开源浏览器
  • 小白学HTML,操作HTML网页篇(1)
  • 密码工程原理与技术——总复习
  • 灰度图像,RGB图像和二值图像
  • 从OSI到TCP/IP:Linux网络架构深度解析
  • react - 根据路由生成菜单
  • 多模态大模型研究每日简报(2025-07-14)
  • AI应用服务