Comment supprimer la duplication dans Makefile?

Existe-t-il un moyen de simplifier ce type de répétition dans un 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 

Fondamentalement, je souhaite exécuter une commande make build simple à partir du niveau supérieur et ne reconstruit ces sous-projets que si nécessaire. J’aimerais ne pas avoir à utiliser un Makefile pour chaque sous-projet car c’est également répétitif. Tout ce que j’ai essayé en ce qui concerne les chemins génériques n’a pas fonctionné, alors demandez-vous s’il existe même un moyen de le faire. Par exemple, j’ai essayé de faire quelque chose comme ça (similaire pour js et css) mais pas de chance:

 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 

Des idées comment faire ce SEC?

Un bon début serait d’arrêter de répéter les objectives / etc. dans les corps de règles eux-mêmes et utilisez plutôt les variables automatiques. Donc '$@' pour le nom du fichier cible, '$(@D)' pour le chemin du répertoire (comme dirname ) du nom du fichier cible, etc.

Ce qui vous amène:

 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) > '$@' 

Il est ensuite utile de comprendre que les règles de modèle sont utiles lorsque vous avez des objectives et des conditions préalables qui partagent des modèles de nom de fichier et des corps de règles similaires. Vous pouvez également commencer à les utiliser. Ils vous donnent également une variable automatique supplémentaire.

Vous obtenez cette étape (intermédiaire):

 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) > '$@' 

Et eux, vous voyez que vous venez de recevoir deux règles dupliquées, donc vous les combinez.

 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) > '$@' 

Et puis, comme make ne gère pas les cibles / conditions préalables du répertoire comme on pourrait le souhaiter, vous pouvez supprimer les cibles lib/background/build , lib/page/build et lib/popup/build et simplement lister les fichiers réels. comme prérequirejs pour la 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) > '$@' 

Je devrais probablement mentionner que je n’ai pas testé cela (par manque de volonté de simuler l’agencement du répertoire / etc.) Mais les transformations étaient simples et les concepts sont assez simples, donc ça devrait marcher. Mais tout est possible.

Pour nettoyer les prérequirejs de build vous pouvez utiliser quelque chose comme:

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