Linux From Scratch (Parte 9 - Ajustando el Toolchain)

Ahora que se han instalado las últimas bibliotecas de C, es hora de ajustar la cadena de herramientas para que vincule cualquier programa recién compilado con estas nuevas bibliotecas.



Primero, haremos una copia de seguridad del enlazador /tools y reemplázaremos con el enlazador ajustado que hicimos anteriormente. También crearemos un enlace a su contraparte en /tools/$(uname -m)-pc-linux-gnu/bin:
mv -v /tools/bin/{ld,ld-old}
mv -v /tools/$(uname -m)-pc-linux-gnu/bin/{ld,ld-old}
mv -v /tools/bin/{ld-new,ld}
ln -sv /tools/bin/ld /tools/$(uname -m)-pc-linux-gnu/bin/ld
A continuación, modificamos el archivo de especificaciones de GCC para que apunte al nuevo enlazador dinámico. Simplemente eliminar todas las instancias de "/tools" debería dejarnos la ruta correcta al enlazador dinámico. También ajuste el archivo de especificaciones para que GCC sepa dónde encontrar los encabezados correctos y los archivos de inicio de Glibc. Un comando sed logra esto:
gcc -dumpspecs | sed -e 's@/tools@@g'                   \
    -e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
    -e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' >      \
    `dirname $(gcc --print-libgcc-file-name)`/specs 
Es una buena idea inspeccionar visualmente el archivo de especificaciones para verificar que realmente se realizó el cambio deseado.

Es imprescindible en este punto para asegurar que las operaciones básicas (compilación y enlazado) de las nuevas herramientas funcionan como se esperaba. Para ello, realice las siguientes comprobaciones de validez:
echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
No debería haber errores, y la salida del último comando será (teniendo en cuenta las diferencias específicas de la plataforma en el nombre del vinculador dinámico):
 
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
 
Tenemos que tener en cuenta que en los sistemas de 64 bits /lib es la ubicación de nuestro enlazador dinámico, pero se accede a través de un enlace simbólico en /lib64.
En sistemas de 32 bits, el intérprete debe ser /lib/ld-linux.so.2.

Ahora nos aseguramos de que lo hemos configurado para usar los archivos de inicio correctos:
grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
La respuesta devería ser tal que así:
/usr/lib/../lib/crt1.o succeeded
/usr/lib/../lib/crti.o succeeded
/usr/lib/../lib/crtn.o succeeded 

Verificamos que el compilador esté buscando los archivos de encabezado correctos:
grep -B1 '^ /usr/include' dummy.log
La respuesta devería ser parecida a esto:

#include <...> search starts here:
 /usr/include


Luego, verificamos que el nuevo enlazador se esté usando con las rutas de búsqueda correctas:
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
Las referencias a rutas que tienen componentes con '-linux-gnu' deben ignorarse, pero de lo contrario la salida del último comando debería ser:
SEARCH_DIR("/usr/lib")
SEARCH_DIR("/lib")

A continuación, nos aseguramos de que estamos utilizando la libc correcta:
grep "/lib.*/libc.so.6 " dummy.log

La respuesta será semejante a esto:
attempt to open /lib/libc.so.6 succeeded
 

Por último, asegúrese de que GCC esté usando el enlazador dinámico correcto:
grep found dummy.log
El resultado del último comando debe ser (teniendo en cuenta las diferencias específicas de la plataforma en el nombre del vinculador dinámico):
found ld-linux-x86-64.so.2 at /lib/ld-linux-x86-64.so.2


Si el resultado no aparece como se muestra arriba o no se recibe, entonces algo está muy mal. Investigue y vuelva sobre los pasos para descubrir dónde está el problema y corregirlo. La razón más probable es que algo salió mal con el ajuste del archivo de especificaciones. Cualquier problema deberá ser resuelto antes de continuar con el proceso.
Salimos del directorio:
cd ../..
Hasta aquí el ajuste de Toolchain. Ahora seguiremos con la configuración, compilación e instalación de los paquetes para el sistema.

Zlib-1.2.11
El paquete Zlib contiene rutinas de compresión y descompresión utilizadas por algunos programas. 

Tiempo aproximado de compilación: menos de 0.1 SBU
Tamaño de disco requerido: 4.5 MB
Descomprimimos el paquete:
tar -xvf zlib-1.2.11.tar.xz
Entramos en el directorio recién creado:
cd zlib-1.2.11
Preparamos Zlib para compilación:
./configure --prefix=/usr
Creamos el paquete:
make 
Probamos el resultado:
make check
Realizamos la instalación del paquete:
make install
La biblioteca compartida debe moverse a /lib y, como resultado, se deberá volver a crear el archivo .so en /usr/lib:
mv -v /usr/lib/libz.so.* /lib
ln -sfv ../../lib/$(readlink /usr/lib/libz.so) /usr/lib/libz.so 
Salimos del directorio:
cd ..

File-5.33
El paquete File contiene una utilidad para determinar el tipo de un archivo o archivos dado. 
Tiempo aproximado de compilación: 0.1 SBU
Tamaño de disco requerido: 16 MB
Entramos en el directorio que ya habíamos creado en capítulos anteriores:
cd file-5.33
Preparamos para compilación:
./configure --prefix=/usr
Compilamos el paquete:
make
Realizamos los tests:
make check
Instalamos el paquete:
make install
Salimos del directorio:
cd ..

Readline-7.0
La reinstalación de Readline hará que las bibliotecas antiguas se muevan a .old. 
Descomprimimos el paquete:
tar -xvf readline-7.0.tar.gz
Entramos en el directorio:
cd  readline-7.0
Si bien esto normalmente no es un problema, en algunos casos puede desencadenar un error de vinculación en ldconfig. Esto se puede evitar emitiendo los siguientes dos seds: 
sed -i '/MV.*old/d' Makefile.in
sed -i '/{OLDSUFF}/c:' support/shlib-install
Preparamos el paquete para compilación:
./configure --prefix=/usr    \
            --disable-static \
            --docdir=/usr/share/doc/readline-7.0
Compilamos el paquete:
make SHLIB_LIBS="-L/tools/lib -lncursesw"
Instalamos el paquete:
make SHLIB_LIBS="-L/tools/lib -lncurses" install
Ahora mueva las bibliotecas dinámicas a una ubicación más adecuada y arregle algunos enlaces simbólicos:
mv -v /usr/lib/lib{readline,history}.so.* /lib
ln -sfv ../../lib/$(readlink /usr/lib/libreadline.so) /usr/lib/libreadline.so
ln -sfv ../../lib/$(readlink /usr/lib/libhistory.so ) /usr/lib/libhistory.so
Si lo desea, instale la documentación:
install -v -m644 doc/*.{ps,pdf,html,dvi} /usr/share/doc/readline-7.0
Salimos del directorio:
cd.. 

M4-1.4.18
Entramos en el directorio:
cd m4-1.4.18
Preparamos para compilar:
./configure --prefix=/usr
Compilamos:
make
Realizamos los tests:
make check
Instalamos el paquete:
make install
Salimos del directorio:
cd ..

Bc-1.07.1
El paquete Bc contiene un lenguaje de procesamiento numérico de precisión arbitrario.
Tiempo aproximado de compilación: 0.1 SBU
Tamaño de disco requerido: 3.7 MB

Descomprimimos el paquete:
tar -xvf bc-1.07.1.tar.gz
Entramos dentro del directorio:
cd bc-1.07.1
Primero, cambiamos un script interno para usar sed en lugar de ed:
cat > bc/fix-libmath_h << "EOF"
#! /bin/bash
sed -e '1   s/^/{"/' \
    -e     's/$/",/' \
    -e '2,$ s/^/"/'  \
    -e   '$ d'       \
    -i libmath.h

sed -e '$ s/$/0}/' \
    -i libmath.h
EOF 
Cree enlaces simbólicos temporales para que el paquete pueda encontrar la biblioteca readline y confirmar que su biblioteca requerida libncurses está disponible. Aunque las bibliotecas están en /tools/lib en este punto, el sistema usará /usr/lib al final de esta publicación.
ln -sv /tools/lib/libncursesw.so.6 /usr/lib/libncursesw.so.6
ln -sfv libncurses.so.6 /usr/lib/libncurses.so
Corregimos un problema de configuracióndebido a la falta de archivos en las primeras etapas de LFS:
sed -i -e '/flex/s/as_fn_error/: ;; # &/' configure
 Preparamos el paquete para compilación:
./configure --prefix=/usr           \
            --with-readline         \
            --mandir=/usr/share/man \
            --infodir=/usr/share/info 
Compilamos el paquete:
make
Realizamos los tests:
echo "quit" | ./bc/bc -l Test/checklib.b
Instalamos el paquete:
make install
Salimos del directorio:
cd ..

Binutil
El paquete Binutils contiene un enlazador, un ensamblador y otras herramientas para manejar archivos de objetos.
Tiempo aproximado de compilación: 6.0 SBU
Tamaño de disco requerido: 4.2 GB
Verificamos que los PTY funcionan correctamente dentro del entorno chroot realizando una prueba simple:
expect -c "spawn ls"
Devería mostrar algo así:
spawn ls
Si, en cambio, la salida incluye el mensaje a continuación, entonces el entorno no está configurado para una operación PTY adecuada. Este problema debe resolverse antes de ejecutar las suites de prueba para Binutils y GCC:
The system has no more ptys.
Ask your system administrator to create more.
Entramos en el directorio:
cd binutils-2.30
Borramos el directorio build que habíamos construido en pasos anteriores:
rm -R -f build
Creamos el directorio build donde compilaremos el paquete de nuevo:
mkdir -v build 
cd build
Configuramos el paquete:
../configure --prefix=/usr       \
             --enable-gold       \
             --enable-ld=default \
             --enable-plugins    \
             --enable-shared     \
             --disable-werror    \
             --enable-64-bit-bfd \
             --with-system-zlib
Compilamos el paquete:
make tooldir=/usr
NOTA: El conjunto de pruebas para Binutils en esta sección se considera crítico. No lo salte en ninguna circunstancia.
Probamos los resultados:
make -k check
Se sabe que una prueba, debug_msg.sh, falla.
Instalamos el paquete:
make tooldir=/usr install
Salimos del directorio:
cd ../..

GMP-6.1.2

El paquete GMP contiene bibliotecas matemáticas. Estos tienen funciones útiles para la aritmética de precisión arbitraria.
Tiempo aproximado de compilación: 1.2 SBU
Tamaño de disco requerido: 60 MB
Descomprimimos el paquete:
tar -xvf gmp-6.1.2.tar.xz
Entramos en el directorio:
cd  gmp-6.1.2
Si estamos compilando para x86 de 32 bits, pero tiene una CPU que es capaz de ejecutar código de 64 bits y ha especificado CFLAGS en el entorno, el script de configuración intentará configurar 64 bits y fallará. Evite esto invocando el comando configure a continuación con:
ABI=32 ./configure ...
La configuración predeterminada de GMP produce bibliotecas optimizadas para el procesador host. Si se desean bibliotecas adecuadas para procesadores menos capaces que la CPU del host, se pueden crear bibliotecas genéricas ejecutando lo siguiente:
cp -v configfsf.guess config.guess
cp -v configfsf.sub   config.sub 
Preparamos para compilación:
./configure --prefix=/usr    \
            --enable-cxx     \
            --disable-static \
            --docdir=/usr/share/doc/gmp-6.1.2
Compilamos el paquete y generamos la documentación HTML:
make
make html
Probamos los resultados:
make check 2>&1 | tee gmp-check-log
Nos aseguramos de que pasen todas las 190 pruebas en el conjunto de pruebas. Verifique los resultados emitiendo el siguiente comando:
awk '/# PASS:/{total+=$3} ; END{print total}' gmp-check-log
Instalamos el paquete y su documentación:
make install
make install-html
Salimos del directorio:
cd ..

MPFR-4.0.1

El paquete MPFR contiene funciones para matemáticas de precisión múltiple.
Tiempo aproximado de compilación:: 1.0 SBU
Tamaño de disco requerido: 36 MB
Descomprimimos el paquete:
tar -xvf  mpfr-4.0.1.tar.xz
Entramos en el directorio:
cd mpfr-4.0.1
Preparamos MPFR para su compilación:
./configure --prefix=/usr        \
            --disable-static     \
            --enable-thread-safe \
            --docdir=/usr/share/doc/mpfr-4.0.1
Compilamos el paquete y generamos la documentación HTML:
make
make html
NOTA: El conjunto de pruebas para MPFR en esta sección se considera crítico. No lo salte en ninguna circunstancia.

Comprobamos los resultados y nos aseguramos que todas las pruebas lo pasan:
make check
Instalamos el paquete y su documentación:
make install
make install-html
Salimos del directorio:
cd ..

MPC-1.1.0

El paquete MPC contiene una biblioteca para la aritmética de los números complejos con alta precisión arbitraria y correcta redondeo del resultado.
Tiempo aproximado de compilación: 0.3 SBU
Tamaño de disco requerido: 21 MB

Descomprimimos el paquete:
tar -xvf mpc-1.1.0.tar.gz
Entramos en el directorio:
cd mpc-1.1.0
Preparamos el paquete para su compilación:
./configure --prefix=/usr    \
            --disable-static \
            --docdir=/usr/share/doc/mpc-1.1.0
Compilamos el paquete y generamos la documentación HTML:
make
make html
Comprobamos los resultados:
make check
Instalamos el paquete y su documentación:
make install
make install-html
Salimos del directorio:
cd ..

GCC-8.1.0 
El paquete GCC contiene la colección del compilador GNU, que incluye los compiladores C y C ++. 
Tiempo aproximado de compilación: 81 SBU (con tests)
Tamaño de disco requerido: 3.1 GB
Entramos en el directorio:
cd gcc-8.1.0
Si se basa en x86_64, cambie el nombre del directorio predeterminado para las bibliotecas de 64 bits a "lib":
case $(uname -m) in
  x86_64)
    sed -e '/m64=/s/lib64/lib/' \
        -i.orig gcc/config/i386/t-linux64
  ;;
esac
Eliminamos el enlace simbólico creado anteriormente, ya que el gcc final incluye se instalará aquí:
rm -f /usr/lib/gcc
La documentación de GCC recomienda construir GCC en un directorio de compilación dedicado, por lo que eliminaremos el directorio build creado anteriormente:

rm -R -f build
Y ahora volvemos a crearlo y entrar en el directorio:
mkdir -v build
cd build
Preparamos el paquete para compilarlo:
SED=sed                               \
../configure --prefix=/usr            \
             --enable-languages=c,c++ \
             --disable-multilib       \
             --disable-bootstrap      \
             --with-system-zlib
Compilamos el paquete:
make
IMPORTANTE: En esta sección, el conjunto de pruebas para GCC se considera crítico. No lo salte en ninguna circunstancia.
Se sabe que un conjunto de pruebas en el conjunto de pruebas de GCC agota la pila, por lo que debe aumentar el tamaño de la pila antes de ejecutar las pruebas:
ulimit -s 32768
Probamos los resultados, pero no nos detedremos en los errores:
make -k check
Para recibir un resumen de los resultados del conjunto de pruebas, ejecute:
../contrib/test_summary
NOTA: En algunas combinaciones de configuración de kernel y procesadores AMD, puede haber más de 1100 fallos en las pruebas gcc.target/i386/mpx (que están diseñadas para probar la opción MPX en los procesadores Intel recientes). Estos pueden ser ignorados de forma segura en los procesadores AMD.

 Instalamos el paquete:
make install
Cree un enlace simbólico requerido por la FHS por razones "históricas".
ln -sv ../usr/bin/cpp /lib
Muchos paquetes usan el nombre cc para llamar al compilador de C. Para satisfacer esos paquetes, crea un enlace simbólico:
ln -sv gcc /usr/bin/cc
Agregamos un enlace simbólico de compatibilidad para habilitar la creación de programas con Link Time Optimization (LTO):
install -v -dm755 /usr/lib/bfd-plugins
ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/8.1.0/liblto_plugin.so \
        /usr/lib/bfd-plugins/
Ahora que nuestra última cadena de herramientas está en su lugar, es importante asegurarse nuevamente de que la compilación y el enlace funcionen como se espera. Hacemos esto al realizar los mismos controles de cordura que hicimos anteriormente en el capítulo:
echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
No debería haber errores, y la salida del último comando será (teniendo en cuenta las diferencias específicas de la plataforma en el nombre del vinculador dinámico):
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
Ahora nos aseguramos de que estamos configurados para usar los archivos de inicio correctos:
grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
La respuesta devería ser algo semejante a esto:
/usr/lib/gcc/x86_64-pc-linux-gnu/8.1.0/../../../../lib/crt1.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/8.1.0/../../../../lib/crti.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/8.1.0/../../../../lib/crtn.o succeeded
Dependiendo de la arquitectura de nuestra máquina, lo anterior puede diferir ligeramente, la diferencia generalmente es el nombre del directorio después de /usr/lib/gcc. Lo importante a tener en cuenta aquí es que gcc ha encontrado los tres archivos crt * .o bajo el directorio /usr/lib.

Verificamos que el compilador esté buscando los archivos de encabezado correctos:

grep -B4 '^ /usr/include' dummy.log
 Y el resultado sería algo parecido a esto:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.1.0/include
 /usr/local/include
 /usr/lib/gcc/x86_64-pc-linux-gnu/8.1.0/include-fixed
 /usr/include
Una vez más, tenemos que tener en cuenta que el directorio nombrado después de su triplete objetivo puede ser diferente al anterior, dependiendo de su arquitectura.
Luego, verifique que el nuevo enlazador se esté usando con las rutas de búsqueda correctas:
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
Las referencias a rutas que tienen componentes con '-linux-gnu' deben ignorarse, pero de lo contrario la salida del último comando debería ser:
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64")
SEARCH_DIR("/usr/local/lib64")
SEARCH_DIR("/lib64")
SEARCH_DIR("/usr/lib64")
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");
Un sistema de 32 bits puede ver algunos directorios diferentes. Por ejemplo, aquí está el resultado de una máquina i686:
SEARCH_DIR("/usr/i686-pc-linux-gnu/lib32")
SEARCH_DIR("/usr/local/lib32")
SEARCH_DIR("/lib32")
SEARCH_DIR("/usr/lib32")
SEARCH_DIR("/usr/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");
A continuación, asegúrese de que estamos utilizando el libc correcto:
grep "/lib.*/libc.so.6 " dummy.log
 La respuesta devería ser algo así:
attempt to open /lib/libc.so.6 succeeded
Por último, comprobamos de que GCC esté usando el enlazador dinámico correcto:
grep found dummy.log
El resultado del último comando debe ser (teniendo en cuenta las diferencias específicas de la plataforma en el nombre del vinculador dinámico):
found ld-linux-x86-64.so.2 at /lib/ld-linux-x86-64.so.2
Si el resultado no aparece como se muestra arriba o no se recibe, entonces algo está muy mal. Investigaremos y vuelveremos sobre los pasos para descubrir dónde está el problema y corregirlo. La razón más probable es que algo salió mal con el ajuste del archivo de especificaciones. Cualquier problema deberá ser resuelto antes de continuar con el proceso.

Finalmente, movemos el archivo:
mkdir -pv /usr/share/gdb/auto-load/usr/lib
mv -v /usr/lib/*gdb.py /usr/share/gdb/auto-load/usr/lib
Salimos del directorio:
cd ../..
 Y hasta aquí este capítulo. Para la siguiente publicación, continuaremos con el paquete Bzip2.




Comentarios

Publicaciones populares

Activar tema Negro (gris oscuro) en Microsoft Office 2016/2019

Acerca de los mensajes de tipo... "Por favor no agreges a este usuario es un virus!"

Temas oficiales para Windows XP