5.11. GCC-4.2.1 - Fase 2

El paquete GCC contiene la colección de compiladores GNU, que incluye los compiladores C y C++.

Tiempo estimado de construcción: 4.2 SBU
Espacio requerido en disco: 553 MB

5.11.1. Reinstalación de GCC

Ahora están instaladas las herramientas necesarias para comprobar GCC y Binutils: Tcl, Expect y DejaGNU. Por lo que ahora pueden reconstruirse GCC y Binutils enlazándolos con la nueva Glibc y comprobarlos adecuadamente (si llevas a cabo los bancos de pruebas en este capítulo). Sin embargo, una cosa a tener en cuenta es que estos bancos de pruebas son altamente dependientes del correcto funcionamiento de las pseudo-terminales (PTYs) suministradas por tu distribución anfitrión. Las PTYs se implementan normalmente mediante el sistema de ficheros devpts. Comprueba si tu sistema anfitrión está configurado correctamente en este aspecto ejecutando una simple prueba:

expect -c "spawn ls"

La respuesta podría ser:

The system has no more ptys.
Ask your system administrator to create more.

El sistema no tiene más ptys.
Pídele al administrador del sistema que cree más.

Si recibes el mensaje anterior, tu sistema anfitrión no está configurado para operar correctamente con PTYs. En este caso no hay razón para ejecutar los bancos de pruebas de GCC y Binutils hasta resolver este asunto. Puedes consultar la FAQ de LFS en http://www.linuxfromscratch.org/faq//lfs/faq.html#no-ptys para obtener información sobre cómo conseguir que funcionen las PTYs.

Como se explicó anteriormente en Sección 5.7, “Ajustar las herramientas”, bajo circunstancias normales el guión fixincludes de GCC se ejecuta para corregir posibles ficheros de cabecera rotos. Como GCC-4.2.1 y Glibc-2.6.1 ya han sido instalados en este punto, y se sabe que sus respectivos ficheros de cabecera no necesitan ser corregidos, no se necesita el guión fixincludes. Como se mencionó anteriormente, de hecho el guión puede contaminar el entorno de construcción al instalar cabeceras corregidas procedentes del anfitrión dentro del directorio privado de cabeceras de GCC. La ejecución del guión fixincludes puede evitarse ejecutando los siguientes comandos:

cp -v gcc/Makefile.in{,.orig}
sed 's@\./fixinc\.sh@-c true@' gcc/Makefile.in.orig > gcc/Makefile.in

El proceso "bootstrap" realizado en Sección 5.4, “GCC-4.2.1 - Fase 1” construye GCC con la opción -fomit-frame-pointer. Las construcciones no "bootstrap" omiten dicha opción, así que aplica el siguiente sed para usarla y asegurar construcciones consistentes del compliador:

cp -v gcc/Makefile.in{,.tmp}
sed 's/^XCFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in.tmp \
  > gcc/Makefile.in

El siguiente comando cambiará la localización del enlazador dinámico usado por GCC para usar el instalado en /tools. También elimina /usr/include de la ruta de búsqueda de inclusiones de GCC. Al hacer esto ahora en vez de ajustar el fichero de especificaciones tras la instalación se asegura que el nuevo enlazador dinámico se utiliza durante la construcción actual de GCC. Esto es, todos los binarios creados durante la construcción se enlazarán contra la nueva Glibc. Ejecuta:

for file in $(find gcc/config -name linux64.h -o -name linux.h)
do
  cp -uv $file{,.orig}
  sed -e 's@/lib\(64\)\?\(32\)\?/ld@/tools&@g' \
  -e 's@/usr@/tools@g' $file.orig > $file
  echo "
#undef STANDARD_INCLUDE_DIR
#define STANDARD_INCLUDE_DIR 0" >> $file
  touch $file.orig
done

En caso de que lo anterior parezca dificil de entender, vamos a analizarlo. Primero se encuentran todos los ficheros bajo el directorio gcc/config cuyo nombre sea linux.h o linux64.h. Cada fichero encontrado es copiado a un fichero del mismo nombre pero añadiendo el sufijo “.orig”. Entonces la primera expresión sed añade “/tools” delante de cada aparición de “/lib/ld”, “/lib64/ld” o “/lib32/ld”, mientras que la segunda reemplaza “/usr”. Entonces se añaden al final del fichero las sentencias de definición que modifican las rútas de búsqueda de inclusiones. Por último, se utiliza touch para actualizar la marca de tiempo de los ficheros copiados. Al usarlo junto con cp -u se evitan cambios no deseados en los ficheros originales en caso de que el comando se ejecute dos veces inadvertidamente.

Vuelve a crear un directorio de construcción dedicado:

mkdir -v ../gcc-build
cd ../gcc-build

Prepara GCC para su compilación:

../gcc-4.2.1/configure --prefix=/tools \
    --with-local-prefix=/tools --enable-clocale=gnu \
    --enable-shared --enable-threads=posix \
    --enable-__cxa_atexit --enable-languages=c,c++ \
    --disable-libstdcxx-pch --disable-bootstrap

Significado de las nuevas opciones de configure:

--enable-clocale=gnu

Esta opción asegura que se seleccione el modelo de locale correcto para las librerías de C++ en todos los casos. Si el guión configure encuentra instalada la locale de_DE, seleccionará el modelo correcto de gnu. Sin embargo, las personas que no instalan la locale de_DE pueden correr el riesgo de construir librerías de C++ incompatibles en la ABI debido a que se selecciona el modelo de locale genérico, que es incorrecto.

--enable-threads=posix

Esto activa el manejo de excepciones C++ para código multihilo.

--enable-__cxa_atexit

Esta opción permite el uso de __cxa_atexit, en vez de atexit, para registrar destructores C++ para objetos estáticos locales y objetos globales. Es esencial para un manejo de destructores completamente compatible con los estándares. También afecta al ABI de C++ obteniendo librerías compartidas y programas C++ interoperables con otras distribuciones Linux.

--enable-languages=c,c++

Esta opción asegura que se construyan tanto el compilador de C como el de C++.

--disable-libstdcxx-pch

No construye la cabecera precompilada (PCH) para libstdc++. Necesita mucho espacio y nosotros no la utilizamos.

--disable-bootstrap

Ahora GCC se auto-reconstruye (bootstrapping) por defecto. Sin embargo, nuestro método de construcción debería proporcionarnos un compilador sólido sin necesidad de auto-reconstruirlo cada vez.

Compila el paquete:

make

Aquí no hace falta usar el objetivo bootstrap, ya que el compilador que estamos utilizando para construir GCC ha sido construido a partir de la misma versión de las fuentes de GCC que usamos antes.

La compilación está completa. Como se mencionó antes, no es obligatorio ejecutar los bancos de pruebas de las herramientas temporales en este capítulo. Si de todas formas deseas ejecutar el banco de pruebas de GCC, hazlo con el siguiente comando:

make -k check

La opción -k se usa para que el banco de pruebas se ejecute por completo y sin detenerse ante el primer error. El banco de pruebas de GCC es muy exhaustivo y es casi seguro que generará algunos fallos.

Para una relación de las pruebas fallidas más importantes, mira en Sección 6.12, “GCC-4.2.1.”

Instala el paquete:

make install
[Atención]

Atención

En este punto es obligatorio parar y asegurarse de que las operaciones básicas (compilación y enlazado) de las nuevas herramientas funcionan como se espera. Para esto vamos a hacer una simple comprobación:

echo 'main(){}' > dummy.c
cc dummy.c
readelf -l a.out | grep ': /tools'

Si todo funciona correctamente, no debe haber errores y la salida del último comando debe ser:

[Requesting program interpreter:
    /tools/lib/ld-linux.so.2]

[Intérprete de programa solicitado:
    /tools/lib/ld-linux.so.2]

Confirma que /tools/lib aparezca como el prefijo de tu enlazador dinámico.

Si no recibes una salida como la mostrada arriba, o no hay salida alguna, algo está seriamente mal. Investiga y revisa tus pasos para encontrar el problema y corregirlo. El problema debe resolverse antes de continuar. Primero, repite la comprobación de sanidad usando gcc en vez de cc. Si esto funciona significa que falta el enlace simbólico /tools/bin/cc. Vuelve a la Sección 5.4, “GCC-4.2.1 - Fase 1” e instala el enlace simbólico. Seguidamente, asegúrate de que tu PATH es correcto. Puedes comprobarlo ejecutando echo $PATH y verificando que /tools/bin está en cabeza de la lista. Si el PATH está mal puede significar que no has ingresado como usuario lfs o que algo salió mal en la Sección 4.4, “Configuración del entorno”. Otra opción es que algo pudo ir mal en el anterior arreglo del fichero specs. En este caso, repite el arreglo del fichero asegurándote de copiar y pegar los comandos como se recomendó.

Cuando todo esté bien, borra los ficheros de prueba:

rm -v dummy.c a.out

Los detalles sobre este paquete se encuentran en la Sección 6.12.2, “Contenido de GCC”.