GNU make avec de nombreux répertoires cibles
-
06-09-2019 - |
Question
Je dois intégrer la génération de nombreux fichiers HTML dans un Makefile
existant.
Le problème est que les fichiers HTML doivent relever de nombreux répertoires différents.
Mon idée est d'écrire une règle implicite qui convertit le fichier source (* .st) dans le fichier html correspondant
%.html: %.st
$(HPC) -o $@ $<
et une règle qui dépend de tous les fichiers html
all: $(html)
Si le fichier HTML est pas dans le make
builddir ne trouve pas la règle implicite: *** No rule to make target
.
Si je change la règle implicite comme si
$(rootdir)/build/doc/2009/06/01/%.html: %.st
$(HPC) -o $@ $<
il se trouve, mais je dois avoir une règle implicite pour presque tous les fichiers du projet.
Selon Implicite Règle algorithme de recherche dans le GNU manuel d'make
, travaux de recherche de règle comme ceci:
- t de Split dans une partie du répertoire, appelé d, et le reste, appelé n. Pour Par exemple, si t est
src/foo.o', then d is
src / 'et n est `foo.o'.- Faites une liste de toutes les règles modèle dont l'une des cibles correspond t ou n. Si le motif cible contient une slash, elle est comparée à t; autrement, contre n.
Pourquoi la règle implicite ne se trouve pas, et quelle serait la solution la plus élégante, en supposant GNU make
est utilisé?
Voici une version dépouillée de mon Makefile
:
rootdir = /home/user/project/doc
HPC = /usr/local/bin/hpc
html = $(rootdir)/build/doc/2009/06/01/some.html
%.html: %.st
$(HPC) -o $@ $<
#This works, but requires a rule for every output dir
#$(rootdir)/build/doc/2009/06/01/%.html: %.st
# $(HPC) -o $@ $<
.PHONY: all
all: $(html)
La solution
Comme Maria Shalnova je make récursif (bien que je suis en désaccord avec « récursive Marque Considéré comme nuisible »), et en général il est préférable de faire quelque chose à partir d'une source, il, et non l'inverse. Mais si vous devez, je suggère une légère amélioration: ont generateHtml générer que la règle, pas les commandes
.Autres conseils
La meilleure solution que je trouve à ce jour est de générer une règle implicite par répertoire cible via foreach-eval-call , comme cela est expliqué dans la section
Votre règle implicite actif fait La règle en commentaire fait Une solution est de vous faire êtes mise en page source correspondent à votre destination / mise en page de résultats. Une autre option est de créer les règles au besoin avec $(rootdir)/build/doc/2009/06/01/some.html
dépendent $(rootdir)/build/doc/2009/06/01/some.st
. Si $(rootdir)/build/doc/2009/06/01/some.st
n'existe pas, la règle ne sera pas utilisé / trouvé. $(rootdir)/build/doc/2009/06/01/some.html
dépendent some.st
. eval
. Mais ce sera assez compliqué: define HTML_template
$(1) : $(basename $(1))
cp $< $@
endef
$(foreach htmlfile,$(html),$(eval $(call HTML_template,$(htmlfile))))
Une autre possibilité est d'avoir le commando make
lui-même appeler récursive avec le -C argument avec tous les répertoires de sortie.
Récursive make
est un peu la norme pour traiter avec les sous-répertoires, mais méfiez-vous des conséquences mentionnées dans l'article « récursif Marque Considered Harmful »