Äîêóìåíò âçÿò èç êýøà ïîèñêîâîé ìàøèíû. Àäðåñ îðèãèíàëüíîãî äîêóìåíòà : http://www.arcetri.astro.it/irlab/doc/library/linux/AppLinux/al15.htm
Äàòà èçìåíåíèÿ: Tue Sep 21 18:08:32 1999
Äàòà èíäåêñèðîâàíèÿ: Sat Dec 22 13:20:58 2007
Êîäèðîâêà:

Ïîèñêîâûå ñëîâà: ï ï ð ð ð ð ð ð ï ï ï ï ï ï ï ï
Appunti Linux: Applicativi distribuiti in forma sorgente o compilata [inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]

10. Applicativi distribuiti in forma sorgente o compilata

La maggior parte dei programmi per Unix il cui utilizzo viene concesso gratuitamente, viene distribuita in forma sorgente. CiÐ significa che per poterli utilizzare, questi programmi devono essere compilati. Fortunatamente, nella maggior parte dei sistemi Unix Õ disponibile il compilatore ANSI C GNU che permette di uniformare questo procedimento di compilazione.

Alcuni programmi vengono distribuiti in forma giÞ compilata (e senza sorgenti) soprattutto quando si tratta di prodotti commerciali. Anche in questi casi si possono incontrare problemi nell'installazione.

In generale, i problemi che derivano dall'installazione di questi applicativi nasce dalla mancanza di sostegno da parte del sistema di gestione dei pacchetti della propria distribuzione GNU/Linux.

10.1 Struttura tipica di un pacchetto sorgente

Un programma distribuito in forma sorgente si trova di solito confezionato in un archivio il cui nome ha un'estensione .tar.gz o .tgz (ottenuto attraverso tar e gzip), oppure ancora con un'estensione .tar.bz2 (tar e bzip2). Prima di poter procedere con la sua compilazione deve essere estratto il suo contenuto. Solitamente si fa questo in una directory di lavoro. Nell'esempio che segue, si fa riferimento a un pacchetto ipotetico archiviato nel file pacch.tar.gz:

cd ~/tmp

tar xzvf pacch.tar.gz

Se invece si trattasse dell'archivio pacch.tar.bz2, sarebbe stato necessario decomprimerlo attraverso un comando un po' piÛ complesso:

cd ~/tmp

cat pacch.tar.bz2 | bunzip2 | tar xvf -

Di solito si ottiene una struttura ad albero piÛ o meno articolata in sottodirectory, e nella directory principale di questa struttura si trovano:

Seguendo l'esempio visto poco prima, dovrebbe essere stata creata la directory pacch/.

cd pacch

ls

10.1.1 Documentazione necessaria alla compilazione

I file di testo che si trovano nella directory principale del pacchetto contenente il programma sorgente, servono per presentare brevemente il programma e per riassumere le istruzioni necessarie alla sua compilazione. Di solito, queste ultime sono contenute nel file INSTALL. In ogni caso, tutti questi file vanno letti, in particolare quello che spiega il procedimento per la compilazione e l'installazione.

Il modo piÛ semplice per leggere un file Õ l'utilizzo del programma less, o in sua mancanza di more.

less README

less INSTALL

10.1.2 ./configure

La composizione classica di un pacchetto distribuito in forma sorgente, prevede la presenza di uno script il cui scopo Õ quello di costruire un file-make adatto all'ambiente in cui si vuole compilare il programma. CiÐ Õ necessario perchÈ i vari sistemi Unix sono diversi tra loro per tanti piccoli dettagli.

Spesso questo script Õ in grado di accettare argomenti. CiÐ puÐ permettere, per esempio, di definire una directory di destinazione del programma, diversa da quella predefinita.

Quando questo script di preparazione manca, occorre modificare manualmente il file-make in modo che sia predisposto correttamente per la compilazione nel proprio sistema.

Per evitare ambiguitÞ, questo script viene sempre avviato indicando un percorso preciso, e cioÕ ./configure.

10.1.3 File-make

Il file-make, o makefile, Õ quel file che viene letto da Make, precisamente dall'eseguibile make, e serve per coordinare le varie fasi della compilazione ed eventualmente anche per l'installazione del programma compilato. Il nome di questo file puÐ essere diverso, generalmente si tratta di Makefile, oppure di makefile.

Questo file viene generato frequentemente da uno script, di solito si tratta di ./configure, ma se manca deve essere controllato e, se necessario, modificato prima della compilazione.

Spesso Õ bene controllare il contenuto del file-make anche quando questo Õ stato generato automaticamente.

10.2 Fasi tipiche di una compilazione e installazione

I pacchetti piÛ comuni si compilano e si installano con tre semplici operazioni.

./configure

Genera automaticamente il file-make.

make

Esegue la compilazione generando i file eseguibili.

make install

Installa gli eseguibili e gli altri file necessari nella loro destinazione prevista per il funzionamento: l'ultima fase deve essere eseguita con i privilegi dell'utente root.

10.3 Problemi

Le note di questo capitolo valgono solo in linea di massima: Õ sempre indispensabile leggere le istruzioni che si trovano nei file di testo distribuiti insieme ai sorgenti dei programmi.

I problemi maggiori si hanno quando non Õ stato predisposto uno script ./configure o simile, e si Õ costretti a modificare il file-make.

In altri casi, il file-make potrebbe non prevedere la fase di installazione (make install), per cui si deve installare il programma copiando pezzo per pezzo nella destinazione giusta.

Spesso l'installazione non rispetta la struttura standard del proprio filesystem. CiÐ nel senso che magari vengono piazzati file che devono poter essere modificati, all'interno di una zona che si voleva riservare in sola lettura.

Quando si utilizza una distribuzione GNU/Linux ben organizzata, si trova una gestione dei pacchetti installati che permette l'eliminazione e l'aggiornamento di questi senza rischiare di lasciare file inutilizzati in giro. Quando si installa un programma distribuito in forma originale, viene a mancare questo supporto della gestione dei pacchetti. In questi casi si cerca di installare tali pacchetti al di sotto della directory /opt/, o almeno al di sotto di /usr/local/.

10.4 Installazione di programmi giÞ compilati

L'installazione di programmi giÞ compilati per GNU/Linux, anche se potrebbe sembrare piÛ semplice rispetto a un procedimento che richiede la compilazione, potrebbe creare qualche problema a chi non conosce perfettamente l'interdipendenza che c'Õ tra le varie parti del sistema operativo.

I problemi e le soluzioni che si descrivono nelle sezioni seguenti, riguardano a volte anche i programmi distribuiti in forma sorgente. Infatti, alcune volte, i programmi distribuiti in questo modo non sono stati preparati per un'installazione soddisfacente, di conseguenza bisogna provvedere da soli a collocare i file nelle posizioni corrette e a sistemare tutto quello che serve.

10.4.1 Scelta della piattaforma

Quando si cerca del software per il proprio sistema che puÐ essere ottenuto solo in forma giÞ compilata, occorre fare attenzione alla piattaforma. Infatti, non basta che si tratti di programmi compilati per GNU/Linux, occorre che gli eseguibili siano adatti al tipo di elaboratore su cui GNU/Linux Õ in funzione.

Normalmente, per identificare l'architettura dei «PC», si utilizza la sigla i386 nel nome dei file degli archivi.

10.4.2 Eseguibili e variabili di ambiente

Un programma distribuito in forma binaria, deve essere estratto normalmente dall'archivio compresso che lo contiene. A volte Õ disponibile uno script o un programma di installazione, altre volte Õ necessario copiare manualmente i file nelle varie destinazioni finali. Quando si puÐ scegliere, Õ preferibile collocare tutto quanto a partire da un'unica directory discendente da /opt/.

A volte, perchÈ il programma possa funzionare Õ necessario predisporre o modificare il contenuto di alcune variabili di ambiente. Il caso piÛ comune Õ costituito da PATH che deve (o dovrebbe) contenere anche il percorso necessario ad avviare il nuovo programma. Spesso, i file di documentazione che accompagnano il software indicano chiaramente tutte le variabili che devono essere presenti durante il loro funzionamento.

La dichiarazione di queste variabili puÐ essere collocata direttamente in uno dei file di configurazione della shell utilizzata (per esempio /etc/profile, oppure ~/.bash_profile o altri ancora a seconda di come Õ organizzato il proprio sistema).

10.4.3 Librerie dinamiche

Alcuni programmi utilizzano delle librerie non standard, e spesso queste vengono collocate al di fuori delle directory standard predisposte per contenerle. Per fare in modo che queste librerie risultino disponibili, ci sono due modi possibili:

  1. modificare la configurazione di /etc/ld.so.cache;

  2. utilizzare la variabile di ambiente LD_LIBRARY_PATH.

Per agire secondo la prima possibilitÞ, occorre prima comprendere come sia organizzato questo sistema. Il file /etc/ld.so.cache viene creato a partire da /etc/ld.so.conf che contiene semplicemente un elenco di directory destinate a contenere librerie. Il programma ldconfig serve proprio a ricreare il file /etc/ld.so.cache leggendo /etc/ld.so.conf, e per questo viene avviato solitamente dalla stessa procedura di inizializzazione del sistema, per garantire che questo file sia sempre aggiornato.

Dovrebbe essere chiaro, ormai, il modo giusto di includere nuovi percorsi di librerie nel file /etc/ld.so.cache: occorre indicare questa o queste directory nel file /etc/ld.so.conf e quindi basta avviare il programma ldconfig.

L'utilizzo della variabile di ambiente LD_LIBRARY_PATH Õ meno impegnativo, e soprattutto puÐ essere modificato facilmente attraverso dei semplici script. CiÐ permette, per esempio, di fare in modo che solo un certo programma «veda» certe librerie. In ogni caso, quando si intende usare questa variabile di ambiente, Õ importante ricordare di includere tra i vari percorsi anche quelli standard: /lib/, /usr/lib/ e /usr/local/lib/. L'esempio seguente rappresenta un pezzo di uno script (potrebbe trattarsi di /etc/profile) in cui viene assegnata la variabile di ambiente in questione.

LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/opt/mio_prog/lib:/opt/tuo_prog/lib
export LD_LIBRARY_PATH

Se un certo programma richiede determinate librerie che potrebbero entrare in conflitto con altri programmi, Õ indispensabile l'utilizzo della variabile di ambiente LD_LIBRARY_PATH, configurandola esclusivamente nell'ambito del processo di quel programma. In pratica, si tratta di avviare il programma attraverso uno script che genera l'ambiente adatto, in modo che non si rifletta negli altri processi, come mostrato nell'esempio seguente:

#! /bin/sh

# modifica il percorso di ricerca delle librerie
LD_LIBRARY_PATH="/opt/mio_programma/lib:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH

# avvia il programma
mio_programma

# al termine dello script non resta traccia

Avviando lo script, viene modificata la variabile di ambiente LD_LIBRARY_PATH per quel processo e per i suoi discendenti (viene esportata), quindi, al termine del programma termina anche lo script, e con lui anche gli effetti di queste modifiche.

Si osservi in particolare il fatto che nella nuova definizione del percorso delle librerie, viene posto all'inizio quello per le librerie specifiche del programma, in modo che venga utilizzato per primo; subito dopo, viene inserito l'elenco dei percorsi eventualmente giÞ esistente.

10.4.4 $ ldd

ldd [<opzioni>] <programma>...

ldd emette l'elenco delle librerie condivise richieste dai programmi indicati come argomenti della riga di comando. Si utilizza ldd per determinare le dipendenze di uno o piÛ programmi dalle librerie.

Esempi

ldd /bin/bash[Invio]

	libncurses.so.4 => /usr/lib/libncurses.so.4 (0x40000000)
	libdl.so.1 => /lib/libdl.so.1.7.14 (0x40045000)
	libc.so.5 => /lib/libc.so.5.4.38 (0x40048000)

L'esempio mostra le dipendenze dalle librerie di /bin/bash. Il risultato ottenuto indica il nome delle librerie e la collocazione effettiva nel sistema, risolvendo anche eventuali collegamenti simbolici.

10.5 File di differenze, o patch

Quando si ha a che fare con programmi il cui aggiornamento Õ frequente, come avviene nel caso del kernel, si possono anche trovare aggiornamenti in forma di file di differenze (patch), cioÕ di file che contengono solo le variazioni da una versione all'altra. Queste variazioni si applicano ai file di una versione per ottenerne un'altra.

Se la versione da aggiornare Õ stata espansa a partire dall'ipotetica directory ~/tmp/, per applicarvi una modifica, sarÞ necessario posizionarsi sulla stessa directory e poi eseguire il comando seguente:

patch < <file-di-differenze>

PuÐ darsi che la posizione in cui ci si deve trovare sia diversa o che i sorgenti da aggiornare debbano trovarsi in una posizione precisa. Per capirlo, dovrebbe bastare l'osservazione diretta del contenuto del file di differenze.

L'applicazione delle variazioni, puÐ fallire. Se non si vuole perdere il rapporto degli errori, questi possono essere ridiretti in un file specifico.

patch < <file-di-differenze> 2> <file-degli-errori>

Se gli aggiornamenti sono piÛ d'uno, occorre applicare le modifiche in sequenza.

Il capitolo 58 tratta meglio questo problema.

10.6 Aggiornamento delle librerie standard

Oltre al problema delle librerie specifiche di un programma particolare, cosa giÞ descritta in questo capitolo, ci puÐ essere la necessitÞ di aggiornare le librerie standard di GNU/Linux a seguito di qualche aggiornamento di altro software.

Normalmente, la propria distribuzione GNU/Linux dovrebbe offrire questi aggiornamenti in forma di archivi giÞ pronti, installabili attraverso li proprio sistema di gestione dei pacchetti. CiÐ garantendo la sistemazione di una serie di dettagli importanti.

Quando si Õ costretti a fare da soli Õ importante fare attenzione. In particolare, quando si interviene in ciÐ che risiede nella directory /lib/, se si commette un errore, si rischia di bloccare il sistema senza possibilitÞ di rimedio.

I file delle librerie sono organizzati normalmente con un numero di versione piuttosto articolato. Quando ciÐ accade, Õ normale che a questi file siano affiancati una serie di collegamenti simbolici strutturati in modo che si possa accedere a quelle librerie anche attraverso l'indicazione di versioni meno dettagliate, oppure semplicemente attraverso nomi differenti. Questi collegamenti sono molto importanti perchÈ ci sono dei programmi che dipendono da questi; quando si aggiorna una libreria, occorre affiancare la nuova versione a quella vecchia, e quindi si devono modificare questi collegamenti. Solo alla fine, sperando che tutto sia andato bene, si puÐ eliminare eventualmente il vecchio file di libreria.

Per fare un esempio pratico, si suppone di disporre della libreria libc.so.9.8.7, articolata nel modo seguente:

libc.so -> libc.so.9
libc.so.9 -> libc.so.9.8.7
libc.so.9.8.7

Volendo sostituire questa libreria con la versione 9.8.10, il cui file ha il nome libc.so.9.8.10, occorre procedere come segue:

ln -s -f libc.so.9.8.10 libc.so.9

Come si vede, per generare il collegamento, Õ stato necessario utilizzare l'opzione -f che permette di sovrascrivere il collegamento preesistente. Infatti, non sarebbe stato possibile elimiare prima il collegamento vecchio, perchÈ cosË si sarebbe rischiato il blocco del sistema.

libc.so -> libc.so.9
libc.so.9 -> libc.so.9.8.10
libc.so.9.8.7
libc.so.9.8.10

In generale, per sicurezza, Õ meglio lasciare le librerie vecchie, perchÈ ci potrebbero essere ugualmente dei programmi che ne hanno ancora bisogno.

Quando la libreria da aggiornare ha subito un aggiornamento molto importante, per cui i numeri delle versioni sono molto distanti rispetto a quanto si utilizzava prima, conviene evitare di sostituirle, mentre Õ solo il caso di affiancarle. Volendo ritornate all'esempio precedente, si puÐ supporre che la libreria da aggiornare sia arrivata alla versione 10.1.1, con il file libc.so.10.1.1. Intuitivamente si comprende che il collegamento simbolico libc.so.9 non puÐ puntare a questa nuova libreria, mentre resta il dubbio per libc.so.

In generale Õ meglio lasciare stare le cose come sono, a meno di scoprire che qualche programma cerca proprio la libreria libc.so e si lamenta perchÈ non si tratta della versione adatta a lui. Comunque, sempre seguendo l'esempio, sarebbe il caso di riprodurre un collegamento equivalente a libc.so.9, denominato ovviamente libc.so.10.

libc.so -> libc.so.9
libc.so.9 -> libc.so.9.8.7
libc.so.9.8.7
libc.so.10 -> libc.so.10.1.1
libc.so.10.1.1

10.7 Riferimenti

---------------------------

Appunti Linux 1999.09.21 --- Copyright © 1997-1999 Daniele Giacomini --  daniele @ pluto.linux.it


[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]