【问题标题】:How to remove duplication in Makefile?如何删除 Makefile 中的重复项?
【发布时间】:2014-08-27 20:49:12
【问题描述】:

有没有办法简化 Makefile 中的这种重复?

duo = ./node_modules/.bin/duo

build: lib/background/build lib/page/build lib/popup/build

lib/background/build: lib/background/build/build.js lib/background/build/build.css
lib/page/build: lib/page/build/build.js lib/page/build/build.css
lib/popup/build: lib/popup/build/build.js lib/popup/build/build.css

lib/background/build/build.js: lib/background/index.js node_modules component.json
  @mkdir -p lib/background/build
  @$(duo) lib/background/index.js > lib/background/build/build.js

lib/page/build/build.js: lib/page/index.js node_modules component.json
  @mkdir -p lib/page/build
  @$(duo) lib/page/index.js > lib/page/build/build.js

lib/popup/build/build.js: lib/popup/index.js node_modules component.json
  @mkdir -p lib/popup/build
  @$(duo) lib/popup/index.js > lib/popup/build/build.js

lib/background/build/build.css: lib/background/index.css node_modules component.json
  @mkdir -p lib/background/build
  @$(duo) lib/background/index.css | $(myth) > lib/background/build/build.css

lib/page/build/build.css: lib/page/index.css node_modules component.json
  @mkdir -p lib/page/build
  @$(duo) lib/page/index.css | $(myth) > lib/page/build/build.css

lib/popup/build/build.css: lib/popup/index.css node_modules component.json
  @mkdir -p lib/popup/build
  @$(duo) lib/popup/index.css | $(myth) > lib/popup/build/build.css

基本上,我想从顶层运行一个简单的make build 命令,它只在必要时重建这些子项目。我不想为每个子项目使用 Makefile,因为这也是重复的。我尝试过的与通配符路径相关的一切都没有成功,所以想知道是否有办法做到这一点。例如,我尝试做这样的事情(对于 js 和 css 都类似)但没有运气:

js = $(shell find lib test -type f -name '*.js' ! -path "*build.js")

$(js)/build/build.js: node_modules component.json
  # somehow get the directory such as lib/background based on the make command?
  local dir=$(shell dirname $(shell dirname $@))
  @mkdir -p $(dir)/build
  @$(duo) $(dir)/index.js > $(dir)/build/build.js

任何想法如何使这个干燥?

【问题讨论】:

  • 该尝试行不通,因为$(js) 是一个文件名列表,因此将在目标槽中扩展为一个文件名列表,其中/build/build.js 附加到最后的文件名列表。

标签: c build makefile dry


【解决方案1】:

一个好的开始是停止重复目标/等。在规则体本身中,并为它们使用自动变量。所以'$@'为目标文件名,'$(@D)'为目标文件名的目录路径(如dirname)等

这让你:

duo = ./node_modules/.bin/duo

build: lib/background/build lib/page/build lib/popup/build

lib/background/build: lib/background/build/build.js lib/background/build/build.css
lib/page/build: lib/page/build/build.js lib/page/build/build.css
lib/popup/build: lib/popup/build/build.js lib/popup/build/build.css

lib/background/build/build.js: lib/background/index.js node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) lib/background/index.js > '$@'

lib/page/build/build.js: lib/page/index.js node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) lib/page/index.js > '$@'

lib/popup/build/build.js: lib/popup/index.js node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) lib/popup/index.js > '$@'

lib/background/build/build.css: lib/background/index.css node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) lib/background/index.css | $(myth) > '$@'

lib/page/build/build.css: lib/page/index.css node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) lib/page/index.css | $(myth) > '$@'

lib/popup/build/build.css: lib/popup/index.css node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) lib/popup/index.css | $(myth) > '$@'

然后意识到pattern rules 很有帮助,当您拥有共享文件名模式和类似规则主体的目标和先决条件时,您也可以开始使用它们。他们还给你一个额外的automatic variable

你进入这个(中间)阶段:

duo = ./node_modules/.bin/duo

build: lib/background/build lib/page/build lib/popup/build

lib/background/build: lib/background/build/build.js lib/background/build/build.css
lib/page/build: lib/page/build/build.js lib/page/build/build.css
lib/popup/build: lib/popup/build/build.js lib/popup/build/build.css

%/build/build.js: %/index.js node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) '$*'/index.js > '$@'

%/build/build.js: %/index.js node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) '$*'/index.js > '$@'

%/build/build.js: %/index.js node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) '$*'/index.js > '$@'

%/build/build.css: %/index.css node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) '$*'/index.css | $(myth) > '$@'

%/build/build.css: %/index.css node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) '$*'/index.css | $(myth) > '$@'

%/build/build.css: %/index.css node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) '$*'/index.css | $(myth) > '$@'

您会发现它们实际上只是有两个重复的规则,因此您将它们组合起来。

duo = ./node_modules/.bin/duo

build: lib/background/build lib/page/build lib/popup/build

lib/background/build: lib/background/build/build.js lib/background/build/build.css
lib/page/build: lib/page/build/build.js lib/page/build/build.css
lib/popup/build: lib/popup/build/build.js lib/popup/build/build.css

%/build/build.js: %/index.js node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) '$*'/index.js > '$@'

%/build/build.css: %/index.css node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) '$*'/index.css | $(myth) > '$@'

然后,由于 make 没有像人们喜欢的那样处理目录目标/先决条件,您可以删除 lib/background/buildlib/page/buildlib/popup/build 中间目标,并将实际文件列为先决条件对于build

duo = ./node_modules/.bin/duo

build: lib/background/build/build.js lib/background/build/build.css \
       lib/page/build/build.js lib/page/build/build.css \
       lib/popup/build/build.js lib/popup/build/build.css

%/build/build.js: %/index.js node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) '$*'/index.js > '$@'

%/build/build.css: %/index.css node_modules component.json
        @mkdir -p '$(@D)'
        @$(duo) '$*'/index.css | $(myth) > '$@'

我可能应该提一下,我没有对此进行测试(因为不想模拟目录布局/等),但是转换是直截了当的,并且概念相当简单,所以它应该可以正常工作。但一切皆有可能。

要清理build 先决条件,您可以使用以下内容:

build: $(foreach d,background page popup,$(addprefix lib/$d/build/,build.js build.css))

【讨论】:

  • 老兄,没门。你是大师!这太酷了,清理了这么多。
  • 有什么方法可以清理build: <deps> 依赖关系,所以它们也是有模式的吗?像build: %/build/build.js %/build/build.css 这样的东西?这似乎对我不起作用。 make: *** No rule to make target '%/build/build.js', needed by 'build'. Stop.
  • 是的,那样不行。如果你愿意,你可以用一些 make 函数来清理它。等等。
  • 任何想法如何让它工作? %/build/build.js: %/index.js %/lib/*.js node_modules component.json,其中%/lib/*.js 我希望它匹配与%/lib 相关的所有javascript 文件,这可能是lib/page/lib/*.jslib/popup/lib/*.js 等。虽然会出现一些奇怪的行为,但无法正常工作。
猜你喜欢
  • 1970-01-01
  • 2012-08-10
  • 2020-10-23
  • 2022-01-27
  • 2014-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多