如何删除Makefile中的重复?

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

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

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

然后,当您拥有共享文件名模式和类似规则主体的目标和先决条件时,您也可以开始使用这些规则,这样才能实现模式规则 。 它们还为您提供了额外的自动变量 。

你得到这个(中间)阶段:

 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))