Capítulo 3: Compilación cruzada

Autor: Emiliano P. López - Santa Fe (Argentina)

Introducción

La compilación de código fuente que, realizada bajo una determinada arquitectura genera código ejecutable para una arquitectura diferente se denomina compilación cruzada. Para realizar este tipo de compilación es necesario contar con una serie de programas y librerías que establezcan un ambiente propicio para llevar a cabo esta tarea. Este ambiente se denomina entorno de compilación cruzada.
En el capítulo anterior hemos definido dos tipos de sistemas, el Huesped, es en donde se realiza la compilación del sistema, y el Objetivo donde se ejecuta el código.
A lo largo de este capítulo se detallará la configuración de un entorno de compilación cruzada sobre un sistema operativo GNU/Linux como así también la configuración y descripción de los componentes que forman parte de este proceso.

Sistema huesped

Como hemos descripto en el capítulo 2, la implementación de un entorno de compilación cruzada nos brinda la posibilidad de aprovechar los recursos que disponemos en una computadora tipo PC.
Esta tarea se ha llevado a cabo sobre una PC de escritorio con las siguientes características:

  • Procesador: intel pentium II de 800 Mhz
  • Memoria RAM: 768 MB
  • Disco Rígido: 80 GB
  • Lectora - grabadora de CD
  • Lectora - grabadora de memorias compact flash
  • Conexión a internet
  • Sistema operativo: Debian1 stable etch release 4.0.

Sistema objetivo

El dispositivo que se ha seleccionado es un Routerboard 532. Este equipo ha sido diseñado para realizar funciones en redes de datos bajo un sistema operativo denominado RouterOS desarrollado por el mismo fabricante. El mismo realiza tareas de router, firewall, proxy, servidor DHCP, cliente/servidor VPN entre otras.
Las características específicas se detallan en los siguientes items.

  • Procesador:
    • MIPS 32 4Kc - 266MHz procesador SOC
    • Posee unidad de administración de memoria (MMU, del inglés Memory Managment Unit )
    • No posee unidad de punto flotante (FPU, del inglés Float Point Unit)
  • Memoria: 32MB DDR
  • Almacenamiento: 128MB NAND integrados, slot CompactFlash type I/II slot
  • Puertos ethernet: un puerto IDT Korina 10/100 Mbit/s Fast Ethernet con soporte Auto-MDI/X y dos puertos VIA VT6105 10/100 Mbit/s Fast Ethernet con soporte Auto-MDI/X.
  • Slots MiniPCI: dos slots MiniPCI Type IIIA/IIIB
  • Puerto serie: un RS232C asincrónico, conector DB9

La elección de este dispositivo se basa en su arquitectura de hardware, ya que el microprocesador es ampliamente soportado por el kernel Linux además la posibilidad de conexión de una memoria compact flash, en donde se almacenará el sistema GNU/Linux.

En la documentación del fabricante se encuentra disponible varios diagramas descriptivos de los componentes mencionados en la lista previa. En la figura 1 se observa un diagrama en bloques descriptivo sobre la comunicación entre microprocesador y, buses y componentes.

bloques-hdatos.png
Fig. 1

En la siguiente figura 2 y 3 se observa una comparación entre un diagrama de la ubicación de los componentes en la placa y una fotografía de el Routerboard 532 en donde hemos resaltado el bus MiniPCI, el conector compact flash, las interfaces ethernet RJ45 y serie RS-232.

rb-referencias.png
rb-hdatos.png
Fig. 2 Fig. 3

Comunicación entre sistema huesped y objetivo

La transferencia del sistema GNU/Linux desde la PC hacia el Routerboard se realizará mediante un medio de almacenamiento externo. Más precisamente almacenaremos el sistema en una memoria compact flash de 1 GB de capacidad conectada a la computadora mediante un grabador de memorias conectado a través del puerto USB. Una vez realizada la transferencia completa del sistema, se conectará al slot compact flash del Routerboard para que el mismo realice el arranque del sistema desde este medio, en vez de iniciar desde su memoria NAND donde se encuentra almacenado el sistema de fábrica. En las figuras 5,6 y7 observamos la bahia de conexión para la memoria, la tarjeta CF y el lector-grabador de memorias.

cf-conector.png
con-flash.png
cf-reader.jpg
Fig5. Conector de memoria CF Fig6. Memoria de 1 GB Lector-grabador de memorias

Otra alternativa de arranque que permite el Routerboard es a través de la red, es decir, ni bien el equipo arraca busca por FTP una imagen del sistema para inicar. Esta alternativa es muy útil en las primeras etapas, ya que se evita la conexión y desconexión de la tarjeta de memoria, evitando desgastes y roturas en los conectores.
Una vez que el sistema se encuentra estable, es preferible utilizar la tarjeta de memoria y realizar la configuraciones extras utilizando una consola terminal.
Para configurar el Routerboard y seleccionar el modo de arranque, se ha utilizado un cable denominado modem-nulo que se conecta desde el puerto serie de la PC a la interfaz RS-232 del dispositivo. En las figuras siguientes observamos las conexiones entre la placa y la computadora, y el modo en que se ha realizado el cable modem-nulo.

cross-conection.png
nullmodem.png
Conexión entre RB y PC cable modem-nulo
FALTA: 
- Mostrar fotografía del cable modem nulo.
- Mostrar las opciones de booteo del RB

Componentes toolchains

HACER: 
-explicar las herramientas que vamos configurar
-los archivos de configuración
-mostrar los pasos con el buildroot, errores, captura de pantallas y y proceso de compilación

Los componentes necesarios para implementar el entorno de compilación cruzada consisten básicamente en tres elementos:

  • Compilador C : compilador de C básico
  • Librería C: implementa las llamadas al sistema mediante APIs.
  • Binutils: conjunto de programas para compilación, enlazado, ensamblado y depuración de código.

Cada una de estas herramientas funciona en dependencia de las otras, es por esto que configurar y compilarlas es una operación delicada. La complejidad radica en que no existe una compatibilidad asegurada entre las diferentes versiones de los componentes. Por esto, la primer etapa consiste en seleccionar las versiones de cada uno de estos componentes compatibles entre sí.

La combinación de diferentes versiones han dado resultados no esperados. Suele ser frustrante la repetición de estos pasos una y otra vez, y que luego de horas de compilación aparezcan errores de todo tipo.

Las versiones de las herramientas con las que se ha obtenido una compilación exitosa son las siguientes:

  • Compilador: gcc 3.4.2
  • Librería C: uClibc 0.9.28
  • Binutils 2.16.1

Este conjunto de herramientas se han configurado y compilado utilizando un paquete de software denominado Buildroot2 .
Buildroot nos brinda una interfaz amigable para seleccionar las versiones de las toolchains y configuraciones extras para implementar el entorno de compilación cruzada. Este software nos permite seleccionar a través de diferentes menúes las características que son necesarias de implementar.

Buildroot

Específicamente, Buildroot es un conjunto de makefiles y parches que permiten generar tanto el entorno de compilación cruzada como el sistema de archivo raíz para el sistema objetivo, otorgando una manera organizada de realizar las configuraciones. Por las características mencionadas es una alternativa muy utilizada para el trabajo con sistemas GNU/Linux embebido.

Estructura interna

Buildroot es basicamente un conjunto de Makefiles que descargan, configuran y compilan un determinado software. Esto incluye aplicar parches para diferentes paquetes de software, principalmente los involucrados en las herramientas para la compilación cruzada (toolchain).
Básicamente hay un archivo Makefile por software, denominados con la extensión .mk . Los Makefiles están divididos y ubicados en 4 secciones (directorios) :

  • project: contiene Makefiles y archivos asociados para todo el software relacionado con la compilación del sistema de archivo raíz .
  • toolchain: contiene Makefiles y archivos asociados para todo el software relacionado con las herramientas de compilación cruzada: binutils, ccache, gcc, gdb, kernel-headers, y uClibc.
  • package: contiene Makefiles y archivos asociados para todas aquellas herramientas de espacio de usuario que Buildroot puede compilar y agregar al sistema de archivo raíz. Existe un subdirectorio por herramienta.
  • target : contiene Makefiles y archivos asociados para el software relacionado con la generación de la imagen del sistema de archivos raíz. Cuatro tipo de sistemas de archivos son soportados: ext2, jffs2, cramfs y squashfs. Para cada uno de estos existe un subdirectorio con los archivos necesarios. También hay un directorio default que contiene la estructura del sistema de archivos objetivo.

Funcionamiento

Cada directorio contiene al menos dos archivos:

  • XYZ.mk es el Makefile que descarga, configura, compila e instala el software XYZ.
  • Config.in archivo de descripción de la herramienta de configuración. Describe las opciones relacionadas con el software seleccionado o en uso.

El Makefile principal realiza los siguientes pasos:

1- Crea el directorio de descarga (dl). Aquí es donde los tarballs serán descargados. Es interesante conocer que se encuentran en este directorio debido a que puede ser útil guardarlos para evitar futuras descargas.

2- Crea el directorio compartido (build_ARCH, donde ARCH es nuestra arquitectura). Es aquí donde todas las herramientas no configurables del espacio de usuarios serán compiladas.

3- Crea el directorio específico del proyecto de compilación (project_build_ARCH/$PROJECT). Es aquí donde todas las herramientas configurables del espacio de usuario son compiladas.

4- Crea el directorio donde los resultados específicos del proyecto se almacenan (binaries/$PROJECT). Es aquí donde la imagen del RFS es guardada, además es utilizada para almacenar la imagen del kernel Linux y cualquier utilitario, bootloaders, etc. necesarios para el sistema objetivo.

5- Crea el directorio de compilación de las toolchains (toolchain_dir_ARCH). Acá es donde se compila las toolchains de la compilación cruzada.

6- Instala el directorio de la plataforma (build_ARCH/staging_dir). Aquí es donde las toolchains de la compilación cruzada son instaladas.

7- Crear el directorio target y la estructura del sistema target (project_build_ARCH/root). Aqui se encuentra el directorio que contiene el sistema de archivos final.

8- Resuelve dependencias para los paquetes seleccionados.

En base a la arquitectura de hardware que hayamos seleccionado se remplaza ARCH por la arquitectura seleccionada. Para el caso del routerboard 532 esta será mipsel. Estos directorios han quedado de la siguiente manera:

build_mipsel_nofpu
dl
package
target
toolchain
toolchain_build_mipsel_nofpu

Configuración y uso

El menú de opciones y el modo de realizar la compilación es idéntica a la compilación y configuración del kernel Linux, incluso los comandos para iniciar el proceso son los mismos.
Para comenzar el proceso de configuración es necesario ubicarse dentro del directorio donde se ha descomprimido la descarga de Buildroot y lugo se debe ejecutar el siguiente comando,

emiliano@pianobar:~/buildroot$ make menuconfig
broot-main.png
Fig.10:Configuración de buildroot

En la Fig10 se observa el menú principal de configuración de Buildroot. Las opciones disponibles y sus respectivas funciones son las siguientes:
En los siguientes puntos se describen las opciones de configuración que provee la interfaz de Buildroot y se detallan las alternativas seleccionadas.

Target architecture
Aqui se define la arquitectura que posee el microprocesador del sistema objetivo. Para el caso del Routerboard 532 la opción a seleccionar es mipsel (Fig.11). Si bien la arquitectura es mips, se debe elegir la variante mipsel que esta relacionada al endianismo del microprocesador. El endianismo es una descripción de diferentes sistemas, hace referencia al orden en que se almacenan físicamente los bytes (2 bytes), si el byte más significativo (MSB) se almacena después o antes que el byte menos significativo (LSB). El microprocesador que posee el Routerboard 532 es Little endian, esto es, se almacena primero LSB y luego el MSB.
Build options
En esta sección se encuentra la configuracion general (Fig.12). Se pueden modificar el nombre de los directorios de descarga, el método y comando para realizar la descarga desde internet, los mirrors de Sourceforge, los nombres de los comandos y otras opciones globales.
Toolchain type
Además de utilizar Buildroot como generador de las herramientas de compilación cruzada, es posible utilizar herramientas externas (Fig.13).
Toolchain options
Bajo esta opción se puede seleccionar la configuración y versiones del conjunto de toolchains (binutils, gcc, librería C), los headers del kernel, herramientas de depuración tanto para el sistema objetivo como para el sistema huesped (Fig.14). En base al Routerboard 532 se han seleccionado las siguientes opciones.
  • gcc 3.4.2
  • uClibc 0.9.28
  • binutils 2.16.1
  • kernel headers 2.4.31
  • Use software floating point by default
Package selection for the target
Aqui se pueden seleccionar los binarios deseados para el sistema raíz objetivo, herramientas de desarrollo y utilizar una versión reducida de Busybox para generar el sistema de archivos raíz con sus binarios por defecto (Fig.15). En este punto no se ha seleccionado ninguna opción, debido que el sistema de archivo raíz se generará con Budybox de modo independiente.
Target options
La selección del tipo de sistema de archivos para el sistema objetivo (Fig.16). Aquí se ha seleccionado ext2 como sistema de archivos.
Board support options
Aquí se puede dar soporte específico para hardware determinado y protocolos ya predefinidos (Fig.17). En este punto no se ha realizado selección alguna.
br-target-arch.png br-build-op.png
Fig.11:Arquitectura mipsel Fig.12: Config. general
br-tchain-type.png br-tchain-options.png
Fig.13: toolchain Buildroot Fig.14: Versiones toolchain
br-pack-selection.png br-target-op.png
Fig.15:RFS Fig.16: sistema de archivos
br-board-sup.png
Fig.17:soporte de hw. y protocolos

Luego del proceso de configuración que se ha descripto en los puntos anteriores y una vez guardados los cambios se procede con la etapa de compilación. Simplemente se realiza el comando make estando ubicado en el directorio principal de Buildroot. Esto inicia el proceso de compilación de las herramientas de compilación cruzada. Dependiendo de la velocidad de procesamiento del equipo huesped y de la velocidad de la conexión a internet el proceso de compilación puede tardar algunas horas, para el equipo descripto al inicio del capítulo y una conexión a internet de 800 kbps ha llevado aproximadamente entre una y dos horas. El proceso muestra en su etapa incial los siguientes mensajes:

emiliano@pianobar:~/tesis/tesis/play/lab_buildroot/buildroot$ make
Checking build system dependencies:
CC clean:                                       Ok
CXX clean:                                      Ok
CPP clean:                                      Ok
CFLAGS clean:                                   Ok
INCLUDES clean:                                 Ok
wget --passive-ftp -P /mnt/tesis/tesis/play/lab_buildroot/buildroot/dl http://www.uclibc.org/downloads/toolchain/linux-libc-headers-2.4.31.tar.bz2
Petición HTTP enviada, esperando respuesta... 200 OK
100%[==================================================================>] 4.194.659     93.31K/s    ETA 00:00

Si bien se ha destacado que Buildroot permite generar el sistema de archivos raíz a ser utilizado en el sistema objetivo, aquí se ha realizado con otra herramienta específica para esta tarea denominada BusyBox3, que será explicada en el capítulo siguiente.

La función fundamental de Buildroot es permitirnos obtener un entorno de compilación cruzada funcional para realizar la compilación del sistema y de programas a ser ejecutados en el dispositivo Routerboard 532 brindando una interfaz amigable o al menos más intuitiva que realizar la configuración manual de los parámetros en cada archivo de configuración.
Si bien Buildroot brinda un ambiente organizado y simplificado a la hora de realizar un entorno de compilación cruzada, muchas veces ha sido necesario modificar desde los archivos de configuración fuente debido a errores en el proceso de compilación, por eso es útil conocer cuáles son estos archivos.
Los archivos de configuración relevantes son los siguientes:

  • buidroot/.config Bajo este archivo se encuentra la configuración global de Buildroot, modificar este archivo es equivalente a seleccionar las opciones que provee la interfaz de comando make menuconfig.
  • buildroot/toolchain/uClibc/uClibc-0.9.28.config Aquí se encuentran parámetros relacionados con la librería uClibc, con el tipo de microprocesador del dispositivo objetivo como el endianismo, la cantidad de bits, si posee unidad de punto flotante, etc.
  • buildroot/toolchain_build_mipsel_nofpu/uClib-0.9.28/.config

Bajo el directorio buildroot/package/ se encuentran los subdirectorios con el nombre de cada paquete, dentro de estos se pueden encontrar los archivos con extensión .mk que poseen la información sobre las dirección web de donde será descargado, el número de versión y otra información modificable.

Para el caso del paquete fakeroot, cuyo archivo de configuración fakeroot.mk se encuentra bajo la ruta buildroot/package/fakeroot, se ha modificado la variable FAKEROOT_VERSION con el valor 1.5.10.

El archivo de configuración global se denomina .config, en el mismo están todas las selecciones que se han realizado a través de la interfaz interactiva del comando make menuconfig.

SEGUIR CON ESTO
Ruta de los archivos de configuración
Como carajo usar este entorno para compilar algo
acordarse de setear la variable de entorno PATH
Y NADA MÁS IRÍA ACÁ, CREO…

Los parámetros seleccionados en cada opción del menú de configuración se han includo de modo detallado en el apéndice A.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License