Ho cercato per molto tempo una buon preprocessore HTML open source. Ho avuto
modo di provare diverse soluzioni, ma nessuna di queste si adattava alle mie
esigenze. Volevo qualcosa di semplice, facile da imparare ma al contempo potente
e flessibile, uno strumento su cui potessi avere il pieno controllo. Per
essere concisi - qualche cosa in stile con lo spirito di Unix.
Trovai in WPP la risposta alle mie esigenze.
È ben progettato ed è possibile estenderlo. Ha alcune funzionalità integrate
che sono estremamente importanti per lo sviluppo in abito web, tutto il resto
può essere facilmente ottenuto tramite l'inclusione di codice Perl nelle
pagine da preprocessare.
Il manuale di WPP è disponibile sul sito del progetto
(
http://wpp.sf.net).
Questo articolo non è un tutorial su WPP. Se volete imparare le basi di WPP
andate a leggere il manuale sul suo sito
[2].
Questo documento è una raccolta
di note su come integrare
make
e WPP per semplificarvi la vita.
Descriverò il processo di creazione di un Makefile da zero, anche se la
sintassi di
make
vi è già familiare, potreste trovare
alcuni spunti e trucchi interessanti procedendo nella lettura.
Introduzione
Generare un sito web con WPP è molto simile alla compilazione di un programma.
Ci sono dei files "raw" (sorgenti) e dei documenti html (analoghi al codice
oggetto) generati dalla trasformazione dei "raw" files tramite
wpp
.
In questa metafora è praticamente naturale l'adozione del tool
make
della GNU per lavorare con WPP e semplificare la
"compilazione" dei propri siti. Ho intenzione di mettere in luce i seguenti
vantaggi che derivano dall'uso di make:
-
Risoluzione delle dipendenze: solo i files modificati o la modifica di uno
o più files da cui dipendono, sono rigenerati, questo è estremamente
comodo specie quando il sito è composto da numerose pagine.
-
La sintassi dei Makefiles è estremamente potente e flessibile. È
necessario spendere un po' di tempo per crearli, ma una volta fatti le cose
diventano molto più veloci, basta lanciare
make
ed il resto
va da sé.
-
Make è un tool standard e molto diffuso. Perché reinventare la ruota?
Tutto quello che imparate ora potrebbe tornare utile in futuro. I Makefiles
possono essere molto complicati, in questo articolo presenterò solo alcune
funzionalità di base, se volete saperne di più vi suggerisco di leggere
le pagine in formato "info" del manual di make. Sono disponibili anche
on-line sul sito GNU: http://www.gnu.org/manual/make-3.80/
Regole di base
WPP è uno strumento comodo ma quando il sito su cui state lavorando diventa
progressivamente più grande diviene anche più difficile operare delle
modifiche. È necessario ricordarsi di rigenerare ogni file a mano con wpp dopo
ogni modifica, è sufficiente dimenticarsi ciò per avere un sito non
aggiornato se non addirittura con degli errori. Questo può non essere un
problema per un sito personale (home page), ma è sicuramente una cosa più
grave in siti dove non ci si può permettere questo genere di sviste (ad
esempio quelli di una societa`).
Inoltre la mia pigrizia mi porta a cercare di ridurre le operazioni di
manutenzione al minimo, il più semplici possibili.
Per fortuna, come vedremo più avanti in questo articolo, con l'aiuto di
make
questo compito può essere facilmente automatizzato.
Prima di tutto è necessario creare un file che si chiami
Makefile
(o
makefile
) nella directory principale del vostro progetto.
Quando viene eseguito il comando
make
le informazioni contenute in
questo file verranno usate per rigenerare tutti i files destinazione (html) a
partire dai sorgenti (raw) quando questi o le loro dipendenze risultino
modificati (in realtà viene usata la data di modifica del file).
Ogni makefile contiene in una serie di regole. Ogni regola è definita da
elementi base così:
target : dipendenze ...
commandi
...
Ricordate che ogni linea dei "comandi" è preceduta da un carattere di
tabulazione (tab), NON sono spazi! Inserire degli spazi, un errore comune da
chi è alle prime armi con make, è causa dell'errore di "missing separator".
Target
è il file di destinazione o un alias (una sequenza a
piacere di caratteri, come "all", "full"). Le dipendenze sono i sorgenti da cui
generare il target. Quando uno di questi cambia è possibile eseguire l'intero
target e lanciare i "comandi" per rigenerarlo.
Se una delle dipendenze ha un suo target nel Makefile questo verrà eseguito
prima di quello chiamato. Ricordate che che quando si esegue
make bogus
il target "bogus" viene invocato,
make
senza
argomenti richiama il primo target (default).
Nei Makefiles si possono definire delle variabili usando la sintassi
VARIABILE="valore". Da quella linea in poi ogni occorrenza di $(VARIABILE)
verrà sostituita con "valore".
Un semplice makefile per WPP (nella sua configurazione standard) localizzato
nella directory dove sono i "raw" files potrebbe esser fatto così:
# definizione di una variabile
WPP=/usr/bin/wpp
# prima regola (default), senza comandi
all : ../about.html ../index.html
# regola: come creare about.html
../about.html : about.raw config
$(WPP) about.raw
# regola: come creare index.html
../index.html : index.raw config templates/logo.tmpl
$(WPP) index.raw
Scommetto che avete già indovinato che tutto quello che segue il carattere '#'
è un commento, ignorato da
make
. Cercherò di spiegare come opera
questo primo makefile:
-
Comincia con il target 'all', il primo target, ne guarda le dipendenze.
-
Esiste il target '../about.html', quindi lo analizza:
-
Se almeno uno dei files 'about.raw' o 'config' è stato modificato
esegue il comando '/usr/bin/wpp about.raw' per rigenerare
'../about.html'.
-
Esiste il target '../index.html', quindi lo analizza:
-
Se almeno uno dei files 'index.raw' o 'config' è stato modificato
esegue il comando '/usr/bin/wpp index.raw' per rigenerare
'../index.html'.
-
Torna al target 'all' e termina perché non ci sono comandi e altre
dipendenze da vagliare.
Regole di pattern
Per fare in modo di aggiornare il sito dopo aver modificato uno o più raw
files serve solo eseguire
make
. Ma ci sono alcuni svantaggi, il
nostro makefile richiede la modifica manuale ogni volta che aggiungiamo un
nuovo file serve inserire la rispettiva regola. Questo diviene progressivamente
più scomodo al crescere del sito da mantenere. Per fortuna si può ovviare a
questo problema usando le regole di pattern matching di
make
:
all: ../index.html ../about.html
# regola per creare TUTTI gli html dai raw
../%.html : %.raw
@wpp -x $<
Il target di default "all" semplicemente afferma che il nostro sito consiste in
due files. La seconda regola è usata per rigenerare ogni file il cui nome
cominci per '../' e termini con '.html' (nell'esempio sono sia ../index.html
che ../about.html).
Afferma anche che "../file.html" dipende dal sorgente "file.raw", quando questo
risulti modificato il file di destinazione verrà ricostruito con il comando
"wpp -x file.raw" ("$<" è una variabile predefinita che contiene il nome
della prima dipendenza). Il carattere "@" davanti al comando serve a far si che
make
non stampi il comando a video prima dell'esecuzione dello
stesso.
Funzioni
A questo punto, dopo aver aggiunto un nuovo file bisogna aggiornare tutte le
dipendenze della regola "all", non serve creare nuove regole. Ma noi siamo
pigri e vogliamo qualche cosa di più, vogliamo evitare di ricordare di dover
aggiornare qualsiasi cosa. Ovviamente è possibile, ma richiede alcune
modifiche al nostro makefile:
DSTDIR = ../html
WPP = wpp -D DEFAULT_OUTPUTDIR=$(DSTDIR)
# lista di tutti i .raw nella directory corrente
SRC = $(subst ./,, $(shell find -name "*.raw"))
# lista di tutti gli html che vogliamo creare in DSTDIR
DST = $(addprefix $(DSTDIR)/, $(SRC:.raw=.html))
all : $(DST)
$(DSTDIR)/%.html : %.raw
$(WPP) $<
Come potete notare per rendere il makefile più flessibile è stata definita
una variabile addizionale chiamata DSTDIR che contiene il nome della directory
di destinazione.
WPP ha bisogno di conoscerne il valore tramite DEFAULT_OUTPUTDIR
(
cfr. la sezione 4 del manuale di WPP).
Inoltre sono state usate alcune caratteristiche di
make
che non
sono state menzionate precedentemente: le funzioni.
Ogni chiamata funzione si presenta in questo modo:
All'inizio è stata usata la funzione "shell" per passare il comando
"find -name '*.raw'" alla shell.
Come probabilmente saprete il comando stampa una lista dei files che terminano
con .raw nell'intera gerarchia di directories, partendo da quella corrente.
L'output dovrebbe somigliare a questo:
./index.raw
./about.raw
./contact/email.raw
Make si occupa di convertire i terminatori di linea in spazi ma è necessario
rimuovere il "./" dall'inizio di ogni valore. Questo può essere ottenuto
tramite la funzione "subst":
Questa funzione sostituisce ogni occorrenza di "from" all'interno della stringa
"text" con la stringa "to".
In questo modo abbiamo assegnato nella variabile SRC la lista di tutti files
.raw presenti nella directory corrente. Non possiamo usarla nel target di
default perché dovremmo mettere i files .html (non i .raw). Da notare che non
possiamo usare "find" per cercare i .html perché potrebbero non esistere
ancora.
Usando
$(SRC:.raw=.html)
possiamo sostituire il suffisso '.raw'
con '.html' in ogni parola contenuta nella variabile SRC, i valori modificati
vengono ritornati e possono essere assegnati ad un'altra variabile.
Tuttavia i files di destinazione sono in DSTDIR, usiamo "addprefix" per
aggiungere il prefisso "$(DSTDIR)/" prima di ogni parola nella lista ritornata.
Ecco come viene ottenuta DST.
Ora possiamo usare $DST per le dipendenze del target di default.
# default rule
all : $(DST)
Dipendenze automatiche
Potremmo finire qui. Ma cosa succede se viene modificato qualche template in
uso in qualche file? E se viene riscalata un'immagine che è usata da WPP
tramite la macro @HTML_IMAGE@ per determinarne automaticamente le dimensioni?
In questo caso il comando
make
mostrerà questo messaggio:
make: `all' is up to date.
Questo perché
make
conosce solo le dipendenze dirette dei
files
html nella regola 'all': i raw files. Non sa nulla dei templates, delle
immagini, dei file di configurazione di WPP o qualsiasi altro documento che
può influenzare l'output di WPP. Dobbiamo dire a make ogni dipendenza, non
volendolo fare a mano è possibile ricorrere allo switch "-d" di WPP:
-d, --depend Generate dependencies for make.
Sembra che l'autore abbia previsto quello che stiamo cercando di ottenere!
Questa opzione forza WPP a guardare in ogni file e mostrare ogni immagine usata
o (opzionalmente) ogni link locale via RURL. Genera anche le dipendenze verso i
files di configurazione ed i templates. L'output generato è nel formato di
make
:
../html/l5k/index.html: \
Config \
TEMPLATES/head.tmpl \
../html/portal.gif \
../html/index.raw
Il carattere "\" alla fine di una riga serve per indicare che questa continua
sotto. A questo punto potremmo copiare direttamente le dipendenze nel nostro
makefile ma sarebbe una perdita di tempo qualora si dovesse rigenerarle,
meglio tenere il tutto in un file separato per poterlo aggiornare solo quando
serve:
# rule to build 'Makefile.dep', alias 'dep'
Makefile.dep dep :
@$(WPP) -d $(SRC) > Makefile.dep
Oltre a questo serve aggiungere un'istruzione
include Makefile.dep
alla fine del makefile in modo da utilizzare le dipendenze generate. Il target
si chiama "Makefile.dep" così da essere invocato automaticamente qualora make
non trovasse il file delle dipendenze. L'alias "dep" serve per abbreviare
qualora voleste forzare la rigenerazione delle dipendenze con il comando
make dep
.
Cleaning up
Adesso avete un sistema perfettamente funzionante basato su
make
.
Alla fine possiamo aggiungere un'ultima regola la quale verrà usata per
rimuovere ogni file generato nella directory di destinazione (
attenzione:
controllate la correttezza del comando altrimenti rischiereste di perdere files
importanti!):
clean :
find $(DSTDIR) -name "*.html" -exec rm -f {} \;
Ora potrete digitare
make clean
per rimuovere ogni file non
necessario e liberare un po' di spazio o rigenerare l'intero sito "ex novo".
Questo è tutto, spero che la maggior parte dei semplici "trucchi" inclusi in
questo documento vi siano d'aiuto e possano semplificare di molto la gestione
del vostro sito con WPP.
"May the Source be with You!"