Montando un toolchain con crosstool-ng

written by uve 1 March 2011

Hace un rato explicaba en qué consiste la compilación cruzada y ahora vamos a ver como montar un toolchain para poder hacer esto. Para ello he elegido la herramienta crosstool-ng ya que nos permite automatizar el proceso.

En mi caso voy a generar una toolchain para generar código en una arquitectura MIPS, ya que voy a implementar algunos programitas para un router. Además, he elegido Debian Squeeze como plataforma de trabajo, pero también lo he probado sobre Ubuntu 10.04 con el mismo resultado.

Lo primero es preparar el entorno para poder empezar a compilar. Para ello vamos a instalar los siguientes paquetes:

$ sudo apt-get install build-essential gawk bison flex automake libtool cvs lzma ncurses-dev

Lo siguiente es descargar la última versión (o la versión que necesitemos), que en mi caso es la versión 1.10.0 de crosstool-ng. Voy a trabajar directamente sobre el home del usuario user, así que supongo que tras la descarga, el fichero lo tendremos en /home/user/.

Empezamos por la extracción, configuración e instalación de la herramienta:

$ mkdir /home/user/crosstool
$ mkdir -p /home/user/toolchain/mips
$ tar xvjf crosstool-ng-1.10.0.tar.bz2
$ cd crosstool-ng-1.10.0/
$ ./configure --prefix=/home/user/crosstool/
$ make && make install

Para aclarar esto un poco, yo voy a utilizar los siguientes directorios:

  • /home/user/crosstool-ng-1.10.0/ -> Los fuentes de la herramienta
  • /home/user/crosstool/ -> Directorio donde está instalada la herramienta (binarios que utilizaremos para la construcción del toolchain)
  • /home/user/toolchain/ -> Directorio donde voy a tener las toolchains generadas
  • /home/user/toolchain/mips/ -> Archivos de crosstool-ng generados en este mini-tutorial
  • /home/user/toolchain/x-tools/ -> Directorios con los toolchains generado

Realmente, la instalación de crosstool-ng no se ha realizado en rutas del sistema, por lo que los ejecutables no están disponibles. Para que la terminal pueda encontrar los ejecutables debemos de tocar una variable del entorno:

$ export PATH="${PATH}:/home/user/crosstool/bin/"

Y ahora vamos a configurar nuestro toolchain. Este entorno le resultará familiar a todo aquel que haya compilado el kernel de Linux :)

$ cd /home/user/toolchain/mips/
$ ct-ng menuconfig

Aquí podemos ver una pantalla como la siguiente:

menuconfig

Estas son las opciones que he elegido:

  • Paths and misc options
    • Prefix directory: ${HOME}/toolchain/x-tools/${CT_TARGET}
  • Target options
    • Target Architecture: mips
    • Endianness: Big endian
    • Floating point: software
  • Toolchain options
    • Tuple's vendor string: ns
  • Operating System
    • Target OS: linux
    • Linux kernel version: 2.6.31.14
  • Binary utilities
    • binutils version: 2.19.1
  • C compiler
    • C compiler: gcc
    • gcc version: 4.3.2
    • [*] Optimize gcc libs for size
  • C library
    • C library: uClibc
    • uClibc version: 0.9.30.1
    • Configuration file: ${HOME}/toolchain/uClibc-0.9.30.1-mips-nofpu-config
    • Threading implementation to use: linuxthreads

¿Por qué estos parámetros? Algunos son dependientes del hardware, y están determinados por éste. En mi caso, uso una arquitectura MIPS fabricada por Atheros (y este fabricante emplea BigEndian), y además no hay disponible una FPU. En cuanto a las versiones del software utilizado, podemos jugar con ellas a nuestro antojo. Aquí podemos ver un listado (en la sección de Status) de algunas plataformas de gente que ya ha probado, podemos utilizarlas sin "problemas". El parámetro Tuple's vendor string es una cadena de texto que crosstool-ng usará como parte del nombre del toolchain. En mi caso, el nombre del toolchain será mips-ns-linux-uclibc. Cada cuál que use el nombre por defecto, o si no se indica se usará unknown. Y por último, aquí dejo el fichero que he utilizado para compilar uClibc.

Una vez configurado, toca la compilación. crosstool-ng se encarga de descargar los fuentes, extraerlos y configurarlos. Este es un proceso bastante largo y su tiempo de duración depende mucho de la conexión a Internet y la máquina que esté compilando. A mí me ha tardado alrededor de 50 minutos. Para compilar:

$ ct-ng build

Si el proceso falla, pues tendremos que ir cambiando las distintas configuraciones (a través de menuconfig) y volver a lanzar el proceso de construcción. Por suerte para nosotros, los fuentes descargados, siguen descargados; los paquetes compilados, siguen compilados; ... Así que el proceso seguirá prácticamente por donde iba antes de fallar.

Y para terminar, vamos a probar compilar un simple main. Lo primero es añadir los binarios del toolchain al PATH del sistema, para ejecutarlos sin problemas:

$ export PATH="${PATH}:/home/user/toolchain/x-tools/mips-ns-linux-uclibc/bin/"
$ mips-ns-linux-uclibc-gcc test.c -o test

Tags

La teoría es cuando crees saber algo, pero no funciona.
La práctica es cuando algo funciona, pero no sabes por qué.
Los programadores combinan la teoría y la práctica:
Nada funciona y no saben por qué.