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 '='
      

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

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

相关文章

FCBP 认证考试要点摘要

理论知识 数据处理与分析&#xff1a;包括数据的收集、清洗、转换、存储等基础操作&#xff0c;以及数据分析方法&#xff0c;如描述性统计分析、相关性分析、数据挖掘算法等的理解和应用 。数据可视化&#xff1a;涉及图表类型的选择与应用&#xff0c;如柱状图、折线图、饼图…

类和对象下

目录 1. 赋值运算符重载 1.1 运算符重载 1.2 赋值运算符重载 1.3 日期类的实现 1.4 const修饰成员变量 2. 构造函数之初始化列表 3. 类型转换 3. static成员 4. 友元 5. 内部类 6. 日期差 1. 赋值运算符重载 1.1 运算符重载 当运算符被用于类类型的对象时&#x…

oracle RAC各版本集群总结和常用命令汇总

oracle RAC学习 RAC介绍 RAC&#xff1a;高可用集群&#xff0c;负载均衡集群&#xff0c;高性能计算集群 RAC是⼀种⾼可⽤&#xff0c;⾼性能&#xff0c;负载均衡的share-everything的集群 8i:内存融合雏形 内存融合雏形&#xff08;Oracle Parallel Server&#xff09;…

今天我们来聊聊Maven中两个高级的概念—— 插件和目标

插件&#xff08;plugin&#xff09; Maven的核心是一个插件执行框架;所有的工作都是由插件完成的。 Maven中Plugin分为两种类型&#xff1a; build类型Plugin只能在build阶段执行&#xff0c;在POM中需要在 <build/> 标签下进行配置。 reporting类型&#xff1a;在si…

[每周一更]-(第125期):模拟面试|NoSQL面试思路解析

文章目录 39|Elasticsearch 高可用:怎么保证 Elasticsearch 的高可用?1. Elasticsearch 的节点有什么角色?一个节点可以扮演多个角色吗?2. 在实践中,怎么合理安排不同节点扮演的角色?3. 什么是候选主节点和投票节点?投票节点可以被选为主节点吗?为什么要引入投票节点?…

【人工智能】Transformers之Pipeline(二十七):蒙版生成(mask-generation)

​​​​​​​ 目录 一、引言 二、蒙版生成&#xff08;mask-generation&#xff09; 2.1 概述 2.2 facebook/sam-vit-base 2.3 pipeline参数 2.3.1 pipeline对象实例化参数 2.3.2 pipeline对象使用参数 2.3.3 pipeline对象返回参数 2.4 pipeline实战 2.5 模型排…

蓝牙设备驱动开发

文章目录 一、蓝牙协议架构二、蓝牙协议的HCI传输层三、编程框架 一、蓝牙协议架构 蓝牙是无线数据和语音传输的开放式标准&#xff0c;它将各种通信设备、计算机及其终端设备、各种数字数据系统、甚至家用电器采用无线方式联接起来。它的传输距离为10cm&#xff5e;10m&#…

【Linux】开启你的Linux之旅:初学者指令指南

Linux相关知识点可以通过点击以下链接进行学习一起加油&#xff01; 在 Linux 开发中&#xff0c;GDB 调试器和 Git 版本控制工具是开发者必备的利器。GDB 帮助快速定位代码问题&#xff0c;Git 则提供高效的版本管理与协作支持。本指南将简明介绍两者的核心功能与使用技巧&…

你还没有将 Siri 接入GPT对话功能吗?

由于各种原因&#xff0c;国内ios用户目前无缘自带 AI 功能&#xff0c;但是这并不代表国内 ios 无法接入 AI 功能&#xff0c;接下来手把手带你为iPhone siri 接入 gpt 对话功能。 siri 接入 chatGPT 暂时还无法下载 ChatGPT app&#xff0c;或者没有账号的读者可以直接跳到…

bash命令缓存导致命令执行失败的问题

1、问题背景 为了修复老版本 vsftpd 的安全漏洞&#xff0c;需要把生产环境上 vsftpd 版本升级到 vsftpd-3.0.5&#xff0c;因为直接使用 rpm 包的方式进行升级还涉及到下层依赖包的升级(生产环境上的依赖包版本不能随意变更&#xff0c;可能会影响其他上层应用)&#xff0c;所…

import.meta.glob动态加载图片

import.meta.glob 基于Vite&#xff08;Vue 3 默认构建工具&#xff09;&#xff0c;用于动态导入模块&#xff0c;特别是当你需要批量导入文件或模块时. const modules import.meta.glob(/path/to/files/**/*.js);注意&#xff1a;import.meta.glob 是针对 源代码&#xff…

困扰解决:mfc140u.dll丢失的解决方法,多种有效解决方法全解析

当电脑提示“mfc140u.dll丢失”时&#xff0c;这可能会导致某些程序无法正常运行&#xff0c;给用户带来不便。不过&#xff0c;有多种方法可以尝试解决这个问题。这篇文章将以“mfc140u.dll丢失的解决方法”为主题&#xff0c;教大家有效解决mfc140u.dll丢失。 判断是否是“mf…

状态模式S

状态模式&#xff08;State Pattern&#xff09;是行为设计模式的一种&#xff0c;它允许一个对象在其内部状态发生改变时改变其行为。这个对象被视为类型的有限状态机&#xff08;Finite State Machine&#xff09;。 在状态模式中&#xff0c;我们创建表示各种状态的对象和一…

Webman中实现定时任务

文章目录 Webman中实现定时任务一、引言二、安装与配置1、安装Crontab组件2、创建进程文件3、配置进程文件随Webman启动4、重启Webman5、Cron表达式&#xff08;补充&#xff09;例子 三、使用示例四、总结 Webman中实现定时任务 一、引言 在现代的后端开发中&#xff0c;定时…

瀚高创库建表pgsql

1.瀚高下载地址&#xff1a; 下载 (highgo.com)https://www.highgo.com/down_main.html 2.瀚高linux安装 上传deb文件到ubuntu系统中 执行 dpkg -i hgdb-see-4.5.8-fe4791c.x86_64.deb 命令安装数据库 安装完成后&#xff0c;会在/opt 目录下生成安装目录 数据库安装完毕后…

5.11【机器学习】

先是对图像进行划分 划分完后&#xff0c; 顺序读取文件夹&#xff0c;在文件夹里顺序读取图片&#xff0c; 卷积层又称为滤波器&#xff0c;通道是说滤波器的个数&#xff0c;黑白通道数为1&#xff0c;RGB通道个数为3 在输入层&#xff0c;对于输入层而言&#xff0c;滤波…

Ajax基础总结(思维导图+二维表)

一些话 刚开始学习Ajax的时候&#xff0c;感觉很模糊&#xff0c;但是好像学什么都是这样的&#xff0c;很正常&#xff0c;但是当你学习的时候要持续性敲代码&#xff0c;边敲代码其实就可以理解很多了。然后在最后的总结&#xff0c;其实做二维表之后&#xff0c;就可以区分…

Python 自动化办公的 10 大脚本

大家好&#xff0c;我是你们的 Python 讲师&#xff01;今天我们将讨论 10 个实用的 Python 自动化办公脚本。这些脚本可以帮助你简化日常工作&#xff0c;提高效率。无论是处理 Excel 文件、发送邮件&#xff0c;还是自动化网页操作&#xff0c;Python 都能派上用场。 1. 批量…

【北京迅为】iTOP-4412全能版使用手册-第二十章 搭建和测试NFS服务器

iTOP-4412全能版采用四核Cortex-A9&#xff0c;主频为1.4GHz-1.6GHz&#xff0c;配备S5M8767 电源管理&#xff0c;集成USB HUB,选用高品质板对板连接器稳定可靠&#xff0c;大厂生产&#xff0c;做工精良。接口一应俱全&#xff0c;开发更简单,搭载全网通4G、支持WIFI、蓝牙、…

[Linux] 信号(singal)详解(一)

标题&#xff1a;[Linux] 信号(singal)详解 水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 一、认识信号 1、认识信号 2、信号特点 3、基本概念 二、信号的产生&#xff08;5种方式&#xff09; 三、信号的保存 正文开始&#xff1a; 一、认识信号 1、认识信…