Introducción
Después de la introducción a Buildroot veremos un ejemplo práctico de uso de esta herramienta para crear un rootfs mínimo para nuestra Raspberry Pi. En esta entrada explicaré las opciones básicas para la configuración de Buildroot y, aunque está orientado al uso de Raspberry Pi, es fácilmente portable a cualquier otra tarjeta de desarrollo cambiando muy pocas opciones.
Descargando Buildroot y configurando el entorno
Lo primero que tenemos que hacer para empezar a trabajar es descargar y configurar el entorno de desarrollo para Buildroot. Para esta entrada, tendremos un directorio llamado buildroot del que colgarán dos subdirectorios: src, donde tendremos los fuentes de Buildroot descargados y bin, donde se guardará la salida de Buildroot.
Así pues, lo primero que tenemos que hacer es crear nuestro directorio buildroot y, a continuación, descargar los fuentes de Buildroot. La forma elegida de hacerlo es a través de Git, ya que así obtendremos la versión mas reciente.
javieralso@bender:~/buildroot$ git clone git://git.buildroot.net/buildroot src Cloning into 'src'... remote: Counting objects: 112395, done. remote: Compressing objects: 100% (42898/42898), done. remote: Total 112395 (delta 76724), reused 103010 (delta 68912) Receiving objects: 100% (112395/112395), 31.88 MiB | 491.00 KiB/s, done. Resolving deltas: 100% (76724/76724), done. Checking connectivity... done javieralso@bender:~/buildroot$
A continuación creamos el directorio bin colgando de buildroot y lanzamos la interfaz de configuración de Buildroot desde el directorio con los fuentes:
javieralso@bender:~/buildroot/src$ make menuconfig O=../bin
Con la opción O=../bin, haremos que los archivos generados durante la configuración se guarden en el directorio bin.
Creando nuestra configuración
A partir de este momento, podemos empezar a crear una configuración nueva para que Buildroot genere el rootfs que necesitamos. Una vez invocado el comando anterior, se mostrará una ventana como la mostrada en la figura siguiente:
Configuración de la Arquitectura
La arquitectura utilizada por Raspberry Pi es ARM Little Endian, en concreto utiliza un procesador arm1176jzf-s. Configuramos la arquitectura desde el menú Target options --> Target architecture, donde seleccionaremos la opción ARM (little endian). La opción Target architecture variant la marcaremos con la opción arm1176jzf-s correspondiente al procesador del SoC montado por nuestra tarjeta. También configuraremos la opción Target EABI al valor EABIhf, con lo que optimizaremos el uso del hardware para punto flotante. Esta opción sólo deberá activarse si todo el software a ejecutar por nuestra RPI va a ser compilado por esta toolchain, ya que de lo contrario habrá problemas con el linker. Elijamos la opción que elijamos aquí, es importante que Floating point estrategy tenga activa la opción VFPv2, de este modo activaremos el coprocesador de punto flotante de nuestro micro. Deberá quedar algo similar a la siguiente figura:
Opciones de la Toolchain
El siguiente menú a configurar es Toolchain, donde configuraremos algunas opciones de la toolchain, como por ejemplo algunos flags a utilizar. En este punto deberemos modificar los siguientes puntos:
- Activamos la opción Enable IPv6 support.
- Activamos la opción Enable large file support.
- Activamos la opción Enable toolchain locale/i18n support.
- Activamos la opción Enable WCHAR support.
- Activamos la opción Enable RPC support.
- Activamos la opción Compile and install uClibc utilities.
- En Additional GCC options añadimos lo siguiente: --with-float=hard --with-fpu=vfp.
- Habilitamos el soporte para C++ (Enable C++ support).
- Activamos la opción Enable compiler tls support.
- En Generate locale data configuramos las locales es_ES (o cualquier otro que consideremos).
- Activamos el uso de MMU con la opción Enable MMU support.
- En Target Optimizations configuramos los flags -pipe -mfloat-abi=hard -mfpu=vfp.
Este menú permite elegir mas opciones, como por ejemplo el tipo de toolchain a utilizar (compilada por Buildroot o externa), Librería del Sistema a utilizar o Headers del núcleo a usar. Por el momento, nos bastará con dejar el resto de opciones como están.
Configuración del sistema
En el menú System Configuration tenemos un gran número de opciones que también son configurables, como por ejemplo el System Banner (el mensaje de bienvenida del prompt del sistema), el nombre del sistema (System hostname), la codificación de las contraseñas, contraseña del administrador (cuidado con poner aquí la contraseña de administración porque ésta no quedará protegida en el archivo de configuración) y varias opciones mas. En nuestro caso debemos de activar el acceso por consola serie al sistema habilitando la opción Run a getty (login prompt) after boot. En el menú getty options configuramos el valor ttyAMA0 en la opción TTY port, Baudrate a 115200 y TERM environment variable lo configuramos con vt100. También puede ser necesario marcar la casilla remount root filesystem read-write during boot.
Finalmente, una opción interesante es Root filesystem overlay directories. Aquí podremos escribir una lista de directorios que se copiarán "tal cual" al rootfs creado. En mi caso, lo utilizo para copiar los módulos del núcleo que utilizo (yo compilo el núcleo por separado, por lo que tengo que agregar los módulos a mano) y el directorio con el firmware necesario para el hardware que lo necesite, por ejemplo, una tarjeta wifi.
También podemos definir una serie de scripts que se ejecutarán antes y después de la creación del rootfs final.
Una vez que hemos configurado este menú, abandonamos y vamos al siguiente.
Núcleo y bootloader
Además del rootfs para nuestro sistema, Buildroot es también capaz de descargar, parchear y compilar tanto un núcleo como un bootloader para nuestro sistema. En mi caso, ambos componentes prefiero compilarlos por separado para tener un mayor control sobre ellos. Por ello, tanto en el menú Kernel, como en el menú Bootloader tengo desactivadas todas las opciones posibles.
Paquetes para el sistema
El menú Target Packages contiene una completa lista de paquetes que pueden ser compilados y añadidos a nuestro sistema, desde una Shell hasta juegos, librerías o herramientas de desarrollo. Lo aconsejable para empezar a trabajar es no tocar ninguna de las opciones de este menú para que se compile lo mínimo y así ahorrar tiempo e ir añadiendo paquetes conforme vayamos viendo que nuestra distribución va funcionando.
Sistemas de Archivos
El menú Filesystem Images permite seleccionar los formatos de salida en los que se generará nuestro rootfs. De momento, nosotros tan sólo necesitamos tener activa la opción tar the root filesystem, que deberá estar activa por defecto.
Utilidades para el Host
Finalmente, el menú Host utilities permite seleccionar algunas herramientas que pueden sernos de utilidad en la máquina host para utilizarlas como parte de nuestra toolchain. En este menú no es necesario marcar ninguna opción.
Generación de la imagen
Una vez que hemos configurado todas las opciones, salimos de la herramienta de configuración guardando los cambios. Ahora podemos movernos directamente al directorio bin que creamos anteriormente y desde ahí ejecutar make. A partir de ahí, Buildroot comenzará a descargar, parchear y compilar todos los paquetes que hemos configurado, empezando por crear la toolchain para nuestro nuevo sistema. Dependiendo de nuestra conexión a internet y de nuestra máquina, este proceso durará bastante, así que paciencia (mucha paciencia). Si nuestra máquina es multinúcleo, Buildroot tratará de paralelizar al máximo el trabajo para terminar antes.
Tras la compilación, se habrá generado una estructura de directorios como la explicada en el el anterior artículo sobre Buildroot, donde tendremos todas las herramientas, toolchain y rootfs para nuestra RPI.
Algunos objetivos interesantes
Aparte del objetivo por defecto de make, que como sabemos, genera todas las herramientas junto con el rootfs del sistema, podemos encontrar algunos otros objetivos bastante interesantes. Por ejemplo, con make legal-info, Buildroot generará un subdirectorio llamado legal-info en el que guardará toda la información legal de los paquetes que lo requieran, de modo que podremos distribuirla con nuestro sistema si fuese necesario.
Otra objetivo interesante es make savedefconfig. Esta opción generará un archivo de nombre defconfig en el que tendremos guardada la configuración generada anteriormente. De éste modo podremos volver a generar el sistema desde cero si fuese necesario.
Finalmente, podemos cargar cualquier configuración por defecto guardada en el directorio configs que cuelga de los fuentes de Buildroot. Para ello, basta con invocar make nombre_del_archivo, sin la ruta absoluta. Por ejemplo, si copiamos nuestro archivo defconfig generado anteriormente al subdirectorio configs renombrándolo como test_buildroot_defconfig, podremos volver a cargar esta configuración invocando make test_buildroot_defconfig.
Configuración por defecto de Buildroot
Como he comentado hace un momento, Buildroot dispone de varios archivos de configuración por defecto para bastantes tarjetas dentro del subdirectorio configs. A fecha actual (Septiembre de 2013), existe un archivo llamado rpi_defconfig con una configuración básica para Raspberry Pi. Esta configuración no sólo genera el rootfs, también genera el bootloader y el núcleo y podemos partir de ella si tuviésemos problemas con la configuración explicada anteriormente (nuevas versiones de Buildroot pueden hacer que algunas opciones dejen de existir o de funcionar). Para poder cargar esta configuración por defecto, tendremos que invocar make rpi_defconfig. De este modo, tendremos una configuración básica que con toda seguridad funcionará y a partir de la cual podremos empezar a trabajar.
Conclusiones
Como hemos podido comprobar, Buildroot es una herramienta bastante potente que nos permite, con bastante facilidad, crear distribuciones completas para sistemas empotrados basados en GNU/Linux. Aunque existen otras herramientas que tienen el mismo fin, como por ejemplo el Proyecto Yocto u OpenEmbedded, Buildroot destaca por su facilidad de uso.
Hay que recordar que esta entrada tan solo ha sido un breve resumen del uso de Buildroot. Existen infinidad de opciones y menús de configuración y también es posible añadir nuevos paquetes si fuese necesario para nuestro sistema.
También es posible, si se desea, generar configuraciones por separado para los distintos componentes, como pueden ser el núcleo o Busybox.
Referencias
La documentación on-line de Busybox está bastante actualizada y dispone de toda la información necesaria para su uso y configuración.