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

Makefile 入门指南:构建自动化编译流程

个人主页:chian-ocean

文章专栏

前言

makeMakefile 是编译和构建软件项目时非常常用的工具和文件,它们通常配合使用来自动化项目的编译过程。

在这里插入图片描述

make

定义make 是一个构建自动化工具,用于根据项目文件的依赖关系自动完成编译、链接和构建过程。

make主要用途

  1. 编译源代码:自动从源代码生成可执行文件。
  2. 管理项目依赖:只重新编译那些发生变化的文件,确保编译过程更高效。
  3. 简化构建任务:把繁琐的编译命令写入 Makefile,并通过简单的 make 命令执行它们

make 的工作方式

  • Makefile 文件make 的核心工作是读取一个叫 Makefile 的文件,该文件定义了目标(要生成的文件)、它们的依赖关系以及生成它们的命令。
  • 依赖管理:
    • 每个目标文件都有一组依赖和一个生成它的命令。
    • make 会比较源文件和目标文件的修改时间,如果源文件比目标文件更新,make 就会重新生成目标文件。
  • 增量编译:通过判断哪些文件已修改,make 只重新编译必要的部分。这种特性对于大型项目非常有用,因为它能极大地节省编译时间。

Makefile

定义Makefile 是一个文本文件,描述了如何构建项目文件的规则、文件之间的依赖关系,以及执行的具体构建命令。

makefile主要用途

  • 描述整个构建过程,使得 make 工具能够理解如何编译和链接项目。
  • 让开发人员能够清晰地看到项目的依赖关系和构建步骤,并且可以在团队中共享。

makefile基本组成

  • 目标(Target):通常是要生成的文件,例如对象文件或可执行文件。
  • 依赖(Dependencies):目标文件所依赖的其他文件,如源文件和头文件。
  • 命令(Commands):生成目标文件所需执行的命令。
target: dependenciescommand

注意:在命令行前面必须是 TAB 键,这在 Makefile 中是语法上的硬性要求,不能用空格代替。

makefile示例

code:code.o                                                                                   g++ -o code code.o
code.o:code.sg++ -c code.s -o code.o
code.s:code.ig++ -S code.i -o code.s
code.i:code.cpp g++ -E code.cpp -o code.i 
clean:rm -rf code code.i code.o code.s

当前目录:

在这里插入图片描述

执行:

make

在这里插入图片描述

makeMakefile 的优点

  1. 提高效率:手动编译多个源文件不仅繁琐,而且容易出错。make 能将这些编译过程自动化,只需简单地运行 make 即可完成所有工作。
  2. 管理复杂的依赖关系:对于大型项目,源代码之间的依赖关系错综复杂,make 可以通过 Makefile 自动处理这些依赖关系,确保每次构建只重新编译必需的部分。
  3. 团队合作和跨平台:通过编写一个清晰的 Makefile,开发者可以确保构建过程在不同的系统上是一致的,不同的开发人员都可以轻松构建相同的项目。

进度条小程序

void progressBar()
{char s[5] = "|/-\\";  // 旋转动画符号的数组char bar[NUM];        // 用于存储进度条符号的数组memset(bar, '\0', sizeof(bar));  // 将 bar 数组初始化为空字符int cnt = 0;          // 进度计数int len = sizeof(s);  // 符号数组 s 的长度while (cnt <= 100)    // 循环直到进度达到 100{// 打印进度条printf("[%-100s][%d%%][%c]\r", bar, cnt, s[cnt % len]);![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/dec237a1d49b491aa017974af7d009b3.png)fflush(stdout);  // 强制刷新输出缓冲区,确保进度条即时显示bar[cnt++] = STYLE;  // 在进度条的当前位置填入一个符号usleep(100000);      // 休眠 100 毫秒}printf("\n");  // 输出换行符,表示进度条结束
}

你提供的代码是一段用 C 语言编写的实现控制台进度条的函数。这段代码使用了一些经典的字符和动画效果来模拟一个在控制台中显示的进度条。下面我将逐步解析代码,并解释每个部分的功能。

代码解析

void progressBar()
{char s[5] = "|/-\\";  // 旋转动画符号的数组char bar[NUM];        // 用于存储进度条符号的数组memset(bar, '\0', sizeof(bar));  // 将 bar 数组初始化为空字符int cnt = 0;          // 进度计数int len = sizeof(s);  // 符号数组 s 的长度while (cnt <= 100)    // 循环直到进度达到 100{// 打印进度条printf("[%-100s][%d%%][%c]\r", bar, cnt, s[cnt % len]);fflush(stdout);  // 强制刷新输出缓冲区,确保进度条即时显示bar[cnt++] = STYLE;  // 在进度条的当前位置填入一个符号usleep(100000);      // 休眠 100 毫秒}printf("\n");  // 输出换行符,表示进度条结束
}

代码详解

  1. 定义字符数组用于旋转动画 (s[5] = "|/-\\")

    • char s[5] = "|/-\\";s 数组包含了四个不同的字符符号:'|''/''-''\\',这四个符号会在进度条的动画中轮流显示,制造一种旋转的效果。
  2. 初始化进度条字符串 (bar[NUM])

    • char bar[NUM];bar 用于存储进度条的状态,其中每个字符代表进度条的一部分。NUM 需要预先定义,通常等于 101,以便存储 100 个字符和一个结束符 '\0'
    • memset(bar, '\0', sizeof(bar));:使用 memset 将整个 bar 数组初始化为 '\0',确保没有多余字符影响输出。
  3. 进度条循环 (while(cnt <= 100))

    • while(cnt <= 100):这个循环从 0 到 100,表示进度百分比从 0% 逐步增加到 100%。
  4. 显示进度条 (printf)

    printf("[%-100s][%d%%][%c]\r", bar, cnt, s[cnt % len]);
    
    • [%-100s]:输出长度为 100 的字符串,%- 表示左对齐,所以进度条会从左到右扩展。
    • [cnt%]:显示当前进度百分比。
    • [s[cnt % len]]:这个部分用于动画效果,通过 cnt % len 的余数来取 s 数组中的字符,实现旋转动画。
    • \r:回车符,将光标返回到当前行的开头,以便刷新这行内容,达到更新进度条的效果。
  5. 刷新输出缓冲区 (fflush(stdout))

    • fflush(stdout);:刷新标准输出缓冲区,确保 printf 的内容能够立即显示到控制台,而不会被缓存。
  6. 更新进度条 (bar[cnt++] = STYLE)

    • bar[cnt++] = STYLE;STYLE 应该是一个宏定义,用于表示进度条填充的符号。例如,可以定义 STYLE 为:
      #define STYLE '='
      
      每次循环,bar 中对应的位置会填入 STYLE,逐步扩展进度条的长度。
  7. 休眠 (usleep(100000))

    • usleep(100000);:让程序暂停 100000 微秒(即 100 毫秒),控制进度条的更新速度,避免其变化过快看不清。
  8. 打印结束的换行符 (printf("\n"))

    • printf("\n");:当进度到达 100% 时,打印一个换行符,使光标移到下一行,避免与后续输出混淆。

代码中的注意事项

  1. NUM 的定义

    • 需要预先定义 NUM,通常设置为 101 来存储 100 个字符的进度条和一个结束符 \0。例如:
      #define NUM 101
      
  2. STYLE 的定义

    • 进度条的填充符号 STYLE 也需要定义。例如,可以这样定义:
      #define STYLE '='
      

进度条和一个结束符 \0。例如:
c #define NUM 101

  1. STYLE 的定义
    • 进度条的填充符号 STYLE 也需要定义。例如,可以这样定义:
      #define STYLE '='
      

相关文章:

Makefile 入门指南:构建自动化编译流程

个人主页&#xff1a;chian-ocean 文章专栏 前言 make 和 Makefile 是编译和构建软件项目时非常常用的工具和文件&#xff0c;它们通常配合使用来自动化项目的编译过程。 make 定义&#xff1a;make 是一个构建自动化工具&#xff0c;用于根据项目文件的依赖关系自动完成编译…...

C#热更原理与HybridCLR

一、Mono的诞生 在Mono之前,C#虽然很好,但是只在windows家族平台上使用,就这点C#与Java就无法比。于是微软公司向ECMA申请将C#作为一种标准。在2001年12月,ECMA发布了ECMA-334 C#语言规范。C#在2003年成为一个ISO标准(ISO/IEC 23270)。意味着只要你遵守CLI(Common Lang…...

里氏替换原则:Java面向对象设计的基石

在面向对象编程&#xff08;OOP&#xff09;中&#xff0c;继承是一个强大的工具&#xff0c;它允许我们创建新的类&#xff08;子类&#xff09;来复用和扩展现有类&#xff08;父类&#xff09;的功能。然而&#xff0c;继承也带来了复杂性&#xff0c;特别是在确保子类能够正…...

恒创科技:服务器操作系统和客户端操作系统之间的区别

客户端操作系统和服务器操作系统是两种不同的操作系统&#xff0c;旨在满足计算机网络环境中的特定目的。虽然每种类型的操作系统在基本功能方面都有一些相似之处&#xff0c;但它们针对不同的用例进行了优化&#xff0c;并具有针对其特定角色量身定制的特定功能。 什么是服务器…...

做异端中的异端 -- Emacs裸奔之路4: 你不需要IDE

确切地说&#xff0c;你不需要在IDE里面编写或者阅读代码。 IDE用于Render资源文件比较合适&#xff0c;但处理文本&#xff0c;并不划算。 这的文本文件&#xff0c;包括源代码&#xff0c;配置文件&#xff0c;文档等非二进制文件。 先说说IDE带的便利: 函数或者变量的自动…...

Unity3d C# 摄像头检测敌方单位(目标层级)并在画面中标注(含源码)

前言 需要实现的功能是通过一个专门的检测摄像头将出现在摄像头画面内的敌方单位检测出来&#xff0c;并通过框选的UI框在画面中标记出来。检测摄像头支持自动检测和手动控制检测&#xff0c;同时需要实现锁定模式&#xff0c;检测到一个敌方单位直接锁定到对象上等功能。 效…...

js 16进制加密

function hexEncode(str) { let hexEncodedStr ‘’; for (let i 0; i < str.length; i) { let charCode str.charCodeAt(i); let hexCode charCode.toString(16).padStart(2, ‘0’); hexEncodedStr ‘\x’ hexCode; } return hexEncodedStr; } // 示例用法 let ori…...

性能测试之压测

1、首先需要提前准备好需要压测的接口地址及对应的接口参数 写好对应的压测接口及对应参数脚本 2、添加线程组&#xff08;根据对应的需求提供的QPS及需要压测的数量如有&#xff09; 如&#xff1a;40个线程&#xff0c;循环次数为永远&#xff08;或者根据自身情况设置循…...

CentOS修改yum.repos.d源,避免“Could not resolve host: mirrorlist.centos.org”错误

1、问题现象 由于CentOS停止维护&#xff0c;mirrorlist.centos.org网站也关闭不可访问。导致CentOS默认配置的yum.repos.d源也不可用&#xff0c;所以执行yum命令会报“Could not resolve host: mirrorlist.centos.org”错误。具体如下&#xff1a; Could not retrieve mirror…...

Python 三目运算实战详解

Python 的三目运算符&#xff08;也称为条件表达式&#xff09;是一种简洁的方式来执行基于条件的赋值或返回值。它的语法类似于其他编程语言中的三元运算符&#xff0c;但有一些细微的不同。在 Python 中&#xff0c;三目运算符的语法如下&#xff1a; value_if_true if cond…...

JVM 性能调优 -- CMS 垃圾回收器 GC 日志分析【Full GC】

前言&#xff1a; 上一篇我们分析了 Minor GC 的发生过程&#xff0c;因为 GC 日志没有按我们预估的思路进行打印&#xff0c;其中打印了 CMS 垃圾回收器的部分日志&#xff0c;本篇我们就来分析一下 CMS 垃圾收集日志。 JVM 系列文章传送门 初识 JVM&#xff08;Java 虚拟机…...

PS的学习

背景差色较大&#xff0c;就魔棒 魔棒的连续就是倒水点的跨越问题 魔棒的容差的选择就有点看经验了&#xff0c;看颜色的统一程度选择 Ctrl D 取消当前所有的选区 至于快速选择工具&#xff0c;和对象选择工具也差不多&#xff0c;只不过控制范围变成了一块一块的&#x…...

数据集搜集器(百科)008

对数据集搜集器&#xff08;百科&#xff09;007进行一下改进&#xff1a; 错误处理&#xff1a;增加更多的错误处理&#xff0c;比如网络请求超时、解析错误等。 用户界面&#xff1a;增加一些提示信息&#xff0c;让用户更清楚当前的操作状态。 多线程处理&#xff1a;确保多…...

Java学习,反射

Java反射是Java编程语言的一个重要特性&#xff0c;它允许程序在运行时查看任意对象所属的类&#xff0c;获取类的内部信息&#xff08;包括构造器、字段和方法等&#xff09;&#xff0c;并能动态地调用对象的方法或构造器。 反射概念 反射&#xff08;Reflection&#xff09…...

数据结构 (18)数的定义与基本术语

前言 数据结构是计算机科学中的一个核心概念&#xff0c;它描述了数据元素之间的关系以及这些元素在计算机中的存储方式。 一、数的定义 在计算机科学中&#xff0c;“数”通常指的是树形数据结构&#xff0c;它是一种非线性的数据结构&#xff0c;由节点&#xff08;或称为元素…...

Flink的双流join理解

如何保证Flink双流Join准确性和及时性、除了窗口join还存在哪些实现方式、究竟如何回答才能完全打动面试官呢。。你将在文中找到答案。 1 引子 1.1 数据库SQL中的JOIN 我们先来看看数据库SQL中的JOIN操作。如下所示的订单查询SQL&#xff0c;通过将订单表的id和订单详情表ord…...

《使用Python进行数据挖掘:理论、应用与案例研究》

嘿&#xff0c;今天我要给你们介绍一本使用Python进行数据挖掘的好书。这本书是由吴迪博士撰写的&#xff0c;他是雷曼学院商学院的助理教授&#xff0c;也是数据科学的实战派。 在这个时代&#xff0c;数据多得让人眼花缭乱&#xff0c;要从中找出有用的信息&#xff0c;那可不…...

Go语言技巧:快速统一字符串中的换行符,解决跨平台问题

统一字符串中的 Windows \r\n 换行符 — Go语言实现 在编程中&#xff0c;尤其是处理跨平台的文本数据时&#xff0c;换行符的处理是一个常见的问题。Windows 系统使用 \r\n 作为换行符&#xff0c;而 Unix-like 系统&#xff08;如 Linux 和 macOS&#xff09;使用 \n。在 Go…...

算法训练营day20(二叉树06:最大二叉树,合并二叉树,搜索二叉树,验证搜索二叉树)

第六章 二叉树 part06 今日内容 ● 654.最大二叉树 ● 617.合并二叉树 ● 700.二叉搜索树中的搜索 ● 98.验证二叉搜索树 详细布置 654.最大二叉树 又是构造二叉树&#xff0c;昨天大家刚刚做完 中序后序确定二叉树&#xff0c;今天做这个 应该会容易一些&#xff0c; 先看视…...

Leetcode(区间合并习题思路总结,持续更新。。。)

讲解题目&#xff1a;合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c; 并返回一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间。示例 1&#xff1a;输入&a…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...