5. /Makefile
MDLS=atbe
OUE n e
al
l:
frdri $MDLS;d
o i n (OUE) o
(d$dr $MK}al;
c $i; {AE l)
dn
oe
/ant/Makefile
al mi.
l: ano
mi.:mi. ./e/as.
ano anc .bepreh
$C)-./e - mi.
(C I.be c anc
6. /bee/Makefile
OJ=./n/anopreo
B .atmi. as.
al po
l: rg
po:$OJ
rg (B)
$C)- $ $OJ
(C o @ (B)
preo precpreh
as.: as. as.
$C)- prec
(C c as.
7. ...e se generassimo parse.{c,h} da una grammatica
yacc?
precpreh prey
as. as.: as.
$YC)- prey
(AC d as.
m ytbcprec
v .a. as.
m ytbhpreh
v .a. as.
9. SOLUZIONE 2
Ripetere
MDLS=atbe
OUE n e
al
l:
frdri $MDLS;d
o i n (OUE) o
(d$dr $MK}al;
c $i; {AE l)
dn
oe
frdri $MDLS;d
o i n (OUE) o
(d$dr $MK}al;
c $i; {AE l)
dn
oe
tempo di build raddoppiato!
...e non è detto che basti! (sono necessarie tante
ripetizioni quanti gli archi che attraversano i moduli
del progetto)
10. SOLUZIONE 3
Ribuildare sempre e comunque
.HN:./e/as.
POY .bepreh
./e/as.:
.bepreh
c ./e;
d .be
mk cen
ae la;
mk al
ae l
...ma non siamo ancora compatibili con make -j
11. SOLUZIONE 4
Prevenzione
ma...
Miller, P.A. (1998), Recursive Make Considered
Harmful, AUUGN Journal of AUUG Inc., 19(1)
14. TUP
Un sistema di build che non è a conoscenza del
completo grafo sarà quindi più lento
19. SCALABILITÀ
I progetti crescono gradualmente, e le operazioni più
comuni coinvolgono il rebuil dopo poche modifiche
contenute su pochi file
20. CORRETTEZZA
Evita di costringere lo sviluppatore ad eseguire un
mk cen
ae la
nel caso in cui rimangano vecchi target nel tree,
moduli esterni potrebbero iniziare a dipendervi,
nascondendo il problema fino a quando il file non
verrà cancellato manualmente
21. ±«³§´¡µþ±õ³¢±õ°ÕÀ
Evitare l'impatto sulle performance con un
c fo mk
d o; ae
rischia di avere effetti diversi sul risultato rispetto ad
un semplice
mk
ae
e costringe lo sviluppatore a memorizzare queste
differenze
22. IL BOUND O(N) DI MAKE E SIMILI
Questi sistemi di build, percorrono l'albero delle
dipendenze, verificando se sia necessario aggiornarli
uno per uno Ma per fare questa decisione, occorre
analizzare tutte le dipendenze a ritroso
23. IL BOUND O(LOG^2(N)) DI TUP
Sistemi di build come Tup, preferiscono invece
tenere memorizzato uno stato del grafo completo su
disco (un database SQLite).
Nel grafo, Tup memorizza anche i comandi usati per
generare i file, questo serve a:
Tenere traccia della generazione multipla di file
Rieseguire i comandi, quando un
argomento/opzione di questi viene cambiata
Cancellare i file generati, quando il comando non è
più richiesto
24. Da questo, Tup poi ricava la lista dei cambiamenti in
tempo O(log(n)) (essendo i nodi indicizzati nel db)
A questo punto, ricavando le dipendenze si può
ottenere il grafo parziale che rappresenta i passi che
verranno svolti nella build.
Nel caso di un progetto tipico, questo viene
strutturato come un albero sul filesystem,
permettendoci quindi di ottenere un tempo atteso
come O(log(n)), da qui O(log^2(n)) per l'intera build.
Build System Rules and Algorithms
25. REDO
Questo build sytem ha un approccio diverso:
anch'esso punta ad avere un completo grafo di tutte
le dipendenze, ma queste vengono specificate
all'interno di diversi file e verranno letti da processi di
redo chiamati ricorsivamente
Un primo prototipo di redo è stato implementato in
sole 250 righe Bash! (Mentre l'implementazione di
riferimento sono meno di 2000 righe Python)
26. Per ottenere un binario chiamato myprog, da due
sorgenti "a.c" e "b.c", sono necessari solo 2 file:
dfutod
eal..
rd-fhne$.
eoicag 2c
gc-D-F$. - - $ $.
c M M 2d c o 3 2c
ra DP <2d
ed ES $.
rd-fhne$DP#:
eoicag {ES*}
mpo.o
yrgd
DP=aobo
ES". ."
rd-fhne$ES
eoicag DP
gc- $ $ES
c o 3 DP
27. I file sono dei normali script shell (ma possono
essere sostituiti da qualunque altro linguaggio di
scripting) e le dipendenze sono specificate con le
chiamate al comando redo-ifchange
redo-ifchange indica di rieseguire lo script corrente,
solo nel caso in cui le dipendenze (fornite come
argomento) siano cambiate
28. Per verificare se queste dipendenze sono cambiate,
anche redo usa lo stesso approccio di tup: un
database sqlite
Se queste non sono cambiate, redo deve solo
esaminare il db, senza dover rileggere ed eseguire i
relativi file .do
Le dipendenze, come in default.o.do possono essere
calcolate facilmente usando un altro programma
esterno, come lo stesso gcc usato per compilare,
senza bisogno di alcuna sintassi particolare
29. Redo abbraccia la filosofia Unix di piccoli programmi
componibili grazie a pipeline e ridirezioni dell'output,
e di default aggiunge tutto l'output nel file generato,
questo permette, con queste 2 semplici righe:
rd-fhneflls
eoicag ieit
ge ^r/flls
rp sc ieit
di rigenererare una lista intermedia di dipendenze
che potrà essere quindi riusata dal resto della build.
30. Redo disincentiva l'uso di variabili globali, e
spingendo l'unica vera informazione che dev'essere
accessibile a tutte le parti della build (ovvero il grafo
delle dipendenze) in un unico db, è possibile ripetere
una parte della build che aveva dato errore senza
problemi, essendo ogni passaggio modulare.
31. Questo viene anche invogliato dal formato stesso
dell'output, ecco un ipotetico esempio:
$rd tc
eo /
rd tc
eo /
rd
eo tcc
/.
rd
eo tccc
/..
rd
eo tcccb
/...
rd
eo tcccbb
/....
32. L'indentazione caratterizza il livello della ricorsione a
cui è arrivato redo, ma copiando e incollando l'ultima
riga per rieseguirla verbosamente, ci possiamo
rendere conto che ognuno di questi è un comando
valido:
$rd tcccbb-
eo /.... x
rd tcccbb
eo /....
*s -xdfutbd cccb. cccbbrd2tp
h e eal..o ... b .....eo.m
+rd-fhnecccbba
eoicag .....
+eh at-
co -ob
+ctcccbba
a .....
+.sep11
/le .
rd tcccbb(oe
eo /.... dn)
33. Un altro vantaggio è quindi l'evidente assenza di flag
ed opzioni ripetute centinaia di volte nell'output delle
tipiche compilazioni con make, output reso ancor
meno leggibile nel caso in cui la compilazione sia
avvenuta in parallelo, nascondendo quindi l'ordine
logico che sottende alla build
Redo on Github
34. Altri sistemi di build o risorse interessanti:
Ninja: un build system veloce e di "basso
livello"
Fabricate: trova le dipendenze
automaticamente
Shake: un altro strumento che si concentra
sulla gestione accurata delle dipendenze e
rebuild minimi
Boilermake: un boilerplate makefile che segue
un approccio non ricorsivo
35. Altri sistemi di build o risorse interessanti:
Il punto di vista di Bruce Eckel nel 2004 su Ant,
le alternative disponibili all'epoca e le difficoltÃ
nel loro sviluppo
Un linguaggio puramente dichiarativo come
XML non è una buona scelta per un sistema di
build: come James Duncan Davidson arrivò a
sceglierlo nella creazione di Ant