Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

makefile et généricité

1 réponse
Avatar
mpg
Bonjour,

je suis plus ou moins débutant en makefiles, et je suis actuellement en
train d'essayer d'en faire un pour convertir des répertoires de pages de
man en pdf et en html. Pour l'instant, j'ai un Makefile à la racine
(répertoire man) comme suit :

DIR = man1 man5

all: $(DIR)
pdf: $(DIR)
html: $(DIR)
clean: $(DIR)

$(DIR):
$(MAKE) -C $@ $(MAKECMDGOALS)

.PHONY: $(DIR)

et deux, resp. dans man1 et man5 (seules sections présentes) comme ça :

SRC = $(wildcard *.5)
PDF = $(patsubst %.5, %.pdf, $(SRC))
HTML = $(patsubst %.5, %.html, $(SRC))

all: html pdf
pdf: $(PDF)
html: $(HTML)

clean:
-rm -f -- $(PDF) $(HTML)

%.pdf: %.5
groff -man $< | ps2pdf - $@

%.html: %.5
groff -man -Thtml $< > $@

en remplaçant partout .5 par .1 pour man1/Makefile.

La ressemblance très forte entre les deux derniers fichiers me fait penser
qu'il y aurait sans doute moyen de factoriser un peu tout ça, mais je ne
vois pas trop comment procéder. J'ai essayé de mettre des règles comme :

%.pdf: %.$(SEC)
groff -man $< | ps2pdf - $@

dans le Makefile racine puis de définir SEC = 5 dans le man5/Makefile,
visiblement ce n'est pas du goût de make. Pour la génération des listes PDF
et HTML, je ne vois pas non plus.

Je suis preneur de toute piste ou pointeur vers la partie adéquate de la
documentation. Le truc n'a pas besoin d'être portable donc si des
fonctionnalités spécifiques de GNU make peuvent aider, ça ne pose pas de
problème de les utiliser.

Merci d'avance !

Manuel.

1 réponse

Avatar
Xavier Gachon
Le 16-07-2008, mpg a écrit :
en remplaçant partout .5 par .1 pour man1/Makefile.

La ressemblance très forte entre les deux derniers fichiers me fait penser
qu'il y aurait sans doute moyen de factoriser un peu tout ça, mais je ne
vois pas trop comment procéder. J'ai essayé de mettre des règles comme :

%.pdf: %.$(SEC)
groff -man $< | ps2pdf - $@

dans le Makefile racine puis de définir SEC = 5 dans le man5/Makefile,
visiblement ce n'est pas du goût de make. Pour la génération des listes PDF
et HTML, je ne vois pas non plus.



Tu peux definir SEC dans le makefile racine (en se basant sur le MAKECMDGOALS)
et le passer en argument des sub-make, qui deviennent alors tous les memes et
peuvent etres remplacés par un include ou un lien symbolique. Ainsi le
makefile racine devient:

$(DIR):
$(MAKE) -C $@ $(MAKECMDGOALS) SEC=$(subst man,,$@)

man1/Makefile et man5/Makefile deviennent par exemple:

include ../make.rules

et man/make.rules contient:

SRC = $(wildcard *.$(SEC))
PDF = $(patsubst %.$(SEC), %.pdf, $(SRC))
HTML = $(patsubst %.$(SEC), %.html, $(SRC))

all: html pdf
pdf: $(PDF)
html: $(HTML)

clean:
-rm -f -- $(PDF) $(HTML)

%.pdf: %.$(SEC)
groff -man $< | ps2pdf - $@

%.html: %.$(SEC)
groff -man -Thtml $< > $@

Ou mieux en definissant SEC dans le sub-make et en faisant l'include ensuite.
Bref il est simplement necessaire que SEC soit defini avant la lecture des
regles ou transmis au sub-make, la doc fournis une section specifique
pour l'utilisation recursive de make.

Ceci dit pour gerer une arbo de dossiers bien etablie, un unique makefile
definissant les regles pour chaque dossier me semble dans ce cas particulier
plus adapté, quitte a generer automatiquement les dependances, qqchose du
genre (GNU) :

----

SECTIONS=1 5 8

PDF_COMMAND=groff -man $< | ps2pdf - $@
HTML_COMMAND=groff -man -Thtml $< > $@

#
# l'equivalent de ta variables SRC appliquée a toutes les sections.
#
SRC=$(wildcard $(foreach s,$(SECTIONS),man$(s)/*.$(s)))

#
# les cibles correspondantes.
#
PDF=$(foreach s,$(SECTIONS),$(patsubst %.$(s),%.pdf,$(filter %.$(s), $(SRC))))
HTML=$(foreach s,$(SECTIONS),$(patsubst %.$(s),%.html,$(filter %.$(s),$(SRC))))

#
# les regles "generales".
#
all: pdf html
clean: ; rm -f -- $(PDF) $(HTML)
distclean: clean ; rm -f make.rules

pdf: $(PDF)
html: $(HTML)

#
# il ne manque que les regles par formats de fichiers et sections, qui dans
# un cas simple comme proposé peuvents etres definie a la main:
#
# man1/%.pdf: man1/%.1 ; $(PDF_COMMAND)
# man5/%.pdf: man5/%.5 ; $(PDF_COMMAND)
# man1/%.html: man1/%.1 ; $(HTML_COMMAND)
# man5/%.html: man5/%.5 ; $(HTML_COMMAND)
#
# ou les generer totomatiquement:
#
# en l'occurence je rajoute des regles pour generer par type
# et par section: pdfX pour les fichiers pdf de la section X
# et htmlY pour les fichiers html de la section Y. Tu pourrais
# egalement fournir des regles de nettoyage par type et par
# section, etc... voir le fichier make.rules generés par
# la regle suivante et les section de la doc concernant
# les includes (et l'utilisation de regles pour les generer).
#

ifneq ($(MAKECMDGOALS),distclean)
-include make.rules
endif

pdf_rule=man$$i/%.pdf: man$$i/%.$$i ; $$(PDF_COMMAND)
html_rule=man$$i/%.html: man$$i/%.$$i ; $$(HTML_COMMAND)

make.rules: $(SRC)
TMP=$$(mktemp) &&
for i in $(SECTIONS); do {
echo "pdf$$i: $$(filter man$$i%,$$(PDF))" &&
echo "html$$i: $$(filter man$$i%,$$(HTML))" &&
echo "$(pdf_rule)" &&
echo "$(html_rule)" &&
: ; } >> $$TMP ;
done &&
mv -f $$TMP $@ ;

----

hope this help.