MaCocoa 007

Capitolo 007 - L'ambiente di sviluppo

Dopo il paradigma Object-oriented e il linguaggio Objective C, finalmente si comincia a toccare qualcosa con mano.

Sorgenti: Qualcosa di originale...

Primo inserimento: 29 Ottobre 2001.

Profonde modifiche per aggiornamento XCode 2.1: 3 Agosto 2005.

Integrazione con maggiori spiegazioni su XCode: 24 settembre 2006.

XCode

XCode è l'ambiente integrato di sviluppo (Integrated Development Environment, IDE) utilizzato per scrivere, costruire e verificare la correttezza di programmi da far girare sotto Mac OS X. Utilizzando XCode si possono creare applicazioni, plug-in, driver, framework, salvaschermi, eccetera, utilizzando diversi linguaggi, strumenti e tecnologie. sono compresi degli strumenti per scrivere il codice, modificarlo e analizzarlo; per trasformare il codice in codice eseguibile, verificarne la correttezza, eseguirlo passo passo o tutto d'un fiato.

Uno IDE è una sorta di collante che aiuta lo sviluppatore a mantenere consistente il proprio lavoro, ed allo stesso tempo permette di ignorare alcuni dettagli necessari alla produzione di software. è certamente possibile scrivere, costruire ed eseguire del software senza alcun IDE di supporto. In effetti, una volta non esistevano gli ambienti integrati. Uno aveva un editor di testi, un compilatore, un linker e in qualche caso un loader. Nei casi fortunati, c'era anche un debugger. Un editor serve per scrivere il programma in uno dei linguaggi noti di programmazione. Un compilatore trasforma il testo scritto in linguaggio macchina, producendo quel che si dice file oggetto. Un linker si preoccupa di raccogliere tutti i file oggetto pertinenti all'applicazione, aggiungerci un po' di librerie e produrre un unico file, l'eseguibile. Il loader serve quando l'eseguibile deve essere lanciato in esecuzione; nella maggior parte dei casi tale funzione è svolta dal sistema operativo. Non sempre le cose funzionano al primo colpo, per cui si usa un debugger, ovvero un programma che, facendo le veci del loader e dell'ambiente operativo, manda in esecuzione l'applicazione permettendo di eseguire una istruzione alla volta e verificare cosa sta succedendo. Tutta questa sequenza di operazioni era organizzata a mano, utilizzando tipicamente programmi funzionanti tramite linea di comando, ricorrendo a convenzioni più o meno arbitrarie e stratagemmi assortiti. Poi sono arrivate le interfacce grafiche e gli ambienti integrati di sviluppo, ed il mondo non è stato più lo stesso.

Aggiungo qualche parola per chi fosse in confusione con i termini compilazione e linking. Come è noto, un calcolatore capisce solo di numeri. Per far eseguire delle operazioni ad un calcolatore, occorre impartirgli istruzioni nel così detto Linguaggio Macchina (che altro non è una opportuna sequenza di numeri). Il primo passo per rendere comprensibile il tutto ad un essere umano è il linguaggio Assembler; questo è un metodo per scrivere istruzioni macchina in formato testo. Il programma Assemblatore non fa altro che tradurre parola per parola le istruzioni assembler in linguaggio macchina (c'è un rapporto uno ad uno tra le istruzioni in linguaggio assembler e le istruzioni in linguaggio macchina). Un secondo passo è di scrivere le istruzioni in un linguaggio di alto livello, ad esempio, il C. Una volta scritto un programma in C, occorre trasformare le istruzioni C in linguaggio macchina; è il compito del compilatore (questa volta ad una singola istruzione C corrispondono generalmente più e molte istruzioni in linguaggio macchina). L'ho fatta troppo facile: in realtà il linguaggio macchina crudo non può essere eseguito; occorre effettuare una operazione detta appunto di linking (effettuata dal linker), che aggiusta tutto il linguaggio macchina e produce una applicazione eseguibile. È ancora tutto molto semplificato (e a volte anche impreciso), ma per il momento basta così.

Con l'avvento dell'interfaccia grafica totale globale, la linea di comando non era più di moda, per cui si è dovuti per forza passare a strumenti per lo sviluppo che non ragionassero più a linea di comando; per fare questo, è nato il concetto di progetto, già presente anche prima, ma non così esplicito. Un progetto è la collezione di tutti i file che partecipano, a vario titolo, alla costruzione dell'applicazione. L'elenco dei file, che prima era scritto su un foglio di carta di fianco allo schermo a fosfori verdi, adesso è scritto esplicitamente su una finestra a video. Non solo, ma anche le relazioni tra gli stessi file, in pratica tutte le direttive ai compilatori, al linker (quali librerie utilizzare, e perché) e al debugger sono presentate a video, in un file che non contiene altro che riferimenti ad altro file, appunto il file di progetto.

Una volta che tutte queste operazioni possono essere svolte attraverso una interfaccia grafica, ecco che nasce l'ambiente integrato di sviluppo. La cosa bizzarra è che, a parte qualche caso isolato, non è che sia cambiato molto (i programmatori sono fondamentalmente dei conservatori: conosco persone che preferiscono lavorare a linea di comando perché dicono essere più veloci a scrivere un comando piuttosto che fare selezionare una voce di menu). L'ambiente integrato di sviluppo non è altro che un modo elegante di lanciare in esecuzione un editor di testi, per compilare un dato file, per linkare tra loro tutti i file oggetto. Ma, sotto sotto, il lavoro sporco è ancora svolto utilizzando linee di comando.

Arrivando alla fine di questa storia edificante, riassumo dicendo che XCode (ma in generale ogni IDE) non è altro che una comoda interfaccia grafica per il processo di sviluppo di una applicazione: invece di avere anche fare con diversi file sparsi nelle cartelle, XCode permette di raccogliere in un unico posto ed in forma elettronica l'elenco dei documenti che concorrono alla costruzione di una applicazione (sì, anche i documenti di progetto e di help); a partire da questi file, mattoni base dell'applicazione, si indicano le operazioni che devono essere svolte per la produzione dell'applicazione stessa, quindi sono specificate le operazioni di compilazione e di linking; fornisce inoltre supporto per la trattazione dei testi tramite un editor, la documentazione di progetto, con la possibilità di costruire un dizionario dei simboli, facilitando la ricerca di informazioni, e per finire supporta il debugging dell'applicazione con qualcosa in più che lanciare in esecuzione il programma di debugging. Con intuitivi comandi impartiti tramite mouse (ed anche con la tastiera per quelli più noiosi) si possono ristrutturare i legami in maniera semplice e veloce, eseguire operazioni complesse con un clic, cose del genere.

Ma, occorre ribadirlo, XCode non fa quasi alcunché del lavoro grosso. XCode non compila, XCode non costruisce interfacce grafiche, XCode non lancia in esecuzione l'applicazione, XCode non permette di "debuggare" una applicazione. Piuttosto, si appoggia a compilatori esterni per compilare applicazioni, a debugger esterni per eseguire le applicazioni una istruzione alla volta; il tutto, però eseguito in maniera integrata, tanto che non ci si accorge del passaggio tra uno strumento ed un altro.

Gli XCode Tool sono un insieme di strumenti forniti direttamente da Apple. L'installazione del sistema (o qualunque versione pre-installata dello stesso) NON include gli XCode Tools. Si può controllare facilmente se sono già presenti o meno: basta verificare se esiste la cartella Developer al livello principale del disco. Se esiste, è verosimile che l'installazione abbia già avuto luogo. Se non esiste, o se volete essere sicuri di installare le ultime versioni disponibili, ci sono due strategie: utilizzate il CD/DVD di installazione del sistema, dove sono sempre riportati, oppure scaricarli dalla rete. Nel primo caso, avete una comoda e veloce possibilità di procedere, ma non siete sicuri di avere l'ultima versione disponibile. Nel secondo caso, preparatevi ad una lunga attesa (l'ultima volta che ho li ho scaricati, erano di più di 900 Mega).

Apple distribuisce gratuitamente gli XCode Tools. Occore solamente registrarsi presso la Apple Developer Connection. Ci sono diverse opzioni; la più semplice è appunto gratuita e non vi da altri diritti se non scaricare dalla rete gratuitamente l'ambiente di sviluppo ed altri file interessanti.

Se non avete una connessione di rete veloce o un amico compiacente, e vi accontentate della versione presente nei dischi del sistema operativo, l'installazione è molto semplice. Nel mio caso (10.4) ho due DVD. Inserendo il primo, Sui dischi si trova una cartella chiamata XCode Tools, all'interno della quale c'è il file XCodeTools.mpkg. Doppio clic, e parte una procedura di installazione. Le opzioni di default sono sufficienti ad installare una versione correttamente funzionante di XCode.

Una volta installata, l'applicazione XCode vera e propria si trova nella cartella /Developer/Applications della partizione che contiene il sistema operativo. Per mia comodità, ho trascinato l'icona di Xcode sul dock, in modo da averlo sempre ad un clic di distanza.

L'installazione di default inserisce anche tutta (ehm, non credo, ma comunque, una gran parte) la documentazione necessaria per lo sviluppo delle applicazioni. Ancora una volta, la versione più aggiornata si trova in rete, ma XCode non mancherà di avvertirvi (nel caso abbiate una connessione ad internet attiva) che è disponibile un aggiornamento della documentazione stessa.

Prima di aprire l'applicazione, ci sono tre concetti da imparare: Progetto, Target, Eseguibile (Project, Target, Executable).

Il Progetto è il costrutto base di XCode: è la raccolta di tutti i documenti relativi ad un particolare progetto di programmazione. Sono compresi i file sorgente (nei vari linguaggi), le risorse che descrivono l'interfaccia grafica, le librerie, i file di help, eccetera. Un documento di XCode è un progetto.

Ogni progetto possiede uno o più obiettivi di realizzazione, i Target; l'obiettivo di un progetto è appunto di produrre qualcosa, ed il target rappresenta questo qualcosa. Un target è definito da una serie di regole per la costruzione dell'applicazione; queste regole indicano, ad esempio, quali file utilizzare per la compilazione, in che ordine, come assemblarli tra loro, eccetera. Ci sono dei casi molto semplici (un file, una applicazione), ma questi sono la norma solo nei primi passi di un programmatore. Generalmente si finisce con l'avere un sacco di file da gestire, ciascuno con le proprie regole. L'insieme di tutte queste regole è appunto un target. Uno stesso progetto può avere diversi target, perché i prodotti finali a cui si può arrivare sono più d'uno. Ad esempio, all'interno di un singolo progetto di programmazione possono trovare luogo diverse realizzazioni, ad esempio una applicazione stand-alone, un plug-in, un comando da eseguire attraverso il terminale, eccetera.

Infine, associato ad ogni Target c'è un eseguibile, ovvero l'applicazione che deve essere lanciata in esecuzione per verificare l'effetto delle operazioni di sviluppo. Normalmente, c'è una associazione diretta tra il target e lo executable, ovvero tra ciò che è stato prodotto dalle operazioni di costruzione dell'applicazione e ciò che si va ad eseguire. Non sempre è così: ci sono dei casi speciali in cui il target non è direttamente eseguibile (ad esempio, un salvaschermo o un pannello delle preferenze). In questi casi, lo Executable è un'altra applicazione (che andrà scelta a mano dal programmatore).

La Finestra di XCode

Ora che abbiamo un'idea di cosa aspettarci, lanciamo XCode e vediamo cosa salta fuori.

figura 01

figura 01

Vedo già il primo problema non appena richiedo tramite menu la creazione di un nuovo progetto. Mi si presenta una finestra con un elenco piuttosto corposo di opzioni.

Cominciare con un progetto interamente vuoto mi pare uno spreco, però riconosco che la maggior parte delle voci non ho idea (beh, non esageriamo, posso fare ipotesi serie...) di cosa siano.

Lo scopo finale sarà costruire una Cocoa Document-based Application, presumendo di passare attraverso una più semplice Cocoa Application, saltando a pie' pari Bundle, Framework e Kernel Extension (per non parlare delle altre cose scritte in Java). Sono interessato anche alla famiglia dei Tool, che presumo essere applicazioni funzionanti a linea di comando o anche meno. Per il momento ignoro tutto il resto e comincio con uno Standard Tool, che mi ispira essere un semplice programma a linea di comando scritto in C.

Infatti.

Dopo aver dato un nome opportuno al progetto (mc007, usando parche quantità di fantasia), quello che salta fuori è un template con il programma 'Ciao Mondo' caro a tutti i programmatori in erba. Un template è il nome comune di uno scheletro precostituito sul quale poi intervenire modificando le parti di interesse.

figura 04

figura 04

Vediamo più da vicino la finestra del progetto (che potrebbe differire dalla vostra a causa di diverse versioni di XCode, o semplice personalizzazione dell'interfaccia).

Sulla sinistra c'è una colonna chiamata Group & Files. In cima c'è il progetto, all'interno del quale sono compresi i vari file che gli appartengono. Questi sono organizzati attraverso una serie di cartelle. Attenzione che l'organizzazione non è necessariamente quella dei file sul disco rigido, anzi, generalmente è diversa. Oltretutto, si tratta di collegamenti, i file esistono al di fuori di XCode, ed ogni modifica con altri mezzi esterni a XCode si riflette all'interno di XCode. Facendo doppio clic su uno di questi elementi, si apre un editor adatto al tipo di file.

Gli altri gruppi di elementi (mi veniva da scrivere oggetti, ma adesso questa bella parola generica che era oggetti bisogna riservarla agli oggetti della programmazione OOP) sono chiamati Smart Groups e sono di natura diversa; in comune hanno il fatto che sono organizzati in maniera automatica e che si aggiornano per riflettere lo stato del progetto. I gruppi più importanti sono il gruppo che raccoglie i Target del progetto e quello degli Executables. Gli altri gruppi (che possono anche non essere presenti, in dipendenza della configurabilità di XCode) raccolgono informazioni relative al progetto: l'elenco degli errori di compilazione, i risultati delle operazioni di ricerca, segnalibri, eccetera.

Il contenuto del resto della finestra dipende dalla selezione operata nella colonna di destra. Ad esempio, selezionando il progetto, la finestra è divisa in due parti (magari si deve ridimensionare il pannello): in quella superiore sono riportati i file del progetto, e nella parte inferiore, selezionando uno di questi file, si presenta (se disponibile) un editor per quel tipo di file.

L'editor di testo è senz'altro quello più utilizzato per la scrittura dei programmi. Si tratta di un onesto editor di testo, con le tipiche caratteristiche di un editor per programmazione; caratteristica interessante (ma effettive su macchine con adeguati processori) è l'autocompletamento: cominciando a scrivere il nome di un metodo o funzione, l'editor propone una serie di alternative possibili, suggerendo anche la sintassi. L'editor può aprirsi all'interno della finestra principale, o anche su una finestra a parte; è anche possibile scegliere un editor esterno.

Per completare (si fa per dire) l'esplorazione iniziale, rimangono da considerare i menu e le icone presenti all'interno della finestra principale. Queste icone duplicano alcune funzioni disponibili sui menu, quindi non ne parlerò molto. Tra i menu, ci sono i soliti File, Edit, Format e Find, che servono alle operazioni base sui file, alla manipolazione del testo e le funzioni accessorie. C'è poi il menu View, che serve a riarrangiare le viste all'interno delle finestre, ed il menu Windows seleziona le finestre stesse. I tre menu più importanti sono Project, Build e Debug. Con il menu Project si gestisce il progetto: ci sono comandi per aggiungere e togliere file (la riorganizzazione si fa facile con drag'n'drop), e per configurare i target e gli executable (e le build phases, che al momento ignoro). Con il menu Build si passa all'esecuzione delel regole, e quindi alla trasformazione del progetto in un eseguibile: ci sono i vari comandi per compilare, linkare e debuggare. Questo si svolge all'interno del menu Debug, che è molto più vivace quando è attivo il debugger (che, per chi sa, è gdb con una facciata in stile Macintosh). Ignoro i menu Design e SCM (che è piuttosto scarno), e ricordo l'esistenza del menu Help, che apre le pagine dello help di XCode, ma anche dell'intera documentazione Apple su Cocoa (e Carbon e tutto il resto).

Come dicevo, i pulsanti all'interno della finestra duplicano molte voci del menu, e la cui descrizione puntuale ci porterebbe troppo lontano; potete giocarci un po', oppure consultare il manuale di XCode, che vi spiegherà con ogni dettaglio la funzione di tutto.

Scrivo il programma

Tutto ciò è molto nebuloso, quindi vediamo in pratica come operare. Abbiamo già pronto, perché il template ce lo ha fornito, un file sorgente main.c; si tratta del solito programma 'ciao mondo' che è tradizione scrivere la prima volta che si accede ad un nuovo ambiente di sviluppo. Possiamo fare delle modifiche, siamo all'interno di file dove scrivere istruzioni C, quindi possiamo fare qualche semplice modifica qui e li. Per provare meglio ambienti in cui è possibile utilizzare la linea di comando, per tradizione scrivo ciao mondo tante volte quante indicate da un parametro di linea di comando.

Scriverò quindi il seguente programma, piuttosto stupido:

#include <stdio.h>

int main (int argc, const char * argv[])
{
    short    i, num;
    
    if ( argc != 2 )
    {
        printf("Uso: mc007 num \n\tdove num e' il numero di ripetizioni\n");
        exit( 0 ) ;
    }
    num = atoi( argv[1]);
    for ( i = 0; i < num ; i ++ )
        printf("Ciao mondo (%d-sima volta)\n", i+1);
    return 0;
}

Fatto questo, procedo a compilare il file, o meglio, a fare il Build dell'intero progetto. La procedura di build consiste nell'insieme delel operazioni di compilazione dei file sorgente, seguita poi dall'operazione di linking. C'è un apposito comando di menu, oppure l'icona con un martello.

Non sembra che l'operazione renda felice XCode; vado a vedere la finestra di Build, in cui sono riportate appunto le informazioni per la compilazione ed il linking.

figura 99

figura 99

Il succo della faccenda è che il file main.c è compilato, e sono riportati tre warning (qualcosa di molto meno grave di un errore, che non impedisce in linea di principio il funzionamento del programma, ma che io, paranoico come sono, non accetto nella maniera più assoluta) che riguarda, ad esempio, la dichiarazione della funzione atoi, da me usata ma mai dichiarata (e tanto meno definita). atoi, come tutti sanno, è una funzione che trasforma il contenuto di una stringa in un numero intero, ed è una classica funzione di libreria del linguaggio C.

Il warning è riportato, molto pulitamente, nel pannello superiore. Nella finestra di mezzo lo stesso warning è evidenziato attraverso i messaggi tipici (e criptici) del compilatore, mentre nel terzo pannello è visualizzato il codice sorgente. Facendo clic sul messaggio di zarning warning, nella finestra del codice sorgente è evidenziata la riga che offende il compilatore.

Sciocco che sono, ho dimenticato di includere il file stdlib.h; vado a correggere il file main.c, aggiungendo coma seconda riga l'ulteriore direttiva

    #include <stdlib.h>

e ricompilo. Perfetto, nemmeno un warning (ed in effetti, anche gli altri due warning dipendendo dalla mancata inclusione del file).

Siamo pronti per lanciare in esecuzione il programma. Si utilizza il comando Run Executable o l'icona equivalente (un tondo verde con triangolo nero interno, non presente nella mia configurazione, ma che potete comodamente inserire nella toolbar). Si apre la finestra Run Log, e all'interno compare la seguente scritta:

Uso: mc007 num
    dove num e' il numero di ripetizioni

mc007 has exited with status 0.

Sembra sbagliato, ma in realtà è giusto. Non avendo passato alcun parametro al programma, il programma ha stampato il messaggio di avvertimento su come usarlo, e non ha fatto altro.

Per usare la linea di comando, bisogna aprire il Terminale, ed andare a ragionare con la linea di comando. Bene, cercate Terminale nella applicazioni, lanciatelo, e portatevi, pieni di buona volontà, nella directory corretta. La mia (il mio utente è djzero00, il vostro non lo so) è la seguente

/Users/djzero00/Documents/macProg/devTest/mc007

figura 98

figura 98

La directory parte dal posto dove avete detto di conservare il progetto (per me, mc007), e scende ulteriormente di un paio di livelli, dentro la cartella build/Development, dove sono appunto conservati i risultati della compilazione.

Ciò che ci interessa è l'eseguibile mc007. Per lanciare in esecuzione il programma, si tratta di fare semplicemente mc007. Lo faccio, e non funziona... (salta fuori mc007: Command not found.) Ah, per forza, il path non è corretto. Scrivo

./mc007 3

e tutto funziona.

figura 97

figura 97

Mi fermo e spiego: quando si ha a che fare con un sistema operativo che rende disponibile una linea di comando (Unix, in primis, e Dos che lo ha copiato...), molta attenzione deve essere posta sui path. Un programma è tipicamente eseguito solamente se individuato univocamente non solo dal suo nome, ma dal suo percorso completo. Ovviamente, è molto noioso scrivere ogni volta il percorso completo, per cui sono state create alcune facilitazioni; la prima facilitazione è l'individuazione di alcune cartelle in cui cercare comandi sconosciuti. Queste cartelle sono conservate nella variabile (del terminale) PATH. Potete vedere quali sono le cartelle individuate guardando il valore di questa variabile con il comando io ottengo qualcosa del genere:

DjZeroPB:~ djzero00$ echo $PATH
/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
DjZeroPB:~ djzero00$

La directory in cui si trova l'eseguibile non compare nell'elenco, quindi, niente esecuzione. Sono quindi costretto a specificare il percorso completo, ma è un po' noioso. Uso allora la seguente scorciatoia, sempre disponibile in un ambiente Unix: esiste la possibilità di indicare "il percorso in cui mi trovo adesso" attraverso il carattere "." (solo il punto). A questo punto, scrivo solamente

./mc007 3

e tutto comincia a funzionare.

figura 02

figura 02

figura 05

figura 05

Potete provare con altri numeri, ma non otterrete nulla di più eccitante. Torniamo allora dentro XCode. Esiste un metodo per passare argomenti al programma senza dover passare attraverso il terminale: si tratta di attribuire degli ooportuni valori alle proprietà dell'eseguibile. Per farlo, si seleziona la voce Edit Active Executable mc007 dal menu Project. Si ottiene così una finestra divisa in quattro tab. Selezionando il tab Arguments, è possibile aggiungere argomenti di lancio al programma, come abbiamo fatto da linea di comando. Inserisco 4 con il pulsante +. Torno allora ad eseguire il programma. La finestra Run Log si attiva e mostra il nuovo risultato. Meraviglia.

Sono arrivato a completare uno dei passi fondamentali nell'avvicinare un nuovo ambiente operativo. Ho preparato un file nel linguaggio di programmazione, l'ho compilato, l'ho eseguito. Fatto questo, tutto il resto sono solo dettagli che si aggiungono.

Licenza Creative Commons
Eccetto dove diversamente specificato, i contenuti di questo sito sono rilasciati sotto Licenza Creative Commons.
Pagina a cura di Livio Sandel (macocoa2012@gmail.com).