16.4. Compilazione

Adesso che il software è stato configurato in maniera corretta, tutto quello che resta da fare è compilarlo. Questa fase in genere è facile, e non presenta seri problemi.

16.4.1. make

Lo strumento preferito per compilare sorgenti dalla comunità del software libero è make. Presenta due caratteristiche particolarmente interessanti:

Le azioni che devono essere eseguite per ottenere una versione compilata dei sorgenti sono conservate in un file chiamato normalmente Makefile o GNUMakefile. Quando make viene invocato, infatti, legge questo file - se esiste - nella directory corrente. Se non esiste, è sempre possibile specificare un altro file usando l'opzione -f del comando make.

16.4.2. Regole

make opera in accordo con un sistema di dipendenze. Pertanto compilare un file binario (target) richiede il completamento di una serie di passi ("dipendenze"). Ad esempio, se vogliamo creare l'ipotetico file binario glloq, i file oggetto main.o e init.o, file intermedi del processo di compilazione, devono essere compilati e collegati (linked). Questi file oggetto sono anch'essi dei risultati della compilazione, e le loro dipendenze sono i file sorgenti.

Questo testo costituisce un'introduzione minima allo scopo di sopravvivere nel mondo spietato di make. Se volete saperne di più, vi consigliamo di recarvi sul sito web di APRIL (http://www.april.org/groupes/doc/), dove troverete una documentazione su make molto più dettagliata. Per una documentazione veramente esaustiva, fate riferimento a Managing Projects with Make, seconda edizione, O'Reilly, di Andrew Oram e Steve Talbott.

16.4.3. Attenti, pronti, via!

In genere l'uso di make segue un certo numero di convenzioni. Ad esempio:

Il primo passo è quello di compilare il programma, e quindi di digitare (esempio del tutto immaginario):

$ make
gcc -c glloq.c -o glloq.o
gcc -c init.c -o init.o
gcc -c main.c -o main.o
gcc -lgtk -lgdk -lglib -lXext -lX11 -lm glloq.o init.o main.o -o glloq

Perfetto, il file binario è stato compilato in maniera corretta. Adesso siamo pronti per la fase successiva, che prevede l'installazione dei file della distribuzione (file binari, file di dati, etc.). Consultate la sezione Installazione.

16.4.4. Spiegazioni

Se la vostra curiosità vi ha spinto a dare un'occhiata al file Makefile, avrete scoperto che contiene dei comandi noti (rm, mv, cp, etc.), ma anche delle stringhe di caratteri dall'aspetto inusuale, qualcosa come $(CFLAGS).

Si tratta di variabili, cioè stringhe che normalmente si trovano all'inizio del file Makefile e vengono successivamente sostituite dal valore con il quale sono associate. Il loro uso semplifica molto le cose quando si vogliono usare le stesse opzioni di compilazione più volte nella stessa riga.

Ad esempio, per stampare su video la stringa "foo" usando il comando make all:

TEST = foo
all:
        echo $(TEST)

Nella maggior parte dei casi sono presenti le seguenti variabili:

  1. CC: indica il compilatore. In genere è cc, che nella maggioranza dei sistemi aperti è sinonimo di gcc. Se in dubbio, inserite qui gcc.

  2. LD: si tratta del programma usato per portare a termine l'ultima fase del processo di compilazione (consultate la sezione Le quattro fasi della compilazione). Come opzione predefinita, è il comando ld.

  3. CFLAGS: sono argomenti supplementari che vengono forniti al compilatore durante le prime fasi di compilazione. Fra questi:

    • -I<path>: indica al compilatore dove trovare alcuni header supplementari (-I/usr/X11R6/include, ad esempio, consente di includere gli header che si trovano nella directory /usr/X11R6/include).

    • -D<symbol>: definisce un simbolo addizionale, utile per programmi la cui compilazione dipende dai simboli definiti (ad esempio: usa il file string.h se è definito HAVE_STRING_H).

    Spesso ci sono righe di compilazione come questa:
    $(CC) $(CFLAGS) -c foo.c -o foo.o

  4. LDFLAGS (o LFLAGS): sono argomenti usati durante l'ultima fase del processo di compilazione. Fra di loro:

    • -L<path>: specifica un percorso supplementare dove cercare librerie (ad esempio: -L/usr/X11R6/lib).

    • -l<library>: specifica una libreria supplementare da usare durante l'ultima fase del processo di compilazione.

16.4.5. Cosa fare... se non funziona?

Non lasciatevi prendere dal panico, può capitare a tutti. Fra le cause di errore più comuni:

  1. glloq.c:16: decl.h: No such file or directory

    Il compilatore non è riuscito a trovare l'header corrispondente. La fase di configurazione del software, tuttavia, avrebbe dovuto prevenire questo errore. Ecco come risolvere il problema:

    • controllate che l'header in questione esista realmente sul disco in una delle seguenti directory: /usr/include, /usr/local/include, /usr/X11R6/include, oppure una delle loro sotto-directory. Se così non fosse, cercatelo su tutto il disco rigido, con il comando find o locate), e, se ancora non riusciste a trovarlo, accertatevi di aver installato la libreria corrispondente. Troverete esempi relativi ai comandi find e locate nelle loro rispettive pagine di manuale.

    • controllate che l'header in questione sia accessibile in lettura: digitate less <percorso>/<file>.h per esserne sicuri.

    • se si trova in una directory come /usr/local/include o /usr/X11R6/include, può essere necessario aggiungere un nuovo argomento al compilatore: aprite il file Makefile corrispondente (fate attenzione e aprite il file giusto, nella directory dove si è interrotto il processo di compilazione [1]) con il vostro editor di testi preferito (Emacs, VI, etc.). Cercate la riga incriminata, e aggiungete la stringa -I<percorso> - dove <percorso> è il percorso che indica dove può essere trovato l'header in questione - subito dopo il punto in cui viene invocato il compilatore (gcc, o $(CC), a volte). Se non sapete dove aggiungere questa opzione, inseritela all'inizio del file, dopo CFLAGS=<qualcosa> o dopo CC=<qualcosa>.

    • lanciate make ancora una volta e, se si interrompe di nuovo, controllate che questa opzione (si veda il punto precedente) sia stata aggiunta durante la compilazione sulla riga in questione.

    • se ancora non funziona, chiedete aiuto al vostro guru locale, oppure rivolgetevi alla comunità del software libero per risolvere il vostro problema (consultate la sezione Supporto tecnico).

  2. glloq.c:28: `struct foo' undeclared (first use this function)

    Le strutture sono particolari tipi di dato usati da tutti i programmi. Un gran numero di strutture vengono definite dal sistema negli header: il messaggio significa che il problema è sicuramente causato da un header mancante o usato in modo inappropriato. La procedura corretta per risolvere il problema è la seguente:

    • cercate di accertare se la struttura in questione è definita nel programma o dal sistema. Un metodo possibile è l'impiego del comando grep per controllare se la struttura è stata definita in uno degli header.

      Ad esempio, quando siete nella directory principale della distribuzione digitate:

      $ find . -name '*.h'| xargs grep 'struct foo' | less

      È possibile che sullo schermo compaiano un gran numero di righe di testo (una per ogni volta che è definita una funzione che fa uso di questo tipo di struttura, ad esempio). Se esiste, trovate la riga dove è definita la struttura esaminando il file header che avete individuato usando il comando grep.

      La definizione di una struttura è:

      struct foo {
            <contenuto della struttura>
      };

      Controllate che corrisponda con quanto avete trovato: se le cose stanno così, questo significa che l'header non è incluso nel file .c difettoso. Ci sono due soluzioni:

      • aggiungete la riga #include "<filename>.h" all'inizio del file .c difettoso.

      • oppure fate un copia-incolla della definizione della struttura all'inizio di questo file (non è proprio elegante, ma per lo meno dovrebbe funzionare).

    • Se invece non corrisponde, fate la stessa cosa con i file header di sistema (che in genere si trovano nelle directory /usr/include, /usr/X11R6/include, o /usr/local/include). Ma stavolta usate la riga #include <<filename>.h>.

    • Se questa struttura risulta ancora non esistente, cercate di scoprire in quale libreria (ovvero un set di funzioni riunito in un unico pacchetto) dovrebbe essere definita: controllate nel file INSTALL o README quali sono le librerie usate dal programma, e il numero di versione richiesto. Se la versione di cui ha bisogno il programma non è quella installata sul vostro sistema, aggiornate la libreria in questione.

    • Se, malgrado tutto, ancora non funziona, accertatevi che il programma funzioni correttamente con la vostra architettura (alcuni programmi non sono stati ancora portati su tutti i sistemi Unix). Controllate anche di aver correttamente configurato il programma (quando avete lanciato configure, ad esempio) per la vostra architettura.

  3. parse error

    Si tratta di un problema piuttosto complicato da risolvere, in quanto spesso l'errore appare relativamente a una certa riga, ma dopo che il compilatore l'ha incontrato. Talvolta si tratta semplicemente di un tipo di dati non definito. Se incontrate un messaggio d'errore come:

    main.c:1: parse error before `glloq_t
    main.c:1: warning: data definition has no type or storage class

    allora il problema sta nel fatto che il tipo glloq_t non è stato definito. La soluzione è più o meno la stessa che per il problema precedente.

    Nota

    potrebbe esserci un parse error nelle vecchie librerie curses, se la memoria non m'inganna.

  4. no space left on device

    Questo è un problema che può essere risolto facilmente: non è rimasto spazio sufficiente sul disco rigido per generare un file binario a partire dai sorgenti. La soluzione consiste nel liberare una quantità di spazio sufficiente nella partizione che contiene la directory di installazione (cancellate file temporanei o directory di sorgenti, disinstallate i programmi che non utilizzate). Se avete decompresso quest'ultima in /tmp, fatelo piuttosto in /usr/local/src, in modo da evitare di riempire inutilmente la partizione /tmp. Controllate, inoltre, se vi sono file core> sul vostro disco. In caso affermativo, cancellateli, o fateli cancellare se appartengono a un altro utente.

  5. /usr/bin/ld: cannot open -lglloq: No such file or directory

    Questo significa, come avrete capito, che il programma ld (usato da gcc durante l'ultima fase del processo di compilazione) non riesce a trovare una libreria. Per includere una libreria, ld cerca un file il cui nome si trova negli argomenti del tipo -l<library>. Questo file è lib<library>.so, se ld non riesce a trovarlo, produce un messaggio d'errore. Per risolvere il problema, seguite i passi descritti qui di seguito:

    1. Controllate che il file sia presente sul disco rigido usando il comando locate. Le librerie grafiche si trovano, in genere, in /usr/X11R6/lib. Ad esempio:

      $ locate libglloq

      Se questa ricerca non è fruttuosa, potete effettuarne un'altra usando il comando find (ad esempio: find /usr -name libglloq.so*). Se proprio non riuscite a trovare la libreria, vuol dire che non è presente sul vostro sistema e dunque dovrete installarla.

    2. Una volta localizzata la libreria, accertatevi che ld possa accedervi: il file /etc/ld.so.conf specifica dove potrà trovare queste librerie: aggiungete il percorso della libreria incriminata al termine del file (è possibile che si debba riavviare il computer perché questa modifica venga recepita dal sistema). Potete anche aggiungere la stessa directory modificando il contenuto della variabile d'ambiente LD_LIBRARY_PATH: se la directory da aggiungere è /usr/X11R6/lib, ad esempio, digitate:

      export \ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/X11R6/lib

      (se la vostra shell è Bash).

    3. Se ancora non funziona, accertatevi che il formato della libreria sia quello di un file eseguibile (cioè ELF) usando il comando file. Se si tratta di un link (noto anche come collegamento) simbolico, controllate che il link sia valido e che non punti a un file inesistente (ad esempio con il comando nm libglloq.so). I permessi potrebbero essere errati, ad esempio se usate un account che non sia root, oppure se la libreria è protetta in lettura.

  6. glloq.c(.text+0x34): undefined reference to `glloq_init'

    Il problema riguarda un simbolo che non è stato risolto durante l'ultima fase del processo di compilazione. Si tratta, in genere, di problemi dovuti alle librerie. Le cause possono essere molteplici:

    • la prima cosa da fare è sapere se il simbolo dovrebbe trovarsi in una libreria. Ad esempio, se si tratta di un simbolo che comincia con gtk, appartiene alla libreria gtk. Se il nome della libreria non è immediatamente identificabile (frobnicate_foobar), potete elencare i simboli di una libreria usando il comando nm. Ad esempio,

      $ nm libglloq.so
      0000000000109df0 d glloq_message_func
      000000000010a984 b glloq_msg
      0000000000008a58 t glloq_nearest_pow
      0000000000109dd8 d glloq_free_list
      0000000000109cf8 d glloq_mem_chunk

      Aggiungendo l'opzione -o al comando nm permette di stampare il nome della libreria su ogni riga, il che facilita la ricerca. Supponiamo di dover trovare il simbolo bulgroz_max, una soluzione brutale ma efficace è effettuare una ricerca come:

      $ nm /usr/lib/lib*.so | grep bulgroz_max
      $ nm /usr/X11R6/lib/lib*.so | grep bulgroz_max
      $ nm /usr/local/lib/lib*.so | grep bulgroz_max
      /usr/local/lib/libfrobnicate.so:000000000004d848 T bulgroz_max

      Perfetto! Il simbolo bulgroz_max viene definito nella libreria frobnicate (la lettera maiuscola T si trova davanti al suo nome). A questo punto non dovete fare altro che aggiungere -lfrobnicate nella riga di compilazione modificando il file Makefile: inserite questa stringa al termine della riga in cui vengono definite le variabili LDFLAGS o LFGLAGS (oppure CC, nel peggiore dei casi), o nella riga che corrisponde alla creazione del file binario.

    • la compilazione viene effettuata con una versione della libreria che non è quella richiesta dal software. Leggete il file README o INSTALL della distribuzione per sapere qual è la versione che dev'essere usata.

    • non tutti i file oggetto della distribuzione sono linkati correttamente. Il file dove viene definita questa funzione è assente. Digitate nm -o *.o per sapere di quale file si tratta e aggiunge il file .o corrispondente sulla riga di compilazione se è assente.

    • la funzione o variabile causa del problema forse non esiste. Cercate di cancellarla: modificate il file sorgente in questione (il suo nome viene indicato all'inizio del messaggio di errore). Si tratta di una soluzione disperata, che avrà come sicura conseguenza un funzionamento "anarchico" del software (segfault all'avvio, etc.).

  7. Segmentation fault (core dumped)

    Talvolta il compilatore si pianta in modo deplorevole, e produce questo messaggio d'errore. Non possiamo darvi altro consiglio se non quello di installare una versione più recente.

  8. spazio esaurito su /tmp

    La compilazione necessita di uno spazio di lavoro temporaneo durante le sue diverse fasi: se questo spazio non è disponibile, non viene portata a termine con successo. È quindi necessario ripulire la partizione, ma state attenti ad alcuni programmi in esecuzione (il server X, delle pipe, etc.) che potrebbero piantarsi se vengono cancellati alcuni dei file temporanei: dovete sapere quello che state facendo! Se /tmp fa parte di una partizione che contiene altro (ad esempio la directory radice), cercate e cancellate eventuali file di tipo core.

  9. make/configure in ricorsione infinita

    Molto spesso si tratta di un problema relativo al tempo sul vostro sistema. make, infatti, ha bisogno di conoscere la data fornita dall'orologio di sistema e la data dei file che controlla. Compara le date e usa il risultato per sapere se il bersaglio è più recente rispetto alla dipendenza.

    Alcuni problemi di data possono indurre make a costruire se stesso in maniera ricorsiva, senza interruzioni (o a costruire e costruire di nuovo un sotto-albero in ricorsione infinita). In tal caso, l'uso del comando touch (il cui scopo qui è di aggiornare i file in questione all'ora corrente) in genere risolve questo problema.

    Ad esempio:

    $ touch *

    O anche (più rozzo, ma efficace):

    $ find . | xargs touch

Note

[1]

Analizzate il messaggio di errore restituito da make. Le ultime righe, in genere, contengono il nome di una directory (sono messaggi simili a questo: make[1]: Leaving directory `/home/benj/Project/foo'). Scegliete la riga con il numero più alto e spostatevi nella directory indicata: per essere sicuri che sia quella giusta, lanciate di nuovo make per ottenere lo stesso messaggio di errore.


Tux on Star from MandrakeSoft Linux è un marchio registrato di Linus Torvalds. Tutti gli altri marchi e copyright appartengono ai rispettivi proprietari.
Se non diversamente specificato, i diritti di tutto il contenuto di queste pagine e di tutte le immagini sono proprietà di MandrakeSoft S.A. e MandrakeSoft Inc. 2000.
http://www.linux-mandrake.com/