如何删除Makefile中的重复?

时间:2014-08-27 20:49:12

标签: c build makefile dry

有没有办法在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

有关如何制作此DRY的任何想法吗?

1 个答案:

答案 0 :(得分:3)

良好的第一个开始是停止重复目标/等。在规则体中,并使用自动变量代替它们。所以'$@'表示目标文件名,'$(@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))