Makefile编写和相关语法规则
makefile基本概念
Makefile 本质上是一个文本文件,它包含了一系列规则和指令,用于告诉构建工具(如 make)如何编译和链接程序,以及如何处理项目中的各种文件。其核心思想是通过定义目标(target)、依赖关系(dependencies)和生成目标的命令(commands),来实现项目的自动化构建。
makefile编写
makefile文件编写,就是要明确基础格式如下:
目标:依赖
(tab键)命令
举个具体的小例子:
main:main.c add.c
# 使用gcc编译器将main.c和add.c这两个源文件进行编译和链接操作,
# 最终生成一个名为main的可执行文件。
gcc -o main main.c add.c
严格按照上述的基础格式写,但是这里有一个问题:如果我们得更新add.c中的代码,相应的两个文件都得重新先.c文件编译生成.o文件,再由.o文件链接成linux操作系统的可执行文件,如果一个大工程有上百个文件这样的代码处理起来太过于冗余。所以我们可以把每个文件的编译过程拆开。
第一版本
main:main.o add.o
# 链接命令,将 main.o 和 add.o 链接生成可执行文件 main
gcc main.o add.o -o main
main.o:main.c
# 编译命令,将 main.c 编译为目标文件 main.o
gcc -c main.c -o main.o
add.o:add.c
# 编译命令,将 add.c 编译为目标文件 add.o
gcc -c add.c -o add.o
上述写法,当更新 add.c 文件时,确实能够更智能地处理编译和链接过程,避开第一个版本的一些缺点,就不必重复重新执行gcc -c main.c -o main.o
这条指令。
但是,Makefile有相应的语法规则,帮助我们写出更加简洁的代码;
比如,
- 我们可以自定义变量,a = b,$(a)来替代b;
$<
就对应着 “依赖文件列表” 中的第一个文件;$@
就对应着"目标文件";- gcc 可以用专门符号$(CC)表示;
- 而且类似的func.o: func.c这种.o和.c转换的语句太过于冗余,这里可以使用%.o:%.c去替代所有当前文件夹下.c文件编译得到.o文件
$^
表示当前规则的所有依赖文件,以空格分隔。如果依赖文件中有重复的,重复的文件只会出现一次。
所以根据上述规则,假设main用target代替,main.o add.o用object替换,我们可以得到下面的版本。
第二版本
target=main
object=main.o add.o
CC=gcc
$(target):$(object)
$(CC) -o $@ $^
%.o:%c
$(CC) -c $<
得到上述版本,已经非常简洁了,但是还是有个问题,我们想要得到的是Linux可执行文件main,中间还生成了.o文件,所以我们还可以更精益求精些,删除这些中间文件。
第三版本
target=main
object=main.o add.o
CC=gcc
$(target):$(object)
$(CC) -o $@ $^
%.o:%.c
$(CC) -c $<
clean:
rm -f $(object)
最后这个版本就可以利用简洁代码实现,main.c add.c文件编译链接生成可执行文件main,并且删除中间生成的冗余文件