Si alguna vez iniciaste una compilación de Yocto y la viste arrastrarse durante horas, no estás solo. Una compilación predeterminada de core-image-sato puede tomar medio día o más dependiendo de tu hardware.
Esta guía cubre todas las técnicas prácticas para acelerar tus compilaciones de Yocto, basada en Scarthgap 5.0 LTS (soportado hasta abril de 2028). Si no sabes por dónde empezar, simplemente trabaja las secciones de arriba a abajo — están ordenadas por impacto.
Por qué las compilaciones de Yocto son tan lentas
Antes de saltar a las soluciones, entendamos qué hace que las compilaciones de Yocto sean lentas en primer lugar.
BitBake procesa miles de tareas con cadenas de dependencias complejas. Para core-image-sato, descarga aproximadamente 6 GB de código fuente y compila miles de paquetes. Tres cuellos de botella principales dominan el tiempo de compilación.
1. E/S de almacenamiento
Las compilaciones involucran cantidades masivas de lecturas y escrituras de archivos pequeños. Si estás compilando en un HDD, este es tu mayor cuello de botella con diferencia. Cambiar a SSD NVMe marca una diferencia inmediata.
2. Mala configuración del paralelismo de CPU
BitBake auto-detecta la cantidad de núcleos de tu CPU para compilaciones paralelas, pero si no tienes suficiente RAM, el OOM killer interviene. Configurar un paralelismo demasiado bajo deja tu CPU ociosa.
3. Caché sin usar
La caché de estado compartido (sstate-cache) te permite saltarte tareas sin cambios en recompilaciones. Pero la configuración predeterminada la almacena dentro del directorio de compilación — así que cada vez que haces rm -rf build/, tu caché se va con él.
Replantea tus requisitos de hardware
Antes de ajustar la configuración del software, asegúrate de que tu hardware esté a la altura. Hay una diferencia significativa entre los requisitos mínimos oficiales y lo que realmente necesitas para un flujo de trabajo productivo.
| Componente | Mínimo oficial | Recomendación práctica |
|---|---|---|
| RAM | 8 GB | 32 GB o más |
| Disco | 90 GB (core-image-sato) | 500 GB SSD NVMe |
| CPU | 4 núcleos | 8–12 núcleos |
RAM
Cada hilo paralelo de BitBake (BB_NUMBER_THREADS) requiere aproximadamente 2 GB de RAM. Ejecutar 8 hilos significa que necesitas al menos 16 GB solo para la compilación, más memoria para el SO y la caché de páginas. 32 GB es el piso práctico.
Con 64 GB, más archivos permanecen en la caché de páginas del SO, reduciendo significativamente los tiempos de espera de E/S.
CPU
Las compilaciones de Yocto escalan hasta aproximadamente 12 núcleos. Más allá de eso, la E/S se convierte en el cuello de botella y añadir más núcleos no ayuda mucho. Una CPU rápida de 8–12 núcleos ofrece la mejor relación costo-rendimiento.
Almacenamiento
Cambiar de HDD a SSD NVMe proporciona la mayor mejora de rendimiento. La constante E/S de archivos pequeños durante las compilaciones satura completamente un disco giratorio. Un SSD SATA ayuda, pero NVMe es notablemente más rápido.
Sin rm_work, una compilación de core-image-sato necesita aproximadamente 90 GB de espacio en disco. Con rm_work habilitado, eso se reduce a aproximadamente 22 GB. En cualquier caso, un SSD de 500 GB+ te da espacio para múltiples proyectos.
Reduce el tiempo de recompilación en un 80% con sstate-cache
La caché de estado compartido (sstate-cache) es la forma más efectiva de acelerar las compilaciones de Yocto. Almacena la salida de tareas completadas y las reutiliza cuando las entradas no han cambiado.
La trampa de la configuración predeterminada
Por defecto, la sstate-cache reside dentro del directorio de compilación.
# Rutas predeterminadas (dentro de build/)
build/sstate-cache/
build/downloads/
El problema: ejecutar rm -rf build/ para empezar de cero también elimina tu caché. Borrar el directorio de compilación es una operación común al cambiar de rama o solucionar problemas — y con la configuración predeterminada, pierdes horas de trabajo en caché cada vez.
Mueve la caché fuera del directorio de compilación
Añade estas líneas a conf/local.conf.
# conf/local.conf
SSTATE_DIR = "/home/shared/yocto/sstate-cache"
DL_DIR = "/home/shared/yocto/downloads"
Este simple cambio preserva tu caché entre reinicios del directorio de compilación y permite que múltiples proyectos compartan la misma caché.
Comparte la caché en un equipo
Para desarrollo en equipo, aloja la sstate-cache en un servidor y compártela vía HTTP o NFS.
# conf/local.conf — obtener de un mirror remoto de sstate
SSTATE_MIRRORS = "file://.* http://sstate-server.local/sstate/PATH;downloadfilename=PATH"
PATH es una variable especial que Yocto expande a la ruta de directorio específica de la arquitectura automáticamente.
También puedes hacer mirror de las descargas de fuentes.
# conf/local.conf — mirror de fuentes
SOURCE_MIRROR_URL = "http://mirror-server.local/sources/"
INHERIT += "own-mirrors"
BB_GENERATE_MIRROR_TARBALLS = "1"
Configurar BB_GENERATE_MIRROR_TARBALLS = "1" crea tarballs de los repositorios Git y los almacena en DL_DIR. Esto está deshabilitado por defecto pero es esencial para compilaciones offline y compartir en equipo.
Ajuste de BB_NUMBER_THREADS y PARALLEL_MAKE
Dos variables controlan el paralelismo de compilación en BitBake. Es fácil confundirlas, pero sirven para propósitos diferentes.
| Variable | Controla | Valor predeterminado |
|---|---|---|
BB_NUMBER_THREADS | Número de tareas paralelas de BitBake | Cantidad de núcleos de CPU (auto-detectado) |
PARALLEL_MAKE | Número de trabajos make paralelos (-j N) | Cantidad de núcleos de CPU (auto-detectado) |
Ambos se establecen por defecto a la cantidad de núcleos de tu CPU. En meta/conf/bitbake.conf, están definidos como:
BB_NUMBER_THREADS ?= "${@oe.utils.cpu_count()}"
PARALLEL_MAKE ?= "-j ${@oe.utils.cpu_count()}"
Cuándo ajustar
Los valores predeterminados auto-detectados asumen que todos los núcleos están disponibles y que tienes suficiente RAM. Si te estás quedando sin memoria, necesitas reducir ambos valores. Si te sobra RAM, los valores predeterminados generalmente están bien.
Configuración manual
# conf/local.conf — ejemplo: 8 núcleos / 32 GB RAM
BB_NUMBER_THREADS = "8"
PARALLEL_MAKE = "-j8"
Importante: reducir solo BB_NUMBER_THREADS no ayuda si PARALLEL_MAKE sigue siendo alto — los procesos individuales de make seguirán generando demasiados hilos. Siempre ajusta ambos juntos.
Control basado en presión (Langdale 4.1+)
BitBake soporta control dinámico de paralelismo basado en la presión del sistema, en lugar de valores fijos. Esta característica está disponible desde Langdale (4.1) y funciona en Scarthgap.
# conf/local.conf — control dinámico basado en carga
BB_PRESSURE_MAX_CPU = "150"
BB_PRESSURE_MAX_IO = "80"
BB_PRESSURE_MAX_MEMORY = "50"
Esto usa /proc/pressure/ de Linux para monitorear la presión de CPU, E/S y memoria en tiempo real. Cuando la presión excede un umbral, BitBake retrasa el inicio de nuevas tareas. Es más flexible que valores fijos y se adapta automáticamente a diferente hardware.
Optimización del sistema de archivos y almacenamiento
Incluso con SSD NVMe, la configuración del sistema de archivos puede exprimir más rendimiento.
Opciones de montaje
La documentación oficial recomienda ajustar noatime y commit=.
# /etc/fstab — partición de compilación
/dev/nvme0n1p2 /home/build ext4 defaults,noatime,commit=30 0 2
- noatime: Deshabilita las actualizaciones de tiempo de acceso. Con miles de lecturas de archivos pequeños durante una compilación, esto elimina operaciones de escritura innecesarias
- commit=30: Extiende el intervalo de escritura a disco de los 5 segundos predeterminados a 30 segundos. Aumenta el riesgo por pérdida de energía pero reduce la frecuencia de escritura durante compilaciones
tmpfs (Beneficio limitado)
Podrías pensar que colocar TMPDIR en tmpfs (disco RAM) ayudaría, pero la documentación oficial señala:
"Aunque esto puede ayudar a acelerar la compilación, los beneficios son limitados debido a que el compilador usa
-pipe."
Dado que el compilador evita escribir archivos intermedios a disco, la ganancia de tmpfs es mínima. Considéralo solo como último recurso después de aplicar todas las demás optimizaciones, y solo si tienes 64 GB+ de RAM.
Formato de paquete
El PACKAGE_CLASSES predeterminado es package_rpm (formato RPM).
# conf/local.conf — IPK es el más liviano
PACKAGE_CLASSES = "package_ipk"
IPK es más liviano que RPM y más rápido de empaquetar. Es la elección estándar para dispositivos embebidos, así que a menos que necesites RPM específicamente, cambiar a IPK ahorra tiempo.
Elimina funcionalidades innecesarias para compilaciones más ligeras
La configuración predeterminada de Yocto incluye muchas funcionalidades que son irrelevantes para dispositivos embebidos. Reducir el alcance de la compilación recorta tanto el tiempo de compilación como el tamaño de la imagen.
Reducir DISTRO_FEATURES
Las DISTRO_FEATURES predeterminadas de Scarthgap incluyen:
# DISTRO_FEATURES predeterminadas de Poky (Scarthgap)
# acl alsa bluetooth debuginfod ext2 ipv4 ipv6 pcmcia usbgadget
# usbhost wifi xattr nfs zeroconf pci 3g nfc x11 vfat seccomp
# + Adiciones de Poky: opengl ptest multiarch wayland vulkan
Para un dispositivo embebido sin pantalla, las funcionalidades relacionadas con GUI son innecesarias.
# conf/local.conf — ejemplo de configuración sin pantalla
DISTRO_FEATURES:remove = "x11 wayland opengl vulkan bluetooth wifi 3g nfc pcmcia"
Usa rm_work para reducir el uso de disco
La clase rm_work elimina automáticamente los directorios de trabajo después de que cada receta se compila.
# conf/local.conf
INHERIT += "rm_work"
# Excluir recetas que necesitas depurar
RM_WORK_EXCLUDE += "my-custom-recipe"
Según la documentación oficial, esto reduce el uso de disco para core-image-sato de 90 GB a aproximadamente 22 GB. Con menos datos en disco, más archivos caben en la caché de páginas, mejorando indirectamente la velocidad de compilación.
La desventaja es que el código fuente y los archivos objeto se eliminan después de la compilación, dificultando la depuración. Usa RM_WORK_EXCLUDE para mantener los directorios de trabajo de las recetas que estás desarrollando activamente. Para técnicas de depuración, consulta la guía de depuración de errores de compilación.
Deshabilitar paquetes de depuración
# conf/local.conf
INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
Esto previene la generación de paquetes de símbolos de depuración, que son innecesarios para imágenes de producción.
La opción del servidor de compilación VPS
Compilar Yocto en tu laptop la bloquea durante horas. Un servidor de compilación VPS te permite descargar el trabajo sin ocupar tu máquina local.
Por qué VPS funciona para Yocto
- Especificaciones altas bajo demanda: No necesitas tener una estación de trabajo de 16 núcleos / 32 GB a tiempo completo
- sstate-cache persistente: Mantén la caché en el servidor y compártela entre miembros del equipo
- Integración CI/CD: Conecta GitHub Actions o GitLab CI a tu servidor de compilación
Especificaciones recomendadas
Las compilaciones completas de Yocto necesitan al menos 8 núcleos y 32 GB de RAM. Usa estas como guías.
| Caso de uso | CPU | RAM | Almacenamiento |
|---|---|---|---|
| Mínimo (core-image-minimal) | 4 núcleos | 16 GB | 100 GB SSD |
| Estándar (core-image-sato) | 8 núcleos | 32 GB | 300 GB SSD |
| Grande / Compartido en equipo | 16 núcleos | 64 GB | 500 GB+ NVMe |
Busca proveedores que ofrezcan almacenamiento SSD NVMe y al menos 8 núcleos con 32 GB de RAM. Los principales proveedores de nube (AWS, DigitalOcean, Hetzner, Vultr) tienen todos planes en este rango.
Configuración en un VPS
En Ubuntu 24.04 LTS, instala los paquetes necesarios.
sudo apt update
sudo apt install -y gawk wget git diffstat unzip texinfo gcc build-essential \
chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils \
iputils-ping python3-git python3-jinja2 python3-subunit zstd liblz4-tool \
file locales libacl1
sudo locale-gen en_US.UTF-8
Luego clona poky y configura la ruta de sstate-cache.
git clone git://git.yoctoproject.org/poky
cd poky
git checkout -t origin/scarthgap -b my-scarthgap
source oe-init-build-env
# Establecer rutas externas de sstate-cache y descargas
echo 'SSTATE_DIR = "/home/build/sstate-cache"' >> conf/local.conf
echo 'DL_DIR = "/home/build/downloads"' >> conf/local.conf
bitbake core-image-minimal
Conclusión
La clave para compilaciones más rápidas de Yocto es abordar primero las optimizaciones de mayor impacto.
| Prioridad | Técnica | Impacto |
|---|---|---|
| Crítica | Mover sstate-cache/DL_DIR fuera del árbol de compilación | 80%+ reducción en tiempo de recompilación |
| Alta | Cambiar a SSD NVMe | Elimina el cuello de botella de E/S |
| Alta | Ajustar BB_NUMBER_THREADS/PARALLEL_MAKE | Previene OOM, optimiza uso de CPU |
| Media | Habilitar rm_work | Uso de disco 90 GB → 22 GB |
| Media | Reducir DISTRO_FEATURES | Menos paquetes a compilar |
| Media | Cambiar PACKAGE_CLASSES a IPK | Empaquetado más rápido |
| Baja | Opciones de montaje noatime/commit= | Mejora pequeña a moderada |
| Baja | tmpfs | Beneficio limitado (según la documentación oficial) |
Empieza moviendo tu sstate-cache y DL_DIR a una ubicación persistente fuera del directorio de compilación. Ese solo cambio transforma la experiencia de recompilación diaria. A partir de ahí, ajusta según sea necesario para tu hardware y flujo de trabajo específicos.
Si quieres profundizar en el sistema de compilación de Yocto, estos libros son excelentes referencias. Mastering Embedded Linux Development cubre Scarthgap y recorre todo desde los internos del sistema de compilación hasta la escritura práctica de recetas.