In questa sezione cercherò di descrive come soddisfare l'esigenza di ogni programmatore: quella di giungere ad un'applicazione binaria, modificando i sorgenti di Glade e compilandoli.
Nonostante questo obiettivo non tratterò le problematiche inerenti a risolvere gli errori di compilazione e le eventuali dipendenze che é necessario soddisfare per poter compilare i sorgenti. Le persone che incorrono in questi problemi possono fare riferimento ai testi adeguati, normalmente disponibili nei siti dei vari pacchetti utilizzati o sulle mailing-list di supporto ad essi.
Per modificare i sorgenti generati da Glade e non incappare in brutte sorprese occorre prima capire come questo si comporta rispetto ad essi, leggendo la sezione "Come funziona Glade", poiché esso sovrascrive alcuni files.
Ogni widget può emettere diversi segnali il compito di catturarli compete ad un signal-handler, il quale per quanto interessa a questo documento può essere trattato come una funzione che viene chiamata dal motore GTK+ al momento opportuno.
Brevemente posso aggiungere che il motore GTK+ sa quali funzioni chiamare perché Glade si occupa, usando la funzione gtk_signal_connect( ) di connettere il segnale alla funzione. Glade scrive questo codice nel file interface.c .
Selezionato un widget di cui si vuole catturare un segnale occorre visualizzare la finestra "Proprietà: widget" e muoversi sulla sezione "Segnali".
In questa sezione viene mostrata una lista dei segnali e dei relativi signal-handlers che li catturano: la prima volta risulterà vuota.
Vi sono poi dei campi da completare ma di norma basta selezionare il segnale usando il combo menù detto etichettato con "Segnali". Premendo il tasto [...] comparirà una finestra che contiene solo i segnali che il widget selezionato é in grado di emettere: uno di questi deve essere selezionato e poi si preme il tasto [OK].
Ad esempio: nel caso di un bottone si può scegliere il segnale "clicked" e alla pressione del tasto [OK] si ritorna automaticamente alla finestra "Proprietà: button1" e si vede che Glade suggerisce anche il nome del gestore del segnale (ad es.: "on_button1_clicked"). Premendo il tasto [Aggiungi] si aggiunge il segnale e il suo gestore nella lista sopra citata.
A questo punto il segnale é creato e si può eliminare o modificare selezionandolo nella lista e premendo rispettivamente i bottoni [Cancella] e [Elimina].
Premesso di aver creato un signal-handler mediante Glade occorre fargli scrivere i sorgenti premendo il tasto "Crea eseguibile" nella finestra principale.
Con questa operazione Glade modifica i files interface.c e callbacks.c [16], sempre che si siano scelti i nomi di default.
Rifacendosi all'esempio precedente del bottone nel file callbacs.c viene generata una funzione vuota (cioé priva di codice all'interno) simile alla seguente:
void on_button1_clicked (GtkButton *button, gpointer user_data) { }
Il nome del gestore che avevate abbinato al segnale di quel widget diventa il nome della funzione.
La funzione rende disponibile al suo interno anche alcune variabili:
Riempire il corpo della funzione é un compito che comunque spetta al programmatore.
Quando un programmatore ha scritto i sorgenti dell'applicazione ha ancora due passaggi da compiere:
In ambito Linux esistono dei pacchetti atti a ridurre queste procedure a semplici routine: automake e autoconfigure.
Glade fa uso dei pacchetti automake e autoconfigure mettendo in grado il programmatore, che abbia soddisfatto le dipendenze fra i pacchetti e abbia installato le librerie necessarie [19], di compilare immediatamente il suo prodotto. Ovviamente errori di editing del codice a parte ;-)
Questo é utile al programmatore (specialmente al programmatore alle prime armi che altrimenti si troverebbe ad affrontare molte problematiche tutte assieme e potrebbe rimanerne scoraggiato) per ben due motivi:
Il primo punto é evidente, il secondo può esserlo meno. Si deve tenere conto che é auspicabile che molti dei progetti sviluppati con Glade siano OpenSource. Questo significa che molti utenti (anche inesperti di programmazione) potrebbero desiderare un binario compilato per la loro distribuzione oppure per la loro piattaforma.
Anche un utente tutto sommato a digiuno di programmazione potrebbe essere indotto per necessità a modificare i sorgenti, ad esempio per cambiare la stringa di inizializzazione del modem (in fondo si tratta di editare un #define o poco più ;-) ma poi si troverebbe di fronte al problema di ottenere il binario eseguibile [19].
Il fatto che Glade minimizzi la procedura di compilazione/linking aiuta enormemente il programmatore OpenSource che almeno all'inizio non si trova costretto di occuparsi di questi particolari e può immediatamente rilasciare.
Per compilare un progetto occorre scendere in riga di comando e mediante il comando cd (change directory) posizionarsi nella directory del progetto (che di certo conoscete perché é scritta nelle opzioni del progetto e Glade non vi permette di Salvare il progetto senza prima passare da quella finestra):
$ ./autogen.sh [ invio ] $ make [ invio ]
La prima istruzione é necessaria solo la prima volta che si compila il progetto.
Il binario, se tutto va per il verso giusto, si trova all'interno dell'albero del progetto nella directory che di default é chiamata src.
Di default il binario ha il nome del progetto e si esegue, lanciandolo dalla cima dell'albero del progetto, in questo modo:
$ src/nome_progetto [ invio ]
Se il risultato vi soddisfa potrete anche installare il progetto sul sistema ma per farlo dovete avere i permessi di root:
$ su root[ invio ] <password> [ invio ] # make install [ invio ] # exit [ invio ]
Una volta che si é installato il progetto il binario dovrebbe essere in path ed accessibile ad ogni utente.
Molto del lavoro si riduce a riempire/modificare il corpo dei signal-handler ma crescendo di dimensioni potreste trovare scomodo mantenere tutti i signal-handlers nel solo files callbacks.c: spezzare questo file oppure aggiungere altri files contenenti le vostre funzioni potrebbe diventare ben presto un'esigenza.
Un modo davvero semplice, senza doversi preoccupare di editare i makefiles, per aggiungere un file di sorgente (con relativo header) può essere quello di includere tale file (oltre all'header, dopo di esso) nel main.c:
... #include "miofile.h" #include "miofile.c" void main( ) { ...
Il vantaggio di questa procedura, tutto sommato poco ortodossa, é quello di evitare di modificare i makefiles che vengono gestiti, almeno in maniera indiretta, da Glade:
La modularizzazione dei sorgenti in vari files aiuta il programmatore ad orientarsi fra essi ed a circoscrivere gli errori di compilazione/editazione. Un secondo vantaggio é quello di poter compilare solo il modulo editato, con risparmio di tempo, e non tutti i sorgenti del progetto. Il modulo, editato e compilato, verrà poi linkato agli altri moduli originali.
Includere files sorgenti nel main.c ha lo svantaggio di ricompilare tutti i moduli inclusi e non soltanto quello editato.
Per progetti inferiori alle 5000 righe di codice la perdita di tempo durante la compilazione rispetto alla modifica del makefiles é tutto sommato vantaggiosa, fino alle 10000 righe può ancora essere tollerata se la macchina che compila é veloce.
Oltre le 20000 righe di codice é auspicabile che il programmatore sappia risolversi il problema dei makefiles e abbia scelto un linguaggio ad oggetti, come il C++, piuttosto che uno procedurale come il C.
Mi rendo conto che alcuni esperti/puristi, specialmente in leggendo questa sezione, abbiano avuto modo di storcere il naso 8*) per via delle soluzioni forse troppo semplicistiche fornite.
Posso solo scusarmi, ringraziandoli di aver letto un documento che evidentemente non era indirizzato a loro ma un target più "popolare" e rinnovando il mio impegno ad evolvermi fino a poter soddisfare anche i palati più fini ;-)