Come vengono avviati GCC e g ++?


186

Questo mi ha infastidito per un po '. Come si compilano GCC e g ++?

Immagino che ogni revisione venga compilata con una revisione precedentemente costruita. È vero? E se lo è, significa che le versioni più vecchie di g ++ e GCC sono state scritte in assembly?


13
Ogni revisione può finalmente essere compilata da sola. :)
Martin Hennings,

4
Questo è interessante da leggere se vuoi vedere come sono nati i primi compilatori.
Parkovski,

1
@parkovski Il link è morto?
Nubcake,

Link visto l'ultima volta il 4 giugno 2016: web.archive.org/web/20160604035203/homepage.ntlworld.com/…
akraf

Risposte:


175

La versione più vecchia di GCC è stata compilata usando un altro compilatore C, poiché ce n'erano altri quando è stato scritto. Il primissimo compilatore C di sempre (circa 1973, IIRC) fu implementato nell'assembly PDP-11 , o nel linguaggio di programmazione B che lo precedeva, ma in ogni caso il compilatore B fu scritto in assembly.Allo stesso modo, il primo compilatore C ++ in assoluto (CPre / Cfront , 1979-1983) fu probabilmente implementato prima in C, quindi riscritto in C ++.

Quando compili GCC o qualsiasi altro compilatore self-hosting, l'intero ordine di costruzione è:

  1. Crea una nuova versione di GCC con il compilatore C esistente
  2. ricostruisci la nuova versione di GCC con quella che hai appena creato
  3. (facoltativo) ripetere il passaggio 2 a scopo di verifica.

Questo processo si chiama bootstrap . Verifica la capacità del compilatore di compilare se stesso e si assicura che il compilatore risultante sia costruito con tutte le ottimizzazioni implementate da solo.

EDIT : Drew Dormann, nei commenti, indica il resoconto di Bjarne Stroustrup sulla prima implementazione del C ++ . È stato implementato in C ++ ma tradotto da ciò che Stroustrup chiama un "preprocessore" da C ++ a C; non un compilatore completo secondo la sua definizione, ma comunque C ++ è stato avviato in C.


19
La versione in 3 passaggi del processo di compilazione bootstrap è davvero per la verifica: il compilatore stesso viene utilizzato come proprio test case. GCC compilato con [altro] dovrebbe produrre gli stessi risultati (binari identici, macro di sconto simili __DATE__e __TIME__che variano anche tra le invocazioni dello stesso compilatore) di GCC compilato con [GCC compilato con [altro]] - in caso contrario, si tratta di un bug e la build bootstrap a 3 stadi è progettata per catturarlo.
pmdj

19
@pmjordan: "Altrimenti, questo è un bug" o, meno probabilmente, una backdoor subdola in fase di introduzione ("Riflessioni sulla fiducia").
Steve Jessop,

12
@sleske: non è vero. L'output binario del passaggio 2 deve essere identico all'output binario del passaggio 3, altrimenti c'è un bug da qualche parte. Il motivo è come dice pmjordan: NewCompiler1 e NewCompiler2 sono programmi con sorgente identica (quella di NewCompiler). Viene fornito un input identico (l'origine per NewCompiler). Pertanto, produrranno un output identico indipendentemente dal compilatore stesso (in questo caso, NewCompiler1 è stato compilato con OldCompiler e NewCompiler2 è stato compilato con NewCompiler1). Cioè, NewCompiler2 e NewCompiler3 sono identici binari.
Steve Jessop,

12
Ti sei mai chiesto: cosa succederebbe se perdessimo tutti i binari del compilatore C? E ha dovuto ricominciare da capo? Ecco come farei: c'è il compilatore Tiny C (che in realtà può compilare il kernel Linux, quindi è abbastanza completo). Tutti i suoi file sorgente C formano solo 30k righe di codice, inclusi i commenti. Anche se è stato un certo sforzo, qualcuno che capisce C potrebbe imparare dalle fonti, come generare output binario e "compilare" le fonti TCC dalla mano (in realtà sto pensando a schede perforate qui). Quindi ricompila TCC con quello e usalo per avviare GCC o simili.
datenwolf,

11
@datenwolf: qualcosa del genere, sì. Se possiamo presumere che abbiamo perso tutti i binari del compilatore C, ma abbiamo ancora un assemblatore, allora potremmo scrivere un programma assemblatore TinyTinyC. Sarebbe un compilatore C meno completo di funzionalità rispetto a TinyC: non abbiamo bisogno che sia in grado di compilare GCC o il kernel Linux, abbiamo solo bisogno che sia in grado di compilare TinyC. Quindi eseguilo sul sorgente di TinyC, che ci fornisce un compilatore C in grado di compilare Linux (e speriamo glibc e GCC) e siamo in affari. Se non abbiamo nemmeno un assemblatore, avremmo prima avviato uno di questi, è più facile di un compilatore C.
Steve Jessop,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.