Makefile学习笔记

发布时间 2023-08-25 21:47:47作者: ddup123

规则:每条规则由三个部分组成分别是目标(target), 依赖(depend)和命令(command)。

#示例
# 规则1
app:a.o b.o c.o
    gcc a.o b.o c.o -o app
# 规则2
a.o:a.c
    gcc -c a.c
# 规则3
b.o:b.c
    gcc -c b.c
# 规则4
c.o:c.c
    gcc -c c.c

 

makefile有自动推导功能,有时漏写一些构建规则,但是程序还是会被编译

# 这是一个完整的 makefile 文件
calc:add.o  div.o  main.o  mult.o  sub.o
        gcc  add.o  div.o  main.o  mult.o  sub.o -o calc

 

借助自定义变量名写makefile

#普通写法
calc:add.o  div.o  main.o  mult.o  sub.o
        gcc  add.o  div.o  main.o  mult.o  sub.o -o calc
        
#使用了自定义变量写法
obj=add.o  div.o  main.o  mult.o  sub.o
target=calc
$(target):$(obj)
        gcc  $(obj) -o $(target)

 

预定义变量:在 Makefile 中有一些已经定义的变量,用户可以直接使用这些变量,不用进行定义。在进行编译的时候,某些条件下 Makefile 会使用这些预定义变量的值进行编译

#CC    C 语言编译器的名称    cc
#普通写法
calc:add.o div.o main.o mult.o sub.o
gcc add.o div.o main.o mult.o sub.o -o calc

#使用了自定义变量和预定义变量的写法
obj=add.o div.o main.o mult.o sub.o
target=calc
CFLAGS=-O3 # 代码优化
$(target):$(obj)
$(CC) $(obj) -o $(target) $(CFLAGS)

自动变量:

$@	表示目标文件的名称,包含文件扩展名
$^	依赖项中,所有不重复的依赖文件,这些文件之间以空格分开
$< 表示依赖项中第一个依赖文件的名称
#示例
#普通写法 calc:add.o div.o main.o mult.o sub.o gcc add.o div.o main.o mult.o sub.o
-o calc # 使用自动变量, 替换相关的内容 calc:add.o div.o main.o mult.o sub.o gcc $^ -o $@ # 自动变量只能在规则的命令中使用

makefile里的函数:

wildcard:获取指定目录下指定类型的文件名,其返回值是以空格分割的、指定目录下的所有符合条件的文件名列表。

# 使用举例: 分别搜索三个不同目录下的 .c 格式的源文件
src = $(wildcard /home/robin/a/*.c /home/robin/b/*.c *.c)  # *.c == ./*.c
# 返回值: 得到一个大的字符串, 里边有若干个满足条件的文件名, 文件名之间使用空格间隔
/home/robin/a/a.c /home/robin/a/b.c /home/robin/b/c.c /home/robin/b/d.c e.c f.c

 

patsubst按照指定的模式替换指定的文件名的后缀,

#示例
src = a.cpp b.cpp c.cpp e.cpp # 把变量 src 中的所有文件名的后缀从 .cpp 替换为 .o obj = $(patsubst %.cpp, %.o, $(src)) # obj 的值为: a.o b.o c.o e.o

 

 练习

# 目录结构
├── include
│   └── head.h ==> 头文件, 声明了加减乘除四个函数
├── main.c ==> 测试程序, 调用了head.h中的函数
└── src
├── add.c ==> 加法运算
├── div.c ==> 除法运算
├── mult.c ==> 乘法运算
└── sub.c ==> 减法运算

# 最终的目标名 app
target = app
# 搜索当前项目目录下的源文件
src=$(wildcard *.c ./src/*.c)
# 将文件的后缀替换掉 .c -> .o
obj=$(patsubst %.c, %.o, $(src))
# 头文件目录
include=./include
$(target):$(obj)
        gcc $^ -o $@

# 模式匹配规则
# 执行汇编操作, 前两步: 预处理, 编译是自动完成
%.o:%.c
        gcc $< -c -I $(include) -o $@

# 添加一个清除文件的规则
.PHONY:clean

clean:
        -rm $(obj) $(target) -f