【问题标题】:What is the difference between %.c and *.c in GNU MakeGNU Make 中的 %.c 和 *.c 有什么区别
【发布时间】:2015-07-27 12:22:35
【问题描述】:

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)

?

谢谢。

【问题讨论】:

  • 不同的 Make 函数使用不同的通配符。 vpath 指令使用%wildcard 函数使用*。除了这不是制作通配符的最大缺点之外,它没有更多内容。
  • 更清楚地说,$(wildcard ...) 函数使用 shell 通配(就像你运行 ls *.c 一样)。使自己只使用简单的模式匹配(使用%)。

标签: makefile gnu-make


【解决方案1】:

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 表示:您可以使用此规则使 any名称以.a 结尾的文件来自名称相同但以.b.c 结尾的文件。所以我们可以使用来自x.bx.c 的规则来生成x.a,但永远不能来自y.bz1.c,即使x.bx.b 尚不存在也是如此,只要因为它们也可以制作(尽管这个例子没有显示)。如果不存在,GNU Make 将(令人困惑地)表现得好像规则不存在,正如您在示例中看到的那样。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 我不太确定为什么这个答案被编辑,然后未经编辑。似乎 reinierpost 只是用示例扩展了我的答案,然后决定将其发布为他自己的答案而不注明出处。如果定期这样做,他的高分可能主要是由空编辑和反刍的帖子产生的。或者他只是意识到我的答案与他想要的答案相比有多么糟糕。
    • 对不起,这只是一个错误:我以为我正在创建自己的答案,但我错误地点击了您答案上的编辑按钮,我是在完成我的答案后才发现的回答。这怎么会发生,我不知道。
    • 顺便说一句,我认为您的回答并未确定主要区别。 * 匹配文件系统上的文件,而 % 不匹配。 * 只匹配目标,% 定义目标和依赖项名称的公共部分。
    猜你喜欢
    • 2013-06-16
    • 2014-06-07
    • 2013-12-02
    • 1970-01-01
    • 2011-04-05
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    • 2010-09-09
    相关资源
    最近更新 更多