Linux make与makefile 项目自动化构建工具

本文章将对make与makefile进行一些基础的讲解。

假设我们要建造一座房子,建造过程涉及很多步骤,比如打地基、砌墙、安装门窗、粉刷墙壁等。每个步骤都有先后顺序,并且有些步骤可能依赖于其他步骤的完成。比如,你必须先打好地基才能砌墙,必须先砌好墙才能安装门窗。这时候,你需要一个详细的施工流程表,告诉工人每一步该做什么,以及在什么条件下可以进行下一步。make 和 makefile 就像是这个施工流程表。

一、什么是 make 和 makefile

  • makefile​:是一个文本文件,里面包含了一系列的规则,这些规则定义了如何从源文件生成目标文件,以及各个目标文件之间的依赖关系。
  • make​:是一个构建自动化工具,它会读取 makefile 中的规则,并根据这些规则来决定哪些文件需要重新编译或构建。

二、makefile 的基本结构

一个典型的 makefile 包含以下几个部分:

  • ​目标(Target)​​:你想要生成的东西,比如一个可执行文件或一个目标文件。
  • ​依赖(Dependency)​​:生成目标所需要的文件。
  • ​命令(Command)​​:为了生成目标需要执行的命令。

一个简单的 makefile 示例:

# 目标:生成可执行文件 main
main: main.o add.o sub.ogcc main.o add.o sub.o -o main# 目标:生成 main.o
main.o: main.cgcc -c main.c# 目标:生成 add.o
add.o: add.cgcc -c add.c# 目标:生成 sub.o
sub.o: sub.cgcc -c sub.c# 清理生成的文件
clean:rm -f main main.o add.o sub.o

解释

  1. ​目标 main​:

    • ​依赖​​:main.oadd.o 和 sub.o
    • ​命令​​:gcc main.o add.o sub.o -o main。这个命令表示将 main.oadd.o 和 sub.o 链接成一个可执行文件 main
  2. ​目标 main.o​:

    • ​依赖​​:main.c
    • ​命令​​:gcc -c main.c。这个命令表示将 main.c 编译成目标文件 main.o
  3. ​目标 add.o 和 sub.o​:

    • 类似于 main.o,分别将 add.c 和 sub.c 编译成目标文件。
  4. ​目标 clean​:

    • ​命令​​:rm -f main main.o add.o sub.o。这个命令用于清理生成的可执行文件和目标文件。

三、make 的工作原理

当你运行 make 命令时,make 会读取 makefile 文件,并按照以下步骤工作:

  1. ​读取 makefile​:make 会解析 makefile 中的规则,构建一个依赖图。
  2. ​确定目标​​:默认情况下,make 会尝试生成 makefile 中第一个目标(在这个例子中是 main)。
  3. ​检查依赖​​:make 会检查目标的依赖文件是否存在,以及这些依赖文件是否有更新。如果依赖文件不存在或比目标文件新,make 会执行相应的命令来更新目标文件。(如何检查的呢?)
  4. ​执行命令​​:make 会按照依赖图的顺序执行命令,生成最终的目标。

四、示例运行

假设你有以下文件:

  • main.c
  • add.c
  • sub.c

运行 make 命令:

make 会根据 makefile 中的规则,依次编译 main.cadd.c 和 sub.c,然后将它们链接成可执行文件 main

如果你修改了 add.c 文件,再次运行 make

make 会检测到 add.c 文件有更新,只重新编译 add.c 成 add.o,然后重新链接生成 main

如果你想清理生成的文件,可以运行:

make clean

make 会执行 clean 目标中的命令,删除 mainmain.oadd.o 和 sub.o 文件。

五、 .PHONY

在 makefile 中,.PHONY 是一个特殊的目标,用于声明某些目标是“伪目标”。伪目标不是实际的文件,而是用于执行特定的命令或任务。使用 .PHONY 可以避免与同名文件冲突,并且可以提高 make 的执行效率。

1.为什么需要 .PHONY
  1. ​避免与文件名冲突​​:如果有一个目标名与文件名相同,make 会误认为该目标是文件,而不是一个任务。使用 .PHONY 可以避免这种冲突。
  2. ​提高执行效率​​:make 会检查文件的时间戳来决定是否需要重新生成目标文件。对于伪目标,make 不需要检查时间戳,可以直接执行相应的命令,从而提高执行效率。
  3. ​明确意图​​:使用 .PHONY 可以明确告诉其他开发者,这个目标是一个虚拟的任务,而不是一个实际的文件。
2.如何使用 .PHONY

以下是一个简单的 makefile 示例,展示了如何使用 .PHONY

# 声明伪目标
.PHONY: clean test# 默认目标
all: main# 生成可执行文件 main
main: main.o add.o sub.ogcc main.o add.o sub.o -o main# 生成 main.o
main.o: main.cgcc -c main.c# 生成 add.o
add.o: add.cgcc -c add.c# 生成 sub.o
sub.o: sub.cgcc -c sub.c# 清理生成的文件
clean:rm -f main main.o add.o sub.o# 运行测试
test:./mainecho "All tests passed!"

在这个示例中:

  • .PHONY: clean test 声明了 clean 和 test 是伪目标。
  • clean 目标用于清理生成的文件,它不生成任何实际的文件。
  • test 目标用于运行测试,它也不生成任何实际的文件。

示例解释

1.声明伪目标

.PHONY: clean test

这行代码告诉 makeclean 和 test 是伪目标,而不是实际的文件。即使当前目录下存在名为 clean 或 test 的文件,make 也会执行相应的命令。

2. 使用伪目标

  • ​清理文件​​:

    make clean

    这条命令会执行 clean 目标中的命令,删除 mainmain.oadd.o 和 sub.o 文件。

  • ​运行测试​​:

    make test

    这条命令会执行 test 目标中的命令,运行 main 可执行文件,并输出 "All tests passed!"。

3. 避免冲突

假设当前目录下有一个名为 clean 的文件,如果没有使用 .PHONY 声明 clean 为伪目标,make 会认为 clean 是一个文件,而不是一个任务。此时,运行 make clean 不会执行任何命令,因为 clean 文件已经存在,且没有依赖关系需要更新。

通过使用 .PHONY,可以避免这种冲突,确保 make clean 总是执行清理命令。

.PHONY 不仅可以用于常见的清理和测试任务,还可以用于其他任何不需要生成实际文件的任务。

  • .PHONY 的作用​​:声明伪目标,避免与文件名冲突,提高执行效率,明确意图。
  • ​如何使用​​:在 makefile 中使用 .PHONY 关键字,后跟伪目标的名称列表。
  • ​常见用途​​:清理文件、运行测试、生成文档、打包发布、代码风格检查等。
  • 伪目标总是会被执行,不会被拦截。(比如我们重复make会提示已经make了不让我们make,但是如果我们把他搞成伪目标,那么就不会受此限制了)。

六、优点

  1. ​自动化​​:make 可以自动处理文件之间的依赖关系,只重新编译需要更新的文件,节省时间和资源。
  2. ​可维护性​​:通过 makefile,你可以清晰地定义项目的构建流程,方便团队协作和项目管理。
  3. ​灵活性​​:makefile 支持复杂的规则和条件判断,可以适应各种构建需求。

七、缺点

  1. ​维护成本​​:随着项目规模的增大,makefile 可能会变得非常复杂,维护起来比较困难。

八、总结

  • makefile​:是一个包含构建规则的文本文件,定义了如何从源文件生成目标文件以及各个目标文件之间的依赖关系。
  • make​:是一个构建自动化工具,读取 makefile 中的规则,并根据这些规则决定哪些文件需要重新编译或构建。

通过 make 和 makefile,你可以高效地管理和构建项目,确保每次构建都是基于最新的文件状态。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/74594.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何判断多个点组成的3维面不是平的,如果不是平的,如何拆分成多个平面

判断和拆分三维非平面为多个平面 要判断多个三维点组成的面是否为平面,以及如何将非平面拆分为多个平面,可以按照以下步骤进行: 判断是否为平面 平面方程法: 选择三个不共线的点计算平面方程:Ax By Cz D 0检查其…

多layout 布局适配

安卓多布局文件适配方案操作流程 以下为通过多套布局文件适配不同屏幕尺寸/密度的详细步骤,结合主流适配策略及最佳实践总结: 一、‌创建多套布局资源目录‌ ‌按屏幕尺寸划分‌ 在 res 目录下创建以下文件夹(根据设备特性自动匹配&#xff…

Java 大视界 -- Java 大数据在智能农业无人机植保作业路径规划与药效评估中的应用(165)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…

美关税加征下,Odoo免费开源ERP如何助企业破局?

近期,美国特朗普政府推行的关税政策对全球供应链和进出口企业造成巨大冲击,尤其是依赖中美贸易的企业面临成本激增、利润压缩和合规风险。在此背景下,如何通过数字化转型优化管理效率、降低运营成本成为企业生存的关键。本文以免费开源ERP系统…

go游戏后端开发25:红中麻将规则介绍

一、游戏基础规则介绍 在开发红中麻将游戏之前,我们需要先了解其基础规则。红中麻将的牌面由 a、b、c、d 四种花色组成,其中 a、b、c 分别代表万、条、筒,每种花色都有 1 - 9 的九种牌,每种牌各有四张,总计 36 张 4 …

Unity:平滑输入(Input.GetAxis)

目录 1.为什么需要Input.GetAxis? 2. Input.GetAxis的基本功能 3. Input.GetAxis的工作原理 4. 常用参数和设置 5. 代码示例:用GetAxis控制角色移动 6. 与Input.GetAxisRaw的区别 7.如何优化GetAxis? 1.为什么需要Input.GetAxis&…

OpenCV:计算机视觉的强大开源库

文章目录 引言一、什么是OpenCV?1.OpenCV的核心特点 二、OpenCV的主要功能模块1. 核心功能(Core Functionality)2. 图像处理(Image Processing)3. 特征检测与描述(Features2D)4. 目标检测&#…

AI浪潮下的IT职业转型:医药流通行业传统IT顾问的深度思考

AI浪潮下的IT职业转型:医药流通行业传统IT顾问的深度思考 一、AI重构IT行业的技术逻辑与实践路径 1.1 医药流通领域的智能办公革命 在医药批发企业的日常运营中,传统IT工具正经历颠覆性变革。以订单处理系统为例,某医药集团引入AI智能客服…

Qt进阶开发:QFileSystemModel的使用

文章目录 一、QFileSystemModel的基本介绍二、QFileSystemModel的基本使用2.1 在 QTreeView 中使用2.2 在 QListView 中使用2.3 在 QTableView 中使用 三、QFileSystemModel的常用API3.1 设置根目录3.2 过滤文件3.2.1 仅显示文件3.2.2 只显示特定后缀的文件3.2.3 只显示目录 四…

KAPC的前世今生--(下)下RPCRT4!NMP_SyncSendRecv函数分析

第一部分:nt!KiDeliverApc函数调用nt!IopCompleteRequest函数后准备返回 1: kd> kv # ChildEBP RetAddr Args to Child 00 ba3eec18 80a3c83b 896e4e40 ba3eec64 ba3eec58 nt!IopCompleteRequest0x3a3 (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv…

深入理解C++引用:从基础到现代编程实践

一、引用的本质与基本特性 1.1 引用定义 引用是为现有变量创建的别名,通过&符号声明。其核心特点: 必须初始化且不能重新绑定 与被引用变量共享内存地址 无独立存储空间(编译器实现) 类型必须严格匹配 int value 42; in…

嵌入式Linux开发环境搭建,三种方式:虚拟机、物理机、WSL

目录 总结写前面一、Linux虚拟机1 安装VMware、ubuntu18.042 换源3 改中文4 中文输入法5 永不息屏6 设置 root 密码7 安装 terminator8 安装 htop(升级版top)9 安装 Vim10 静态IP-虚拟机ubuntu11 安装 ssh12 安装 MobaXterm (SSH)…

软件工程面试题(二十七)

1、j a v a 对象初始化顺序 1.类的初始化(initialization class & interface) 2.对象的创建(creation of new class instances) 顺序:应为类的加载肯定是第一步的,所以类的初始化在前。大体的初始化顺序是: 类初始化 -> 子类构造函数 -> 父类构造函数 -&g…

《AI大模型开发笔记》MCP快速入门实战(一)

目录 1. MCP入门介绍 2. Function calling技术回顾 3. 大模型Agent开发技术体系回顾 二、 MCP客户端Client开发流程 1. uv工具入门使用指南 1.1 uv入门介绍 1.2 uv安装流程 1.3 uv的基本用法介绍 2.MCP极简客户端搭建流程 2.1 创建 MCP 客户端项目 2.2 创建MCP客户端…

Java中的正则表达式Lambda表达式

正则表达式&&Lambda表达式 正则表达式和Lambda表达式是Java编程中两个非常实用的特性。正则表达式用于字符串匹配与处理,而Lambda表达式则让函数式编程在Java中变得更加简洁。本文将介绍它们的基本用法,并结合示例代码帮助理解。同时要注意&…

Talend API Tester

背景 工作中有时会需要调测http接口,postman无疑是最常用最流行的工具,但是有一个致命问题,必须要登录,而工作经常是私网环境,导致使用非常不方便。因此想找一个Windows系统上的轻量级、无需登录即可使用的http测试工…

leetcode数组-移除元素

题目 题目链接:https://leetcode.cn/problems/remove-element/ 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为…

什么是市盈率,通俗解释清楚

市盈率就是“股价和公司盈利能力”的一个比例关系,简单来说,就是你花多少钱买股票,要等多少年才能通过公司赚的钱“回本”。 假设你买了一家公司的股票,花了100块钱,这家公司每年能赚10块钱。那市盈率就是100除以10&am…

突破传统认知:聚类算法的底层逻辑与高阶应用全景解析

一、维度革命:重新定义聚类分析的认知边界 在人工智能的浩瀚星空中,聚类算法犹如一组精密的星际导航仪,帮助我们在无序的数据宇宙中发现隐藏的秩序。这项起源于人类本能分类需求的技术,经历了从简单分组到智能识别的蜕变&#xf…

【愚公系列】《高效使用DeepSeek》051-产品创新研发

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…