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