Introducción
En esta serie de artículos, quiero comentar sobre el sistema de construcción de distribuciones buildroot y compartir mi experiencia en su personalización. Aquí habrá una experiencia práctica sobre cómo crear un pequeño sistema operativo con interfaz gráfica y funcionalidad mínima.
Primero que nada, no se debe confundir el sistema de construcción con la distribución. Buildroot puede compilar un sistema a partir de un conjunto de paquetes que se le han proporcionado. Buildroot se basa en archivos make y, por lo tanto, tiene enormes posibilidades de personalización. ¿Sustituir un paquete por otra versión, añadir tu propio paquete, cambiar las reglas de construcción del paquete, personalizar el sistema de archivos después de instalar todos los paquetes? Todo esto lo sabe hacer buildroot.
En Rusia se utiliza buildroot, pero en mi opinión, hay poca información en ruso para principiantes.
El objetivo del trabajo es compilar una distribución con arranque en vivo, interfaz icewm y navegador. La plataforma objetivo es virtualbox.
¿Por qué compilar tu propia distribución? A menudo se necesita funcionalidad limitada con recursos limitados. Aún más frecuentemente en la automatización se necesitan crear firmware. Adaptar una distribución de propósito general, eliminando paquetes innecesarios y convirtiéndola en firmware, es un camino mucho más laborioso que compilar una nueva distribución. El uso de Gentoo también tiene sus limitaciones.
El sistema buildroot es muy potente, pero no hará nada por ti. Solo puede ofrecer posibilidades y automatizar el proceso de construcción.
No se consideran ni comparan sistemas de construcción alternativos (yocto, open build system y otros).
Dónde conseguirlo y cómo empezar
Sitio del proyecto — . Aquí se puede descargar la versión actual y leer la guía. También se puede contactar con la comunidad, hay un seguimiento de errores, listas de correo y un canal IRC.
Buildroot opera con defconfig para la placa objetivo de construcción. Defconfig es un archivo de configuración que contiene solo las opciones que no tienen valor predeterminado. Este archivo determina qué y cómo se compilará. Además, se pueden configurar por separado los configs de busybox, linux-kernel, uglibc, cargadores u-boot y barebox, pero todos estarán vinculados a la placa objetivo.
Después de descomprimir el archivo descargado o clonar desde git, obtenemos un buildroot listo para trabajar. Se puede leer en la guía sobre la estructura de directorios, pero hablaré sobre los más importantes:
board — catálogo de archivos específicos para cada placa. Estos pueden ser scripts para la creación de imágenes del sistema (iso, sdcart, cpio y otros), el directorio overlay, la configuración del núcleo y más.
configs — el propio defconfig de la placa. Defconfig es una configuración incompleta de la placa. Contiene solo los parámetros que difieren de las configuraciones predeterminadas.
dl — directorio con los códigos fuentes/archivos descargados para la construcción.
output/target — sistema de archivos compilado del sistema operativo obtenido. A partir de él se crean imágenes para arranque/instalación.
output/host — utilidades host para la compilación.
output/build — paquetes compilados.
La configuración de la compilación se realiza a través de KConfig. Este mismo sistema se utiliza para la construcción del núcleo de linux. Lista de los comandos más utilizados (ejecutar en el directorio buildroot):
- make menuconfig — abrir la configuración de la compilación. También se puede hacer utilizando una interfaz gráfica (make nconfig, make xconfig, make gconfig).
- make linux-menuconfig — abrir la configuración del núcleo.
- make clean — limpiar los resultados de la compilación (todo lo que está en output).
- make — compilar el sistema. En este caso, no se realiza la recompilación de los procesos ya compilados.
- make defconfig_name — cambiar a una configuración específica de defconfig.
- make list-defconfigs — mostrar la lista de defconfig.
- make source — solo descargar archivos de instalación, sin compilar.
- make help — mostrar una lista de posibles comandos.
Notas importantes y consejos útiles.
Buildroot no recompila paquetes ya compilados. Por lo tanto, puede surgir una situación en la que se requiera una recompilación completa.
Se puede recompilar un paquete específico con el comando. make packagename-rebuild. Por ejemplo, se puede recompilar el núcleo de linux:
make linux-rebuild.Buildroot mantiene el estado de cualquier paquete creando archivos .stamp en el directorio output/build/$packagename.

Por lo tanto, se puede recompilar root-fs e imágenes sin recompilar paquetes:
rm output/build/host-gcc-final-*/.stamp_host_installed; rm -rf output/target; find output/ -name ".stamp_target_installed" | xargs rm -rf; make.Variables útiles.
En buildroot hay un conjunto de variables para facilitar la configuración.
- $TOPDIR — directorio raíz de buildroot.
- $BASEDIR — directorio OUTPUT.
- $HOST_DIR, $STAGING_DIR, $TARGET_DIR — directorios de construcción del sistema de archivos host, del sistema de archivos en staging, y del sistema de archivos objetivo.
- $BUILD_DIR — directorio con paquetes descompuestos y compilados.
Visualización
En buildroot hay opciones de visualización. Se puede construir un esquema de dependencias, un gráfico de tiempo de compilación, y un gráfico del tamaño de los paquetes en el sistema final. Los resultados se generan en formato pdf (se puede elegir entre svn, png) en el directorio output/graph.
Ejemplos de comandos de visualización:
make graph-depends.construir el árbol de dependenciasmake -graph-dependsconstruir el árbol de dependencias de un paquete específicoBR2_GRAPH_OUT=png make graph-buildgenerar un gráfico del tiempo de compilación con salida en PNGmake graph-sizeconstruir un gráfico del tamaño de los paquetes
Scripts útiles
En el directorio buildroot hay un subdirectorio utils con scripts útiles. Por ejemplo, hay un script que verifica la validez de la descripción de los paquetes. Esto puede ser útil al agregar sus propios paquetes (lo haré más tarde). En el archivo utils/readme.txt hay una descripción de estos scripts.
Construyamos una distribución base
Es importante recordar que todas las operaciones se realizan con un usuario normal, no root.
Todos los comandos se ejecutan en la raíz de buildroot. La entrega de buildroot ya incluye un conjunto de configuraciones para muchas placas comunes y virtualización.
Veamos la lista de configuraciones:

Cambiamos a la configuración qemu_x86_64_defconfig
make qemu_x86_64_defconfigY comenzamos la compilación
makeLa construcción se completa con éxito, veamos los resultados:
![]()
Buildroot ha compilado imágenes que se pueden ejecutar en Qemu y verificar que funcionan.
qemu-system-x86_64 -kernel output/images/bzImage -hda output/images/rootfs.ext2 -append "root=/dev/sda rw" -s -SEl resultado: un sistema ejecutado en qemu:

Creación de la configuración de su propia placa
Agregar archivos de la placa
Veamos la lista de configuraciones:

En la lista vemos pc_x86_64_efi_defconfig. Vamos a crear nuestra propia placa, copiando su configuración:
cp configs/pc_x86_64_bios_defconfig configs/my_x86_board_defconfigInmediatamente creamos un directorio para la placa para almacenar nuestros scripts, rootfs-overlay y otros archivos necesarios:
mkdir board/my_x86_boardCambiamos a esta defconfig:
make my_x86_board_defconfigAsí, ahora la configuración de compilación (almacenada en .config en la raíz del directorio de buildroot) corresponde a la máquina objetivo x86-64 con arranque legacy (bios).
Copiaremos la configuración de linux-kernel (será útil más adelante):
cp board/pc/linux.config board/my_x86_board/Configuración de parámetros de compilación a través de KConfig
Iniciamos la configuración:
make menuconfig Se abrirá la ventana de KConfig. Hay posibilidad de configurar con interfaz gráfica (make nconfig, make xconfig, make gconfig):

Entramos en la primera sección de Opciones de destino. Aquí se puede seleccionar la arquitectura de destino para la compilación.

Opciones de construcción: aquí hay varias configuraciones de compilación. Se pueden indicar directorios de código fuente, la cantidad de hilos de compilación, espejos para descargar código fuente y otras configuraciones. Dejar las configuraciones por defecto.
Toolchain: aquí se configura el propio conjunto de herramientas de compilación. Hablaremos más sobre ello.

Tipo de toolchain – el tipo de toolchain que se utiliza. Puede ser el integrado en buildroot o un toolchain externo (se puede indicar un directorio con el toolchain ya compilado o un URL para descargarlo). Para diferentes arquitecturas hay opciones adicionales. Por ejemplo, para arm, simplemente se puede elegir la versión del toolchain externo Linaro.
Biblioteca C – selección de la biblioteca C. Esto afecta el funcionamiento de todo el sistema. Generalmente se utiliza glibc, que soporta todas las funcionalidades posibles. Sin embargo, puede ser demasiado grande para un sistema embebido, por lo que a menudo se eligen uglibc o musl. Elegiremos glibc (esto será necesario más adelante para utilizar systemd).
Encabezados del Kernel y serie de Encabezados del Kernel Personalizados – debe coincidir con la versión del kernel que estará en el sistema compilado. Para los encabezados del kernel, también se puede indicar la ruta a un tarball o un repositorio de git.
VERSIONES DEL COMPILADOR GCC – selección de la versión del compilador que se utilizará para la compilación.
Habilitar soporte C++ – elegiremos construir con soporte para bibliotecas C++ en el sistema. Esto nos será útil más adelante.
Opciones adicionales de gcc – se pueden especificar opciones adicionales para el compilador. Por ahora no las necesitamos.
La configuración del sistema permite establecer los futuros parámetros del sistema creado:

La mayoría de los elementos son comprensibles por su nombre. Presten atención a los siguientes puntos:
Ruta a las tablas de usuarios — tabla con los usuarios que se crearán ().
Ejemplo de archivo. Se creará un usuario llamado user con la contraseña admin, automáticamente gid/uid, usando /bin/sh como shell, grupo predeterminado user, miembro del grupo root, comentario Foo user.
[alexey@alexey-pc buildroot ]$ cat board/my_x86_board/users.txt
user -1 user -1 =admin /home/user /bin/sh root Foo userDirectorios de superposición del sistema de archivos raíz — carpeta que se superpone al target-fs compilado. Agrega nuevos archivos y reemplaza los existentes.
Scripts personalizados para ejecutar antes de crear las imágenes del sistema de archivos — Scripts que se ejecutan justo antes de empaquetar el sistema de archivos en imágenes. De momento dejaremos el script vacío.
Pasemos a la sección del Kernel.

Aquí se configuran las opciones del kernel. El propio kernel se configura a través de make linux-menuconfig.
Se puede establecer la versión del kernel de varias maneras: elegir de las opciones disponibles, introducir la versión manualmente, indicar el repositorio o un tarball ya preparado.
Configuración del Kernel — ruta al archivo de configuración del kernel. Se puede elegir la configuración predeterminada para la arquitectura seleccionada o defconfig de Linux. En las fuentes de Linux hay un conjunto de defconfigs para diferentes sistemas objetivo. Se puede encontrar lo necesario, . Por ejemplo, para la placa beagle bone black se puede .
La sección Target packages permite elegir qué paquetes se instalarán en el sistema a construir. Por ahora dejaremos esto sin cambios. Más tarde, añadiremos nuestros propios paquetes a esta lista.
Imágenes del sistema de archivos: una lista de imágenes de sistemas de archivos que se construirán. Añadiremos una imagen ISO.

Gestores de arranque: selección de gestores de arranque para compilar. Elegiremos isolinix.

Configuración de Systemd
Systemd se ha convertido en uno de los pilares de Linux, junto con el kernel y glibc. Por ello, he separado su configuración en un apartado distinto.
Se configura a través de make menuconfig, luego Target packages → System tools → systemd. Aquí se puede especificar qué servicios de systemd se instalarán y se iniciarán al arrancar el sistema.

Guardar la configuración del sistema
Guardamos esta configuración a través de KConfig.
Después, guardaremos nuestro defconfig:
make savedefconfigConfiguración del núcleo de Linux
La configuración del núcleo de Linux se llama con el siguiente comando:
make linux-menuconfigAñadiremos soporte para la tarjeta gráfica de Virtualbox.

Añadiremos soporte de integración de Virtualbox Guest.

Guardamos y salimos. IMPORTANTE: la configuración se guardará en output/build/linux-$version/config, pero no en board/my_x86_board/linux.config

Por lo tanto, es necesario copiar manualmente la configuración al lugar de almacenamiento:
cp output/build/linux-4.19.25/.config board/my_x86_board/linux.configLuego, realizaremos una reconstrucción completa de todo el sistema. Dado que buildroot no reconstruye lo ya compilado, hay que especificar manualmente los paquetes para la reconstrucción. Para no perder tiempo y nervios, es más fácil volver a compilar un sistema pequeño completamente:
make clean;makeAl finalizar la construcción, ejecutamos VirtualBox (verificado en las versiones 5.2 y 6.0) con arranque desde el CD. Parámetros del sistema:

Arranque desde la ISO construida:

Lista de materiales utilizados
- Manual de Buildroot
Fuente: habr.com
