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: dependencies
     command
  • 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.o
      
      CXXFLAGS = -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)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

I.MX6ULL Linux C语言开发环境搭建(点灯实验)

系列文章目录 I.MX6ULL Linux C语言开发 I.MX6ULL Linux C语言开发 系列文章目录一、前言二、硬件原理分析三、构建步骤一、 C语言运行环境构建二、软件编写三、链接脚本 四、实验程序编写五、编译下载验证 一、前言 汇编语言编写 LED 灯实验&#xff0c;但是实际开发过程中汇…

二叉排序树的创建

二叉排序树就是节点经过排序构建起的二叉树&#xff0c;其有以下性质&#xff1a; 1. 若它的左子树不为空&#xff0c;则左子树上所有节点的值均小于它的根节点的值。 2. 若它的右子树不为空&#xff0c;则右子树上所有节点的值均大于它的根节点的值。 3. 它的左、右子树也分…

Golang并发编程-协程goroutine任务取消(Context)

文章目录 前言一、单个任务的取消二、 所有任务取消三、Context的出现Context的定义Context使用 总结 前言 在实际的业务种&#xff0c;我们可能会有这么一种场景&#xff1a;需要我们主动的通知某一个goroutine结束。比如我们开启一个后台goroutine一直做事情&#xff0c;比如…

探索Python编程乐趣:制作气泡反弹小游戏

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;Python编程的轻松入门 二、游戏实现原理&#xff1a;气泡反弹的逻辑 …

Linux|如何在 awk 中使用流控制语句

引言 当您从 Awk 系列一开始回顾我们迄今为止介绍的所有 Awk 示例时&#xff0c;您会注意到各个示例中的所有命令都是按顺序执行的&#xff0c;即一个接一个。但在某些情况下&#xff0c;我们可能希望根据某些条件运行一些文本过滤操作&#xff0c;这就是流程控制语句的方法。 …

【MyBatis】MyBatis解析全局配置文件源码详解

目录 一、前言 思维导图概括 二、配置文件解析过程分析 2.1 配置文件解析入口 2.2 初始化XMLConfigBuilder 2.3 XMLConfigBuilder#parse()方法&#xff1a;解析全局配置文件 2.3.1 解析properties配置 2.3.2 解析settings配置 2.3.2.1 元信息对象&#xff08;MetaClas…

结构型模式之桥接模式

文章目录 概述原理结构图代码示例 小结 概述 桥接模式(bridge pattern) 的定义是&#xff1a;将抽象部分与它的实现部分分离&#xff0c;使它们都可以独立地变化。 桥接模式用一种巧妙的方式处理多层继承存在的问题,用抽象关联来取代传统的多层继承,将类之间的静态继承关系转…

oracle数据库无法连接问题排查

查看数据库告警日志如下图。发现问题时间段&#xff0c;没有数据库服务故障报错&#xff0c;但是存在较多TNS-12535、12560、12170、00505错误&#xff1a; 通过检查问题时间段应用日志&#xff0c;也记录了Caused by:java.sql.SQLRecoverableException: IO 错误: Connection r…

从反向传播(BP)到BPTT:详细数学推导【原理理解】

从反向传播到BPTT&#xff1a;详细推导与问题解析 在本文中&#xff0c;我们将从反向传播算法开始&#xff0c;详细推导出反向传播通过时间&#xff08;Backpropagation Through Time, BPTT&#xff09;算法。重点讨论BPTT中的梯度消失和梯度爆炸问题&#xff0c;并解释如何解…

如何彻底搞懂装饰器(Decorator)设计模式?

对于任何一个软件系统而言&#xff0c;往现有对象中添加新功能是一种不可避免的实现场景&#xff0c;但这一实现过程对现有系统的影响可大可小。从架构设计上讲&#xff0c;我们也知道存在一个开闭原则&#xff08;Open-Closed Principle&#xff0c;OCP&#xff09;&#xff0…

asp.net core接入prometheus2-自定义指标

前提 了解一下asp.net core接入prometheus快速入门 https://blog.csdn.net/qq_36437991/article/details/139064138 新建.net 8空web项目 安装下面三个包 <PackageReference Include"OpenTelemetry.Exporter.Prometheus.AspNetCore" Version"1.8.0-rc.1&…

真拿AI赚到钱的人,不在朋友圈里

1 最近有张两大AI巨头对比的梗图给我看乐了&#xff0c;玩儿AI的还在做产品&#xff0c;玩儿焦虑的已经在数钱了。 这也是在做AI&#xff0c;只不过是唉声叹气的ai。 要我说&#xff0c;现在缺的根本不是AI&#xff0c;而是【有用的AI】。 恩格斯老师说过一句话&#xff1a…

Java 对接百度网盘

文章目录 前言一、创建百度网盘账号二、代码实现1. 常量类2. 工具类3. 授权码模式授权4. 文件分片上传&#xff08;可获取进度&#xff09;--方法一5. 文件下载(可获取进度)--方法一6. 获取文件列表7. 文件分片上传&#xff08;不可获取进度&#xff09;--方法二7. 文件下载&am…

算法之堆排序

堆排序是一种基于比较的排序算法&#xff0c;通过构建二叉堆&#xff08;Binary Heap&#xff09;&#xff0c;可以利用堆的性质进行高效的排序。二叉堆是一个完全二叉树&#xff0c;可以有最大堆和最小堆两种形式。在最大堆中&#xff0c;父节点的值总是大于或等于其子节点的值…

C++与Android处理16进制大端/小端数据实例(二百七十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

“大数据建模、分析、挖掘技术应用研修班”的通知!

随着2015年9月国务院发布了《关于印发促进大数据发展行动纲要的通知》&#xff0c;各类型数据呈现出了指数级增长&#xff0c;数据成了每个组织的命脉。今天所产生的数据比过去几年所产生的数据大好几个数量级&#xff0c;企业有了能够轻松访问和分析数据以提高性能的新机会&am…

夏日采摘季,视频智能监控管理方案助力智慧果园管理新体验

5月正值我国各地西瓜、杨梅、大樱桃、油桃等水果丰收的季节&#xff0c;许多地方都举办了采摘旅游活动&#xff0c;吸引了众多游客前来体验采摘乐趣。随着采摘的人流量增多&#xff0c;果园的管理工作也面临压力。 为了提升水果园采摘活动的管理效果&#xff0c;减少人工巡查成…

harbor 认证

Harbor 认证过程 Harbor以 Docker Registry v2认证为基础&#xff0c;添加上一层权限保护。1.v2 集成了一个安全认证的功能&#xff0c;将安全认证暴露给外部服务&#xff0c;让外部服务去实现2.强制用户每次Docker pull/push请求都要带一个合法的Token&#xff0c;Registry会…

基于jeecgboot-vue3的Flowable新建流程定义(一)

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、vue3版本因为流程分类是动态的&#xff0c;不再固定了&#xff0c;所以新建的时候需要选择建立哪种流程类型的流程 代码如下&#xff1a; <!-- 选择模型的流程类型对话框 -->&…

JDBCTemplate介绍

Spring JDBC Spring框架对Spring的简单封装。提供一个JDBCTemplate对象简化JDBC开发 *步骤&#xff1a; 1、导入jar包 2、创建JDBCTemplate对象。依赖于数据源DataSource *JdbcTemplate templatenew JdbcTemplate(ds); 3、调用JdbcTemplate的方法来完成CRUD的操作 *update()&…