Notas técnicas sobre las herramientas

Esta sección intenta explicar algunos de los razonamientos y detalles técnicos que hay detrás del sistema de construcción. No es esencial que entiendas todo esto inmediatamente. La mayor parte tendrá sentido cuando hayas hecho una construcción real. Eres libre de volver aquí en cualquier momento.

El principal objetivo del Capítulo 5 es proporcionar un entorno temporal sano al que podamos entrar con chroot y a partir del cual podamos generar una construcción limpia y libre de problemas del sistema LFS en el Capítulo 6. Por el camino intentaremos independizarnos todo lo posible del sistema anfitrión, y para eso construimos unas herramientas principales autocontenidas y autohospedadas. Debería tenerse en cuenta que el proceso de construcción ha sido diseñado de forma que se minimice el riesgo para los nuevos lectores y, al mismo tiempo, se proporcione el máximo valor educacional. En otras palabras, se pueden usar técnicas más avanzadas para construir el sistema.

[Importante]

Importante

Antes de continuar, deberías informarte del nombre de tu plataforma de trabajo, conocido con frecuencia como target triplet (triplete del objetivo). Para muchos el "target triplet" posiblemente sea i686-pc-linux-gnu. Una forma simple de determinar tu "target triplet" es ejecutar el guión config.guess que se incluye con las fuentes de muchos paquetes. Desempaqueta las fuentes de Binutils, ejecuta el guión: ./config.guess y anota el resultado.

Igualmente necesitarás saber el nombre del enlazador dinámico de tu plataforma, también conocido como cargador dinámico, que no debe confundirse con el enlazador estándar ld que es parte de Binutils. El enlazador dinámico lo suministra Glibc y su trabajo es encontrar y cargar las librerías compartidas necesarias para un programa, preparar el programa y ejecutarlo. Para la mayoría el nombre del enlazador dinámico será ld-linux.so.2. En plataformas menos conocidas puede ser ld.so.1 y en las nuevas plataformas de 64 bits puede que incluso sea algo totalmente diferente. Debes poder determinar el nombre del enlazador dinámico de tu plataforma mirando en el directorio /lib de tu sistema anfitrión. Un modo seguro es inspeccionar un binario cualquiera de tu sistema anfitrión ejecutando: readelf -l <nombre del binario> | grep interpreter y anotar la salida. La referencia autorizada que cubre todas las plataformas está en el fichero shlib-versions en la raíz del árbol de las fuentes de Glibc.

Algunas claves técnicas sobre cómo funciona el método de construcción del Capítulo 5:

Se instala primero Binutils debido a que, tanto en GCC como en Glibc, la ejecución de ./configure realiza varias pruebas sobre el ensamblador y el enlazador para determinar qué características del software deben activarse o desactivarse. Esto es más importante de lo que uno podría pensar. Un GCC o Glibc incorrectamente configurado puede provocar unas herramientas sutilmente rotas cuyo impacto podría no notarse hasta casi finalizada la construcción de una distribución completa. Por suerte, un fallo en el banco de pruebas normalmente nos avisará antes de perder demasiado tiempo.

Binutils instala su ensamblador y su enlazador en dos ubicaciones, /tools/bin y /tools/$TARGET_TRIPLET/bin. En realidad, las herramientas de una ubicación son enlaces duros a la otra. Un aspecto importante del enlazador es su orden de búsqueda de librerías. Puede obtenerse información detallada de ld pasándole la opción --verbose. Por ejemplo: ld --verbose | grep SEARCH mostrará las rutas de búsqueda actuales y su orden. Puedes ver qué ficheros son realmente enlazados por ld compilando un programa simulado y pasándole la opción --verbose. Por ejemplo: gcc dummy.c -Wl,--verbose 2>&1 | grep succeeded te mostrará todos los ficheros abiertos con éxito durante el enlazado.

El siguiente paquete instalado es GCC y durante su fase ./configure verás, por ejemplo:

checking what assembler to use... /tools/i686-pc-linux-gnu/bin/as
checking what linker to use... /tools/i686-pc-linux-gnu/bin/ld

comprobando qué ensamblador usar... /tools/i686-pc-linux-gnu/bin/as
comprobando qué enlazador usar... /tools/i686-pc-linux-gnu/bin/ld

Esto es importante por la razón mencionada antes. También demuestra que el guión configure de GCC no explora los directorios del PATH para encontrar las herramientas a usar. Sin embargo, durante la operación real del propio gcc, no se utilizan necesariamente las mismas rutas de búsqueda. Puedes saber cuál es el enlazador estándar que utilizará gcc ejecutando: gcc -print-prog-name=ld. Puedes obtener información detallada a partir de gcc pasándole la opción -v mientras compilas un programa simulado. Por ejemplo: gcc -v dummy.c te mostrará los detalles sobre las fases de preprocesamiento, compilación y ensamblado, incluidas las rutas de búsqueda de gcc y su orden.

A continuación se instala Glibc. Las consideraciones más importantes para la construcción de Glibc son el compilador, las herramientas de binarios y las cabeceras del núcleo. Normalmente el compilador no es problema, pues Glibc siempre utilizará el gcc que se encuentre en un directorio del PATH. Las herramientas de binarios y las cabeceras del núcleo pueden ser algo mas problemáticas, así que no nos arriesgaremos y haremos uso de las opciones disponibles de configure para forzar las opciones correctas. Después de ejecutar ./configure puedes revisar el contenido del fichero config.make en el directorio glibc-build para ver todos los detalles importantes. Encontrarás algunas cosas interesantes, como el uso de CC="gcc -B/tools/bin/" para controlar qué herramientas de binarios son usadas, y también el uso de las opciones -nostdinc y -isystem para controlar la ruta de búsqueda de cabeceras del compilador. Estos detalles ayudan a resaltar un aspecto importante del paquete Glibc: es muy autosuficiente en cuanto a su maquinaria de construcción y generalmente no se apoya en las opciones por defecto de las herramientas.

Después de la instalación de Glibc, haremos algunos ajustes para asegurar que la búsqueda y el enlazado tengan lugar solamente dentro de nuestro directorio /tools. Instalaremos un ld ajustado, que tiene limitada su ruta de búsqueda interna a /tools/lib. Entonces retocaremos el fichero specs de gcc para que apunte a nuestro nuevo enlazador dinámico en /tools/lib. Este último paso es vital para el proceso completo. Como se mencionó antes, dentro de cada ejecutable compartido ELF se fija la ruta a un enlazador dinámico. Puedes verificar esto mediante: readelf -l <nombre del binario> | grep interpreter. Retocando el ficheros specs de gcc estaremos seguros de que todo binario compilado desde aquí hasta el final de este capítulo usará nuestro nuevo enlazador dinámico en /tools/lib.

La necesidad de utilizar el nuevo enlazador dinámico es también la razón por la que aplicamos el parche Specs en la segunda fase de GCC. De no hacer esto los propios programas de GCC incluirían dentro suyo el nombre del enlazador dinámico del directorio /lib del sistema anfitrión, lo que arruinaría nuestro objetivo de librarnos del anfitrión.

Durante la segunda fase de Binutils podremos usar la opción --with-lib-path de configure para controlar la ruta de búsqueda de librerías de ld. A partir de este punto el corazón de las herramientas está autocontenido y autohospedado. El resto de los paquetes del Capítulo 5 se construirán todos contra la nueva Glibc en /tools como debe ser.

Tras entrar en el entorno chroot en el Capítulo 6, el primer gran paquete a instalar es Glibc, debido a su naturaleza autosuficiente. Una vez que esta Glibc se instale dentro de /usr, haremos un rápido cambio en las opciones por defecto de las herramientas, entonces procederemos a la construcción real del sistema LFS.