makefile中%和*之间的区别是什么

Jor*_*ran 7 makefile pattern-matching gnu-make

GNU make手册在解释这一部分不擅长,我找不到解释或者我不能推断其他地方的信息.

我知道%是一种通配符,但之间有什么区别%*的背景下targets,dependenciescommands?我在哪里可以使用它,到处都有相同的含义?

target: dependencies ...
    commands
Run Code Online (Sandbox Code Playgroud)

tri*_*eee 7

通配符*仅用于在当前目录中生成匹配文件列表。模式替换字符%是当前可能存在或不存在的文件的占位符。

为了扩展您已经发现的手册中的通配符陷阱示例,

objects = *.o
Run Code Online (Sandbox Code Playgroud)

只是为变量分配了*.o几乎没有用的字面值-一个目标文件,该文件可能依赖于字面命名的文件,而该文件*.c当然也不存在。这样您会得到一个错误和/或不稳定的行为。

正确的表达方式就像

objects := $(patsubst %.c,%.o,$(wildcard *.c))
Run Code Online (Sandbox Code Playgroud)

make本身在这种情况下不执行通配符扩展,但是,当然,如果您将文字值传递*.o给Shell,则在扩展发生时(如果存在匹配项),因此这可能很难调试。 make 在规则的目标中执行通配符扩展,因此您可以说

foo: *.o
Run Code Online (Sandbox Code Playgroud)

并使其完全按照您的预期工作(前提是在评估此依赖项时保证所需文件已存在)。

相比之下,您可以拥有一个带有模式占位符的规则,该规则将用任何匹配的名称填充,以make尝试查找可用于生成所需依赖项的配方。有内置的规则,例如

%.o: %.c
        $(CC) $(CCFLAGS) $^ -o $@
Run Code Online (Sandbox Code Playgroud)

(这里近似真实的东西)说“给定文件匹配%.c,则%.o可以如下生成相应的文件”。在这里,%是一个可以用任何东西代替的占位符;因此,如果将其应用于现有文件,foo.c则会说明如何foo.o生成。

您可以改写为“ *匹配每个匹配文件,同时%匹配任何匹配文件”。


Kaz*_*Kaz 5

双方%*在制作食谱线普通字符; 它们只是传递给外壳。

%表示模式替换中的文件“词干”,如$(patsubst %.o,%.c,$(OBJS)). 该模式%.o应用于 中的每个元素$(OBJS),并%捕获匹配部分。然后在替换模式中%.c,捕获的部分被替换,替换%列表patsubst作为返回值出现。

*$(wildcard ...)操作符的参数中很有用,它类似于 shell *glob 在匹配文件系统中的某些路径时的操作。

在 a 的左侧patsubst, where%表示匹配,它类似于*匹配某些字符。不过也%有一些限制,比如只能出现一次!例如,虽然我们可以扩展通配符*/*.c,当然,我们不能有像$(patsubst %/%.o,%/foo/%.c,...). 这个限制可能会在未来的 GNU Make 版本中被取消,但据我所知,它目前仍然有效。

此外,匹配非空字符序列的%和之间也存在细微差别。通配符模式匹配。取代模式也没有匹配的,因为然后阀杆将是空的,其是不允许的。*%fo*o.cfoo.cfo%o.cfoo.c%