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展示生成的文件