萌芽破土篇
实例1:hello world
编辑 Makefile
all:echo "hello world"
编译执行
$ make
$ make all
结果输出
语法说明
- echo 前面必须只有 TAB(即你键盘上的 TAB键),且至少有一个 TAB,不能用空格代替。
实例2:Makefile定义多个目标
编辑 Makefile
all:echo "hello world"test:echo "hello test"
编译执行
$ make
$ make all
$ make test
结果输出
语法说明
- Makefile 中包含多个目标时,直接使用 make 编译省略模式下,默认编译第一个目标。
实例3:Makefile注释
编辑 Makefile
all:@echo "hello world"test:@echo "hello test"
编译执行
$ make
$ make all
$ make test
结果输出
语法说明
- 使用 @ 符号,告诉make在运行时不要将这一行命令显示出来。
实例4:简单的依赖
编辑 Makefile
all:test@echo "hello world"test:@echo "hello test"
编译执行
$ make
$ make test
结果输出
语法说明
- all:test 告诉 make,all 目标依赖 test 目标,这一依目标在Makefile中又被称为先决条件。出现这种目标依赖关系时,make工具会按照从左到右的先后顺序先构建规则中的每一个目标。比如这里,如果要构建 all ,那么 make 会在构建它之前先构建 test 目标。
实例5:simple程序编译
foo.c 源码
#include <stdio.h>
void foo()
{printf("This is foo()!\n");
}
main.c 源码
extern void foo();int main()
{foo();return 0;
}
编辑 Makefile
all: main.o foo.ogcc -o simple main.o foo.o
main.o: main.cgcc -o main.o -c main.c
foo.o: foo.cgcc -o foo.o -c foo.c
clean:rm simple main.o foo.o
编译执行
$ make
结果输出
语法说明
- 写 Makefile 文件的关键是理清文件之间的依赖关系。
实例6:假目标
实例 5 的 Makefile 中有一个clean文件,我们希望能够通过 clean 命令,清理历史文件。不过,在执行 clean 指令时候发现,没法对文件进行删除。这是因为 make 将 clean 当作条件,且在当前目录找到了这个文件,加上 clean 目标没有任何先决条件,所以,当我们要求 make 为我们构建 clean 目标时,它就会认为 clean 是最新的。
对于这种情况,可以通过 Makefile 中的假目标来解决,假目标可以通过关键字 .PHONY 定义。
编辑 Makefile
.PHONY:clean
all: main.o foo.ogcc -o simple main.o foo.o
maiin.o: main.cgcc -o main.o -c main.c
foo.o: foo.cgcc -o foo.o -c foo.c
clean:rm simple main.o foo.o
编译执行
$ make
$ ./simple
$ make clean
结果输出
语法说明
- Makefile 假目标关键字 .PHONY。
实例7:Makefile变量
编辑 Makefile
.PHONY:clean
CC = gcc
RM = rm
EXE = simple
OBJS = main.o foo.o$(EXE):$(OBJS)$(CC) -o $(EXE) $(OBJS)
main.o:main.c$(CC) -o main.o -c main.c
foo.o:foo.c$(CC) -o foo.o -c foo.c
clean:$(RM) $(EXE) $(OBJS)
编译执行
$ make
$ ./simple
$ make clean
结果输出
语法说明
- 变量定义:变量名=变量值;
- 变量引用:$(变量名) 或 ${变量名}
实例8:Makefile自动变量
编辑 Makefile
.PHONY:clean
CC = gcc
RM = rm
EXE = simple
OBJS = main.o foo.o$(EXE):$(OBJS)$(CC) -o $@ $^
main.o:main.c$(CC) -o $@ -c $^
foo.o:foo.c$(CC) -o $@ -c $^
clean:$(RM) $(EXE) $(OBJS)
编译执行
$ make
$ ./simple
$ make clean
结果输出
语法说明
- $ @ 用于表示一个规则中的目标;当一个规则中目标有多个时,$ @指的是其中任何造成命令被运行的目标;
- $ ^ 用于表示规则中的所有先决条件;
- $ < 用于表示规则中的第一个先决条件。
- 在Makefile中 ’ $ ’ 具有特殊的含义,因此如果需要采用 echo 输出 ’ $ ’ ,则需要用两个连着的 ‘ $ ’;同时 ‘$ @’ 对 Shell 也有特殊的意思,因此需要在 ‘$$@’ 前面增加一个脱字节 ‘ \ ’.
附加实例
//Makefile
.PHONY: all
all: first second third@echo "\$$@ = $@"@echo "$$^ = $^"@echo "$$< = $<"
first second third://输出
$make
$@ = all
$^ = first second third
$< = first
实例9:Makefile特殊变量
1. MAKE
编辑 Makefile
.PHONY: all
all: @echo "MAKE = $(MAKE)"
编译执行
$ make
结果输出
语法说明
- MAKE 变量表示make命令名是什么;
- 使用场景:当我们需要在Makefile中调用另外一个Makefile时需要用到它,采用这种方式有利于写一个容易移植的Makefile。
2. MAKECMDGOALS
编辑 Makefile
.PHONY: all clean
all clean: @echo "\$$@ = $@"@echo "MAKECMDGOALS = $(MAKECMDGOALS)"
编译执行
$ make
$ make all
$ make clean
$ make all clean
结果输出
语法说明
- MAKECMDGOALS 表示是当前用户输入的 make 目标是什么。
实例10:Makefile变量的类别
1. 递归扩展变量
编辑 Makefile
.PHONY: all
foo=$(var1)
var1=-$(var2)
var2=100all: @echo $(foo)
编译执行
$ make
结果输出
语法说明
- = 符号定义的变量称之为递归扩展变量。
2. 简单扩展变量
编辑 Makefile
.PHONY: all clean
x = foo
y = $(x) b
x = later
xx := foo
yy := $(xx) b
xx := laterall:@echo "x = $(y), xx = $(yy)"
编译执行
$ make
结果输出
语法说明
- := 符号定义的变量称之为简单扩展变量。
3. 条件赋值变量
编辑 Makefile
.PHONY: all clean
foo = x
foo ?= y
bar ?= yall:@echo "foo = $(foo), bar = $(bar)"
编译执行
$ make
结果输出
语法说明
- ?= 符号定义的变量称之为条件赋值变量;
- 含义:当变量以前没有定义,就定义它并将左边的值赋给它;如果先前已经定义过了,就不会改变它原来的值。
实例11:Makefile高级变量引用功能
编辑 Makefile
.PHONY: all
foo=a.o b.o c.o
bar := $(foo:.o=.c)all: @echo "bar = $(bar)"
编译执行
$ make
结果输出
语法说明
- 上面实例中变量引用的一种高级功能,在赋值的同时完成后缀替换。
实例12:override指令
编辑 Makefile
.PHONY: all
override foo=100all: @echo "foo = $(foo)"
编译执行
$ make
$ make foo=0
结果输出
语法说明
- override 可以使得定义变量的值不被覆盖。如上面:make foo=0 输出的值依然为100。
实例13:Makefile模式
编辑 Makefile
.PHONY:clean
CC = gcc
RM = rm
EXE = simple
OBJS = main.o foo.o$(EXE):$(OBJS)$(CC) -o $@ $^
%.o:%.c$(CC) -o $@ -c $^clean:$(RM) $(EXE) $(OBJS)
编译执行
$ make
$ ./simple
结果输出
语法说明
- % 字符模式类似Windows操作系统中的通配符。
实例14:addprefix函数
编辑 Makefile
.PHONY: all
without_dir = foo.c bar.c main.o
with_dir := $( addprefix objs/, $(without_dir))all:@echo $(with_dir)
编译执行
$ make
结果输出
语法说明
- addprefix 用于给字符串中每个子串前都加上一个前缀,形式:$(addprefix prefix, names…)
实例15:filter 函数
编辑 Makefile
.PHONY: all
text = a.c b.c c.s d.h
text := $(filter %.c %.s, $(text))
all:@echo $(text)
编译执行
$ make
结果输出
语法说明
- filter 用于从一个字符串中,根据模式得到满足模式的字符串,形式:$(filter pattern…, text)
实例16:filter-out 函数
编辑 Makefile
.PHONY: all
text = a.c b.c c.s d.h
text := $(filter-out %.c %.s, $(text))
all:@echo $(text)
编译执行
$ make
结果输出
语法说明
- filter-out 用于从一个字符串中,根据模式滤除一部分字符串,形式:$(filter-out pattern…, text)
实例17:patsubst 函数
编辑 Makefile
.PHONY: all
text = a.c b.c c.c
text := $(patsubst %.c %.h, $(text))
all:@echo $(text)
编译执行
$ make
结果输出
语法说明
- patsubst 用于字符串替换;同时patsubst函数可以使用模式,所以也可以用于替换前缀等;形式:$(patsubst pattern,replacement,text)
实例18:strip 函数
编辑 Makefile
.PHONY: all
src = a.c b.c c.c
dst := $(strip $(src))
all:@echo "src = $(src)"@echo "dst = $(dst)"
编译执行
$ make
结果输出
语法说明
- patsubst 用于去除变量中多余的空格;形式:$(strip string)
实例19:wildcard 函数
编辑 Makefile
//显示当前Makefile目录下所有 .c 文件
.PHONY: all
src = $(wildcard *.c)
all:@echo $(src)
编译执行
$ make
结果输出(默认Makefile所在目录中包含了foo.c main.c bar.c等文件)
语法说明
- wildcard 通配符函数,类似于 Windows 或 linux 命令行中的 " * ";形式:$(wildcard pattern)