Sistemi di Build Alternativi
-
Upload
dario-bertini -
Category
Documents
-
view
115 -
download
0
Transcript of Sistemi di Build Alternativi
SISTEMI DIBUILD
ALTERNATIVI
SISTEMI DI BUILD?
MA PRIMA...Vediamo come funziona il classico ambiente
./configuremakemake install
.├── ant│ ├── main.c│ └── Makefile├── bee│ ├── Makefile│ ├── parse.c│ └── parse.h└── Makefile
/Makefile
/ant/Makefile
MODULES = ant beeall: for dir in $(MODULES); do \ (cd $$dir; ${MAKE} all); \ done
all: main.omain.o: main.c ../bee/parse.h $(CC) -I../bee -c main.c
/bee/Makefile
OBJ = ../ant/main.o parse.oall: progprog: $(OBJ) $(CC) -o $@ $(OBJ)parse.o: parse.c parse.h $(CC) -c parse.c
...e se generassimo parse.{c,h} da una grammaticayacc?
parse.c parse.h: parse.y $(YACC) -d parse.y mv y.tab.c parse.c mv y.tab.h parse.h
SOLUZIONE 1Riordinare (buildare bee prima di ant)
ma l'ordine viene ignorato da make -j
SOLUZIONE 2Ripetere
tempo di build raddoppiato!
...e non è detto che basti! (sono necessarie tanteripetizioni quanti gli archi che attraversano i moduli
del progetto)
MODULES = ant beeall: for dir in $(MODULES); do \ (cd $$dir; ${MAKE} all); \ done for dir in $(MODULES); do \ (cd $$dir; ${MAKE} all); \ done
SOLUZIONE 3Ribuildare sempre e comunque
...ma non siamo ancora compatibili con make -j
.PHONY: ../bee/parse.h../bee/parse.h: cd ../bee; \ make clean; \ make all
SOLUZIONE 4Prevenzione
ma...
Miller, P.A. (1998), Recursive Make ConsideredHarmful, AUUGN Journal of AUUG Inc., 19(1)
TUPUn sistema di build che non è a conoscenza del
completo grafo sarà quindi più lento
Questa era la situazione con make
Tup invece, partendo da un nodo, riesce a ricavare ilsottografo parziale minimo
Dovendo esaminare tutte le dipendenze: O(n)O(log^2(n))
ScalabilitàCorrettezzaUsabilità
SCALABILITÀI progetti crescono gradualmente, e le operazioni piùcomuni coinvolgono il rebuil dopo poche modifiche
contenute su pochi file
CORRETTEZZAEvita di costringere lo sviluppatore ad eseguire un
nel caso in cui rimangano vecchi target nel tree,moduli esterni potrebbero iniziare a dipendervi,
nascondendo il problema fino a quando il file nonverrà cancellato manualmente
make clean
USABILITÀEvitare l'impatto sulle performance con un
rischia di avere effetti diversi sul risultato rispetto adun semplice
e costringe lo sviluppatore a memorizzare questedifferenze
cd foo; make
make
IL BOUND O(N) DI MAKE E SIMILIQuesti sistemi di build, percorrono l'albero delle
dipendenze, verificando se sia necessario aggiornarliuno per uno Ma per fare questa decisione, occorre
analizzare tutte le dipendenze a ritroso
IL BOUND O(LOG^2(N)) DI TUPSistemi di build come Tup, preferiscono invece
tenere memorizzato uno stato del grafo completo sudisco (un database SQLite).
Nel grafo, Tup memorizza anche i comandi usati pergenerare i file, questo serve a:
Tenere traccia della generazione multipla di fileRieseguire i comandi, quando unargomento/opzione di questi viene cambiataCancellare i file generati, quando il comando non èpiù richiesto
Da questo, Tup poi ricava la lista dei cambiamenti intempo 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 vienestrutturato come un albero sul filesystem,
permettendoci quindi di ottenere un tempo attesocome O(log(n)), da qui O(log^2(n)) per l'intera build.
Build System Rules and Algorithms
REDOQuesto build sytem ha un approccio diverso:
anch'esso punta ad avere un completo grafo di tuttele dipendenze, ma queste vengono specificate
all'interno di diversi file e verranno letti da processi diredo chiamati ricorsivamente
Un primo prototipo di redo è stato implementato insole 250 righe Bash! (Mentre l'implementazione di
riferimento sono meno di 2000 righe Python)
Per ottenere un binario chiamato myprog, da duesorgenti "a.c" e "b.c", sono necessari solo 2 file:
default.o.d
redo-ifchange $2.cgcc -MD -MF $2.d -c -o $3 $2.cread DEPS <$2.dredo-ifchange ${DEPS#*:}
myprog.do
DEPS="a.o b.o"redo-ifchange $DEPSgcc -o $3 $DEPS
I file sono dei normali script shell (ma possonoessere sostituiti da qualunque altro linguaggio discripting) 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 comeargomento) siano cambiate
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 irelativi file .do
Le dipendenze, come in default.o.do possono esserecalcolate facilmente usando un altro programmaesterno, come lo stesso gcc usato per compilare,
senza bisogno di alcuna sintassi particolare
Redo abbraccia la filosofia Unix di piccoli programmicomponibili grazie a pipeline e ridirezioni dell'output,e di default aggiunge tutto l'output nel file generato,
questo permette, con queste 2 semplici righe:
di rigenererare una lista intermedia di dipendenzeche potrà essere quindi riusata dal resto della build.
redo-ifchange filelistgrep ̂src/ filelist
Redo disincentiva l'uso di variabili globali, espingendo l'unica vera informazione che dev'essereaccessibile a tutte le parti della build (ovvero il grafodelle dipendenze) in un unico db, è possibile ripetere
una parte della build che aveva dato errore senzaproblemi, essendo ogni passaggio modulare.
Questo viene anche invogliato dal formato stessodell'output, ecco un ipotetico esempio:
$ redo t/credo t/credo t/c.credo t/c.c.credo t/c.c.c.bredo t/c.c.c.b.b
L'indentazione caratterizza il livello della ricorsione acui è arrivato redo, ma copiando e incollando l'ultima
riga per rieseguirla verbosamente, ci possiamorendere conto che ognuno di questi è un comando
valido: $ redo t/c.c.c.b.b -xredo t/c.c.c.b.b* sh -ex default.b.do c.c.c.b .b c.c.c.b.b.redo2.tmp+ redo-ifchange c.c.c.b.b.a+ echo a-to-b+ cat c.c.c.b.b.a+ ./sleep 1.1redo t/c.c.c.b.b (done)
Un altro vantaggio è quindi l'evidente assenza di flaged opzioni ripetute centinaia di volte nell'output delle
tipiche compilazioni con make, output reso ancormeno leggibile nel caso in cui la compilazione sia
avvenuta in parallelo, nascondendo quindi l'ordinelogico che sottende alla build
Redo on Github
Altri sistemi di build o risorse interessanti:
Ninja: un build system veloce e di "bassolivello"Fabricate: trova le dipendenzeautomaticamenteShake: un altro strumento che si concentrasulla gestione accurata delle dipendenze erebuild minimiBoilermake: un boilerplate makefile che segueun approccio non ricorsivo
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 sviluppoUn linguaggio puramente dichiarativo comeXML non è una buona scelta per un sistema dibuild: come James Duncan Davidson arrivò asceglierlo nella creazione di Ant