代码之家  ›  专栏  ›  技术社区  ›  Izzo

Make中的%和*通配符有什么区别?

  •  0
  • Izzo  · 技术社区  · 2 年前

    我目前正在学习Make,正在努力理解通配符的概念。具体来说,似乎有两个符号可以表示通配符:*和%

    例如,假设我想生成一个变量,用于标识工作目录中的所有.c源文件。我会在*.c中使用传统的*符号。但是,如果我使用patsubst函数,我需要使用%符号而不是*符号:

    // WORKS 
    SRC = $(wildcard *.c)               # list of source files
    OBJS = $(patsubst %.c, %.o, $(SRC)) # list of object files
    
    // DOES NOT WORK!!!!
    SRC = $(wildcard *.c)               # list of source files
    OBJS = $(patsubst *.c, *.o, $(SRC)) # list of object files
    

    有人能在Make通配符的上下文中解释*和%之间的区别吗?

    1 回复  |  直到 2 年前
        1
  •  1
  •   John Bollinger    2 年前

    有人能在Make通配符的上下文中解释*和%之间的区别吗?

    TL;博士:

    • 这一切都是GNU特有的 make

    • * 其他一些角色对 wildcard 函数,但不是 patsubst 。这种模式 扩展的 到匹配模式的现有文件和目录的名称,每个模式可能有多个。

    • % 对于 patsubst 作用这种模式用于 选择 匹配makefile或直接由 制作 ,在捕获与 % 以备日后使用。

    • 这两种规则都适用于规则的目标列表和先决条件列表,但它们在那里的意义有些不同。

    • 这些对 制作 在食谱中,但是 通配符 -样式模式对shell非常重要,shell将在执行的配方中对其进行解释。

    全体的

    首先要明白 $(wildcard) $(patsubst) 是特定于 GNU的实现 属于 制作 、和GNU 制作 还将特殊意义归因于 % , * ,以及规则目标和先决条件中的其他一些字符。POSIX规范 制作 对此只字不提。GNU 制作 如今被广泛使用,这是有充分理由的,但它并不是唯一 制作 你可能会遇到。如果您希望在 制作 那么您必须完全避免这些实现。

    还要明白,对这个问题的完整但相当基本的回答只是“是的 通配符 patsubst 函数识别不同的特殊字符。“这些函数做不同的事情,所以一个函数的特殊字符可以用作另一个函数中的普通字符,这可能很有用。

    通配符

    星号( * )是Bourne shell识别的“路径名扩展”的特殊字符之一,它用可能很多的名称替换模式 现有的 与模式匹配的文件和目录。有更多的字符 * 路径名扩展意义重大,但 % 不在其中。查阅那个术语以获得完整的描述。

    此外,还有波浪号( ~ ),其中 制作 一些shell识别为“波浪形扩展”,即将受影响路径的第一段解释为指定用户的主目录。

    GNU 制作 文档将其为路径名和波浪号扩展识别的字符和结构描述为“通配符”,并对其进行了说明:

    通配符扩展由执行 制作 在目标和先决条件中自动执行。在配方中,shell负责通配符扩展。在其他上下文中,只有当您使用 通配符 作用

    ( GNU make manual, section 4.4 )

    这就是 通配符 出现在问题中的函数出现了——如果您想执行与 制作 在其他一些上下文(如变量定义)中对目标和先决条件名称自动执行,然后可以使用 the wildcard function 因此,

    SRC = $(wildcard *.c)
    

    结果变量 SRC 表示解析makefile时工作目录中所有现有文件的列表,这些文件的名称以 .c

    另一方面 % 对于路径名或波浪号扩展来说并不重要,因此

    SRC = $(wildcard %.c)
    

    将扩展到字面 %.c

    图案

    shell文档使用术语“模式”来表示shell输入,该输入被解释为要进行路径名扩展,而不是文字。然而,GNU 制作 保留一种不同模式的术语 % 角色特征。这涉及两个主要领域: the patsubst function pattern rules

    这个 patsubst 作用

    这个 patsubst 函数通过用指定的替换替换与给定模式匹配的字符串来计算一个字符串或一系列字符串。在一个模式中,第一个 % 字符(如果有的话)匹配任意数量的字符,包括零。从这个意义上说,它可以被描述为通配符,而手册确实使用了这个术语,这有点令人困惑。如果更换件还包含至少一个 % 则第一个替换为与 % 在模式中。

    请注意,这与文件名无关,无论是现有的还是其他的。

    因此

    SRC = main.c other.c
    OBJ = $(patsubst %.c,%.o,$(SRC))
    

    这个 %.c 模式首先匹配 main.c (与 % 匹配 main )然后 other.c (与 % 匹配 other ),以及的结果 OBJ 与此相同:

    OBJ = main.o other.o
    

    无论是否有任何名为 main.c , 其他.c , main.o other.o 存在

    图案规则

    如果规则的目标包含 % ,则由GNU进行解释 制作 作为模式规则。模式规则使用 % 就像 patsubst 做什么时候 制作 需要构建一个目标,但没有针对该特定目标的规则,它将检查目标名称是否与任何模式规则(包括一些内置规则)的目标模式匹配。不需要任何具有该名称的现有文件。如果它找到了匹配项,那么它将使用该规则来构建目标。在这种情况下,为了建立有问题的目标 % 该规则中指定的任何先决条件名称中的字符(如果有的话)将被匹配 % 在目标中,很像在 patsubst

    组合

    通常,在任何给定的上下文中,都只需要这些类型的模式匹配/扩展中的一种,但有时它们可以有效地组合在一起。例如,考虑以下模式规则:

    %.o: %.c *.h
        $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
    

    这说明任何 .o 文件可以从相应的 c 文件和 全部的 这个 .h 文件。

        2
  •  0
  •   Allan Wind    2 年前

    这个 wildcard 函数需要通配符( ~ , * , ? [...] 与文件名匹配),而 patsubst 函数需要一个模式( % )对文本进行操作。像这样的 $(patsubst *.c, *.o, $(SRC)) 表示替换文字字符串 *.c 用绳子 *.o SRC 可能不包含任何文字 *.c 字符串。