Makefile分析

本文用于分析一个Makefile文件。

# Usage:
# make        # 编译所有c文件
# make clean  # 删除所有二进制文件和对象
# make help   #显示帮助信息

.PHONY: all help clean           # 将目标all clean声明为一个伪目标
SRCS=$(wildcard *.c)             # 返回值为当前目录下所有.c文件的列表。

BIN=$(SRCS:%.c=%)                # 这叫做替换引用。在这种情况下,如果SRCS有值'foo.c bar.c',那么BINS将有'foo bar'
 
CC := gcc                        # gcc为C语言编译器、g++为c++编译器
CFLAGS=-Wall -g                  # 为gcc设置编译标志
 
all: $(BIN)                      # 伪目标调用${BINS}中的值作为单独的目标

help:                            # 显示帮助信息
	@printf "Usage:\n"
	@printf "  make\t\t\t编译所有c文件\n"
	@printf "  make clean\t\t删除所有二进制文件和对象\n"
	@printf "  make help\t\t显示帮助信息\n"
 
clean:                          # 清除所有BIN产生的文件
	@echo "Cleaning up..."
	rm  $(BIN)

运行效果:

$ make
gcc -Wall -g    cp02.c   -o cp02
gcc -Wall -g    cp01.c   -o cp01

$ make help
Usage:
  make                  编译所有c文件
  make clean            删除所有二进制文件和对象
  make help             显示帮助信息

$ ls
Makefile  cp01  cp01.c  cp02  cp02.c

$ make clean 
Cleaning up...
rm  cp02 cp01

$ ls
Makefile  cp01.c  cp02.c
函数讲解:
  1. PHONY: all clean

Makefile中的clean目标实际上并没有创建名为“clean”的文件,因此不符合我们为目标所描述的模式。相反,clean目标是作为一个快捷方式来运行清除项目构建文件的命令(命令开头加上“@”,Make在运行时将不会打印到终端)。我们将这样的目标标记为. PHONY的“依赖项”,这是一个不会被构建的伪目标。当Make实用程序遇到伪目标时,它将自动运行相关的命令,而不执行任何依赖项检查。

  1. $(wildcard PATTERN)

函数名称:获取匹配模式文件名函数-wildcard函数功能:列出当前目录下所有符合模式“PATTERN”格式的文件名。

返回值:空格分割的、存在当前目录下的所有符合模式“PATTERN”的文件名。函数说明:“PATTERN”使用shell可识别的通配符,包括“?”(单字符)、“*”(多字符)等。

  1. CFLAGS

CFLAGS变量为gcc设置编译标志:
-g 使用调试信息编译
-Wall 给出详细的编译警告
-O0 不优化生成的代码
-std=c99 使用c99标准语言定义函数

对于隐含规则

如果要使用隐含规则生成你需要的目标,你所需要做的就是不要写出这个目标的规则。那么,make会试图去自动推导产生这个目标的规则和命令,如果 make可以自动推导生成这个目标的规则和命令,那么这个行为就是隐含规则的自动推导。当然,隐含规则是make事先约定好的一些东西。例如,我们有下面的一个Makefile:
foo : foo.o bar.o
cc –o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)

我们可以注意到,这个Makefile中并没有写下如何生成 foo.o 和 bar.o 这两目标的规则和命令。因为make的“隐含规则”功能会自动为我们自动去推导这两个目标的依赖目标和生成命令。

make会在自己的“隐含规则”库中寻找可以用的规则,如果找到,那么就会使用。如果找不到,那么就会报错。在上面的那个例子中,make调用的隐含规则是,把 .o 的目标的依赖文件置成 .c ,并使用C的编译命令 cc –c $(CFLAGS) foo.c 来生成 foo.o 的目标。也就是说,我们完全没有必要写下下面的两条规则:
foo.o : foo.c
cc –c foo.c $(CFLAGS)
bar.o : bar.c
cc –c bar.c $(CFLAGS)

因为,这已经是“约定”好了的事了,make和我们约定好了用C编译器 cc 生成 .o 文件的规则,这就是隐含规则。

当然,如果我们为 .o 文件书写了自己的规则,那么make就不会自动推导并调用隐含规则,它会按照我们写好的规则忠实地执行。

还有,在make的“隐含规则库”中,每一条隐含规则都在库中有其顺序,越靠前的则是越被经常使用的,所以,这会导致我们有些时候即使我们显示地指定了目标依赖,make也不会管。如下面这条规则(没有命令):
foo.o : foo.p
依赖文件 foo.p (Pascal程序的源文件)有可能变得没有意义。如果目录下存在了 foo.c 文件,那么我们的隐含规则一样会生效,并会通过 foo.c 调用C的编译器生成 foo.o 文件。因为,在隐含规则中,Pascal的规则出现在C的规则之后,所以,make找到可以生成 foo.o 的C的规则就不再寻找下一条规则了。如果你确实不希望任何隐含规则推导,那么,你就不要只写出“依赖规则”,而不写命令。

因此,在all: $(BIN) 命令下,Makefile将自动按照隐含规则,用$(CC)对c文件进行编译,并生成可执行文件。

参考
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值