Linux的makefile与进度条小程序实践

news2024/10/27 3:33:23

makefile

  • make命令
    • 主要功能
    • 使用方法
    • 常用选项
  • makefile文件
    • 基本结构
    • 使用案例
    • 变量定义
    • 内置变量(即系统定义的确定变量)
    • 伪目标
    • 模式规则
    • 条件语句
    • 注释
    • makefile中的常用函数
  • 进度条小程序
    • 创建文件
    • 编辑.h文件
    • 编辑.c文件
    • 创建main函数
    • makefile文件
    • 执行效果

make命令

在linux中,make 是一个自动化构建工具,主要用于管理和控制项目的编译过程。它通过读取 Makefile(makefile) 文件中的规则和指令,自动执行所需的命令,以便构建可执行程序、库或其他文件。

主要功能

自动化构建:通过简单的命令(如 make),make 可以根据 Makefile 中的定义自动完成编译和链接过程。

处理依赖关系:make 会检查文件之间的依赖关系,只重新编译那些已更改的源文件,节省时间和资源。

多平台支持:make 是一种标准工具,可以在不同的 Unix-like 系统上使用。

使用方法

基本的 make 命令格式如下:

make [target]

target:要构建的目标。如果不指定目标,make 默认构建第一个目标。

常用选项

-f FILE:指定使用的 Makefile 文件,默认是 Makefile 或 makefile。
-j N:并行构建,N 是并行执行的任务数量。
-k:即使某个目标构建失败,也继续构建其他目标。
-n:显示将要执行的命令,但不实际执行。
-B:强制所有目标重新构建。

makefile文件

在 Makefile 中,语法结构相对简单,主要包括目标、依赖关系和命令。以下是一些基本语法元素:

基本结构

Makefile 的基本结构由规则、目标、依赖和命令组成:

target: dependencies
    command

target:要生成的文件或目标,可以是可执行文件、对象文件等。
dependencies:生成目标所依赖的文件列表。
command:用于生成目标的命令,必须TAB 开头。

使用案例

# 一个简单的示例 Makefile

CC = gcc                # 指定编译器
CFLAGS = -Wall -g      # 编译选项

# 定义目标
all: myprogram

# 规则
myprogram: main.o utils.o
    $(CC) $(CFLAGS) -o myprogram main.o utils.o

# 依赖规则
main.o: main.c
    $(CC) $(CFLAGS) -c main.c

utils.o: utils.c
    $(CC) $(CFLAGS) -c utils.c

# 清理命令
clean:
    rm -f myprogram *.o

变量定义

变量可以使用 = 或 := 定义

VAR = value          # 延迟赋值
VAR := value         # 立即赋值

变量在命令中可以用 $(VAR) 访问

$(CC) $(CFLAGS) -o myprogram main.o utils.o

内置变量(即系统定义的确定变量)

$@:目标文件的名称。
$<:第一个依赖文件的名称。
$^:所有依赖文件的名称。

伪目标

伪目标在 Makefile 中是一种特殊的目标,通常用于执行一些不会生成实际文件的命令,如清理、安装等。伪目标不依赖于文件的存在或更新,它们的存在主要是为了便于管理和执行特定的操作。

1. 伪目标的定义

伪目标通常使用 .PHONY 关键字进行声明,尽管在现代的 Make 工具中,即使不使用 .PHONY,伪目标仍然可以正常工作,但为了确保无论目标文件是否存在,命令都能被执行,建议声明它们为伪目标。

.PHONY: clean install
2. 用法示例

2.1 清理目标
清理目标是最常见的伪目标之一,用于删除生成的文件,如可执行文件和中间文件:

.PHONY: clean

clean:
    rm -f myprogram *.o

在这个示例中,运行 make clean 将会执行 rm -f myprogram *.o 命令,清除生成的文件。

2.2 安装目标
安装目标通常用于将编译好的文件复制到系统的某个目录:

.PHONY: install

install:
    cp myprogram /usr/local/bin/

运行 make install 将把可执行文件复制到 /usr/local/bin/ 目录。

2.3 其他常用伪目标
all:通常是默认目标,表示构建所有需要的目标。
test:用于运行测试。

.PHONY: all test

all: myprogram

test:
    ./run_tests.sh
3. 伪目标的优点

独立于文件:伪目标不依赖于文件的存在,因此即使与目标同名的文件存在,也不会影响命令的执行。

提高可读性:伪目标使得 Makefile 更加清晰,便于维护和理解。

灵活性:可以根据需要定义任意数量的伪目标,以实现不同的功能。

4. 注意事项

尽管使用伪目标非常方便,但要注意确保每个伪目标的命令是无状态的,也就是说,每次执行该命令都应该产生相同的结果。
在定义伪目标时,应避免与实际文件名冲突,虽然不会影响功能,但可能会造成混淆。

模式规则

模式规则是 Makefile 中的一种强大特性,允许用户定义一组规则,用于处理一类文件的生成。这种规则通过模式匹配来简化和自动化构建过程,尤其是在处理大量文件时非常有效。

1. 什么是模式规则

模式规则的基本形式是:

pattern: prerequisites
    recipe

其中,pattern 是一个带有通配符的模式,可以使用 % 来匹配任何字符串。

2. 模式规则的语法

% 可以代表零个或多个字符。
模式规则的目标可以是多种类型的文件。
通常用于生成目标文件,例如从源文件生成对象文件。

3. 例子

3.1 基本示例
假设我们有多个 C 源文件,想要编译成相应的对象文件,可以使用如下模式规则:

%.o: %.c
    gcc -c $< -o $@

%.o 是目标模式,表示任意以 .o 结尾的文件。
%.c 是先决条件模式,表示任意以 .c 结尾的文件。
$< 是第一个先决条件,表示与目标匹配的源文件。
$@ 是当前目标的名字。

当你运行 make 并且有 file1.c 和 file2.c 时,Make 会自动生成 file1.o 和 file2.o。

3.2 多文件规则
可以使用模式规则一次性处理多个文件:

OBJ = file1.o file2.o file3.o

all: $(OBJ)

%.o: %.c
    gcc -c $< -o $@

在这个例子中,make all 会依次处理 file1.c、file2.c 和 file3.c,生成对应的对象文件。

4. 复合模式规则

可以在同一规则中定义多个目标。例如:

program: main.o utils.o
    gcc $^ -o program

%.o: %.c
    gcc -c $< -o $@

这里,program 依赖于 main.o 和 utils.o,而 %.o: %.c 模式规则则用于生成这些对象文件。

条件语句

Makefile 支持条件语句,可以根据不同条件选择执行的命令:

1. ifeq

ifeq 用于判断两个字符串是否相等。

ifeq (条件1, 条件2)
    # 如果条件1 和 条件2 相等,执行的命令
endif

示例

VAR = value

ifeq ($(VAR), value)
    MESSAGE = "VAR is value"
else
    MESSAGE = "VAR is not value"
endif
2.ifneq

ifneq 用于判断两个字符串是否不相等。

ifneq (条件1, 条件2)
    # 如果条件1 和 条件2 不相等,执行的命令
endif

示例

VAR = value

ifneq ($(VAR), other_value)
    MESSAGE = "VAR is not other_value"
endif
3. ifdef

ifdef 用于判断一个变量是否已定义。

ifdef VAR
    # 如果 VAR 已定义,执行的命令
endif

示例

ifdef VAR
    MESSAGE = "VAR is defined"
else
    MESSAGE = "VAR is not defined"
endif
4. ifndef

ifndef 用于判断一个变量是否未定义。

ifndef VAR
    # 如果 VAR 未定义,执行的命令
endif

示例

ifndef VAR
    MESSAGE = "VAR is not defined"
endif

注释

注释以 # 开头,make 会忽略这一行的内容:

# 这是一个注释

makefile中的常用函数

常用的函数,可以帮助处理变量、文件和字符串等。下面是一些常见函数的语法和用法:

1. wildcard

语法: $(wildcard pattern…)

用途: 返回匹配模式的所有文件名。

示例:

SRCS = $(wildcard *.c)

这将把当前目录下所有的 .c 文件名存入 SRCS 变量中。

2. patsubst

语法: $(patsubst pattern, replacement, text)

用途: 将 text 中所有匹配 pattern 的部分替换为 replacement。

示例:

OBJS = $(patsubst %.c, %.o, $(SRCS))

这将把 SRCS 中的 .c 文件名转换为 .o 文件名。

3. subst

语法: $(subst find, replace, text)

用途: 在 text 中替换所有 find 字符串为 replace 字符串。

示例:

NEW_VAR = $(subst foo, bar, foo_baz)

NEW_VAR 的值将是 bar_baz。

4. filter

语法: $(filter pattern…, text)

用途: 从 text 中筛选出与 pattern 匹配的单词。

示例:

SRC_FILES = file1.c file2.c file3.h
C_FILES = $(filter %.c, $(SRC_FILES))

C_FILES 将只包含 file1.c 和 file2.c。

5. filter-out

语法: $(filter-out pattern…, text)

用途: 从 text 中排除与 pattern 匹配的单词。

示例:

SRC_FILES = file1.c file2.c file3.h
C_FILES = $(filter-out %.h, $(SRC_FILES))

C_FILES 将只包含 file1.c 和 file2.c。

6. sort

语法: $(sort list)

用途: 对 list 中的单词进行排序,并去重。

示例:

FILES = b.c a.c c.c a.c
SORTED_FILES = $(sort $(FILES))

SORTED_FILES 将是 a.c b.c c.c。

7. join

语法: $(join list1, list2)

用途: 将两个列表合并为一个列表,按空格分隔。

示例:

A = a1 a2
B = b1 b2
C = $(join $(A), $(B))

C 将是 a1 b1 a2 b2。

8. shell

语法: $(shell command)

用途: 执行 shell 命令并返回其输出。

示例:

CURRENT_DIR = $(shell pwd)

CURRENT_DIR 将是当前工作目录的路径。

9. addprefix

语法: $(addprefix prefix, names…)

用途: 在 names 的每个元素前添加 prefix。

示例:

OBJS = $(addprefix obj/, $(SRCS))

如果 SRCS 是 file1.c file2.c,那么 OBJS 将是 obj/file1.c obj/file2.c。

10. addsuffix

语法: $(addsuffix suffix, names…)

用途: 在 names 的每个元素后添加 suffix。

示例:

FILES = $(addsuffix .bak, $(SRCS))

这将把每个源文件名后加上 .bak 后缀。

进度条小程序

创建文件

使用touch创建各种文件

在这里插入图片描述
在这里插入图片描述

编辑.h文件

写出两个版本的进度条的进度条函数,v1版本是单纯的进度条函数,用来测试进度条逻辑,v2版本则用来实际使用,all为总进度,now为当前进度,以此判断进度条的位置。

在这里插入图片描述

编辑.c文件

1,创建bar进度条,用=代表进度,长度为101,包含\0
2,创建进度百分比,显示到了什么程度
3,创建进度圈圈,以str中的字符不断变化代表函数在执行,有时进度太慢进度条不动,实际是在执行的
4,\r代表从头打印
5,fflush函数刷新缓冲区打印进度条
6,usleep函数休眠控制速度

在这里插入图片描述
在这里插入图片描述

创建main函数

1,all代表总进度
2,speed代表网速
3,now代表现在下载量

在这里插入图片描述

makefile文件

@代表隐藏命令,但是命令会执行

1,第一条代表将.o文件链接成可执行文件
2,第二条代表将.c文件都生成.o文件
3,第三条clean清理生成的文件
4,test展示生成的文件
在这里插入图片描述

执行效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

如何用mmclassification训练多标签多分类数据

这里使用的源码版本是 mmclassification-0.25.0 训练数据标签文件格式如下&#xff0c;每行的空格前面是路径&#xff08;图像文件所在的绝对路径&#xff09;&#xff0c;后面是标签名&#xff0c;因为特殊要求这里我的每张图像都记录了三个标签每个标签用“,”分开&#xff0…

WORFBENCH:一个创新的评估基准,目的是全面测试大型语言模型在生成复杂工作流 方面的性能。

2024-10-10,由浙江大学和阿里巴巴集团联合创建的WORFBENCH&#xff0c;一个用于评估大型语言模型&#xff08;LLMs&#xff09;生成工作流能力的基准测试。它包含了一系列的测试和评估协议&#xff0c;用于量化和分析LLMs在处理复杂任务时分解问题和规划执行步骤的能力。WORFBE…

【Super-resolved q-space learning of diffusion MRI】

扩散MRI的超分辨q-空间学习 摘要&#xff1a; 背景&#xff1a;扩散磁共振成像 (dMRI) 提供了一种强大的工具&#xff0c;可以无创地研究活人大脑中的神经结构。然而&#xff0c;它对神经结构的重建性能依赖于 q 空间中扩散梯度的数量。高角度&#xff08;HA&#xff09;dMRI…

【北京迅为】《STM32MP157开发板嵌入式开发指南》-第六十七章 Trusted Firmware-A 移植

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

(二十三)Java反射

1.反射概念 反射允许对成员变量&#xff0c;成员方法和构造方法的信息进行编程访问&#xff0c;通俗理解就是允许从类里面拿东西&#xff0c;用途有提示词等&#xff0c;如下所示都是通过反射实现的 所以&#xff0c;学习反射就是学习从字节码class文件中获取成员信息并且对其…

流媒体协议.之(RTP,RTCP,RTSP,RTMP,HTTP)(一)

闲着没事做&#xff0c;记录一下开发项目用过的协议&#xff0c;项目中&#xff0c;大多是是实时显示播放的&#xff0c;通过私有协议&#xff0c;传输到上位机&#xff0c;实时播放&#xff0c;延时小于200ms&#xff0c;仿照这些协议&#xff0c;定义的数据格式。如果用这些协…

C语言实现Go的defer功能

之前笔者写了一篇博文C实现Go的defer功能&#xff0c;介绍了如何在C语言中实现Go的defer功能&#xff0c;那在C语言中是否也可以实现这样的功能呢&#xff1f;本文就将介绍一下如何在C语言中实现Go的defer功能。 我们还是使用C实现Go的defer功能中的示例&#xff1a; void te…

一文彻底理解 JavaScript 解构赋值

一、基本概念 为什么需要解构呢&#xff0c;先来看一个例子&#xff1a; const student {name: ZhangSan,age: 18,scores: {math: 19,english: 85,chinese: 100} };function displayInfo(student) {console.log(name:, student.name);console.log(math:, student.scores.mat…

排序(二)快速排序的多种实现方法

目录 一.快速排序 1.左右指针法 2.挖坑法 3.前后指针法 4.非递归实现 5.快速排序特性总结 二.整体代码 1.Sort.h 2.Sort.c 3.Stack.h 4.Stack.c 5.test.c 一.快速排序 1.左右指针法 我们找到一个key,begin去找比key大的值,end去找比key小的值,找到了就将begin和end…

从头学PHP之运算符

关于运算符的图片均来自网络&#xff0c;主要是自己写太麻烦了&#xff0c;程序是个简化自己工作量的方式&#xff0c;能复制粘贴就不要手写了&#xff08;建议初期还是多写写&#xff0c;加深下记忆&#xff09;在这里我就偷个懒&#xff0c;图片涉及到侵权及时&#xff0c;请…

阻塞队列——Java

一、前言 阻塞队列也是队列的一种&#xff0c;但是带有阻塞性质。但是这种阻塞情况是极端情况&#xff0c;在生产、消费者模型中&#xff0c;当生产者与消费者不协调时&#xff0c;就会出现阻塞情况。 二、特性 线程安全 阻塞特性 若队列为空&#xff0c;当尝试出队列时&am…

深度解析跨境支付之跨境支付与国内支付对比

跨境支付和国内支付的不同点主要体现在5个方面&#xff1a; 1.交易币种不同 这一点其实有两层含义 第一层含义是二者的支付行为的交易币种不同&#xff0c;国内支付基本是人民币但是跨境支付可以是人民币也可以是外币&#xff0c;具体交易币种要取决于收款方要求的交易币种。…

数据结构(8.4_1)——简单选择排序

简单选择排序 每一趟在待排序元素中选取关键字最小的元素加入有序子序列 代码实现 //简单选择排序 void SelectSort(int A[], int n) {for (int i 0; i < n - 1; i) {//一共进行n-1趟int min i;//记录最小元素位置for (int j i 1; j < n; j)//在A[i...n-1中选择最…

RabbitMQ延迟消息插件安装(Docker环境)

背景&#xff1a;当我们需要使用RabbitMQ发送延迟消息的时候&#xff0c;为了简化延迟消息发送的实现&#xff0c;一般都会给RabbitMQ安装延迟插件"rabbitmq_delayed_message_exchange" 如下会说明使用Docker启动的RabbitMQ容器如何安装延迟消息插件。 1. Docker启动…

用接地气的例子趣谈 WWDC 24 全新的 Swift Testing 入门(一)

概述 从 WWDC 24 开始&#xff0c;苹果推出了全新的测试机制&#xff1a;Swift Testing。利用它我们可以大幅度简化之前“老态龙钟”的 XCTest 编码范式&#xff0c;并且使得单元测试更加灵动自由&#xff0c;更符合 Swift 语言的优雅品味。 在这里我们会和大家一起初涉并领略…

docker配置mysql8报错 ERROR 2002 (HY000)

通过docker启动的mysql&#xff0c;发现navicat无法连接&#xff0c;后来进入容器内部也是无法连接&#xff0c;产生以下错误 root9f3b90339a14:/var/run/mysqld# mysql -u root -p Enter password: ERROR 2002 (HY000): Cant connect to local MySQL server through socket …

LINUX1.5.1(vim编辑器)

vim: 1. vim 2.vim /PATTERN vi编辑器与三种常见的模式&#xff1a; 复制 粘贴 剪切 删除 编辑 退出 保存 行间跳转 显示行号 查找替换 命令模式&#xff1a;光标的移动&#xff0c;使用快捷键&#xff0c;复制&#xff0c;粘贴&#xff0c;删除等基础操作 编辑模式&…

【mysql进阶】4-7. 通用表空间

通⽤表空间 - General Tablespace 1 通⽤表空间的作⽤和特性&#xff1f; ✅ 解答问题 通⽤表空间是使⽤ CREATE tablespace 语法创建的共享InnoDB表空间 通⽤表空间能够存储多个表的数据&#xff0c;与系统表空间类似也是共享表空间&#xff1b; 服务器运⾏时会把表空间元数…

【C++】智能指针:解决内存泄漏、悬空指针等问题

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;C 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 前言一、RAII二、智能指针原理三、auto_ptr四、unique_ptr五、shared_ptr第一步&#xff1a;实现出RAII的框架第二步&#xff1a;如何…

信息收集-shodan专题一

shodan介绍 一、shodan简介 1.工作原理解析&#xff1a; 2.优缺点 3.功能 二、安装shodan流程 三、shodan使用方法 1.搜索 1.1.search 搜索 1.2. count 总数 1.3. download 下载与解析 2. 指定查看 2.1 指定IP的详细信息 2.2 hostname: 搜索指定的域名 2.3 port:…