Embedded

Подготовка embedded Linux образа с Qt: обзор процесса

Введение

Не каждой команде подходит коммерческий Boot2Qt — для полностью самостоятельного контроля над embedded Linux образом часто используется Yocto Project, более гибкий, но и значительно более сложный путь сборки кастомного Linux-дистрибутива именно под нужды конкретного устройства. В статье разберём общий обзор процесса подготовки такого образа с включённым Qt, без глубокого погружения в саму Yocto (что выходит за рамки Qt-ориентированного цикла статей), но с фокусом на том, как Qt вписывается в этот процесс.

Концепция

Yocto организует сборку дистрибутива через систему «слоёв» (layers) — модульных наборов рецептов (recipes), описывающих, что и как собирать. Существует официальный слой meta-qt6 (или meta-qt5 для пятой версии), добавляющий рецепты для сборки самого Qt и его модулей под целевую архитектуру. Процесс сборки образа сводится к: настройке local.conf с указанием целевой архитектуры платы, подключению нужных слоёв (включая Qt-слой и слой конкретной поддерживаемой платы — BSP), и запуску bitbake для итоговой сборки полного загружаемого образа.

Пример кода: Подготовка embedded Linux образа с Qt

# Типичная структура подготовки Yocto-сборки с Qt (общая схема команд)

# 1. Клонирование основного репозитория Poky (референсная реализация Yocto)
git clone -b kirkstone git://git.yoctoproject.org/poky
cd poky

# 2. Клонирование необходимых слоёв
git clone -b kirkstone git://git.yoctoproject.org/meta-qt6
git clone -b kirkstone https://github.com/meta-raspberrypi/meta-raspberrypi # BSP-слой платы

# 3. Инициализация окружения сборки
source oe-init-build-env

# 4. Подключение слоёв к текущей сборке
bitbake-layers add-layer ../meta-qt6
bitbake-layers add-layer ../meta-raspberrypi

# 5. Запуск итоговой сборки образа с включённым Qt
bitbake core-image-qt6
# conf/local.conf — ключевые настройки сборки
MACHINE = "raspberrypi4-64"
DISTRO_FEATURES:append = " wayland opengl"
IMAGE_INSTALL:append = " qtbase qtdeclarative qtquickcontrols2"
# Кастомный рецепт собственного приложения (my-embedded-app.bb)
SUMMARY = "Моё embedded Qt-приложение"
LICENSE = "CLOSED"

SRC_URI = "git://github.com/mycompany/embedded-dashboard.git;protocol=https;branch=main"
SRCREV = "${AUTOREV}"

DEPENDS = "qtbase qtdeclarative"

inherit cmake_qt6

S = "${WORKDIR}/git"

FILES:${PN} += "${bindir}/EmbeddedDashboard"

Пояснения к коду

Структура команд показывает типичный поток работы с Yocto: основной репозиторий Poky предоставляет базовую инфраструктуру сборки, а дополнительные слои (meta-qt6 для самого Qt, meta-raspberrypi как пример BSP-слоя конкретной платы) подключаются через bitbake-layers add-layer. local.conf определяет целевую машину (MACHINE) и какие конкретно компоненты Qt должны быть включены в итоговый образ (IMAGE_INSTALL) — без явного перечисления нужных модулей Qt (qtdeclarative для QML, qtquickcontrols2 для готовых компонентов интерфейса) итоговый образ может содержать только базовый qtbase, недостаточный для запуска QML-приложения.

Пример кастомного рецепта .bb-файла показывает, как собственное приложение интегрируется в процесс сборки Yocto — inherit cmake_qt6 подключает заранее подготовленный Yocto-класс, умеющий собирать CMake-проекты с правильно настроенным окружением кросс-компиляции для Qt, и DEPENDS явно указывает, какие компоненты Qt должны быть собраны до того, как начнётся сборка самого приложения.

Подводные камни

  • Время полной сборки Yocto-образа с нуля может занимать несколько часов, даже на достаточно мощной машине разработки — особенно при первой сборке, когда нужно скомпилировать буквально весь стек от тулчейна до конечного приложения; кеширование (sstate-cache) существенно ускоряет последующие пересборки, но требует отдельной настройки общего кеша для команды, разделяющей сборочную инфраструктуру.
  • Несовместимость версий слоёв между собой — каждый слой Yocto привязан к конкретному релизу (в примере — kirkstone), и попытка смешать слои из разных, несовместимых релизов часто приводит к труднообъяснимым ошибкам сборки; явное использование одной и той же ветки/релиза для всех клонируемых слоёв — обязательное правило.
  • Отсутствие официального BSP-слоя для конкретной, нестандартной платы заказчика. Для популярных референсных плат (Raspberry Pi, BeagleBone) BSP-слои хорошо поддерживаются сообществом, но для специально разработанной заказной платы потребуется самостоятельная разработка или адаптация BSP-слоя, что требует глубоких знаний embedded Linux, выходящих за рамки чисто Qt-экспертизы команды.
  • Лицензионная чистота итогового образа — при включении сторонних слоёв и рецептов важно отслеживать лицензии всех компонентов, попадающих в итоговый дистрибутив, особенно при коммерческом распространении устройства — Yocto предоставляет инструменты для генерации отчётов о лицензиях всех собранных пакетов, и этим стоит пользоваться осознанно, а не игнорировать на этапе подготовки продукта к выпуску.