【makefile】使用指南 (待续。。。)

相关概念

注释符:#

伪目标 (.PHONY)

clean:
	rm *.o

上述示例中的clean就是一个伪目标,常用于清除生成的文件,以达到完整重编译的左右。
这里并不会生成clean文件。
“伪目标”并不是一个文件,而只是一个标签;由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它是否要执行;我们需要显示地指明这个“伪目标”才能让其生效。
此外,伪目标的取名不能和文件名一致,否则就失去了“伪目标”的意义。为了避免与文件重名的情况,可以使用一个特殊的标记.PHONY来显示地指明一个目标为“伪目标”,而不用管是否有重名的文件存在。

.PHONY: clean
clean:
	rm *.o

上述例子表明:不管是否存在clean文件,只要输入make clean,就可以运行clean这个伪目标。

目标可以成为伪目标的依赖

伪目标一般没有依赖的文件。但也可以指定依赖的文件。Makefile中的第一个目标会被作为“默认目标”,我们可以将伪目标放置在第一位,以作为“默认目标”。一个应用示例就是,如果你的Makefile一次执行若干个可执行文件,但你仅需要输入一次make命令即可,并且所有的目标文件都写在一个Makefile中,那么可以使用“伪目标”的特性:

all: obj1 obj2 obj3
.PHONY: all
obj1: obj1.c utils.o
	cc -o obj1 obj1.o utils.o
obj2: obj2.c utils.o
	cc -o obj2 obj2.o utils.o
obj3: obj3.c common.o
	cc -o obj3 obj3.o common.o

上述的例子,我们使用.PHONY: all声明了一个伪目标all,其依赖于其他三个目标。由于默认目标具有总是被执行的特性,同时由于all又是一个伪目标。伪目标只是一个标签不会生成文件all。而其他三个目标的规则总是被执行,也即可达到生成多个目标的目的。

伪目标可以成为伪目标的依赖

.PHONY: cleanAll cleanObj cleanTemp
cleanAll: cleanObj cleanTemp
	rm *.exe
cleanObj: 
	rm *.o
cleanTemp: 
	rm *.temp

其中, make cleanAll将清除所有的文件(*.exe *.o *.temp),make cleanObj仅清除*.omake cleanTemp仅清除*.temp。这样可以使用不同的命令来达到清除不同种类的文件的目的。

静态模式

使用变量

常见的内置变量Variables

CC:C 编译器的名称。
CFLAGS:C 编译器的选项。
LD:链接器的名称。
LDFLAGS:链接器的选项。
AR:静态库的归档工具。
RM:删除文件的命令。
MAKE:Make 工具的名称。
MAKEFLAGS:Make 工具的选项。
CURDIR:当前工作目录的路径。
SHELL:Shell 程序的名称。
MAKEFILE_LIST:包含当前 Makefile 和所有被包含的 Makefile 的列表。


$(CC):C 编译器的名称。
$(CXX):C++ 编译器的名称。
$(AR):静态库归档工具的名称。
$(LD):链接器的名称。
$(AS):汇编器的名称。
$(FC):Fortran 编译器的名称。
$(RM):删除文件的命令。
$(MAKE):Make 工具的名称。
$(MAKECMDGOALS):被调用的目标列表。
$(MAKEFILE_LIST):包含当前 Makefile 的文件列表。
$(SHELL):Shell 解释器的名称。
$(CURDIR):当前工作目录的绝对路径。
$(PWD):当前工作目录的绝对路径。
$(ARFLAGS):静态库归档工具的选项。
$(LDFLAGS):链接器的选项。
$(ASFLAGS):汇编器的选项。
$(CPPFLAGS):预处理器的选项。
$(CFLAGS):C 编译器的选项。
$(CXXFLAGS):C++ 编译器的选项。
$(FFLAGS):Fortran 编译器的选项。
$(LFLAGS):链接器的选项。


AR:静态库归档程序的名称。
CC:C 编译器的名称。
CXX:C++ 编译器的名称。
CFLAGS:C 编译器的选项。
CXXFLAGS:C++ 编译器的选项。
CPPFLAGS:预处理器选项。
LD:链接器的名称。
LDFLAGS:链接器的选项。
LIBS:要链接的库。
RM:删除文件的命令。
MAKE:Make 工具的名称。
MAKEFLAGS:Make 工具的选项。

MAKEFILE_LIST

CC

CFLAGS

常见的内置函数

开头的$表示要执行一个Makefile的函数。

$(patsubst pattern,replacement,text):替换模式字符串。
$(wildcard pattern):匹配指定模式的文件列表。
$(foreach var,list,text):迭代列表中的每个元素,并将文本应用于每个元素。
$(shell command):执行命令并返回结果。
$(notdir names):从文件名路径中提取文件名部分。
$(basename names):从文件名路径中提取基本名称部分。
$(dir names):从文件名路径中提取目录部分。
$(addsuffix suffix,names):将后缀添加到每个名称。
$(addprefix prefix,names):将前缀添加到每个名称。


$(wildcard pattern):匹配指定模式的文件列表。
$(shell command):执行命令并返回结果。
$(foreach var,list,text):迭代列表中的每个元素,并将文本应用于每个元素。
$(if condition,then-part[,else-part]):根据条件选择不同的文本。
$(call variable,param,…):调用变量,并传递参数。
$(subst from,to,text):将文本中的字符串替换为另一个字符串。
$(patsubst pattern,replacement,text):替换模式字符串。
$(strip string):移除字符串中的前导和尾随空格。
$(findstring find,in):在字符串中查找子字符串。
$(filter pattern…,text):根据模式过滤文本中的元素。
$(dir names):从文件名路径中提取目录部分。
$(notdir names):从文件名路径中提取文件名部分。
$(suffix names):提取文件名路径中的后缀。
$(basename names):提取文件名路径中的基本名称。
$(addsuffix suffix,names):为文件名路径添加后缀。
$(addprefix prefix,names):为文件名路径添加前缀。


$(wildcard pattern):匹配指定模式的文件列表。
$(shell command):执行命令并返回结果。
$(patsubst pattern,replacement,text):替换模式字符串。
$(subst from,to,text):将文本中的字符串替换为另一个字符串。
$(foreach var,list,text):迭代列表中的每个元素,并将文本应用于每个元素。
$(if condition,then-part,else-part):根据条件选择返回不同的部分。
$(filter pattern…,text):筛选出符合模式的文本。
$(addprefix prefix,name…):为名称添加前缀。
$(addsuffix suffix,name…):为名称添加后缀。
$(notdir names):从文件名路径中提取文件名部分。
$(dir names):从文件名路径中提取目录部分。
$(shell command):执行命令并返回结果。
$(error message):输出错误消息并停止构建过程。
$(warning message):输出警告消息。
$(info message):输出一般消息。

wildcard: 扩展通配符

在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数wildcard,它的用法是:$(wildcard PATTERN...) 。在Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空。

一般我们可以使用$(wildcard *.c)来获取工作目录下的所有的.c文件列表。复杂一些用法;可以使用$(patsubst %.c,%.o,$(wildcard *.c)),首先使用“wildcard”函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o。这样我们就可以得到在当前目录可生成的.o文件列表。

因此在一个目录下可以使用如下内容的Makefile来将工作目录下的所有的.c文件进行编译并最后连接成为一个可执行文件:

objects := $(patsubst %.c,%.o,$(wildcard *.c))
 
foo : $(objects)
	cc -o foo $(objects)

其中,%是指匹配零或若干字符(如果需要引用%,使用转义字符\)。这里使用了make的隐含规则来编译.c的源文件,使用一个特殊符号:=对变量进行赋值。

测试用例

在当前TEST目录下,创建两个.c文件(testA.ctestB.c),以及一个目录subdir;然后再目录subdir下,创建两个.c文件(testC.ctestD.c)。整体结构如下图所示:
在这里插入图片描述

紧接着,在TEST目录下,创建makefile文件,其内容如下:

SRCS = $(wildcard *.c ./subdir/*.c)
DIR = $(notdir $(SRCS))
OBJ = $(patsubst %.c, %.o, $(DIR))

all:
	@echo $(SRCS)
	@echo $(DIR)
	@echo $(OBJ)

其中,wildcard可扩展通配符;notdir可去除路径;patsubst可替换通配符。

输出结果为:

testA.c testB.c ./subdir/testC.c ./subdir/testD.c
testA.c testB.c testC.c testD.c
testA.o testB.o testC.o testD.o

解释:
第一行:wildcard把指定目录././subdir/下的所有后缀为.c的文件全部展开;
第二行:notdir将展开的文件去除路径信息,比如将./subdir/testC.c ./subdir/testD.c分别替换为testC.c testD.c
第三行:patsubst$(DIR)中的后缀为.c的变量全部替换为.o。

wildcard

(patsubst pattern,replacement,text)

foreach

(foreach var,list,text)

路径

当前执行路径

makefile所在路径

示例

参考

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值