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

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

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: dependenciescommand

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

使用案例

# 一个简单的示例 MakefileCC = 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.cutils.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: cleanclean:rm -f myprogram *.o

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

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

.PHONY: installinstall:cp myprogram /usr/local/bin/

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

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

.PHONY: all testall: myprogramtest:./run_tests.sh
3. 伪目标的优点

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

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

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

4. 注意事项

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

模式规则

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

1. 什么是模式规则

模式规则的基本形式是:

pattern: prerequisitesrecipe

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

2. 模式规则的语法

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

3. 例子

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

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

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

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

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

OBJ = file1.o file2.o file3.oall: $(OBJ)%.o: %.cgcc -c $< -o $@

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

4. 复合模式规则

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

program: main.o utils.ogcc $^ -o program%.o: %.cgcc -c $< -o $@

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

条件语句

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

1. ifeq

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

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

示例

VAR = valueifeq ($(VAR), value)MESSAGE = "VAR is value"
elseMESSAGE = "VAR is not value"
endif
2.ifneq

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

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

示例

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

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

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

示例

ifdef VARMESSAGE = "VAR is defined"
elseMESSAGE = "VAR is not defined"
endif
4. ifndef

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

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

示例

ifndef VARMESSAGE = "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.mrgr.cn/news/59262.html

相关文章:

  • 神经架构搜索:自动化设计神经网络的方法
  • STMicroelectronics意法半导体车规芯片系列--亿配芯城(ICgoodFind)
  • uboot启动流程
  • 可能是NextJs(使用ssr、api route)打包成桌面端(nextron、electron、tauri)的最佳解决方式
  • 在 Ubuntu 上安装 OpenCV 3.2.0 的详细指南
  • 《性能之巅:洞悉系统、企业与云计算》-观测工具-笔记
  • 刚面完字节!问了大模型微调SFT,估计凉了
  • 国考报名别忘了确认缴费(需传照片)
  • 【ShuQiHere】Linux 桌面环境:选择与定制指南 ️✨
  • <网络> 网络套接字编程(二)
  • 大型项目必备搜索神器,搜索引擎ElasticSearch详细教程
  • Redis 集群 问题
  • Java一些基础代码带你轻松入门
  • #PCIE#基础知识分解之 CC/SRNS/SRIS 时钟架构
  • 基于SSM的网上购物系统的设计与实现
  • 高级 SQL 技巧全面教程:提升你的数据库操作能力
  • [Python学习日记-56] Python 中的包与代码的跨模块代码调用
  • C++ 模板专题 - 表达式模板
  • RabbitMQ 发布确认高级部分
  • 大模型多模态应用深化,AI Agent 如何为应用普及提速(科普一键收藏版)
  • 【Linux】从open到write:系统文件I/O 的奥秘与实战指南
  • Redis 过期策略 问题
  • 关于python的import
  • Spark RDD
  • 事务的原理、MVCC的原理
  • Node-Red二次开发:git下载本地打镜像docker部署