代码之家  ›  专栏  ›  技术社区  ›  Erik Bennett

用隐式规则制造麻烦

  •  0
  • Erik Bennett  · 技术社区  · 7 年前

    我遗漏了一些隐含的规则。这是makefile(GNU make 4.2.1)

    heimdall /tmp 1670> cat Makefile
    
    PARTS= a b c
    
    .SECONDEXPANSION:
    
    data/events2: $$(patsubst %,$$(@D)/%.ppd,$(PARTS))
            /bin/ls -l $^
    
    %/events2: $$(patsubst %,$$(@D)/%.ppd,$(PARTS))
            /bin/ls -l $^
    

    以下是为说明情况而准备的数据:

    heimdall /tmp 1671> ls -1 data data1
    data:
    a.ppd
    b.ppd
    c.ppd
    
    data1:
    a.ppd
    b.ppd
    c.ppd
    

    这里是 make 使用一个明确的规则,就像我所期望的那样。

    heimdall /tmp 1672> make data/events2
    /bin/ls -l data/a.ppd data/b.ppd data/c.ppd
    -rw-rw-r-- 1 bennett None 0 Feb  4 12:19 data/a.ppd
    -rw-rw-r-- 1 bennett None 0 Feb  4 12:19 data/b.ppd
    -rw-rw-r-- 1 bennett None 0 Feb  4 12:19 data/c.ppd
    

    最后,这是:

    heimdall /tmp 1673> make data1/events2
    make: *** No rule to make target 'data1/events2'.  Stop.
    

    为什么隐式规则不匹配?我觉得我错过了一些基本的东西。

    谢谢。

    -e

    1 回复  |  直到 7 年前
        1
  •  1
  •   Ondrej K.    7 年前
    %/events2: $$(patsubst %,$$(@D)/%.ppd,$(PARTS))
    

    不是将在示例结构中匹配的模式规则。从 docs :

    % 在模式规则的先决条件中,表示与 % 在目标中。为了应用模式规则,其目标模式必须与考虑中的文件名匹配,并且其所有先决条件(模式替换之后)必须命名存在或可以创建的文件。这些文件成为目标的先决条件。

    但是在你的目标中 % 会匹配的 data1 . 但实际上没有 % 在先决条件方面进行匹配 patsubst 函数和目录(STEM)被称为 $(@D) .

    我试着用 foreach 功能:

    %/events2: $(foreach part,$(PARTS), %/$(part).ppd)
            /bin/ls -l $^
    

    如果你想坚持 圣徒 这也应该有效:

    %/events2: $(patsubst %,\%/%.ppd,$(PARTS))
            /bin/ls -l $^
    

    不是那样 % 用于匹配目标中的目录名,并用 \ 使它通过 圣徒 毫发无损。

    任何一种方式似乎都与GNU取得了良好的收益:

    $ make data1/events2
    /bin/ls -l data1/a.ppd data1/b.ppd data1/c.ppd
    -rw-r--r-- 1 ondrej users 0 Feb  4 22:00 data1/a.ppd
    -rw-r--r-- 1 ondrej users 0 Feb  4 22:00 data1/b.ppd
    -rw-r--r-- 1 ondrej users 0 Feb  4 22:00 data1/c.ppd