GNU Make中%.c和* .c之间有什么区别

时间:2015-07-27 12:22:35

标签: makefile gnu-make

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)

谢谢。

2 个答案:

答案 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.ax.b中的此规则x.c,但绝不会来自y.bz1.c,即使{{1}也是如此并且x.b尚不存在,只要它们也可以存在(尽管这个例子没有表明)。如果没有,GNU Make将(令人困惑地)表现得就像规则不存在一样,如示例中所示。

答案 1 :(得分:1)

GNU Make中的%*都是通配符函数。它们之间的区别在于%可以用作Text Substitution Function的一部分,而*则不能。

如果您尝试制作尽可能快的makefile,您应该尝试使用* Wildcard Function优先于%替换函数,因为不应该有用于存储的资源匹配项的名称,并将其替换为后续函数调用。如果您对将制造系统优化到极限并不感到困扰,那么您不必担心选择哪一个。