¿Cómo se arrancan GCC y g ++?

186

Esto me ha estado molestando por un tiempo. ¿Cómo se compilan GCC y g ++?

Supongo que cada revisión se compila con una revisión previamente construida. ¿Es esto cierto? Y si es así, ¿significa que las versiones más antiguas de g ++ y GCC se escribieron en conjunto?

usuario1010005
fuente
13
Cada revisión finalmente se puede compilar por sí misma. :)
Martin Hennings
44
Es interesante leer esto si quieres ver cómo surgieron los primeros compiladores.
parkovski
1
@parkovski ¿El enlace está muerto?
Nubcake
Enlace visto por última vez el 4 de junio de 2016: web.archive.org/web/20160604035203/homepage.ntlworld.com/…
akraf

Respuestas:

175

La versión más antigua de GCC se compiló utilizando otro compilador de C, ya que había otros cuando se escribió. El primer compilador de C (ca. 1973, IIRC) se implementó en el ensamblaje PDP-11 o en el lenguaje de programación B que lo precedió, pero en cualquier caso el compilador B se escribió en ensamblador.Del mismo modo, el primer compilador de C ++ (CPre / Cfront , 1979-1983) probablemente se implementó por primera vez en C y luego se reescribió en C ++.

Cuando compila GCC o cualquier otro compilador de alojamiento propio, el orden completo de compilación es:

  1. Cree una nueva versión de GCC con el compilador de C existente
  2. reconstruir una nueva versión de GCC con la que acabas de construir
  3. (opcional) repita el paso 2 para fines de verificación.

Este proceso se llama bootstrapping . Prueba la capacidad del compilador de compilarse a sí mismo y se asegura de que el compilador resultante esté construido con todas las optimizaciones que implementa.

EDITAR : Drew Dormann, en los comentarios, señala la cuenta de Bjarne Stroustrup de la implementación más temprana de C ++ . Fue implementado en C ++ pero traducido por lo que Stroustrup llama un "preprocesador" de C ++ a C; no es un compilador completo según su definición, pero aún así C ++ estaba en bootstrap en C.

Fred Foo
fuente
19
La versión de 3 pasos del proceso de compilación de bootstrap es de hecho para verificación: el compilador en sí se usa como su propio caso de prueba. GCC compilado con [otro] debería producir los mismos resultados (binarios idénticos, descontando macros similares __DATE__y __TIME__que varían incluso entre invocaciones del mismo compilador) que GCC compilado con [GCC compilado con [otro]]; si no, eso es un error, y la construcción de arranque de 3 etapas está diseñada para captar eso.
pmdj
19
@pmjordan: "si no, eso es un error" o, menos probable, una puerta trasera tortuosa en el proceso de introducción ("Reflexiones sobre la confianza en la confianza").
Steve Jessop
12
@sleske: eso no es cierto. La salida binaria del paso 2 debe ser idéntica a la salida binaria del paso 3; de lo contrario, hay un error en alguna parte. La razón es como dice pmjordan: NewCompiler1 y NewCompiler2 son programas con una fuente idéntica (la de NewCompiler). Se les da una entrada idéntica (la fuente de NewCompiler). Por lo tanto, producirán una salida idéntica sin importar con qué compilador se compilaron ellos mismos (en este caso, NewCompiler1 se compiló con OldCompiler y NewCompiler2 se compiló con NewCompiler1). Es decir, NewCompiler2 y NewCompiler3 son binarios idénticos.
Steve Jessop
12
Alguna vez te has preguntado: ¿Qué pasa si perdemos todos los binarios del compilador de C? ¿Y tuvo que arrancar desde cero? Así es como lo haría: está el compilador Tiny C (que en realidad puede compilar el kernel de Linux, por lo que es bastante completo). Todos sus archivos fuente en C conforman solo 30 mil líneas de código, incluidos los comentarios. Aunque incluso fue un esfuerzo considerable, alguien que entienda C podría aprender de las fuentes, cómo generar resultados binarios y "compilar" las fuentes de TCC de la mano (en realidad estoy pensando en tarjetas perforadas aquí). Luego recompile TCC con eso y úselo para arrancar GCC o similar.
datenwolf
11
@datenwolf: algo así, sí. Si podemos suponer que hemos perdido todos los binarios del compilador de C, pero todavía tenemos un ensamblador, entonces podríamos escribir un programa de ensamblador TinyTinyC. Sería un compilador de C con menos funciones completas que TinyC: no lo necesitamos para poder compilar GCC o el kernel de Linux, solo lo necesitamos para poder compilar TinyC. Luego ejecútelo en la fuente de TinyC, que nos da un compilador de C capaz de compilar Linux (y con suerte glibc y GCC) y estamos en el negocio. Si ni siquiera tenemos un ensamblador, primero deberíamos arrancar uno de esos, es más fácil que un compilador de C.
Steve Jessop