makefile 编写规则

1.概念

1.1 什么是makefile

Makefile 是一种文本文件,用于描述软件项目的构建规则和依赖关系,通常用于自动化软件构建过程。它包含了一系列规则和指令,告诉构建系统如何编译和链接源代码文件以生成最终的可执行文件、库文件或者其他目标文件。

1.2 使用makefile的优点

Makefile 主要用于管理大型项目的构建过程,它可以:

  1. 自动检测源代码文件的变化,只编译发生变化的文件,以提高构建效率。
  2. 根据依赖关系自动构建所需的目标文件,无需手动管理编译顺序。
  3. 支持通过简单的命令来进行构建、清理和其他任务,提高了项目的可维护性和可重复性。
  4. 可以轻松地添加自定义的构建规则和操作,满足特定项目的需求。

Makefile 使用一种称为 Make 的构建工具来解析和执行其中的规则。Make 工具会根据 Makefile 中定义的规则和依赖关系,确定需要重新构建的目标文件,并执行相应的命令来完成构建过程。

2.演变的过程

2.1 gcc编译

在我们平常linux下编译文件的时候通过gcc全部编译链接生成可执行的文件

这样编译导致的后果是每次改动某一个代码,其他文件都要跟着编译,非常的繁琐每次,那我们有什么更简单的方法吗,有

2.2 gcc单个文件编译后链接

很明显,大家已经看到了,虽然有一点优化,但不多。这也是不可取的。这时候在linux编译链接的时候就出现了makefile文件。

2.3 Makefile的工作原理

Makefile 的工作原理主要涉及两个部分:规则(rules)和依赖关系(dependencies)。Makefile 中包含了一系列规则,每个规则描述了如何生成一个或多个目标文件,并指定了生成目标文件所需的依赖文件和生成命令。Make 工具会根据这些规则来自动执行构建过程。
下面是 Makefile 的工作原理的详细解释:

1.目标和依赖关系定义:

  • Makefile 中的每个规则由一个或多个目标(targets)和其对应的依赖关系(dependencies)组成。目标通常是文件名,代表生成的目标文件或执行的操作。依赖关系是目标文件所依赖的文件列表,通常是源文件或其他目标文件。
  • 每个规则的格式通常为
 target: dependenciescommand
  • target 是目标文件或操作的名称,dependencies 是生成 target 所需的依赖文件列表,command 是生成 target 的命令。
      检查文件时间戳
    • 在执行 Makefile 时,Make 工具会检查每个目标文件和其依赖文件的时间戳,以确定哪些文件需要重新生成。
    • 如果目标文件不存在,或者其时间戳早于任何一个依赖文件的时间戳,那么 Make 工具会执行生成目标文件的命令。
    • 执行生成命令

      • 当确定需要重新生成目标文件时,Make 工具会执行该目标的生成命令。生成命令通常是编译源文件、链接目标文件或执行其他操作的命令。
      • Make 工具会按照 Makefile 中规定的顺序依次执行每个目标的生成命令,直到所有目标文件都被成功生成。
    • 递归处理依赖

      • 如果一个目标文件的依赖文件也是其他目标文件,则 Make 工具会递归处理这些依赖关系,确保所有依赖文件都被生成。
    • 增量构建

      • Make 工具会根据文件的时间戳判断哪些文件需要重新生成,从而实现增量构建。只有发生了变化的文件及其依赖文件才会重新生成,提高了构建效率。
    • 通过这样的方式,Makefile 提供了一种简洁而有效的方法来管理项目的构建过程,自动化了源代码的编译、链接和其他构建操作,使得项目的开发和维护更加高效和可靠。

      2.4 初阶Makefile文件

    • 这个版本的Makefile虽然有了一定的用途,但还是无法解决文件太多的问题。如何解决这一难题呢,我们接着向下看
    • 2.5 中阶Makefile文件


    • 虽然这个看起来已经比较完善了,但是依旧在文件太多的时候,会出现很多编译.c的文件,那有没有什么办法,让其不用这么麻烦呢
    • 2.6 后阶Makefile文件

    • CXX = gcc
      TARGET = aio
      OBJ = BintrayTree.o Queue.o test.oCXXFLAGS = -c -Wall$(TARGET) : $(OBJ)
      # $@ 表示目标文件
      # $^ 所依赖文件$(CXX) -o $@ $^
      # % 是一个通配符,用于匹配任意长度的字符序列
      %.o : %.c
      # $< 第一个依赖文件$(CXX) $(CXXFLAGS) $< -o $@# .PHONY防止出现于clear重名的文件而发生歧义
      .PHONY: clear
      # make clear 执行下面的命令(删除后缀.o和编译链接后的目标文件)
      clear:rm -r *.o $(TARGET)

    • 这样我们,其实已经足够优化了,但是我们任然有可优化的地方,比如,我们可不可不列出链接的依赖文件,当然可以的

    • 2.7 终极版本

    • 到这里,我们就可以很清楚的认识到Makefile的优化过程
      CXX = gcc
      TARGET = aio
      #将后缀为.c的文件放入windcard中
      SRC = $(wildcard *.c)
      #路径替换,将SRC中的.c替换为.o
      OBJ = $(patsubst %.c, %.o, $(SRC))CXXFLAGS = -c -Wall$(TARGET) : $(OBJ)
      # $@ 表示目标文件
      # $^ 所依赖文件$(CXX) -o $@ $^
      # % 是一个通配符,用于匹配任意长度的字符序列
      %.o : %.c
      # $< 第一个依赖文件$(CXX) $(CXXFLAGS) $< -o $@# .PHONY防止出现于clear重名的文件而发生歧义
      .PHONY: clear
      # make clear 执行下面的命令(删除后缀.o和编译链接后的目标文件)
      clear:rm -r *.o $(TARGET)


      3,Makefile的编码规则

    • 我们之前已经有所了解Makefile的编码规则,但是在这里我还是觉得有必要总体讲一下

      在编写 Makefile 时,遵循一些编码规则可以使其更加清晰、易于维护和跨平台。下面是一些常见的 Makefile 编码规则:

      1.缩进使用Tab键:
      Makefile 中命令行必须使用 Tab 键进行缩进,而不是空格。这是因为 Make 工具默认使用 Tab 键作为命令行的缩进标识,使用空格可能会导致 Make 解析错误。
      2.目标和依赖关系之间的冒号:
      目标(target)和依赖关系(dependencies)之间使用冒号(:)分隔。冒号前面是目标,后面是依赖关系。
      3.命令行前面的Tab键:
      在每个规则中,命令行必须以 Tab 键开头,表示该命令是该规则的执行命令。除了注释以外,任何其他以 Tab 键开头的行都被视为命令。
      4.变量使用大写字母:
      为了与命令和目标区分开,通常将变量使用大写字母命名。例如:CC = gcc。
      5.使用变量代替硬编码的命令和路径:
      使用变量来代替硬编码的命令和路径,使得 Makefile 更加灵活和可移植。例如,将编译器命令使用变量表示:CC = gcc,然后在规则中使用 $(CC) 来引用。

    • 6.使用伪目标:
      对于不产生实际文件的操作(如清理、安装等),使用伪目标(.PHONY)来定义。这样可以确保即使存在同名文件,也不会误导 Make 工具。例如:.PHONY: clean。
      7.注释使用 #:
      使用 # 符号来添加注释,使得 Makefile 更具可读性。注释可以帮助理解 Makefile 中每个规则的作用。
      8.模块化设计:
      将 Makefile 模块化,分成多个小的 Makefile 文件,然后通过 include 指令引入。这样可以提高 Makefile 的可维护性和可读性,减少重复代码。
      9.合理使用条件语句:
      可以使用条件语句(如 ifeq、ifdef 等)来根据不同的条件执行不同的规则或命令,以实现更灵活的构建过程。
      10.跨平台兼容性:
      考虑到不同平台下的路径分隔符和命令格式的差异,编写具有跨平台兼容性的 Makefile。可以使用自动化工具或条件语句来处理不同平台下的差异。

      遵循这些规则可以使 Makefile 更加规范、易读和易于维护,有助于提高项目的构建效率和可靠性。

      4,每期一问

    • 4.1 上期答案

      // 计算树的高度
      int getHeight(struct TreeNode* root) {if (root == NULL) {return 0;}int leftHeight = getHeight(root->left);int rightHeight = getHeight(root->right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
      }// 判断是否是平衡二叉树的辅助函数
      bool isBalancedHelper(struct TreeNode* root) {if (root == NULL) {return true;}int leftHeight = getHeight(root->left);int rightHeight = getHeight(root->right);if (abs(leftHeight - rightHeight) <= 1 && isBalancedHelper(root->left) && isBalancedHelper(root->right)) {return true;}return false;
      }// 判断是否是平衡二叉树
      bool isBalanced(struct TreeNode* root) {return isBalancedHelper(root);
      }

      4.2 本期问题. - 力扣(LeetCode)

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

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

相关文章

Node.js知识点以及案例总结

思考&#xff1a;为什么JavaScript可以在浏览器中被执行 每个浏览器都有JS解析引擎&#xff0c;不同的浏览器使用不同的JavaScript解析引擎&#xff0c;待执行的js代码会在js解析引擎下执行 为什么JavaScript可以操作DOM和BOM 每个浏览器都内置了DOM、BOM这样的API函数&#xf…

开源模型应用落地-食用指南-以最小成本博最大收获

一、背景 时间飞逝&#xff0c;我首次撰写的“开源大语言模型-实际应用落地”专栏已经完成了一半以上的内容。由衷感谢各位朋友的支持,希望这些内容能给正在学习的朋友们带来一些帮助。 在这里&#xff0c;我想分享一下创作这个专栏的初心以及如何有效的&#xff0c;循序渐进的…

STM32F103C8T6 HC-SR04超声波模块——超声波障碍物测距(HAl库)

超声波障碍物测距 一、HC-SR04超声波模块&#xff08;一&#xff09;什么是HC-SR04&#xff1f;&#xff08;二&#xff09;HC-SR04工作原理&#xff08;三&#xff09;如何使用HC-SR04&#xff08;四&#xff09;注意事项 二、程序编写&#xff08;一&#xff09;CubeMX配置1.…

2024全新Langchain大模型AI应用与多智能体实战开发

2024全新Langchain大模型AI应用与多智能体实战开发 LangChain 就是一个 LLM 编程框架&#xff0c;你想开发一个基于 LLM 应用&#xff0c;需要什么组件它都有&#xff0c;直接使用就行&#xff1b;甚至针对常规的应用流程&#xff0c;它利用链(LangChain中Chain的由来)这个概念…

Facebook之魅:数字社交的体验

在当今数字化时代&#xff0c;Facebook作为全球最大的社交平台之一&#xff0c;承载着数十亿用户的社交需求和期待。它不仅仅是一个简单的网站或应用程序&#xff0c;更是一个将世界各地的人们连接在一起的社交网络&#xff0c;为用户提供了丰富多彩、无与伦比的数字社交体验。…

C++实现基础二叉搜索树(并不是AVL和红黑树)

本次实现的二叉搜索树并不是AVL数和红黑树&#xff0c;只是了解流程和细节。 目录 二叉搜索树的概念K模型二叉搜索树的实现二叉搜索树的架构insert插入find 查找中序遍历Inorder删除earse替换法的思路情况一 &#xff1a;假如要删除节点左边是空的。在左边时在右边时 情况二&a…

文心智能体,零代码构建情感表达大师智能体

前言 随着智能体技术的突飞猛进&#xff0c;各行各业正迎来前所未有的变革与机遇。智能体&#xff0c;作为人工智能领域的重要分支&#xff0c;以其自主性、智能性和适应性&#xff0c;正逐步渗透到我们生活的每一个角落&#xff0c;成为推动社会进步和科技发展的新动力。 为了…

visual studio 2022 ssh 主机密钥算法失败问题解决

 Solution - aengusjiang 问题&#xff1a; I follow the document, then check sshd_config, uncomment“HostKey /etc/ssh/ssh_host_ecdsa_key” maybe need add the key algorithms: #HostKeyAlgorithms ssh-ed25519[Redacted][Redacted]rsa-sha2-256,rsa-sha2-512 Ho…

Redis常用命令——String篇

前面我们讲解了一些 Redis 的全局命令&#xff08;Redis常用基本全局命令&#xff09;。所谓全局命令&#xff0c;就是可以匹配任意一个数据结构进行使用。但是不同的数据结构&#xff0c;也有自己的操作命令。本篇文章主要讲解的是 String 的操作命令&#xff0c;希望会对你有…

ClickHouse课件

列式存储数据库&#xff1a;hbase clickhouse 简介 ClickHouse入门 ClickHouse是俄罗斯的Yandex于2016年开源的列式存储数据库&#xff08;DBMS&#xff09;&#xff0c;使用C语言编写&#xff0c;主要用于在线分析处理查询&#xff08;OLAP&#xff09;&#xff0c;能够使用…

2024年电工杯B题论文首发+问题一论文代码分享

问题一论文代码链接&#xff1a;https://pan.baidu.com/s/1kDV0DgSK3E4dv8Y6x7LExA 提取码&#xff1a;sxjm --来自百度网盘超级会员V5的分享 基于数据分析的大学生平衡膳食食谱的优化设计及评价 摘要 大学时期不仅是学术学习和身体成长的关键阶段&#xff0c;更是青年学生…

Hsql每日一题 | day03

前言 就一直向前走吧&#xff0c;沿途的花终将绽放~ 题目&#xff1a;打折日期交叉问题 如下为平台商品促销数据&#xff1a;字段为品牌&#xff0c;打折开始日期&#xff0c;打折结束日期 brand stt edt oppo,2021-06-05,2021-06-09 oppo,2021-06-11,2021-06-21 vivo,…

Java中流的概念细分

按流的方向分类&#xff1a; 输入流&#xff1a;数据流向是数据源到程序&#xff08;以InputStream、Reader结尾的流&#xff09;。 输出流&#xff1a;数据流向是程序到目的地&#xff08;以OutputStream、Writer结尾的流&#xff09;。 按处理的数据单元分类&#xff1a; 字…

PVE 虚拟机环境下删除 local-lvm分区

1、删除逻辑卷 lvremote pve/data 2、扩展逻辑卷 lvextend -l 100%FREE -r pve/root 3、 修改存储目录内容 点击 Datacenter - Storage &#xff08;1&#xff09;删除local-lvm分区 &#xff08;2&#xff09;编辑local分区&#xff0c;在内容一项中勾选所有可选项。

Spring Boot 3.3 正式发布,王炸级更新,应用启动速度直接起飞!

最新消息&#xff0c;Spring Boot 一次性发布了 3 个版本&#xff1a; 3.3.0 3.2.6 3.1.13 Spring Boot 3.3 正式发布了&#xff0c;3.1.x 在前几天也停止维护了。 最新的支持版本如下&#xff1a; 从路线图可以看到每个版本的终止时间&#xff0c;每个版本的生命周期只有…

clickhouse 中的数组(array)和元组(Tuple)—— clickhouse 基础篇(二)

文章目录 数组判断是否为空计算数组长度获取数组元素判断某个元素是否存在数组切片数组元素展开数组元素去重删除连续重复元素连接多个数组数组倒序数组拍平数组元素映射数组元素过滤数组聚合分析计算数组交集计算数组并集计算数组差集SQL 子查询进行集合操作 元组创建元组获取…

LeetCode刷题之HOT100之二叉树的直径

2024/5/25 阴天。这几天睡眠质量都非常好&#xff0c;一切似乎都在慢慢上升。先把题做了 1、题目描述 2、逻辑分析 题目要求就是给一个二叉树&#xff0c;求出两个节点之间的最大长度即为二叉树的直径。怎么做呢&#xff1f;我想不出来。看一下题解吧。题解给出的解法是深度优…

Linux——Docker容器虚拟化平台

安装docker 安装 Docker | Docker 从入门到实践https://vuepress.mirror.docker-practice.com/install/ 不需要设置防火墙 docker命令说明 docker images #查看所有本地主机的镜像 docker search 镜像名 #搜索镜像 docker pull 镜像名 [标签] #下载镜像&…

mybatis-plus 优雅的写service接口中方法(3)

多表联查 上文讲过了自定义sql &#xff0c;和wrapper的使用&#xff0c;但是我们可以发现 我们查询的都是数据库中的一张表&#xff0c;那么怎么进行多表联查呢&#xff0c;当然也是用自定义sql来进行实现 比如说 查询 id 为 1 2 4 的用户 并且 地址在北京 的 用户名称 普…

Elasticsearch不删原有jdk8导致的系列安装和启动问题

以前在空机器直接装elasticsearch&#xff0c;没有遇到什么问题。今天在现有JDK上安装&#xff0c;遇到的问题记录一下&#xff1a; 1. JDK的环境变量配置与我原有的不一致报如下错误&#xff1a; [estestZK-DES-I root]$ /usr/elasticsearch/bin/elasticsearch could not fi…