Quieres incluir tu propia aplicación en una imagen Linux de Yocto. Necesitas compilar un proyecto de GitHub con Yocto. Pero, ¿cómo se escribe un archivo .bb?
Esta guía te lleva paso a paso por la creación de recetas Yocto desde cero, con ejemplos de código funcional en cada paso. Una vez que entiendas cómo funcionan las recetas, puedes empaquetar prácticamente cualquier software en una imagen Yocto.
¿Qué es una receta Yocto?
Una receta es un archivo .bb que describe cómo compilar e instalar una pieza específica de software. Piensa en ella como un script de compilación autónomo que responde cuatro preguntas:
- Dónde obtener el código fuente (
SRC_URI) - Cómo compilarlo (
do_compile) - Dónde instalarlo (
do_install) - Qué licencia usa (
LICENSE)
Nomenclatura de archivos de recetas
Los nombres de archivo de recetas siguen el patrón nombrePaquete_versión.bb:
hello-world_1.0.bb # hello-world versión 1.0
myapp_2.3.1.bb # myapp versión 2.3.1
busybox_1.36.1.bb # busybox versión 1.36.1
BitBake extrae automáticamente el nombre del paquete (PN) y la versión (PV) del nombre de archivo.
Estructura básica de una receta
# hello-world_1.0.bb
# ===== Metadatos =====
SUMMARY = "Hello World sample"
DESCRIPTION = "A minimal example recipe for learning Yocto"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
# ===== Adquisición de fuentes =====
SRC_URI = "file://hello.c"
# ===== Directorio de fuentes =====
S = "${WORKDIR}"
# ===== Compilación =====
do_compile() {
${CC} ${CFLAGS} ${LDFLAGS} -o hello hello.c
}
# ===== Instalación =====
do_install() {
install -d ${D}${bindir}
install -m 0755 hello ${D}${bindir}
}
Variables clave
Metadatos del paquete
| Variable | Descripción | Ejemplo |
|---|---|---|
SUMMARY | Descripción corta de una línea | "Hello World sample" |
DESCRIPTION | Descripción detallada | "A minimal learning example..." |
LICENSE | Identificador de licencia (SPDX) | "MIT", "GPL-2.0-only", "Apache-2.0" |
LIC_FILES_CHKSUM | Checksum del archivo de licencia | file://LICENSE;md5=xxx |
SRC_URI | Dónde obtener las fuentes | "file://", "git://", "https://" |
S | Dónde se desempaquetan las fuentes | $/git |
Variables de compilación e instalación
| Variable | Descripción | Se expande a |
|---|---|---|
${WORKDIR} | Directorio de trabajo para esta compilación | /tmp/work/.../hello-world/1.0-r0/ |
${D} | Raíz de staging para instalación | .../image/ |
${bindir} | Ruta /usr/bin | /usr/bin |
${libdir} | Ruta /usr/lib | /usr/lib |
${sysconfdir} | Ruta /etc | /etc |
${CC} | Compilador cruzado | arm-poky-linux-gnueabi-gcc |
Compilación de una receta Hello World
Compilemos la receta más simple posible y confirmemos que funciona de extremo a extremo.
Crear una capa personalizada
Siempre pon tus recetas en tu propia capa — nunca directamente en las capas de Poky.
cd ~/yocto/poky
source oe-init-build-env build
# Crear una nueva capa
cd ..
bitbake-layers create-layer meta-mylayer
# Añadirla a la compilación
cd build
bitbake-layers add-layer ../meta-mylayer
Consulta la guía de creación de capas para detalles sobre la gestión de capas.
Crear la estructura de directorios y el código fuente
mkdir -p ../meta-mylayer/recipes-example/hello-world/files
Escribe files/hello.c:
// files/hello.c
#include <stdio.h>
int main(void) {
printf("Hello from Yocto!\n");
printf("This app was built with a custom recipe.\n");
return 0;
}
Escribir la receta
Crea hello-world_1.0.bb:
# hello-world_1.0.bb
SUMMARY = "Hello World - Yocto recipe learning example"
DESCRIPTION = "A minimal application demonstrating how to write a custom Yocto recipe"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://hello.c"
S = "${WORKDIR}"
do_compile() {
${CC} ${CFLAGS} ${LDFLAGS} -o hello hello.c
}
do_install() {
install -d ${D}${bindir}
install -m 0755 hello ${D}${bindir}
}
Compilar e incluir en tu imagen
# Compilar la receta individualmente
bitbake hello-world
# El éxito se ve así:
NOTE: Tasks Summary: Attempted 123 tasks of which 120 didn't need to be rerun
Añade a conf/local.conf para incluirlo en la imagen:
IMAGE_INSTALL:append = " hello-world"
Recompila y prueba en QEMU:
bitbake core-image-minimal
runqemu qemux86-64 nographic
# Después del arranque:
root@qemux86-64:~# hello
Hello from Yocto!
This app was built with a custom recipe.
Obtener fuentes desde GitHub
En proyectos reales, normalmente obtendrás las fuentes de un repositorio externo en lugar de incluirlas localmente.
Ejemplo: Añadir nlohmann/json
# nlohmann-json_3.11.3.bb
SUMMARY = "JSON for Modern C++"
DESCRIPTION = "A header-only JSON library for C++"
HOMEPAGE = "https://github.com/nlohmann/json"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE.MIT;md5=f5f7c71504da070bcf4f090205ce1080"
# Obtener de GitHub usando HTTPS
SRC_URI = "git://github.com/nlohmann/json.git;protocol=https;branch=master"
# Fijar a un commit específico — siempre haz esto para reproducibilidad
SRCREV = "9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03"
S = "${WORKDIR}/git"
inherit cmake
EXTRA_OECMAKE = "-DJSON_BuildTests=OFF"
Patrones de SRC_URI
| Tipo de fuente | Formato de SRC_URI |
|---|---|
| Archivo local | file://hello.c |
| Git (HTTPS) | git://github.com/user/repo.git;protocol=https;branch=main |
| Git (SSH) | git://git@github.com/user/repo.git;protocol=ssh;branch=main |
| Tarball HTTP/HTTPS | https://example.com/file.tar.gz |
| Archivo de parche | file://fix-build.patch |
Uso de clases Inherit
Yocto incluye clases que encapsulan patrones de compilación comunes. Usar inherit te ahorra escribir tareas repetitivas de do_compile y do_install.
| Clase | Caso de uso | Qué automatiza |
|---|---|---|
cmake | Proyectos CMake | cmake → make → make install |
autotools | Proyectos Autoconf | configure → make → make install |
meson | Proyectos Meson | meson → ninja → install |
setuptools3 | Paquetes Python | instalación de setuptools / wheel |
systemd | Servicios systemd | Habilitación de servicios |
Ejemplo de proyecto CMake
# myapp-cmake_1.0.bb
SUMMARY = "My CMake App"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "git://github.com/user/myapp.git;protocol=https;branch=main"
SRCREV = "abc123def456..."
S = "${WORKDIR}/git"
inherit cmake
EXTRA_OECMAKE = "-DBUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release"
Ejemplo de proyecto Autotools
# myapp-autotools_1.0.bb
SUMMARY = "My Autotools App"
LICENSE = "GPL-2.0-only"
LIC_FILES_CHKSUM = "file://COPYING;md5=..."
SRC_URI = "https://example.com/myapp-1.0.tar.gz"
SRC_URI[sha256sum] = "def456..."
inherit autotools
EXTRA_OECONF = "--disable-docs"
Servicios systemd
Para iniciar automáticamente tu aplicación en el arranque, usa inherit systemd. Para configuración detallada, consulta la guía de servicios systemd.
Errores comunes y soluciones
Discrepancia de LIC_FILES_CHKSUM
ERROR: License checksum mismatch...
Causa: El hash MD5 en tu receta no coincide con el archivo de licencia real.
Solución: Recalcula el hash correcto:
md5sum LICENSE
do_fetch falló
ERROR: Fetcher failure: Unable to find file...
Causa: Ruta incorrecta en SRC_URI, o problema de red al obtener de Git.
Solución: Verifica tu SRC_URI y SRCREV. Asegúrate de que el hash de commit existe en el repositorio.
Nothing PROVIDES 'hello-world'
ERROR: Nothing PROVIDES 'hello-world'
Causa: La capa que contiene tu receta no está en bblayers.conf.
Solución: Añade la capa:
bitbake-layers add-layer ../meta-mylayer
Discrepancia de checksum de SRC_URI
ERROR: SRC_URI checksum mismatch...
Causa: El checksum de una descarga HTTP/HTTPS no está configurado o no coincide.
Solución: Calcula el checksum correcto:
sha256sum downloaded-file.tar.gz
Conclusión
Esto es lo que hay que recordar sobre escribir recetas Yocto:
- Las recetas son archivos
.bbque describen un proceso de compilación completo - Variables fundamentales:
SRC_URI,do_compile,do_install - Siempre pon tus recetas en una capa personalizada, no en Poky
- Usa
inheritpara manejar automáticamente proyectos CMake/Autotools/Meson - Añade paquetes a una imagen con
IMAGE_INSTALL:append - Siempre fija
SRCREVa un hash de commit específico para reproducibilidad
Una vez que te sientas cómodo escribiendo recetas, puedes empaquetar cualquier cosa en una imagen Yocto. Estos son los siguientes pasos:
- Crear y gestionar capas — arquitectura de capas para tus recetas
- Guía práctica de bbappend — personalizar recetas existentes
- Compilar Linux para Raspberry Pi — desplegar en hardware real
Para profundizar en Linux embebido, estos libros son excelentes referencias.