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

Rad*_*row 5 makefile gnu-make

%.c*.cmakefile 中有什么区别。例如我们可能有:

vpath %.c    $(BASE_DIR)platform/$(TARGET)
Run Code Online (Sandbox Code Playgroud)

Files += $(wildcard *.c) 
Run Code Online (Sandbox Code Playgroud)

两者都包含某个目录中以 .c 结尾的所有文件。但是我们什么时候使用%.c*.c什么时候使用?换句话说,为什么我不能使用

vpath *.c    $(BASE_DIR)platform/$(TARGET)
Run Code Online (Sandbox Code Playgroud)

代替

vpath %.c    $(BASE_DIR)platform/$(TARGET)
Run Code Online (Sandbox Code Playgroud)

?

谢谢你。

rei*_*ost 6

Both % and * in GNU Make can be regarded as wildcards, but in a very different way.

The * character is what the GNU Make manual calls a wildcard: it represents a glob match, a pattern match against files present on the file system. E.g. *.a expands to the list of files present in the current directory whose names end in .a, or to literal *.a if no such files exist.

For example:

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
Run Code Online (Sandbox Code Playgroud)

As you can see, * is interpreted by matching it against the files that happen to exist in the file system. For instance, make interprets *.a as the literal filename *.a until I create files with a names ending in .a, at which point it expands to the names of those files; the same for *.b and *.c.

So use * only if you really want to specify a set of files already present on your file system. This is common for source files (prerequisites in the rules) but it is really weird to use it in targets of rules, like in this example.

The % character also performs pattern matching, but in a very different way: when used on both sides of the :, it is part of a pattern rule, and it states a relationship between the names of the target file(s) and the names of the dependencies.

For example:

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
Run Code Online (Sandbox Code Playgroud)

%字符永远不会与文件系统上的文件匹配,而是表示目标文件名和必备文件名之间的对应关系:%.a: %.b %.c意味着:您可以使用此规则从名称相同但结尾不同的文件中创建名称以 结尾的任何.a文件在.b.c. 因此,我们可以使用来自和 的x.a规则,但不能使用来自或 的规则,即使和尚不存在,只要它们也可以被创建(尽管这个例子没有表明这一点),这也是正确的。如果没有,GNU Make 将会(令人困惑地)表现得好像规则不存在一样,正如您在示例中看到的那样。x.bx.cy.bz1.cx.bx.b


Taf*_*afT 1

GNU Make 中的 和%都是*通配符函数。它们之间的区别在于,可以用作文本替换函数%的一部分,而不能。 *

如果您试图制作尽可能最快的 makefile,您应该尝试使用* 通配符函数而不是%替换函数,因为不应该使用任何资源来存储匹配项的名称并将其替换到后续函数调用中。如果您不介意将 make 系统优化到极限,则无需太担心选择哪一个。