Makefile 基本语法入门,Makefile语法
一、Makefile 简介
Makefile 是一种常用于编译的脚本语言。它可以更好更方便的管理你的项目的代码编译,节约编译时间(没改动的文件不编译)。
注意 Makefile 文件命令必须是 Makefile 或者 makefile,并使用 make 命令编译。
二、1个规则
1. 语法规则
0 1 2 3 |
目标...: 依赖... 命令1 命令2 ... |
2. 目标
目标即要生成的文件。如果目标文件的更新时间晚于依赖文件的更新时间,则说明依赖文件没有改动,目标文件不需要重新编译。否则重新编译并更新目标。
3. 依赖
即目标文件由哪些文件生成。如果依赖条件中存在不存在的依赖条件,则会寻找其它规则是否可以产生依赖条件。
例如:规则一是生成目标 hello.out 需要使用到依赖条件 hello.o,但是 hello.o 不存在。则 Makefile 会寻找到一个生成 hello.o 的规则二并执行。
4. 命令
即通过执行该命令,由依赖文件生成目标文件。
注意每条命令前必须有且仅有一个 tab 保持缩进,这是语法要求。
5. ALL
Makefile 文件默认只生成第一个目标文件即完成编译,但是我们可以通过 “ALL” 指定需要生成的目标文件。
6. 示例
针对以上所说的,先写一个示例让大家了解一下,首先准备一个 hello.c:
0 1 2 3 4 5 6 7 |
#include <stdio.h> int main() { printf("Hello World !\n"); return 0; } |
然后写一个 Makefile
0 1 2 3 |
ALL: hello.out hello.out: hello.c gcc hello.c -o hello.out |
编译并执行:
0 1 2 3 |
$ make gcc hello.c -o hello.out $ ./hello.out Hello World ! |
三、2个函数
1. wildcard
例如
0 |
SRC = $(wildcard ./*.c) |
匹配目录下所有的 .c 文件,并将其赋值给 SRC 变量。
2. patsubst
pat 是 pattern 的缩写,subst 是 substring 的缩写。例如
0 |
OBJ = $(patsubst %.c, %.o, $(SRC)) |
这个函数有三个参数,意思是取出 SRC 中所有的值,然后将 “.c” 替换为 “.o”,最后赋值给 OBJ 变量。
3. 示例
通过上面两个函数,加入我们目录下有很多个 “.c” 后缀的源文件,就不需要写很多条规则语句了,而是可以像下面这样写
0 1 2 3 4 5 6 7 8 9 |
SRC = $(wildcard *.c) OBJ = $(patsubst %.c, %.o, $(SRC)) ALL: hello.out hello.out: $(OBJ) gcc $(OBJ) -o hello.out $(OBJ): $(SRC) gcc -c $(SRC) -o $(OBJ) |
这里我们先将所有的 “.c” 文件编译为 “.o” 文件,这样后面更改某个 “.c” 文件时,其它的 “.c” 文件将不再编译,而只是编译有更改的 “.c” 文件,可以大大节约大项目中的编译速度。
四、3个变量
Makefile 中也有一些已经定义好的常用变量,这里介绍其中常用的3个。
1. $@
表示规则中目标,例如 hello.out。
2. $<
表示规则中的第一个依赖条件,例如 hello.c
3. $^
表示规则中的所有依赖条件,由于我们示例中都只有一个依赖条件,这种情况下 $^ 和 $< 区别不大。
4. 示例
使用这些变量替换上面写的 Makefile,即是:
0 1 2 3 4 5 6 7 8 9 10 |
SRC = $(wildcard *.c) OBJ = $(patsubst %.c, %.o, $(SRC)) ALL: hello.out hello.out: $(OBJ) gcc $< -o $@ $(OBJ): $(SRC) gcc -c $< -o $@ |
五、其它常用功能
1. 代码清理 clean
我们可以编译一条属于自己的 clean 语句,来清理 make 命令所产生的所有文件。例如
0 1 2 3 4 5 6 7 8 9 10 11 12 |
SRC = $(wildcard *.c) OBJ = $(patsubst %.c, %.o, $(SRC)) ALL: hello.out hello.out: $(OBJ) gcc $< -o $@ $(OBJ): $(SRC) gcc -c $< -o $@ clean: -rm -rf $(OBJ) hello.out |
这样我们就可以使用 clean 命令来清理生成的文件了:
0 1 2 3 4 5 6 |
$ ls hello.c hello.o hello.out Makefile $ make clean rm -rf hello.o hello.out $ ls hello.c Makefile |
2. 伪目标 .PHONY
上面我们写了一个 clean 语句,使得我们执行 “make clean” 命令的时候,可以清理我们生成的文件。
但是假如还存在一个文件名就是 clean 文件,那么我们再执行 “make clean” 命令的时候就只是显示
0 1 |
$ make clean make: `clean' is up to date. |
解决方法就是我们使用伪目标,这样就可以避免出现上面的问题了,例如:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
SRC = $(wildcard *.c) OBJ = $(patsubst %.c, %.o, $(SRC)) ALL: hello.out hello.out: $(OBJ) gcc $< -o $@ $(OBJ): $(SRC) gcc -c $< -o $@ clean: -rm -rf $(OBJ) hello.out .PHONY: clean ALL |
通常,我们也会把 ALL 也设置为伪目标。