Elaborato Di Girolamo Rocco N46001341

Transcript

Elaborato Di Girolamo Rocco N46001341
Scuola Politecnica e delle Scienze di Base
Corso di Laurea in Ingegneria Informatica
Elaborato finale in Ingegneria del Software
Confronto tra gli strumenti per la build
automation
Anno Accademico 2014/2015
Candidato:
Di Girolamo Rocco
matr. N46001341
Dedico l’intero percorso universitario e questo traguardo
a coloro che mi hanno sempre sostenuto
e che non hanno mai smesso di credere in me,
mia mamma, mio papà e mio fratello Luca
“La felicità è un percorso, non una destinazione.
Lavora come se non avessi bisogno di denaro,
ama come se non ti avessero mai ferito e balla, come se non ti vedesse nessuno.
Ricordati che la pelle avvizzisce, i capelli diventano bianchi e i giorni diventano anni.
Ma l’importante non cambia: la tua forza e la tua convinzione non hanno età.
Dietro ogni traguardo c’è una nuova partenza.
Dietro ogni risultato c’è un’altra sfida.
Finché sei vivo, sentiti vivo.
Vai avanti, anche quando tutti si aspettano che lasci perdere. ”1
1
Madre Teresa di Calcutta.
Indice
Introduzione
vi
1 Evoluzione storica degli strumenti
1
2 Caratteristiche dei tools
4
2.1
Requisiti base e opzionali degli strumenti di compilazione . . . . . . . . . . . . .
4
2.2
Classificazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
2.3
Il file di configurazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
2.4
Altri aspetti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
3 Shell
7
3.1
Le funzionalità . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
3.2
Il linguaggio interpretato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
4 Make e confronto con Shell
9
4.1
Gestione delle dipendenze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
4.2
Il Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
4.3
Problematiche del Make . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
4.4
GNU make e la sua portabilità . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
5 Apache Ant e confronto con Make
12
5.1
Vantaggi dell’implementazione in Java . . . . . . . . . . . . . . . . . . . . . . . .
12
5.2
Build.xml - Il file di Configurazione . . . . . . . . . . . . . . . . . . . . . . . . . .
13
5.3
Limiti degli script Ant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
5.4
Facilità d’uso, Leggibilità e Testing . . . . . . . . . . . . . . . . . . . . . . . . . .
14
iii
Indice
6 Apache Maven e confronto con Apache Ant
15
6.1
Obiettivi di Maven . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
6.2
POM - Il file di Configurazione . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
6.3
Gestione delle dipendenze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
6.4
Apache Maven e confronto con Apache Ivy . . . . . . . . . . . . . . . . . . . . .
19
6.4.1
19
Gestione delle dipendenze e dei conflitti . . . . . . . . . . . . . . . . . . .
7 Gradle e confronto con Apache Ant e Maven
20
7.1
Integrazione con altri tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
7.2
Struttura Gradle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
7.3
Gestione delle dipendenze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
8 Microsoft MSBuild
24
9 Conclusioni e Sviluppi Futuri
26
Ringraziamenti
28
Bibliografia
30
iv
Elenco delle figure
1.1
Posizione di Gradle rispetto agli altri strumenti per la Build Automation . . . . .
3
5.1
Apache Ant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
6.1
Apache Maven . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
7.1
Gradle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
7.2
Integrazione di Gradle con altri tools . . . . . . . . . . . . . . . . . . . . . . . . .
21
v
Introduzione
Un approccio professionale per sviluppare del software che soddisfi gli standard di qualità
richiede, oltre che la competenza e l’esperienza dello sviluppatore, altri requisiti come: un ambiente di sviluppo adeguato, un buon debugger e, non ultimo, un eventuale tool per la build
automation. In particolare, i tools per la build automation ci permettono di automatizzare
alcune attività del ciclo di vita di un software, tra cui:
• Compilazione: si tratta del procedimento di trasformazione dei codici sorgenti, scritti
dall’utente, in codice binario, leggibile dalla macchina;
• Linking: consiste nel procedimento di integrazione dei vari moduli a cui un programma fa
riferimento con lo scopo di creare una singola unità eseguibile;
• Packaging dei binari: il risultato della compilazione deve assumere una forma compatta e
una chiara connotazione in base al suo scopo: eseguibile, libreria da esportare, etc.;
• Esecuzione di test automatizzati: con lo scopo di garantire l’affidabilità del prodotto software, esso deve essere testato in ogni sua funzionalità e sotto ogni tipo di condizione. Data
la complessità di un software sviluppato oggigiorno, non è sufficiente un essere umano per
effettuare tale strategia di test, ma è necessario automatizzare l’operazione attraverso
software appositamente programmati;
• Distribuzione della soluzione software: una volta che il software è pronto e testato, deve
essere installato e configurato sui sistemi per i quali è stato implementato; da notare che
questo tipo di automazione non ha niente in comune con la deployment automation, che
invece riguarda l’automazione nella fase di distribuzione. Mentre un sistema di build auto-
vi
Introduzione
mation produce codice eseguibile da codice sorgente, un sistema di deployment automation
studia la distribuzione che il codice eseguibile ha rispetto a un ambiente;
• Documentazione del progetto e/o rilascio di note: data la complessità odierna di un software e l’evoluzione che subisce attraverso le varie versioni pubblicate, la redazione di una
buona documentazione è estremamente importante. Ovviamente la documentazione prenderà la forma più consona al tipo di progetto, rispettando gli standard imposti, e al target
di utilizzatore.
Per poter automatizzare queste attività è spesso necessario scrivere del codice in un linguaggio
di scripting (oppure utilizzare programmi visuali). Tale codice è da considerare a pieno titolo
nell’insieme del codice del programma.
Automatizzando le attività sopra elencate attraverso i tools di build automation, i vantaggi
che lo sviluppatore otterrà saranno molteplici, quali:
• Miglioramento della qualità del prodotto;
• Accelerazione dei tempi di compilazione e della fase di collegamento;
• Eliminazione delle attività ridondanti;
• Minimizzazione del “bad builds”, ovvero errori nella fase di costruzione del software;
• Cronologia degli sviluppi e delle release in modo da analizzare i problemi;
• Risparmio di tempo e denaro.
In questo elaborato, cercherò di evidenziare tutte le differenze e le somiglianze tra i principali
tools di build automation, strutturando il lavoro in tre fasi principali: nella prima fase introdurrò
una descrizione storica di come si sono susseguiti i tools e quindi di come è cambiato il modo di
interpretare il concetto di build automation; nella seconda fase evidenzierò quali caratteristiche
uno strumento di compilazione deve e può avere, definendo quindi i requisiti necessari e quelli
opzionali; inoltre metterò in risalto alcuni aspetti che mi permetteranno di effettuare un confronto più dettagliato; infine, nella terza fase effettuerò il confronto tra gli strumenti seguendo
l’ordine cronologico di come gli stessi si sono susseguiti nel tempo.
vii
Capitolo 1
Evoluzione storica degli strumenti
Inizialmente gli sviluppatori effettuavano la chiamata al compilatore tramite riga di comando;
questo metodo funzionava in maniera efficace solo quando veniva richiesta la compilazione di un
solo file sorgente con lo scopo di generare l’oggetto finale distribuibile; quando invece, i moduli
di codice sorgente diventarono molti, e dovendo rispettare uno specifico ordine su come venivano
passati al compilatore, la chiamata al compilatore attraverso riga di comando non era più una
soluzione ragionevole.
Make è stata la soluzione a questo problema: nato nel 1977 per sistemi Unix, si basa su un
file di scripting chiamato Makefile per determinare il grafo delle dipendenze e gli script necessari
per la compilazione da passare alla Shell. Con l’avvento dei processori multi-core, Make si è
evoluto accettando anche un’esecuzione parallelizzabile, che in una nuova versione di Make detta
BSD Make diventa la caratteristica predominante dello strumento.
Make include tutt’oggi altre versioni, tra le quali GNU Make il quale è una sua implementazione per Linux e OS X; e Nmake che normalmente fa parte di Visual Studio ed è quindi una
versione per Microsoft. Quest’ultima supporta le direttive del preprocessore quali l’include e
le espressioni condizionali. Successivamente tale utility è stata sostituita da uno strumento più
funzionale detto MSBuild o Microsoft Build Engine.
Nel tempo il processo di sviluppo è diventato sempre più complesso e l’esigenza di aumentare
l’automazione nella costruzione del software ha portato gli sviluppatori ad aggiungere azioni
preliminari e/o a posteriori alla fase di compilazione, come ad esempio il check-out per il controllo
versione.
1
Capitolo 1. Evoluzione storica degli strumenti
Make comunque non era l’unico strumento disponibile e neanche il più efficiente. All’inizio
del 2000 viene presentato Apache Ant, originario del progetto Tomcat; esso è stato scritto per
superare alcune problematiche che presentava Unix make. Intorno al 2002 era molto utilizzato
dagli sviluppatori java tanto da fornire nelle distribuzioni dei programmi anche il file di configurazione di Ant. Anche se Ant risolve alcuni limiti del Make, porta nuove problematiche, come
ad esempio l’utilizzo dell’XML che, come vedremo in seguito, rende il progetto difficile da gestire
quando quest’ultimo cresce in dimensioni.
Successivamente nel 2004 l’avvento di Apache Maven porta con sé novità e soluzioni, come
l’utilizzo di convenzioni, la gestione delle dipendenze e il controllo di versione; ma non risolve
alcune problematiche della concorrenza, come l’utilizzo dell’XML.
A pochi mesi di differenza dalla pubblicazione di Apache Maven (luglio - settembre) è
stato pubblicato Apache Ivy che è invece un tool specificamente orientato alla gestione delle dipendenze, progettato per essere utilizzabile autonomamente o anche in sinergia con Ant.
Successivamente, nel 2009 è stato integrato come sotto progetto all’interno di Apache Ant.
Negli ultimi anni la build automation ha avuto sempre più rilievo, sia per i tool commerciali
sia open source, andando a supportare con il tempo uno sviluppo a integrazione continua 1 . Da
notare che gli strumenti d’integrazione continua (CruiseControl, Hudson, etc.) sono differenti
dagli strumenti di sviluppo automatizzato (Make, Ant, Maven, etc.). In particolare lo sviluppo
automatizzato è un prerequisito per un uso efficace dello sviluppo a integrazione continua e gli
strumenti d’integrazione continua sono una categoria appartenente agli strumenti per la build
automation.
Un traguardo successivo nell’evoluzione storica prende il nome di advanced build automation,
ovvero un’esecuzione remota per la creazione2 e/o l’elaborazione3 distribuita di un prodotto software. Il processo di sviluppo distribuito deve possedere l’intelligenza artificiale per comprendere
le dipendenze nel codice sorgente al fine di gestire bene le fasi di compilazione e collegamento;
alcuni strumenti comprendono tali relazioni dal codice sorgente (Rational ClearMake distributed, Electric Cloud ElectricAccelerator), altri si basano sulle dipendenze definite dall’utente
1
Integrazione continua: consiste in una strategia di sviluppo con continue chiamate alla fase di compilazione
incluso un test di integrazione per verificare la correttezza del prodotto.
2
Per creazione distribuita (“distribuited build”) significa che le chiamate reali al compilatore e al linker possono
essere servite in più posizione per migliorare la velocita della fase di sviluppo.
3
Per elaborazione distribuita (“distribuited processing”) significa che ogni passo di un processo o di un flusso
di lavoro può essere inviato a una macchina diversa per l’esecuzione.
2
Capitolo 1. Evoluzione storica degli strumenti
(Platform LSF lsmake). Tuttavia non tutti gli strumenti di build automation sono in grado
di eseguire uno sviluppo distribuito; la maggior parte fornisce solo il supporto all’elaborazione
distribuita.
Tutt’oggi un sacco di sviluppatori sono alla ricerca di alternative a strumenti di compilazione
stabili e più efficienti. In questo ambito si fa strada il passaggio dall’utilizzo di XML a un
linguaggio più espressivo e leggibile: uno strumento di compilazione che porta avanti questa
idea è Gant, tool di creazione attraverso il quale si possono combinare caratteristiche Groovy
con le conoscenze esistenti di Ant senza dover scrivere XML.
Tuttavia, uno degli strumenti più utilizzati e più in voga in questi ultimi tempi è Gradle: esso
si inserisce a destra degli strumenti visti fin ora e soddisfa molte esigenze dei moderni strumenti
di compilazione. Gradle fornisce un DSL espressivo, un approccio alla configurazione e gestione
delle dipendenze potente.
Figura 1.1: Posizione di Gradle rispetto agli altri strumenti per la Build Automation
Quindi attraverso questi strumenti abbiamo visto come si è evoluto il modo di interpretare
il concetto di build automation nel settore dello sviluppo software, nonché l’aumento d’interesse
da parte della comunità di sviluppatori nei confronti di tale argomento.
3
Capitolo 2
Caratteristiche dei tools
In questo capitolo verranno raggruppati tutti i possibili requisiti che potranno essere analizzati nei capitoli successivi, in modo da poter mettere in luce tutti i punti di forza e di debolezza
di ogni tool.
2.1
Requisiti base e opzionali degli strumenti di compilazione
In questa sezione sono elencati i requisiti che un sistema di compilazione deve e può possedere.
I requisiti base sono:
• Supporto a frequenti compilazioni in maniera tale da catturare subito eventuali problemi
evitando una compilazione unica con errori disseminati lungo tutto il codice;
• Supporto alla gestione delle dipendenze: a livello professionale lo sviluppo di un software
dipende da altri progetti, librerie e framework che costituiscono le fondamenta del progetto stesso. Gestendo questo aspetto si solleva il programmatore da un compito molto
faticoso che include il soddisfacimento dei vincoli di dipendenza in primo luogo, ma anche
la gestione di eventuali conflitti per l’assegnazione delle dipendenze tra i vari moduli e il
reperimento delle dipendenze in locale o su rete, mettendo a disposizione le versioni più
aggiornate o quelle meglio compatibili;
• Supporto ad uno sviluppo incrementale: 1 ;
1
Sviluppo incrementale: consiste in un modello di sviluppo di un progetto software basato sulla successione dei
seguenti passi principali: pianificazione, analisi dei requisiti, progettazione, implementazione, prove e valutazione.
4
Capitolo 2. Caratteristiche dei tools
• Capacità di collegare una segnalazione sul codice sorgente al relativo codice binario;
• Sviluppo accelerato;
• Estrazione di informazioni e reporting sulle fase di compilazione e di collegamento;
Invece i requsiti opzionali sono:
• Generare note di rilascio e altra documentazione, come le pagine di aiuto;
• Costruire report di stato;
• Esecuzione di test; in particolare nel caso in cui il test sia negativo, lo strumento deve
avere la capacità di produrre una segnalazione;
• Sintesi delle caratteristiche aggiunte / modificate / cancellate con ogni nuova compilazione;
2.2
Classificazione
In base alle operazioni che svolge e a come è stato implementato, ogni tool per la build
automation può appartenere ad una delle seguenti sei categorie: 2 :
• Make based tools - basati sull’utility Make ed ovviamente sono incluse tutte le derivazioni
stesse di Make;
• No Make based tools;
• Build Scripting generation tools - sono strumenti per automatizzare la generazione di script
di costruzione;
• Continuous integration tools - sono strumenti sviluppati principalmente per uno sviluppo
a integrazione continua;
• Configuration management tools - destinati alla configurazione e gestione di sistemi;
• Others tools.
2
Per una lista completa di tutti gli strumenti appartenenti ad ogni categoria riferirsi a [4]
5
Capitolo 2. Caratteristiche dei tools
2.3
Il file di configurazione
Un aspetto che verrà ampiamente discusso nel capitolo successivo sarà il build file o file di
configurazione che la maggior parte dei tools dispongono: le operazioni che devono essere svolte
per trasformare il progetto sorgente nella soluzione finale vengono raccolte in tale file, che a
volte fa riferimento o include altri file secondari; esso è scritto in un linguaggio che può variare
da un linguaggio XML a un linguaggio specifico del dominio (DSL)3 .
2.4
Altri aspetti
Saranno presi in considerazione anche aspetti come:
• Licenza del software;
• Tempo di creazione di uno script;
• Difficoltà di apprendimento;
• Integrazione con altri tool;
• Flessibilità;
• Configurabilità;
• Requisiti e risorse hardware richieste per il funzionamento dello strumento;
3
Un Linguaggio specifico di Dominio è un linguaggio di programmazione o un linguaggio di specifica dedicato
a particolari problemi di un dominio, a una particolare tecnica di rappresentazione e/o a una particolare soluzione
tecnica.
6
Capitolo 3
Shell
La soluzione più semplice ai problemi di build automation è la scrittura di script di Shell.
La Shell è la parte di sistema operativo che permette agli utenti di interagire con il sistema
stesso, impartendo comandi e richiedendo l’avvio di altri programmi. In generale esistono molti
tipi di Shell, che si dividono principalmente in testuali e grafiche: una Shell testuale è un
programma dotato di un’interfaccia a riga di comando, che viene eseguito all’interno di un
terminale. Le più note Shell testuali sono il prompt dei comandi in Windows, la Bash in
Unix/Linux. Le Shell testuali dei sistemi Unix integrano un linguaggio di scripting con il quale
è possibile scrivere veri e propri programmi che possono ad esempio automatizzare le operazioni
di amministrazione di sistema, semplificandole.
Nel caso di Shell grafiche è comune fare riferimento ai cosiddetti desktop environment, che
forniscono agli utilizzatori un ambiente grafico da cui è possibile gestire file e avviare programmi.
L’evoluzione delle Shell grafiche è rappresentata dalle cosiddette GUI (Graphic User Interface),
che hanno una rappresentazione dei dati più user-friendly.
3.1
Le funzionalità
Sono presenti potenti strumenti all’interno della Shell per collegare tra loro diversi programmi per svolgere compiti complessi, come le pipe e la redirezione. Le moderne Shell testuali
posseggono diverse funzionalità ergonomiche, tra le quali:
• Cronologia dei comandi eseguiti, che permette di ripetere gli ultimi comandi digitati;
7
Capitolo 3. Shell
• Completamento automatico dei comandi;
• Job control, che permette di avviare in background più programmi o di sospenderli temporaneamente.
Tutte le Shell (es. Bash, DOS Shell, etc.) forniscono comandi a sufficienza per la gestione del
file system; tuttavia con la Shell non abbiamo nessun supporto alla programmazione ad oggetti
e supporto limitato alla programmazione strutturata.
3.2
Il linguaggio interpretato
Un’altra caratteristica importante è che i linguaggi di Shell scripting sono interpretati: se
vengono utilizzati per realizzare elaborazioni complesse, queste ultime sono difficili da testare.
In generale un linguaggio di scripting è un linguaggio di programmazione interpretato destinato
a compiti di automazione del sistema operativo (batch) o delle applicazioni (macro), o a essere
usato all’interno delle pagine web. Consistono generalmente in semplici programmi il cui scopo
è l’interazione con altri programmi molto più complessi; si distinguono dai programmi con cui
interagiscono poiché quest’ultimi sono solitamente implementati in un linguaggio differente e
non interpretato. La caratteristica di essere linguaggi interpretati comporta:
• Una minore efficienza a run-time: un programma interpretato, in esecuzione, richiede più
memoria ed è meno veloce, a causa dell’overhead introdotto dall’interprete stesso. Durante
l’esecuzione, l’interprete deve infatti analizzare le istruzioni a partire dal livello sintattico,
identificare le azioni da eseguire ed eseguirle; mentre le istruzioni del codice compilato, già
in linguaggio macchina, vengono caricate e istantaneamente eseguite dal processore.
• In compenso, l’interpretazione di un programma può essere più rapida del ciclo compilazione/esecuzione. Questa differenza può costituire un vantaggio durante lo sviluppo,
specialmente se questo viene condotto con tecniche di fast prototyping o durante il debugging. Inoltre, la maggior parte degli interpreti consentono all’utente di agire sul programma
in esecuzione sospendendolo, ispezionando o modificando i contenuti delle sue variabili in
modo spesso più flessibile e potente di quanto si possa ottenere da un debugger per il
codice compilato.
8
Capitolo 4
Make e confronto con Shell
Il Make è un utility sviluppata sui sistemi operativi della famiglia UNIX, ma disponibile su
un’ampia gamma di sistemi, che automatizza il processo di creazione di file che dipendono da altri
file, minimizzando il tempo di compilazione, risolvendo le dipendenze e invocando programmi
esterni per il lavoro necessario. Storicamente i Makefile - file su cui si basa Make per il suo
funzionamento - sono stati inventati per coadiuvare il lavoro dei programmatori (principalmente
C/C++) minimizzando i tempi di compilazione dei programmi e gestendo in maniera automatica
o semiautomatica le dipendenze tra i vari moduli.
Make è il capostipite di un’intera categoria di software per la Build Automation che, partendo
dai suoi algoritmi e dal suo formato, ha permesso la produzione di diverse versioni dello stesso,
come: GNU Make - utility estremamente diffusa -, Cmake - tool per risolvere alcuni problemi
di portabilità del Make - e Nmake - l’antenato dell’attuale MSBuild di Microsoft.
4.1
Gestione delle dipendenze
Il make gestisce anche le dipendenze che ci sono nel progetto. Si utilizza un meccanismo di
controllo tale da confrontare ogni modulo con la sorgente o con i file intermedi da cui esso deriva
(detti file di dipendenza); se tali file hanno subito qualche modifica dall’ultima compilazione,
Make li ricompila. Per determinare se un file non è aggiornato rispetto alle sue fonti, Make
confronta la data di modifica del modulo con quella del file di dipendenza. Un modulo può
essere trattato come non aggiornato se i comandi usati per la compilazione sono cambiati.
9
Capitolo 4. Make e confronto con Shell
4.2
Il Makefile
Una volta definite le dipendenze esse vengono processate dal programma Make che si occupa
di eseguire le istruzioni contenute nel Makefile. Un Makefile è un file di scripting scritto in
linguaggio dichiarativo su cui si basa Make per conoscere cosa deve fare in fase di deployment e
di installazione del software e per definire le interdipendenze che ci sono tra le varie fasi. Si può
pensare a un Makefile come ad una ricetta: Make legge la ricetta, decide quali misure devono
essere eseguite, ed esegue solo quei passaggi che sono necessari per produrre il modulo finito.
Un aspetto in comune tra Shell e Make è la chiamata da linea di comando, poiché make è
distribuito in forma di eseguibile a linea di comando.
L’uso di Make permette di avere tempi di esecuzione più brevi rispetto alla Shell: un programma eseguito interamente dalla riga di comando, ad ogni chiamata deve essere ricompilato,
mentre utilizzando un Makefile e chiamando da Shell il comando Make, viene ricompilato solo
il file sorgente modificato. Anche se è possibile scrivere uno script di complessità sufficiente a
ricompilare solo quei moduli che lo richiedono, Make fa questo lavoro in maniera migliore.
Una differenza sostanziale tra i due strumenti sta nell’utilizzo di un file (il Makefile) da parte
di Make, mentre la Shell si basa solo su ciò che le viene impartito da riga di comando.
Poiché Make dipende dal linguaggio di Shell e quest’ultima non è indipendente dal sistema
operativo, questo comporta che entrambi dipendono dal sistema operativo: cambiando sistema,
la Shell (e quindi Make) cambia. Questo problema può essere gestito generando script di build
specifici per ogni piattaforma, che a loro volta vengono elaborati da Make. Strumenti comuni
per questo processo sono Autoconf e CMake.
Il Makefile non è nativamente compatibile con Windows, né portabile su sistemi Unix; per un
linguaggio indipendente dalla piattaforma come Java, questo è stato un grosso problema. Anche
per le applicazioni che non richiedono l’indipendenza dalla piattaforma, i Makefile risultano
essere una soluzione eccessivamente complessa per sviluppare in Java.
Tra gli aspetti a sfavore dell’utilizzo del Make troviamo anche le limitazioni nell’implementare
strutture di controllo sofisticate all’interno del Makefile.
10
Capitolo 4. Make e confronto con Shell
4.3
Problematiche del Make
Il problema con strumenti come Make, quando utilizzati nella loro configurazione standard,
è che la compilazione viene eseguita in modo sequenziale. Quando ci sono migliaia di file questo
tipo di procedura può essere molto lenta. Con l’avvento dei processori multi-core, Make ha
sfruttato tale vantaggio in una nuova versione che permette anche un’esecuzione parallelizzabile:
BSD Make. BSD Make oltre ad avere questa particolarità, supporta anche le espressioni condizionali e la produzione di obiettivi in fase di esecuzione.
Nonostante i vantaggi, il problema di una compilazione in parallelo è risolvere le dipendenze, infatti se il Makefile non definisce con precisione le dipendenze di ogni modulo, i tempi di costruzione potrebbero rimanere elevati, eliminando il vantaggio dell’utilizzo di sistemi
multi-core.
4.4
GNU make e la sua portabilità
GNU Make invece è un’implementazione Make per Linux/OS X ampiamente utilizzata. Esso
fornisce diverse estensioni rispetto all’originale Make, come la possibilità di definire costrutti
condizionali e funzioni integrate usate per eliminare la necessità di Shell-scripting nelle regole
del Makefile nonché di manipolare le variabili impostate e utilizzate nel Makefile. Compilare
un programma GNU Make è un’operazione abbastanza semplice se si hanno già a disposizione
tutte le librerie richieste. Inoltre GNU Make mette a disposizione moltissime funzionalità che
consentono di utilizzarlo negli ambiti più disparati. I programmi GNU non sono di solito forniti
con Makefile, è infatti necessario lanciare lo script che analizza il sistema su cui sta girando,
creando un Makefile ‘ad hoc’ da poter essere utilizzato sull’attuale piattaforma. Questo sistema
rende un programma GNU, non solo portatile attraverso i vari tipi di Unix, ma anche attraverso
i vari tipi di processori; caratteristica che ne Make ne la Shell hanno.
11
Capitolo 5
Apache Ant e confronto con Make
Figura 5.1: Apache Ant
Apache Ant è un software originario del progetto Tomcat di Apache del 2000. Non è solo
limitato a compilazione del codice, ma anche l’imballaggio, la sperimentazione e molto di più;
quindi può essere utilizzato per operazioni molto più complesse di un semplice build. Come
abbiamo detto nella descrizione storica, è nato con l’intendo di sostituire Make e sopperire ai
suoi difetti. Il difetto più grande era quello della portabilità, in quanto piattaforme diverse
richiedevano comandi di Shell diversi e quindi un Makefile diverso. Ant risolve questo problema
fornendo una grande quantità di funzionalità incorporate in modo tale da comportarsi allo stesso
su tutte le piattaforme. Si basa su un’idea di programmazione procedurale.
5.1
Vantaggi dell’implementazione in Java
Essenzialmente è simile al Make ma è implementato in java, ottenendo uno strumento più
adatto alla costruzione di progetti java, ma non solo: infatti può essere utilizzato anche per
applicazioni basate su altri linguaggi. Inoltre è indipendente dal sistema operativo e dalla
piattaforma su cui gira ma richiede che sia presente una JDK nel sistema. Un altro vantaggio
12
Capitolo 5. Apache Ant e confronto con Make
dell’implementazione in java è la possibilità di creare Javadoc e di utilizzare librerie Ant per
estendere le funzionalità; tali librerie messe a disposizione da Apache svolgono una vasta gamma
di attività attraverso i loro task; viene anche fornita la possibilità di realizzare dei task riusabili.
Grazie a tutti questi aspetti è uno dei tool più utilizzato per la produzione di applicazioni Java.
5.2
Build.xml - Il file di Configurazione
Un aspetto cruciale nell’utilizzare Ant è che non richiede altro codice da scrivere per costruire
l’applicazione, piuttosto l’intero processo è definito da obiettivi che non sono altro che elementi
XML. Quindi la differenza che si evince tra Ant e Make è proprio l’utilizzo in Ant dell’XML per
descrivere il processo di generazione e le sue dipendenze, mentre Make utilizza il Makefile. Per
impostazione predefinita, il file XML è denominato build.xml. Il maggiore inconveniente di Ant
è proprio l’utilizzo di XML: è efficiente per la descrizione dei dati in modo gerarchico poiché si
basa su una struttura di tipo gerarchico, ma perde punti nell’esprimere il flusso del programma
e la logica condizionale. Come uno script di build cresce in complessità, gestire il codice diventa
un incubo.
È prassi dei programmatori tentare di rendere il software quanto più indipendente possibile
e in questo Ant risulta essere molto potente: infatti attraverso semplici direttive è possibile
esportare dove necessario non solo il pacchetto ma anche tutti i file di configurazione.
Il vantaggio principale di Ant risiede nel controllo e nella flessibilità del processo di costruzione. Lo scopo principale è la realizzazione di Jar e War in modo da rendere l’export di
applicazioni Java non solo semplice ma soprattutto customizzabile. Infatti con Ant non solo è
possibile creare i pacchetti java per l’export ma personalizzare il singolo file in modo che sia
configurabile su qualsiasi ambiente.
5.3
Limiti degli script Ant
Dando un occhio più da vicino agli script e alla loro gestione in Ant possiamo notare che:
• La maggior parte delle volte sono generati automaticamente da altri programmi, come ad
esempio da IDE come Eclipse; questo aspetto, insieme alla natura stessa degli script XML
13
Capitolo 5. Apache Ant e confronto con Make
li rende un po’ limitati in quanto a strutture di controllo e alla possibilità di introdurre
comportamenti dinamici;
• Gli script devono per forza risiedere su disco, non possono essere risorse remote;
• Molti script di Ant presentano dei valori di default per delle opzioni che non sono coerenti
con le versioni precedenti dello script che svolge gli stessi compiti; un eventuale modifica
potrebbe bloccare l’esecuzione stessa dello script;
• Nell’espansione di uno script le proprietà non definite non causano un errore che induce il
programmatore a farci attenzione ma vengono considerati come riferimenti non espansi;
5.4
Facilità d’uso, Leggibilità e Testing
Ant può essere richiamato da linea di comando in modo da poter essere facilmente integrato in altri programmi e non necessita di installazione in quanto è sufficiente copiare i file ed
eventualmente, settarne il percorso tra i path predefiniti.
Nel Makefile, qualsiasi regola per creare un tipo di file da un altro può essere scritta in linea
all’interno del Makefile stesso. In Ant invece è più complesso: deve essere scritta l’attività in
Java e inclusa con il file Ant. Tuttavia, questa separazione può migliorare la leggibilità dello
script Ant nascondendo alcuni dettagli di come un task sia eseguito su piattaforme diverse.
Con Ant si possono eseguire script di test e suite di test. Supporta Junit 3, Junit 4, TestNG
etc. Inoltre, è possibile convertire report XML sui test in report HTML.
Quindi Ant è abbastanza flessibile ma non dà alcuna indicazione su come strutturare il
progetto e rende ogni script di build unico e difficile da comprendere in modo proporzionale alla
complessità dello script stesso. Dopo la sua versione iniziale, è stato migliorato con la possibilità
di accettare plug-in. Tuttavia, diverse proposte per una versione Ant 2 sono state fatte, ma
nessuna è stata in grado di trovare grande accettazione dalla comunità degli sviluppatori.
14
Capitolo 6
Apache Maven e confronto con
Apache Ant
Figura 6.1: Apache Maven
Maven non è soltanto un tool per la build automation a differenza di Ant ma fu pensato per
unificare il modo di sviluppare e organizzare diversi progetti della famiglia Apache. Esso è uno
strumento per la gestione di progetti che prevede un insieme di standard, trattazione del ciclo
di vita (dalla costruzione, ai test e documentazione), un sistema di gestione delle dipendenze e
l’uso di plugin per svolgere attività in fasi specifiche del ciclo di vita. Usando Maven si descrive
un progetto usando un ben definito modello, sul quale Maven stesso può applicare una logica
trasversale a partire da un insieme di plugin condivisi o personalizzati.
La parola Maven significa accumulatore di conoscenza” in Yiddish. Maven affronta due
aspetti della costruzione di software: in primo luogo, descrive come il software è costruito,
e in secondo luogo, descrive le sue dipendenze. Una prima differenza tra Ant e Maven sta
nel come vengono classificati i due strumenti: Ant è un insieme di strumenti mentre Maven
è un framework. Allo stesso modo di Make e Ant, Maven può essere eseguito da linea di
comando. Inoltre, cosi come Ant, Maven legge uno o più file xml di configurazione e le variabili
possono essere dichiarate in un file separato detto application.properties (in Ant si chiamava
15
Capitolo 6. Apache Maven e confronto con Apache Ant
build.properties).
Come detto nella definizione, Maven gestisce il ciclo di vita del software, dalla scrittura del
codice al deploy in ambiente di produzione. Le fasi standard di Maven sono le seguenti:
validate, generate-sources, process-sources, generate-resources, process-resources, compile,
process-test-sources, process-test-resources, test-compile, test, package, install, e deploy.
Le fasi possono essere personalizzate. Le operazioni (chiamati goals) di Maven, cosı̀ come
quelle associate ai diversi plugin, ricadono ciascuna in una particolare fase.
6.1
Obiettivi di Maven
Maven si basa sull’applicazione di modelli per realizzare un’infrastruttura che mostra le caratteristiche di visibilità, riutilizzabilità, manutenibilità, e comprensibilità. Senza queste caratteristiche, è altamente improbabile che più persone lavoreranno produttivamente insieme su un
progetto. Senza visibilità è improbabile che un individuo sa cosa un altro ha compiuto. Quando
il codice non è riutilizzato è molto difficile creare un sistema gestibile. Se ci sono molti moduli
divisi senza nessuna correlazione, difficilmente si riuscirà ad avere una visione complessiva del
progetto. Di conseguenza si finisce con l’avere un decadimento della conoscenza condivisa unita
alla frustrazione tra i membri del team. Un effetto naturale quando i processi non funzionano
allo stesso modo per tutti. Maven cerca di risolvere proprio questi problemi e soddisfare queste
caratteristiche, sia a livello di progettazione, che di test, documentazione e cosi via.
6.2
POM - Il file di Configurazione
Uno schema di partenza per il file di configurazione richiede come unici input necessari, il
nome dell’applicazione e il dominio di riferimento degli sviluppatori: la necessità di indicare
sia il nome che il dominio è legata alla possibilità di poter fornire nomi universali (URI) ai
progetti, in modo che possano essere univocamente reperiti sulla rete. Questo aspetto evidenzia
una differenza rispetto ad Ant: Ant richiedeva risorse locali mentre in Maven le risorse possono
essere anche su rete. In particolare nella maggior parte dei casi Maven può funzionare solo e
soltanto in presenza di connessione ad Internet.
16
Capitolo 6. Apache Maven e confronto con Apache Ant
Riguardo il file di configurazione, Ant è procedurale: infatti è necessario fornire informazioni
su cosa fare, in che ordine farle e quando farle, tutte tramite codice; mentre Maven è dichiarativo
e si definisce tutto nel file di configurazione del progetto.
Questo file di configurazione sul quale si basa la filosofia di Maven è chiamato POM scritti in
XML: come abbiamo detto, la configurazione riguarda il nome del progetto, il suo proprietario
e le sue dipendenze da altri progetti. Si possono anche configurare le singole fasi del processo
di creazione, che sono attuate come plugin. I progetti più grandi dovrebbero essere suddivisi
in diversi moduli, ognuno con il proprio POM. Come per Ant, anche per Maven l’utilizzo dell’XML come formato di configurazione è rigorosamente strutturato e altamente standardizzato
comportando un alto livello di dettaglio nel definire la configurazione di un progetto e portando
cosi difficoltà sia nella lettura che nella scrittura del file stesso, soprattutto se si tratta di file
di grandi dimensioni. Tuttavia, la struttura interna del file è diametralmente diversa: mentre
Ant richiede agli sviluppatori di scrivere tutti i comandi che portano alla corretta esecuzione
di un compito, Maven si basa su convenzioni e mette a disposizione gli obiettivi disponibili che
possono essere richiamati nel progetto. Come aggiunta supplementare Maven ha introdotto la
possibilità di scaricare le dipendenze da altri progetti attraverso la rete (in seguito adottato da
Ant attraverso Ivy) che di per sé ha rivoluzionato il modo con il quale viene fornito il software.
La personalizzazione dei target (obiettivi) diventa difficile poiché Maven è focalizzata principalmente sulla gestione delle dipendenze, e scrivere script personalizzati sono in realtà più
difficili in Maven che in Ant. L’unico modo per poter scrivere logica personalizzata in modo
semplice, e quindi uscire dalle convenzioni di Maven, è attraverso l’utilizzo di un plugin chiamato
Mojo.
Maven può essere visto come Ant con delle convenzioni sulla configurazione, quindi non
abbiamo bisogno di fornire informazioni sulla struttura del progetto nel file pom.xml, ottenendo
quindi maggiore facilità d’uso.
In Maven abbiamo maggiori librerie e plug-in di utilità, infatti la maggior parte delle funzionalità di Maven è in plugin: plugin per la costruzione, il collaudo, la gestione, controllo del codice
sorgente, l’esecuzione di un server web, etc. Inoltre Maven è orientato anche alla riutilizzabilità perché è possibile sia pubblicare progetti per poi riutilizzarli in altri ambiti, sia pubblicare
plugin creati all’occorrenza. Maven ha una migliore integrazione con gli IDE sia nella fase di
17
Capitolo 6. Apache Maven e confronto con Apache Ant
costruzione che modifica.
6.3
Gestione delle dipendenze
L’innovazione portata da Maven è la gestione delle dipendenze. Basta dichiarare le dipendenze e le dipendenze transitive
1
e Maven le gestirà scaricandole automaticamente per ogni
modulo che ne ha bisogno incluso nel progetto. Viceversa con Ant, per avere una simile gestione, ci vorrebbe una grande mole di lavoro, anche se si potrebbe risolvere il problema attraverso
l’utilizzo di librerie esterne. Da notare che non sempre viene nominata esattamente l’URL del
progetto da cui dipende ciò che dobbiamo costruire, ma vengono forniti il groupId, l’artifactId
e la version, essi saranno sufficienti a Maven per reperire ciò che serve, nel caso esso sia stato
correttamente pubblicato nell’ambito del dominio com.mycompany.app. In assenza della dichiarazione della URL, Maven cerca in locale e sul sito ufficiale del progetto Maven. Quindi c’è la
possibilità di includere progetti disponibili in remoto e di collegarli dinamicamente a tempo di
compilazione.
Tuttavia la gestione delle dipendenze di Maven include delle insidie:
• Richiesta di spazio sul disco e ram; infatti anche per un progetto semplice viene richiesta
un ampia regolazione della JVM; ancora peggio se poi si utilizza anche un IDE;
• Quando si vuole compilare un modulo, verranno risolte tutte le dipendenze, comprese
quelle transitorie, richiamando tutti i moduli - eventualmente su rete - e richiedendo tempo
nella fase di compilazione. Analogo discorso quando si devono gestire le dipendenze dei
plugin inseriti nel progetto;
• Progetti sviluppati su una singola macchina possono dipendere tra loro attraverso il repository locale 2 . Maven scarica dinamicamente le librerie Java e i plugin da uno o più
repository come il Maven 2 Central Repository, e li memorizza in una cache locale. Sotto questa gestione Maven presenta delle problematiche di sicurezza poiché è impossibile
determinare la provenienza degli artefatti che si includono nel progetto, ne Maven stesso
effettua un controllo sull’affidabilità di questi dati inseriti nella cache locale del repository;
1
Dipendenze transitive: dipendenze esterne che possono avere un riferimento ad altre librerie o risorse
Repository locale: è una struttura di cartelle che agisce sia come una cache per le dipendenze scaricate che
come un luogo di deposito centralizzato per i manufatti costruiti localmente
2
18
Capitolo 6. Apache Maven e confronto con Apache Ant
• Il Manager delle Dipendenze non gestisce i conflitti tra le diverse versioni della stessa
libreria (Ivy è molto meglio);
6.4
Apache Maven e confronto con Apache Ivy
Ivy si può vedere come un’estensione di Apache Ant che si occupa essenzialmente della gestione delle dipendenze di un progetto, reporting e pubblicazione. E’ uno strumento molto flessibile
e configurabile, infatti può essere adattato ad una vasta gamma di gestione delle dipendenze.
Inoltre possiede un potente motore di gestione delle dipendenze transitive.
Poiché il confronto con Apache Ant è stato già effettuato, in questo paragrafo ci focalizzeremo
nell’analizzare principalmente la gestione delle dipendenze che introduce Ivy, rispetto a quella
di Maven.
Prima di passare a tale confronto notiamo che c’è una differenza sostanziale su come sono
definiti i due tool: Apache Maven è uno strumento di gestione dei progetti software e comprensione, mentre Apache Ivy è solo uno strumento di gestione delle dipendenze, integrato con
Ant.
6.4.1
Gestione delle dipendenze e dei conflitti
Apache Ivy si basa sul concetto di configurazione, ovvero un modo per utilizzare, testare
o per vedere un modulo. In ogni configurazione, è possibile dichiarare le dipendenze da altri
moduli, e descrivere qual è la configurazione della dipendenza di cui si ha bisogno. Questo si
chiama mappatura di configurazione. Apache Maven invece ha un modulo chiamato campo
di applicazione nel quale è possibile dichiarare una dipendenza e poi, a seconda dell’ambito, si
otterrà l’artefatto di tale dipendenza con le relative dipendenze ad esso collegate. Però gli ambiti
sono predefiniti e non si possono variare.
Un altro aspetto da analizzare è la gestione dei conflitti, richiamata quando si trattano
dipendenze transitive: Apache Ivy consente di muoversi liberamente utilizzando gestori di conflitti diversi per decidere quale revisione considerare; mentre con Apache Maven, la gestione dei
conflitti è molto semplice: il principio è quello di ottenere la definizione più vicina3 .
3
Se il modulo dipende dalla definizione 1.0, nessuna dipendenza potrà mai riuscire ad ottenere la definizione
1.1 senza un cambiamento nella dichiarazione di dipendenza.
19
Capitolo 7
Gradle e confronto con Apache Ant
e Maven
Figura 7.1: Gradle
Gradle è l’ultimo passo evolutivo negli strumenti di generazione basati su JVM. È un software
multipiattaforma per l’automazione dello sviluppo fondato sulle idee di Apache Ant e Maven.
Ha il potere di Ant e la flessibilità sul ciclo di vita e facilità d’uso di Maven. Il risultato finale
è uno strumento che è stato rilasciato nel 2012 ed ha guadagnato un sacco di attenzione in un
breve periodo di tempo.
Gradle non utilizza XML (che a causa della sua natura gerarchica è meno flessibile) per
descrivere il dominio del problema, ma un domain-specific language (DSL) basato su Groovy
(una delle lingue JVM) il quale a sua volta è basato su Java, che rende semplice definire anche
una logica personalizzata. Non è necessario essere un esperto di Groovy per iniziare poiché,
basandosi su java è possibile migrare gradualmente da un linguaggio all’altro. Costruendo con
Gradle si riescono ad ottenere script molto più brevi e più chiari di quelli scritti per Ant o
Maven.
Gli script Gradle possono essere eseguiti direttamente, al contrario di quelli di Apache Maven.
Inoltre, al contrario di Apache Maven, che definisce il ciclo di vita di un processo, e di Apache
20
Capitolo 7. Gradle e confronto con Apache Ant e Maven
Ant, dove l’ordine dei compiti è determinato dalle dipendenze, Gradle utilizza un grafo aciclico
diretto (DAG) per determinare l’ordine in cui i processi possono essere eseguiti.
Gradle è stato progettato per sviluppi multi-progetto che possono crescere fino a divenire abbastanza grandi e supporta sviluppi incrementali determinando in modo intelligente quali parti
del build tree sono aggiornate (up-to-date), in modo che tutti i processi che dipendono solo da
quelle parti non avranno bisogno di essere rieseguiti; cosı̀ facendo, si riduce significativamente il
tempo di costruzione del progetto, in quanto, durante il nuovo tentativo di costruzione, verranno
eseguite solo le attività il cui codice è effettivamente stato alterato a partire dall’ultima costruzione completata. Gradle supporta anche la costruzione del progetto per processi concorrenti, il
che consente di svolgere alcuni compiti durante la costruzione (ad esempio, i test automatizzati
attraverso gli unit test), eseguiti in parallelo su più core della medesima CPU, su più CPU o su
più computer. Questo aspetto può essere visto come una differenza sostanziale rispetto a Maven
che, come sappiamo, aveva problemi nella gestione delle dipendenze e negli aggiornamenti che
portavano ad avere tempi di compilazione più lunghi. Il software integra in se alcuni punti di
forza di Apache Maven, ovvero: convenzione sulla configurazione, ciclo di vita, gestione delle
dipendenze nello stile di Apache Ivy o Maven e l’utilizzo di repository.
7.1
Integrazione con altri tool
Figura 7.2: Integrazione di Gradle con altri tools
Lo strumento permette di integrare, senza sforzo, progetti scritti in linguaggi di programmazione diversi da Java. Se si arriva da Ant, Gradle non obbliga a effettuare una migrazione
21
Capitolo 7. Gradle e confronto con Apache Ant e Maven
dell’infrastruttura completa, permettendo di riutilizzare le attività Ant standard. I Target Ant
vengono direttamente mappati come compiti Gradle in fase di esecuzione. Gradle possiede una
classe di supporto per gli script Ant chiamata AntBuilder, che si fonde completamente nel DSL
Gradle: attraverso di essa sembra di scrivere XML classico. Invece per Maven, Gradle fornisce
un convertitore per la sua logica; in futuro mira a raggiungere una profonda integrazione anche
con Maven; Inoltre Gradle è compatibile con i repository di Maven e Ivy ma, a differenza di
Maven che ha un repository predefinito, con Gradle è necessario definire il repository che si
desidera utilizzare.
7.2
Struttura Gradle
Proprio come avviene con Apache Maven, la struttura di Gradle è costituita da un nucleo
astratto e da una serie di plugin che ne espandono le funzionalità. Anche la costruzione dei
progetti Java avviene per mezzo di plugin. Alcuni plug-in consentono di monitorare la qualità del software ricorrendo all’esecuzione di controlli automatici ed alla produzione di report
corrispondenti all’attività di costruzione.
Gradle utilizza tre file principali per personalizzare la costruzione:
• build.gradle - Il file contenente tutte le informazioni sul build;
• settings.gradle (opzionale) - Il file contiene la definizione dei moduli di cui si compone il
multi-progetto;
• gradle.properties (opzionale) - Il file contiene un elenco di valori validi per l’inizializzazione
delle proprietà di uno specifico progetto Gradle;
Il processo di costruzione di Gradle si suddivide in due fasi principali, che vengono sempre
eseguite: la configurazione e l’esecuzione. Durante il ciclo di configurazione, vengono delineati
i passi dell’intera costruzione per generare il grafico di dipendenza (DAG) che contiene la sequenza di tutte le fasi da eseguire. La seconda fase consiste nell’attraversamento delle attività
precedentemente rilevate.
22
Capitolo 7. Gradle e confronto con Apache Ant e Maven
7.3
Gestione delle dipendenze
La gestione delle dipendenze in Gradle non solo è altamente configurabile ma si sforza anche
di essere il più possibile compatibile con le infrastrutture di gestione delle dipendenze esistenti
(come ad esempio Maven e Ivy). La capacità di Gradle di gestire le dipendenze non si limita
all’utilizzo di librerie esterne, poiché se gli elementi DSL standard non si adattano alle esigenze
del progetto, si può anche definire un vocabolario proprio attraverso l’utilizzo delle estensioni
di Gradle. Inoltre fornisce un supporto potente per la definizione e l’organizzazione per la
costruzione multi progetto, cosı̀ come la gestione delle dipendenze tra i progetti.
Un requisito fondamentale è la riproducibilità, ovvero se il programma funziona su un’altra
macchina; Make non è riproducibile poiché deve produrre lo stesso risultato su macchine diverse,
indipendentemente dal contenuto della cache locale. Il Manager delle dipendenze di Ivy e Maven
nella loro implementazione corrente non possono garantire pienamente la riproducibilità perché
quando una dipendenza viene scaricata e memorizzata nella cache locale, non viene preso in
considerazione l’origine del manufatto; in situazioni in cui il repository viene modificato per un
progetto, la dipendenza della cache viene considerata risolta, anche se il contenuto del manufatto
potrebbe essere leggermente diverso. Nel peggiore dei casi, questo causerà un difetto che è estremamente difficile da risolvere. Gradle invece, fornisce la propria soluzione per la gestione delle
dipendenze in modo configurabile, affidabile ed efficiente: considera ciascuno dei moduli di un
progetto di grandi dimensioni, un progetto separato il quale può definire le dipendenze a librerie
esterne o altri moduli. Inoltre, ogni sottoprogetto può essere eseguito singolarmente. Gradle
capisce quale sottoprogetto richiede la ricostruzione delle dipendenze, senza dover memorizzare
artefatti nella cache locale. In questo modo Gradle risolve le problematiche sulla sicurezza nella
gestione delle dipendenze presenti invece in Maven.
Se si inizia un nuovo processo Gradle, ogni volta il caricamento di tutte le sue dipendenze
interne e l’esecuzione della logica di build, richiedono un paio di secondi prima che inizi ad
eseguire. Per migliorare le prestazioni di avvio, Gradle può essere eseguito in modalità demone.
In pratica non esegue solo la build, ma mantiene l’esecuzione in background, cosi invocazioni
di build successive saranno sulle spalle del processo daemon esistente. Di conseguenza, Gradle
risulta molto veloce nell’eseguire le operazioni rispetto ai tools concorrenti.
23
Capitolo 8
Microsoft MSBuild
Microsoft Build Engine è una piattaforma per la compilazione di applicazioni che consente
di automatizzare il processo di creazione di un prodotto software, compresa la compilazione del
codice sorgente, l’imballaggio, il controllo, la distribuzione e la creazione di documentazione.
Questo motore, anche noto come MSBuild, fornisce uno schema XML per il file di progetto
che controlla il modo in cui la piattaforma di compilazione elabora e compila il software. Visual
Studio usa MSBuild, ma quest’ultimo non dipende da Visual Studio. Richiamando msbuild.exe
nel progetto o nel file della soluzione, è possibile orchestrare e compilare prodotti in ambienti in
cui Visual Studio non è installato.
MSBuild è un sostituto di Nmake utility (una delle versioni di Make) e agisce su un file
di progetto (MSBuild) con sintassi XML simile ad Apache Ant ma con una struttura e un
funzionamento paragonabile al tradizionale Unix Make: l’utente specifica ciò che verrà utilizzato (tipicamente file di codice sorgente) e ciò che il risultato dovrebbe essere (tipicamente
un’applicazione ), l’utility decide cosa fare e l’ordine in cui farlo.
Visual Studio utilizza MSBuild per caricare, compilare e gestire progetti. I file di progetto
in Visual Studio (con estensione CSPROJ, VBPROJ, VCXPROJ e altre) contengono il codice
XML di MSBuild che viene eseguito quando si compila un progetto usando l’IDE. I progetti di
Visual Studio importano tutte le impostazioni e tutti i processi di compilazione necessari per
eseguire il normale lavoro di sviluppo standard, ma è possibile estenderli o modificarli in Visual
Studio stesso o mediante un editor XML.
È possibile scrivere codice nell’IDE di Visual Studio ed eseguire le compilazioni tramite
24
Capitolo 8. Microsoft MSBuild
MSBuild. In alternativa, è possibile compilare il codice nell’IDE in un computer di sviluppo e
usare una riga di comando di MSBuild per compilare il codice integrato da più sviluppatori.
Come in tutti gli altri strumenti visti e come appena visto, anche in MSBuild si può utilizzare
la chiamata alla compilazione da riga di comando per alcuni compiti; tale chiamata la si può
fare se, ad esempio, si intende modificare il sistema di compilazione, consentendo azioni quali:
• Pre-elaborazione dei file prima che arrivino al compilatore;
• Copia degli output di compilazione in un’altra posizione;
• Creazione dei file compressi dagli output di compilazione;
• Esecuzione di passaggio di post-elaborazione. Ad esempio, può essere utile contrassegnare
un assembly con una versione diversa;
Un altro esempio di chiamata da riga di comando avviene quando Visual Studio non è
installato.
I tools analizzati nei capitoli precedenti sono accomunati anche dall’essere tutti open source,
mentre MSBuild ha licenza proprietaria.
1
1
Un software con licenza proprietaria è un software concesso in licenza sotto diritto legale esclusivo del titolare
del copyright con l’intento che il licenziatario è dato il diritto di utilizzare il software solo a determinate condizioni,
e limitato da altri usi, come ad esempio la modifica, la condivisione, lo studio, la ridistribuzione o il reverse
engineering.
25
Capitolo 9
Conclusioni e Sviluppi Futuri
In questo elaborato ho presentato alcuni dei tools per la Build Automation più famosi
cercando di mettere in evidenza ogni possibile punto di forza e di debolezza di ognuno.
Il confronto e quindi il corpo della tesi, ha avuto inizio con la presentazione della Shell e
del suo limitato livello di automazione; successivamente Make porta l’automazione nella fase
di sviluppo a un gradino più alto. Niente a che vedere con Ant; come abbiamo visto è uno
strumento molto flessibile e molto diffuso soprattutto per progetti java. La sua diffusione la si
deve anche ad ambienti di sviluppo come Eclipse IDE, che permette la costruzione e l’esecuzione
di script Ant, o come il NetBeans IDE che utilizza Ant per il suo sistema di build interno.
Inoltre ambienti di sviluppo come Eclipse, NetBeans, IntelliJ IDEA, JBuilder, JDeveloper,
etc., vanno a sostegno anche di Apache Maven che, come abbiamo visto, si caratterizza per la
sua maggiore facilità d’uso grazie all’utilizzo delle convenzioni, le quali tuttavia, ne riducono
drasticamente la flessibilità. Uno dei vantaggi più grandi di Maven è la gestione dell’intero ciclo
di vita del prodotto software, il che rende tale strumento molto più completo di Apache Ant.
Infine abbiamo Gradle che ha un livello intermedio di flessibilità poiché permette di uscire
facilmente dalle convenzioni sulle quali si basa. Tuttavia se rispettate le convenzioni, l’unico
sforzo sta nell’effettuare la configurazione del progetto il che rende lo strumento semplice da
utilizzare e da gestire.
Una delle grandi idee di Gradle è quello di dare le linee guida e i valori di default ai progetti. Tutte le attività come compilazione, test, produzione di Javadoc, etc., sono completamente integrati rendendo Gradle uno strumento oltre che semplice da utilizzare e gestire anche
26
Capitolo 9. Conclusioni e Sviluppi Futuri
completo.
Anche se relativamente giovane1 , le grandi capacità di Gradle hanno fatto si che dalla pubblicazione di Android Studio (2013) - strumento di sviluppo ufficiale di Android - è stato dichiarato
lo strumento di compilazione di default garantendo cosi, oltre che notevoli vantaggi per l’IDE
stesso, anche una notevole diffusione per Gradle dovuta non solo alla comunità Android ma anche
alle comunità di sviluppo di plugin e alle società di supporto dello strumento come Gradleware
che hanno garantito un livello di affidabilità molto elevato.
Eventuali sviluppi futuri di questo elaborato mi consentirebbero di approfondire alcuni aspetti che sono stati trascurati. In primo luogo si potrebbero approfondire meglio i confronti già
effettuati testando personalmente su ogni tool gli aspetti trattati; ad esempio, si potrebbe analizzare la quantità di codice di scripting da scrivere per poter effettuare una stessa operazione
su ogni strumento.
Inoltre si potrebbe espandere la trattazione inserendo altri tools per la Build Automation; ad
esempio, tool come Rake, il quale è un ottima alternativa per progetti java poiché implementato
in Ruby; oppure tools come quelli di generazione automatica di file di script come Puppet, Salt,
Rex, etc.
Tuttavia il confronto effettuato in questo elaborato pone le linee guida per poter inquadrare
ogni strumento per la Build automation dal punto di vista dell’automazione che esso stesso
introduce nella produzione di un software.
1
Nel 2008 è stata pubblicata la prima release di Gradle
27
Ringraziamenti
Desidero ringraziare tutti coloro che mi hanno aiutato in questo percorso e nella stesura di
questo elaborato con suggerimenti ed osservazioni, anche se spetta a me la responsabilità per
ogni errore presente in questa tesi.
Ringrazio anzitutto il professore Porfirio Tramontana per i suggerimenti e per la disponibilità
nell’incontrarci per discutere riguardo la stesura di questo elaborato.
Ringraziamenti doverosi sono rivolti ai miei genitori, ai nonni e a mio fratello.
Grazie mamma per essermi stata sempre vicina anche a 200 km di distanza, per avermi fatto
da sveglia tutte le mattine e per avermi lavato i vestiti ogni volta che tornavo a casa. Grazie
per i consigli di cui ho sempre tenuto conto, anche se spesso in ritardo.
Grazie papà per non avermi fatto mancare mai nulla, per aver acconsentito ad ogni mia
richiesta. Grazie per ogni km fatto per accompagnarmi. Alla fine di ogni esame, anche se la
prima chiamata era per mamma, ti ho sempre pensato e sapevo che, anche se l’esame fosse
andato male, tu m’avresti incoraggiato a rifarlo e andare avanti.
Grazie Luca che, anche se inizialmente non sapevi cosa studiassi, sei stato sempre disponibile
ad aiutarmi.
Grazie ai nonni che ci sono e che non ci sono più.
Voi tutti siete stati e sarete la motivazione che mi spinge a studiare e a dare il massimo per
rendervi orgoglioso di me.
28
Ringraziamenti
Altri ringraziamenti sono rivolti agli amici.
Grazie a Carmine, amico e collega di università che per quasi quattro anni mi ha sempre
sostenuto e accompagnato in ogni mia scelta. Spero che un giorno raggiunga anche tu questo
traguardo!
Grazie anche ad amici come Alfonso e Rosario per l’amicizia che si è creata nell’ultimo anno
di università e a Maria per esser stata sempre presente nonostante la mia assenza.
Grazie anche a mia cugina Yessica e a Donatella per avermi aiutato nella correzione della
tesi con suggerimenti e osservazioni utilissime.
Infine un grazie a Poli, il pappagallino che, nonostante mangi ogni foglio, ogni quaderno di
appunti e ogni banconota incustodita, ha portato e porta tutt’oggi allegria in casa.
E per chiunque non ho nominato esplicitamente, un grazie va a tutti quelli che sentono in
loro di aver contribuito anche con una parola o con un piccolo gesto al raggiungimento di questo
mio obiettivo.
29
Bibliografia
[1] http://www.html.it/articoli/build-automation-con-gradle-2/
2
[2] http://en.wikipedia.org/wiki/Build-automation1
[3] http://www.drdobbs.com/jvm/why-build-your-java-projects-withgradle/2401686081
[4] http://en.wikipedia.org/wiki/List-of-build-automation-software1
[5] Porfirio Tramontana, Lucidi del corso di Ingegneria del software II,
Cdl Ing.Informatica, Università degli Studi ’Federico II’ Napoli, a.a. 2014/15.
[6] http://ant.apache.org/ivy/m2comparison.html1
[7] http://docs.oracle.com/cd/E19504-01/802-5880/6i9k05dhe/index.html1
[8] http://technologyconversations.com/2014/06/18/build-tools/1
[9] https://msdn.microsoft.com/it-it/library/dd393574.aspx1
[10] https://it.wikipedia.org/wiki/Shell-(informatica)1
[11] https://it.wikipedia.org/wiki/Make1
[12] https://it.wikipedia.org/wiki/Apache-Ant1
[13] https://en.wikipedia.org/wiki/Apache-Maven1
[14] https://it.wikipedia.org/wiki/Gradle1
[15] https://it.wikipedia.org/wiki/Linguaggio-di-scripting1
[16] http://grokcode.com/538/java-build-systems-a-sad-state-of-affairs/1
[17] http://www.gianlucamerendino.com/home/2015/01/11/percorsi-informaticiintroduzione-a-maven/1
2
Visualizzato in data 10/06/2015
30