Compilare sorgenti

di felipe

Le varie distribuzioni di Linux stanno diventando sempre più “facili”, la configurazione e il riconoscimento dell’hardware sono sempre più automatizzati all’installazione e quasi sempre una “ventina” di minuti dopo aver fatto il boot da CD-ROM l’utente si trova con un sistema già funzionante (anche se non sempre ottimizzato). In molti casi la stessa facilità di configurazione si riscontra anche dopo aver installato il tutto, grazie a diverse procedure più o meno “user friendly”. Questo vale anche per le applicazioni, facilmente installabili con una linea di comando o con un semplice click che in realtà mettono in moto sofisticati meccanismi di pacchettizzazione e gestione di eventuali dipendenze.

I problemi semmai arrivano al momento di installare “quella applicazione BELLISSMA e UTLILISSIMA che guarda caso non c’è nel CD”. E magari con un po’ di sfortuna non si trova nemmeno su rpmfind o su linuxpackages o sui mirror più o meno ufficiali di debian… Non è un caso per niente raro: potrebbe darsi che chi sviluppa il software non abbia semplicemente rilasciato una versione in formato rpm o deb o tgz, oppure il software è troppo instabile per essere dato in pasto al pubblico meno smaliziato.

Mettiamo il caso che un tipico utente Mandrake/KDE voglia cimentarsi nella compilazione di un’applicazione presa direttamente da sourceforge o freshmeat…

Procedure preliminari

L’esempio più cretino che sono riuscito a farmi venire in mente è Kodicefiscale, una simpatica utilità che ho appena scaricato e compilato. Il nome, è ormai consuetudine, ci suggerisce che dipende dalle QT/KDE… se fosse dipesa dalle GTK/GNOME magari si sarebbe chiamata Gnodicefiscale :-)

La mia box è attualmente uno strano miscuglio basato essenzialmente su debian woody, ma questo non dovrebbe fare differenza, l’importante è che abbiate installato un compilatore, make e le librerie necessarie alla compilazione.

“Il” compilatore è GCC nelle sue diverse incarnazioni. Io uso la versione 2.95, che pur essendo un po’ datata funziona a dovere, l’ultima release del compilatore GNU è infatti la 3.2 ed è abbastanza stabile ed affidabile, ma la transizione da un compilatore ad un altro non è una cosa da prendere alla leggera… vedere oltre. L’importante è che si cerchi di evitare le serie 2.96 che si trovano nelle red-hat like di qualche tempo fa: questi infatti sono più che altro il frutto di iniziative commerciali della red-hat, hanno molti problemi e se vi rivolgete a qualcuno perchè avete qualche noia a compilare vi diranno: “cambia compilatore”. Per verificare:

$: gcc –version

ne riporta la versione.

Le altre applicazioni (sono tante) dovrebbero venire installate come dipendenze di gcc e make, se usate una distribuzione con un “packet manager” decente (rpm, urpmi, apt), sono essenzialmente librerie di sviluppo, utilità e interpreti vari. Debian ha il comodissimo “task” c-dev :)

Per quanto riguarda le librerie… ci vuole un po’ di “occhio”, di esperienza e di letture dei README inclusi nei sorgenti da compilare, almeno nel caso di non poter utilizzare le scorciatoie offerte dai gestori di pacchetti offerti dalle varie distribuzioni. Ma installiamo la nostra applicazione di esempio per vedere come si verifica la presenza delle librerie necessarie.

L’esempio

Assumo che abbiate installato gcc, make ecc. Scaricate kodicefiscale da http://apps.kde.com, recentemente ne è uscita una versione per KDE3. Io uso una directory chiamata “src” nella mia /home, quindi mi posiziono in src scompattare

$: cd /home/felipe/src

oppure:

$: cd ~/src

che è lo stesso, dal momento che il segno “~” indica la /home dell’utente. Adesso scompatto l’archivio kodicefiscale-3.0.tar.bz2 in questa directory:

$: tar jxf ../kodicefiscale-3.0.tar.bz2

perchè questo comando funzioni dovete avere installato “bzip2“, in modo da poter interagire con tar, in alcune versioni della shell bash il comando appena dato non vale, e si deve “dividere” in due tempi:

$: bunzip2 ../kodicefiscale-3.0.tar.bz2
$: tar xf ../kodicefiscale-3.0.tar

Il primo comando decomprime l’archivio, detto anche “tarball”, il secondo lo scompatta nella directory dove state lavorando (nell’esempio ~/src). Adesso è stata creata una nuova directory: kodicefiscale-3.0/, spostiamoci lì dentro e diventiamo “operativi”.

S: cd kodicefiscale-3.0/
$: ls

Il comando “ls” ci restituisce la lista di tutto ciò che è contenuto dentro la directory. Non ha importanza la dimensione o la funzione dell’applicazione che vogliamo installare, in ogni caso dobbiamo cercare un file chiamato configure. Questo file è uno script abbastanza complesso che serve a generare un’altro file chiamato Makefile, e fa questo eseguendo una serie di piccoli test per verificare che abbiate installato tutto ciò che serve per compilare l’applicazione. Per prima cosa… chiediamo aiuto!

configure
$: ./configure --help

Se usate qualcosa che non sia la shell bash (quella predefinita sui sistemi linux) potreste doverlo fare così:

$: sh configure --help

Notate come nel primo esempio per eseguire lo script configure si debba esplicitamente fare riferimento alla directory corrente usando il punto e lo slash (./). Questo comando farà sì che il vostro terminale si riempia di una sfilza di parametri che possono essere passati allo script stesso. Questi parametri dovrebbero essere tutti opzionali, e servono ad indicare ad esempio dove vorremmo installare la nostra applicazione, oppure quali eventuali parti di codice vorremmo escludere o includere. Nel nostro esempio, come in quasi tutte le applicazioni scritte per KDE, ci sono solo opzioni relative al dove, che fortuna, eh? :)

Il dove predefinito è quasi sempre /usr/local. Tanto per fare una piccola prova empirica, andate in questa directory e guardate cosa c’è dentro… vedrete un piccolo “albero” simile a quello che si trova in /usr, quindi ci sarà /usr/local/bin corrispettivo a /usr/bin, /usr/local/lib corrispettivo a /usr/lib ecc ecc.

Il motivo di questi “doppioni” è che la directory /usr dovrebbe essere riservata ai files contenuti nei pacchetti più o meno ufficiali forniti dalla distribuzione linux che usiamo, mentre /usr/local dovrebbe appunto contenere quello che il sistemista installa “in locale”. Questo consente, tra l’altro, di tenere sotto controllo la “pulizia” e l’ordine della nostra box: infatti è molto più facile controllare se ci sono dei file inutili o indesiderati in /usr/local che nei meandri di /usr

Dunque il secondo passo da fare è provare a dare il comando

$: ./configure

Senza parametri. Oppure se proprio volessimo specificare dove vogliamo installare kodicefiscale, basta usare parametri come “–prefix“. Nella mia Debian (come anche in Mandrake e RedHat), KDE è installato sotto /usr a differenza di Slackware o SuSE, che lo “mettono” in /opt/kde (dibattito infinito a proposito…). Quindi se volessi indicare a configure di installare tutto in /usr darei questo comando:

$: ./configure –prefix=/usr –mandir=/usr/share/man –infodir=/usr/share/info –sysconfdir=/etc/kde

prefix–mandir –infodir e –sysconfdir non sono necessari, li ho messi soloper indicare come si usano altri parametri, in questo caso avrei ottenuto che il “prefisso” fosse /usr, e cioè, come un qualsiasi pacchetto ufficiale,kodicefiscle avrebbe gli eseguibili in /usr/bin, librerie eventuali in /usr/libecc. Se non avessi specificato i parametri –mandir e –infodir dunque avreiinstallato le pagine di manuale e le pagine info (rispettivamente quelleche permetteranno di ottenere aiuto tramite comandi come `man kodicefiscle’ e `info kodicefiscle’) in /usr/man e /usr/info, ma la consuetudine in debian è che queste pagine di manuale vadano in /usr/share (e cmq il pacchetto in questione no ha alcuna pagina di manuale… lol). Infine il parametro –sysconfdirfa sì che qualora ci fossero dei file di configurazione, andrebberoinstallati in /etc/kde.

Adesso entriamo davvero nel “vivo” della compilazione. Configure fa i suoi controlli per impostare tutta una serie di variabili e per controllare che abbiate le librerie necessarie alla compilazione, quando finisce annota i risultati in un file chiamato Makefile.

Parabola: compilare una applicazione è un po’ come scrivere una tesi o un libro, ovviamente avrete tutti scritto dei libri, no? :) Ora immaginate le librerie come delle… librerie! Configure è il nostro… uhm “ricercatore”. Il ricercatore-configure
deve scrivere un “piano di lavoro” (ossia creare il Makefile), cioè una lista di argomenti da trattare e di librerie da consultare, partendo dal materiale che gli è stato affidato (il tarball kodicefiscale-3.0.tar.bz2) e le informazioni che può reperire a riguardo. Ovviamente nella vita reale, chi scrive i libri se ne frega se non trova informazioni *esatte*, ma il nostro ricercatore-configure se non trova quello che cerca va in confusione e vi chiede di fornirgli dell’altro materiale da poter consultare. Se vi è piaciuta la parabola del ricercatore non vi dispiacerete più di tanto se leggerete qualcosa come:

checking for Qt... configure: error: Qt (>= Qt 3.0.3) (library qt-mt)
not found. Please check your installation!
For more details about this problem, look at the end of config.log.
Make sure that you have compiled Qt with thread support!

Hehe… è soltanto il ricercatore che non trova abbastanza informazioni e non sa come interpretare del materiale. Per fortuna il problema ha già in sè la soluzione: configure vi dice che non riesce a trovare le librerie Qt, che poi sono la “base” di ogni applicazione per KDE. Vi chiederete: ma come? Se ho KDE installato non è possibile che non abbia le librerie che ne stanno alla base! La risposta è Si e
No. Ovviamente chi ha installato KDE tramite rpm o apt, ha installato anche
le Qt, ma non “tutte” le Qt.

Normalmente chi prepara (a monte) i pacchetti per le distrubuzioni tende a dividere le librerie vere e proprie dagli “includes” e cioè, seguendo la parabola, direi, dagli “indici”, dalle “bibliografie” e dai “glossari” dei libri di queste librerie. Queste istruzioni vanno normalmente in pacchetti separati che hanno in genere il suffisso “devel” oppure “dev”, cioè “development” (in italiano “sviluppo”). Quindi se noi abbiamo installato solo il pacchetto “libqt3” ad esempio, dovremo anche installare “libqt3-devel” oppure “libqt3-dev” a seconda della distribuzione.

Ovviamente bisogna fare anche attenzione alla versione richiesta da configure,
ma di questo si occupa generalmente il gestore di pacchetti della distribuzione
in uso.

Un discorso a parte in questo senso si deve fare per la Slackware. Un po’ per scelta, un po’ magari per necessità (l’assenza di un vero e proprio gestore di pacchetti che da molti è addirittura considerato uno dei tanti punti forti di questa distribuzione), in una Slackware non troverete mai dei pacchetti di sviluppo, perchè la divisione a monte non è avvenuta, quindi installando le Qt si hanno sia le librerie “runtime” sia gli includes e insomma i file necessari a compilare programmi che usano le
Qt.

Potrebbe però anche succedere che voi siate sicuri al 100% di avere installato “tutte” le Qt o comunque le librerie in questione, e allora? Beh allora potrebbero esserci una infinità di casi: se avete installato le Qt dai CD della vostra distribuzione potreste aver scaricato un tarball troppo vecchio o troppo nuovo per la vostra distribuzione, ad esempio potremmo avere scaricato la vecchia versione di kodicefiscale, che dipende dalle qt-2, mentre noi abbiamo le qt-3.

Se invece avete cercato di fare “i gradassi” e avete installato le Qt da sorgenti… non ci credo, ma se l’aveste fatto potreste aver installato le Qt in qualche posto “strano”, e adesso configure non le trova. In questo caso bisognerebbe trovare dove avete installato le Qt, e “dirlo” a configure tramite i famosi parametri che ci ha presentato il comando “./configure –help” in questo caso sarebbero qualcosa del genere:

$: ./configure –with-qt-dir=/strano/posto/lib/qt –with-qt-includes=/strano/posto/include/qt

Tenendo presente che in applicazioni basate su GTK ci saranno degli appositi parametri come: –with-gtk ecc. Comunque è solo un esempio, il più delle volte succede che si installino delle librerie in /usr/local e che questa directory non sia nel PATH di ricerca delle librerie, basta specificarlo, oppure imparare ad usare ldconfig e il relativo /etc/ld.so.conf.

Esiste anche un’altra possibilità, ed è quello che è capitato a me quando ho installato gcc-3.2: configure non vi trova le Qt (o qualsiasi altra libreria), voi siete strasicuri che sia tutto a posto, i pacchetti ci sono tutti e sono stati installati con il vostro gestore di pacchetti, e allora?!? Beh, i cambiamenti dalle vechie versioni stabili di gcc (la 2.95 per esempio) a quelle nuove sono tali che una applicazione che
si appoggia a delle librerie che sono state compilate col vecchio gcc-2.95 può non compilare col nuovo gcc-3.*… chiaro no? Beh io prima di arrivare a questa conclusione ho fatto i giri più assurdi. Risultato: cercate di usare sempre lo stesso compilatore!
Ci saranno sicuramente molti altri casi che non mi vengono in mente o che non mi sono mai capitati, ma comunque nella peggiore delle ipotesi bisogna armarsi di pazienza e installare tutto ciò che configure chiede: quasi sempre librerie aggiuntive o nuove versioni di applicazioni che già avete. Io cerco sempre di utilizzare il gestore di pacchetti finchè possibile, eventualmente scaricando i sorgenti “debianizzati” (ci sono anche sorgenti “rpmizzati”, quelli che finiscono con src.rpm) in modo da poter compilare pur mantenendo una certa conformità installando poi il tutto con rpm o dpkg. Alla fine si dovrebbe arrivare ad ottenere che configure finisca di fare i suoi controlli con successo e crei alcuni file necessari a proseguire
la compilazione, soprattutto il Makefile, che sarà poi processato da make per la compilazione vera e propria.

Casi particolari

Spesso capita di scaricare sorgenti di applicazioni che non hanno nemmeno lo script configure… In tal caso possiamo essere di fronte a:

  • Applicazioni moldo modeste in termini di dimensioni e richieste, per cui l’intero processo di compilazione si riduce al comando make che nel giro di alcuni secondi dovrebbe creare un eseguibile.
  • Sorgenti scaricati da CVS. Questo è un sistema molto comune usato per sviluppare progetti che si avvalgono di più programmatori ed è usato direttamente da chi vuole le ultimissime novità di una determinata applicazione. Le versioni CVS sono generalmente molto instabili e dovrebbero essere usate solo da chi ha mooolta più pazienza :)Generalmente lo script configure in questi casi manca, ma al suo posto si trova quasi sempre
    qualcosa come cvscompile o autogen.sh, che servono appunto a creare, tra le altre cose, lo script configure, alcuni di questi piccoli script accettano anche i parametri di configure, per cui non è raro poter fare qualcosa come:

    $: ./autogen.sh --help

    Per creare lo script configure e avere allo stesso tempo la lista dei parametri passabili. Se non dovessero esserci nemmeno cvscompile e autogen.sh potrebbe essere necessario compilare usando dei Makefile già pronti con comandi come:

    make -f Makefile.cvs

    o cose del genere, per tutti questi casi è comunque indispensabile leggere SEMPRE e COMUNQUE i vari file README. INSTALL, BUGS ecc ecc. Spesso la soluzione sta proprio dove più ce la si aspetta :)

Casi particolari a parte, una volta completato il configure sarebbe buona norma dare una controllata al file Makefile, ma se si è alle prima armi non credo possa essere di molto aiuto… Non ci resta che dare il fatidico comando:

$: make

Il più delle volte, make si limita a premiare la vostra pazienza dimostrata armeggiando con configure, e quindi a compilare senza ulteriori intoppi. Make processa il file Makefile alla ricerca delle istruzioni generate da configure, essenzialmente richiamando il compilatore con i vari “flags” del caso per operare sui singoli file scritti in vari linguaggi leggibili dall’uomo (per la cornaca kodicefiscale è scritto in C++, come tutto KDE) per “tradurli” in linguaggio macchina.

make
Make produce davvero tanto “output”, nel senso che per una applicazione semplice come kodicefiscale avrete per alcuni minuti il terminate pieno di messaggi. Non è il massimo della vita, lo so, ma sarebbe utile dare un’occhio a quei messaggi, perchè in mezzo al mucchio potrebbero esserci degli errori più o meno gravi. Alcuni errori molto comuni, imputabili a svariate cause, sono i “WARNING”, che avvisano di questa o quella imperfezione, ma ci possono essere errori più gravi, tali anche da bloccare la compilazione restituendo: Error. Triste.
Anche qui comunque c’è un margine di speranza, se proprio non è un “bug”, un errore del codice, potrebbe essere dovuto a qualche libreria che dovrebbe essere aggiornata, o a qualche gioco azzardato compiuto in passato in fatto di librerie, con versioni che vanno in conflitto ecc ecc.

Generalmente comunque make finisce il suo lavoro con il simpatico messaggio di nothing to be done, e questo significa che ha generato tutto ciò che c’era da generare con successo. In questo momento avete già l’eseguibile bell’e pronto, e tranne per alcuni casi, i programmi più semplici possono essere fatti girare anche senza essere installati nelle varie directory finali, come nel nostro caso.

kubrick
Ma siccome non è bello lasciare le cose a metà finiamo la procedura con un bel:

$: make install

Che provvederà a copiare i vari file nelle directory indicate a partire dalla radice che avevamo indicato col parametro –prefix a configure. Fatto. Kodicefiscale è installato e come vedete funziona più che bene. Veramente ci sarebbe qualcosa da ridire sul fatto che lo sviluppatore non abbia rispettato alla lettera il “design” standard delle applicazioni Qt, mi riferisco soprattutto alle dimensioni dei pulsanti, al testo in grassetto… per il resto è carino :)

Ci sono una serie di altri parametri che si possono dare al comando make, elenco i più usati:

  • make clean – elimina tutti i file creati con make, utile se vogliamo ripetere il processo per qualche motivo;
  • make distclean – elimina tutti file creati da make E quelli creati da configure, in pratica riporta le cose allo stato in cui erano quando avete spacchettato l’archivio;
  • make uninstall – oops, avete sbagliato qualcosa? kodicefiscale non vi piace? questo comando cancella i file dalle directory in cui sono stati installati.

Tutti i vari comandi di make non hanno senso se non sono stati preceduti da configure. Per cui se avete installato un’applicazione e dopo aver rimosso i sorgenti volete disinstallarla usando make uninstall, dovrete

  • rispacchettare il tarball in una directory qualsiasi;
  • dare il configure con parametri identici a quelli che avete dato quando avete installato (almeno per quanto riguarda i vari –prefix in cui installare);
  • e solo dopo dare make uninstall.

Conclusioni

Non si finisce mai di imparare (tanto per mantenere il tono biblico-parabolico…) e quindi l’esperienza è tutto, compilare i programmi è un modo per ottenere il massimo dal proprio computer, e quindi ci sono tante altre cose da sapere e tanti accorgimenti da adottare, a forza di man si scoprono tutti :)

Quello che ho scritto fin qui vale per tutte le distribuzioni linux, e anche per gli altri sistemi operativi unix-like, fatte le dovute eccezioni… comunque spero che la prossima volta che leggerete in un README qualcosa come

./configure
make
make install

saprete che c’è molto di più, per fortuna!

9 pensieri su “Compilare sorgenti

  1. Felipe, sai niente se esiste un programma che in qualche modo risolve le dipendenze mentre si compila?

  2. Ma dici che vada? Nel forum stiamo abbozzando un programmino e servirebbe qualcosa che andasse almeno una volta su due…

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...