Sistema Provvisorio
In questa sezione verrà mostrato come costruire (compilare ed installare) un sistema Linux ridotto all'osso, che conterrà solo strumenti sufficienti per iniziare a costruire il sistema LFS finale della sezione successiva (n.6) permettendo, nello stesso tempo, un ambiente di lavoro più agevole.
L'obiettivo verrà raggiunto in due fasi:
- 1 - Costruzione di una nuova toolchain indipendente dal computer ospite (compilatore, assemblatore, linker, librerie e qualche altro tool).
- 2 - Usare la toolchain, appena creata, per costruire gli altri tool essenziali.
I pacchetti verranno realizzati con l'aiuto della directory $LFS/unpack, dove saranno momentaneamente scompattati e compilati, e verranno poi installati nella directory $LFS/tools per tenerli separati sia dai file installati nella prossima sezione sia dalle directory dell'host. Questo per evitare che i pacchetti compilati, che sono puramente temporanei, finiscano per inquinare il nascente sistema LFS.
In questa sezione verranno anche spiegati alcuni dettagli tecnici e logici delle metodologie di costruzione adottate, ma non è essenziale adesso la loro piena comprensione. La maggior parte di queste informazioni sarà più chiara dopo aver eseguito qualche compilazione e, in ogni caso, si potranno sempre rivedere queste annotazioni.
L'obiettivo principale adesso è quello di produrre, in un'area provvisoria, una buona parte degli strumenti necessari in modo che rimangano isolati dal sistema ospite. Utilizzando quindi il chroot, nelle sezioni successive, verranno generati i rimanenti comandi sempre all'interno di questo ambiente, garantendo che il sistema LFS finale sia privo di errori e non inquinato. Questo processo di generazione è stato progettato con il doppio intento di minimizzare i rischi per i nuovi sperimentatori e di avere un alto valore istruttivo.
Prima di continuare bisogna conoscere:
Chiarimenti sul meccanismo di funzionamento della costruzione
- Cambiando leggermente il nome della piattaforma di lavoro, modificando il campo vendor della tripletta target tramite la variabile LFS_TGT, ci si assicura che con la prima compilazione di Binutils e GCC vengano prodotti un cross-linker compatibile ed un cross-compilatore. Invece di produrre binari per un'altra architettura, il cross-linker ed il cross-compilatore produrranno binari compatibili con l'hardware corrente.
- Le librerie temporanee sono cross-compilate. Poiché un cross-compilatore per sua natura non può contare su niente del suo sistema ospite, questo metodo rimuove alla radice potenziali contaminazioni del sistema in costruzione riducendo la probabilità che header o librerie dell'host possano essere incorporati nei nuovi strumenti. La cross-compilazione consente inoltre la possibilità di costruire librerie a 32 o a 64 bit su hardware a 64 bit.
- Un attenta manipolazione del sorgente GCC per dire al compilatore quale linker dinamico verrà usato
Scaletta delle installazioni
- 1 - Verranno installate per prime le binutils perché il file configure eseguito sia da GCC sia da Glibc effettua vari tipi di test sull'assemblatore e sul linker per determinare quali caratteristiche del software abilitare e disabilitare. Ciò è molto più importante di quanto uno possa pensare all'inizio. Una configurazione non corretta di GCC o di Glibc può condurre ad una toolchain solo apparentemente non corrotta, ma i cui effetti negativi potrebbero evidenziarsi anche al termine della costruzione dell'intera distribuzione. Il fallimento di una suite di test può evidenziare questa situazione di errore in tempo utile per evitare di avanzare ulteriormente nel lavoro.
Le binutils installano il loro assemblatore ed il linker in due locazioni: /tools/bin e /tools/$LFS_TGT/bin. I tool in ogni locazione sono collegati stabilmente agli altri. Un aspetto importante del linker è l'ordine di ricerca delle librerie. Si possono ottenere da ld informazioni dettagliate passandogli il flag --verbose. Ad esempio, un
ld --verbose | grep SEARCH
illustrerà i percorsi di ricerca correnti ed il loro ordine. Compilando un programma dummy e passando lo switch --verbose al linker esso mostrerà quali file vengono linkati da ld. Ad esempio:
gcc dummy.c -Wl,--verbose 2>&1 | grep succeeded
mostrerà tutti i file aperti con successo durante la fase di link.
- 2 - Subito dopo verrà installato il pacchetto GCC. Di seguito viene riportato un esempio di ciò che si può vedere durante l'esecuzione del suo configure:
checking what assembler to use... /tools/i686-lfs-linux-gnu/bin/as
checking what linker to use... /tools/i686-lfs-linux-gnu/bin/ld
Ciò è importante per le ragioni sopra menzionate, e dimostra anche che lo script di configurazione di GCC non cerca le directory del PATH per trovare quali tool usare. Tuttavia, durante le correnti operazioni dello stesso gcc non vengono necessariamente usati gli stessi percorsi di ricerca. Per scoprire quale linker standard sarà usato da gcc bisogna eseguire:
gcc -print-prog-name=ld
Quando viene compilato un programma dummy, passando a gcc l'opzione -v da linea di comando, possono essere ottenute informazioni dettagliate; ad esempio:
gcc -v dummy.c
mostrerà informazioni dettagliate riguardanti preprocessore, compilazione, e fase di assemblaggio, inclusi i percorsi di ricerca usati da gcc ed il loro ordine.
- 3 - A seguire verranno installati degli header affidabili (sanitized) delle API di Linux, e questo consentirà alle librerie C standard (Glibc) di interfacciarsi con elementi sicuri forniti dallo stesso kernel Linux.
- 4 - Quindi sarà la volta di Glibc. Le considerazioni più importanti per costruire Glibc riguardano il compilatore, i tool binari e gli header del kernel. Il compilatore normalmente non costituisce un problema perché Glibc userà sempre il compilatore relativo al parametro --host passato al suo script di configurazione, nel nostro caso i686-LFS-linux-gnu-gcc. I tool binari e gli header del kernel possono essere un po' più complicati. Pertanto per non correre rischi si utilizzino gli switch di configurazione disponibili per effettuare le scelte corrette. Dopo l'esecuzione di configure, verificare i contenuti del file config.make nella directory glibc-build per esaminare tutti i dettagli. Notare l'uso di CC="i686-lfs-gnu-gcc" per controllare quali tool binari vengono usati e l'uso dei flag -nostdinc e -isystem per controllare il percorso di ricerca dell'include del compilatore. Queste cose mettono in evidenza un importante aspetto del pacchetto Glibc: è veramente autosufficiente nella costituzione del suo motore interno e generalmente non si basa sui default della toolchain.
- 5 - Durante il secondo step di binutils avremo la possibilità di utilizzare l'opzione --with-lib-path di configure per controllare il percorso di ricerca delle librerie di ld.
- 6 - Durante il secondo step di GCC bisognerà modificare i suoi sorgenti per fargli sapere di utilizzare il nuovo linker dinamico. In caso contrario avverrà che gli stessi programmi GCC avranno il nome del linker dinamico della directory /lib del sistema ospite incluso dentro, cosa che vanificherebbe l'obiettivo di diventare indipendente dall'host.
Da questo punto in poi, il nucleo della toolchain diviene autocontenuta e si auto-ospita. I rimanenti pacchetti della sezione n.5 verranno costruiti tutti con la nuova Glibc in /tools.
- 7 - Una volta entrati nell'ambiente chroot, nella sezione n.6, il primo grosso pacchetto che verrà installato sarà Glibc, a causa della sua natura auto-sufficiente menzionata prima. Una volta installato Glibc in /usr, effettueremo un rapido cambio dei default della toolchain, e quindi si procederà nella costruzione del resto del sistema LFS.
Istruzioni generali di installazione
Quando si costruiscono i pacchetti ci sono diverse considerazioni da fare:
- Molti pacchetti vengono patchati prima della compilazione, ma solo quando la patch è necessaria per aggirare un problema. Spesso una patch sarà necessaria sia in questa sia nella prossima sezione, talvolta solo in una delle due. D'altra parte, non ci si deve preoccupare se sembra che non ci siano le istruzioni per una delle patch scaricate. Applicando una patch ci si può imbattere in messaggi di avvertimento riguardanti offset o fuzz. Questi warning non sono nulla di cui preoccuparsi, in quanto la patch è stata applicata con successo.
- Durante la compilazione di molti pacchetti, ci saranno molti warning che scorreranno sullo schermo. Sono fatti normali, e possono essere ignorati senza problemi. Questi i tipi di avviso che possono apparire: avvisi riguardanti l'uso deprecato, ma non invalidante, della sintassi C o C++. Gli standard C cambiano piuttosto spesso e certi pacchetti usano ancora lo standard precedente. Questo non è un problema, ma fa scattare la comparsa dell'avviso.
- Controllare un'ultima volta che la variabile d'ambiente LFS sia impostata correttamente:
echo $LFS
Verificando che l'output mostri il percorso del punto di mount della partizione, che è /mnt/lfs, nel nostro caso.
- E, infine, devono esere sottolineate 2 cose importanti:
Le istruzioni per la costruzione presuppongono che siano soddisfatti i prerequisiti indicati nella sezione n.1, inclusi i link simbolici indicati:
- bash sia la shell in uso.
- sh sia un link simbolico a bash.
- /usr/bin/awk sia un link simbolico a gawk.
- /usr/bin/yacc sia un link simbolico a bison oppure uno script che esegua bison.
Ogni processo di build sarà realizzato con lo schema seguente:
- 1 - Sistemare tutto il materiale scaricato (sorgenti e patch) in una directory che sarà accessibile dall'ambiente chroot. E' stata predisposta, allo scopo, /mnt/lfs/sources/. Evitare tassativamente di depositare sorgenti in /mnt/lfs/tools/
- 2 - Spostarsi nella directory dei sorgenti.
- 3 - Per ogni pacchetto procedere come segue:
- a - Cancellare tutto il contenuto della directory /mnt/lfs/sources/unpack/
- b - Come utente lfs, estrarre il pacchetto da costruire usando il programma tar e scaricando il materiale in /mnt/lfs/unpack/
- c - Spostarsi nella cartella /mnt/lfs/sources/unpack/
- d - Seguire le istruzioni per la costruzione, fornite per ciascun pacchetto.
- e - Ritornare nella cartella dei sorgenti: /mnt/lfs/sources/
Comportarsi diversamente solo se viene indicato esplicitamente.