makefile中%.c
和*.c
之间的区别是什么?例如,我们可能有:
vpath %.c $(BASE_DIR)platform/$(TARGET)
和
Files += $(wildcard *.c)
两者都包含特定目录中以.c结尾的所有文件。但是,当我们使用%.c
和*.c
时?换句话说,为什么我不能使用
vpath *.c $(BASE_DIR)platform/$(TARGET)
而不是
vpath %.c $(BASE_DIR)platform/$(TARGET)
谢谢。
答案 0 :(得分:2)
GNU Make中的%
和*
都可以视为通配符,但方式却截然不同。
*
字符为what the GNU Make manual calls a wildcard:它代表 glob 匹配,与文件系统上存在的文件匹配。例如。 *.a
扩展到当前目录中存在的文件列表,其名称以.a
结尾,如果不存在此类文件,则扩展为文字*.a
。
例如:
sh> rm -f *.a *.b *.c
sh> cat Makefile
all: *.a
*.a : *.b *.c
@echo $+ > $@
sh> make
make: *** No rule to make target '*.b', needed by '*.a'. Stop.
sh> touch x.a
sh> make
make: *** No rule to make target '*.b', needed by 'x.a'. Stop.
sh> touch y.b
sh> make
make: *** No rule to make target '*.c', needed by 'x.a'. Stop.
sh> touch z1.c z2.c
sh> make
sh> cat x.a
y.b z2.c z1.c
如您所见,*
通过将其与文件系统中恰好存在的文件进行匹配来解释。例如,make
将*.a
解释为文字文件名*.a
,直到我创建名称以.a
结尾的文件,此时它会扩展为这些文件的名称; *.b
和*.c
也一样。
因此,只有在您确实要指定文件系统中已存在的一组文件时才使用*
。这对于源文件(规则中的先决条件)很常见,但在规则目标中使用它确实很奇怪,就像在这个例子中一样。
%
字符也执行模式匹配,但方式完全不同:在:
的两侧使用时,它都是pattern rule的一部分,它表示目标文件名称与依赖项名称之间的关系。
例如:
sh> rm -f *.a *.b *.c
sh> cat Makefile
all: %.a
%.a : %.b %.c
@echo $+ > $@
sh> make
make: *** No rule to make target '%.a', needed by 'all'. Stop.
sh> touch x.a y.b z1.c z2.c
sh> make
make: *** No rule to make target '%.a', needed by 'all'. Stop.
sh> make x.a
make: Nothing to be done for 'x.a'.
sh> make y.a
make: *** No rule to make target 'y.a'. Stop.
sh> touch y.c
sh> make y.a
sh> cat y.a
y.b y.c
%
字符永远不会与文件系统上的文件匹配,而是表示目标文件名和必备文件名之间的对应关系:%.a: %.b %.c
表示:您可以使用此规则使任意文件的名称以.c
结尾,文件的名称相同,但它们以.a
和.b
结尾。因此,我们可以使用x.a
和x.b
中的此规则x.c
,但绝不会来自y.b
或z1.c
,即使{{1}也是如此并且x.b
尚不存在,只要它们也可以存在(尽管这个例子没有表明)。如果没有,GNU Make将(令人困惑地)表现得就像规则不存在一样,如示例中所示。
答案 1 :(得分:1)
GNU Make中的%
和*
都是通配符函数。它们之间的区别在于%
可以用作Text Substitution Function的一部分,而*
则不能。
如果您尝试制作尽可能快的makefile,您应该尝试使用*
Wildcard Function优先于%
替换函数,因为不应该有用于存储的资源匹配项的名称,并将其替换为后续函数调用。如果您对将制造系统优化到极限并不感到困扰,那么您不必担心选择哪一个。