【问题标题】:makefile substitute target pattern twice in its dependencymakefile 在其依赖项中两次替换目标模式
【发布时间】:2023-03-27 00:07:01
【问题描述】:

我有以下项目架构

/
├── makefile
└── doc/
    ├── makefile
    └── uml/
        ├── uml1/
        │   ├── uml1.plantuml
        |   └── res/
        |       ├── ressource1
        |       └── ressource2
        └── uml2/
            ├── uml2.plantuml
            └── res/
                ├── ressource1
                └── ressource2

我的目标是为存在于doc/uml 中的每个目录生成一个png图像到build/doc/uml

父makefile如下

BUILD_PATH?=./build

doc:
    ${MAKE} -C $@ $@ ADOC_OUTPUT_DIR=$(abspath ${BUILD_PATH}/doc)

clean:
    rm -rf build

.PHONY: doc clean

而submakefile就是下面这个

ADOC_OUTPUT_DIR ?= build
UML_OUTPUT_DIR = ${ADOC_OUTPUT_DIR}/uml

UML = $(notdir $(wildcard uml/*))
UML_TARGETS = $(foreach uml, ${UML}, ${UML_OUTPUT_DIR}/${uml}.png)

doc: uml

uml: ${UML_OUTPUT_DIR} ${UML_TARGETS}

${UML_TARGETS}: ${UML_OUTPUT_DIR}/%.png : uml/%/%.plantuml
    plantuml $< -o $(@D)

###################################
##### Directory creation part #####
###################################

${UML_OUTPUT_DIR}:
    mkdir -p $@

.PHONY: doc uml ${UML_TARGETS} ${UML_OUTPUT_DIR}

但是当我使用 make doc 启动它时它失败了

$ make doc
make -C doc doc ADOC_OUTPUT_DIR=/home/julien/test_uml/build/doc
make[1] : Entering directory « /home/julien/test_uml/doc »
make[1]: ***  No rule to make target « uml/gui_state_diagram/%.plantuml », needed by « /home/julien/test_uml/build/doc/uml/gui_state_diagram.png ». Stop.
make[1] : Exiting directory « /home/julien/test_uml/doc »
makefile:12 : the recipe for target « doc » failed
make: *** [doc] Erreur 2

看来问题出在依赖项上不能两次替换'%'。

如果不修改项目架构,我无法找到实现目标的方法(我希望保持与现在一样接近)

有没有办法将模式 '%' 替换两次?

有没有比尝试在目标的依赖项中两次替换 uml 名称更好的方法来实现我的目标?

【问题讨论】:

    标签: linux makefile gnu-make


    【解决方案1】:

    你也可以使用secondary expansion:

    .SECONDEXPANSION:
    ${UML_TARGETS}: ${UML_OUTPUT_DIR}/%.png : uml/$$*/$$*.plantuml
            plantuml $< -o $(@D)
    

    【讨论】:

      【解决方案2】:

      确实,在您的情况下,您不能使用静态模式规则。但是你可以使用the eval function:

      define MY_rule
      ${UML_OUTPUT_DIR}/$(1).png : uml/$(1)/$(1).plantuml
          plantuml $$< -o $$(@D)
      endef
      $(foreach u,$(UML),$(eval $(call MY_rule,$(u))))
      

      【讨论】:

        【解决方案3】:

        由于 uml/%/%.plantuml 中的两个 %s 在文件系统中必须是唯一的,因此额外的目录不会添加任何内容来保持结果路径的唯一性 - uml/foo/foo.plantuml 并不比 uml/foo.plantuml 更有用.我会简单地摆脱uml 下的目录。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-24
          • 2012-02-08
          • 2013-06-05
          • 1970-01-01
          • 2016-09-14
          • 2021-02-24
          相关资源
          最近更新 更多