Esta sección explica 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. Puedes consultar esta sección en cualquier momento durante la construcción.
El principal objetivo del Capítulo 5 es proporcionar un entorno temporal 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.
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 (no debe
confundirse con el enlazador estándar ld, que es parte de Binutils). El
enlazador dinámico suministrado por Glibc encuentra y carga las
librerías compartidas necesarias para un programa, prepara el
programa y lo ejecuta. Usualmente el nombre del enlazador dinámico
es 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. El nombre del enlazador dinámico de tu
plataforma puede determinarse 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:
Similar en principio a la compilación cruzada, donde las herramientas instaladas dentro del mismo prefijo trabajan en cooperación y utilizan una pequeña “magia” de GNU.
Cuidada manipulación de la ruta de búsqueda de librerías del enlazador estándar para asegurar que los programas se enlazan sólo contra las librerías que elegimos.
Cuidada manipulación del fichero specs
de gcc para indicarle al
compilador cuál es el enlazador dinámico a usar.
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 una Glibc incorrectamente configurados puede provocar unas herramientas sutilmente rotas cuyo impacto podría no notarse hasta casi finalizada la construcción de una distribución completa. Un fallo en el banco de pruebas normalmente resaltará dicho error antes de perder demasiado tiempo.
Binutils instala tanto su ensamblador como su enlazador en dos
ubicaciones, /tools/bin
y /tools/$TARGET_TRIPLET/bin
. 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, un 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. Para saber cuál es el enlazador
estándar que utilizará gcc, ejecuta: 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
.
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 y entonces procederemos
a la construcción real del sistema LFS.