Embedded

Установка Qt на Raspberry Pi: системный Qt vs кросс-компиляция с хоста

Введение

Продолжая тему из статьи 341, разберём детальнее два конкретных подхода к получению рабочей среды Qt для Raspberry Pi — использование системных пакетов Qt, поставляемых с самой ОС, и полную кросс-компиляцию Qt из исходников на хост-машине для большего контроля над конфигурацией (включёнными модулями, оптимизациями).

Концепция

Системный Qt (из apt) — самый быстрый путь к работающей среде, но даёт меньше контроля над тем, какие модули Qt включены и с какими графическими бэкендами они собраны. Полная кросс-компиляция Qt из исходников на хосте даёт точный контроль над конфигурацией (например, явное включение нужного графического бэкенда EGLFS для безоконного, kiosk-режима из статьи 348), но занимает значительно больше времени на первоначальную настройку и саму сборку Qt (несколько часов даже на мощном хосте).

Пример кода: Установка Qt на Raspberry Pi

# Подход 1: системный Qt — самый быстрый старт
sudo apt update
sudo apt install qt6-base-dev qt6-declarative-dev qt6-multimedia-dev libgles2-mesa-dev

# Проверка установленной версии и доступных модулей
qmake6 --version
dpkg -l | grep qt6
# Подход 2: кросс-компиляция Qt из исходников на хосте (Ubuntu) —
# для случаев, когда нужен точный контроль над конфигурацией сборки Qt

# Шаг 1: получение sysroot — копии корневой файловой системы Raspberry Pi на хост,
# необходимой кросс-компилятору для линковки против правильных версий системных библиотек
rsync -avz --rsync-path="sudo rsync" pi@raspberrypi.local:/lib sysroot/
rsync -avz --rsync-path="sudo rsync" pi@raspberrypi.local:/usr/include sysroot/usr/
rsync -avz --rsync-path="sudo rsync" pi@raspberrypi.local:/usr/lib sysroot/usr/

# Шаг 2: конфигурация и сборка Qt из исходников с явным указанием sysroot и нужных модулей
./configure -release -opengl es2 -eglfs \
    -device linux-rasp-pi4-v3d-g++ \
    -device-option CROSS_COMPILE=/path/to/toolchain/bin/aarch64-linux-gnu- \
    -sysroot /path/to/sysroot \
    -prefix /usr/local/qt6-rpi \
    -skip qtwebengine  # пропуск тяжёлых, не нужных для конкретного проекта модулей сокращает время сборки

make -j$(nproc)
make install
# Использование собранного кросс-компилированного Qt в проекте — toolchain-файл CMake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER /path/to/toolchain/bin/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /path/to/toolchain/bin/aarch64-linux-gnu-g++)
set(CMAKE_SYSROOT /path/to/sysroot)
set(CMAKE_FIND_ROOT_PATH /usr/local/qt6-rpi)
set(CMAKE_PREFIX_PATH /usr/local/qt6-rpi)

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

Подход через системный Qt требует буквально пары команд apt install, что делает его очевидным выбором для начала экспериментов или небольших проектов, не требующих специфичной конфигурации сборки самого Qt. Сборка из исходников через ./configure с явными флагами -opengl es2 -eglfs -device linux-rasp-pi4-v3d-g++ демонстрирует точную настройку под конкретное аппаратное обеспечение Raspberry Pi 4 (GPU VideoCore VI через v3d-драйвер) — эта точность настройки важна именно для конфигураций, нацеленных на максимальную графическую производительность или безоконный kiosk-режим, тогда как универсальный системный пакет Qt собран с более общими, не специфично оптимизированными настройками.

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

  • Несинхронизированный sysroot, скопированный с устройства до обновления его системных библиотек, и последующая попытка запустить кросс-компилированное приложение на уже обновлённом устройстве — несовпадение версий системных библиотек между sysroot (использованным при сборке) и реальной файловой системой целевого устройства (на момент запуска) может привести к ошибкам совместимости версий динамических библиотек во время выполнения; sysroot стоит обновлять заново при значимых обновлениях системы на самом устройстве.
  • Сборка Qt из исходников без оценки реального времени, которое это займёт, особенно при первой попытке без должной кросс-компиляции (непосредственно на самом Raspberry Pi) — полная сборка Qt на самом устройстве может занимать многие часы или даже не завершиться вовсе из-за ограничений по памяти; кросс-компиляция на мощном хосте практически обязательна для разумного по времени процесса сборки Qt из исходников.
  • Пропуск важных, реально нужных модулей через -skip ради ускорения сборки, без проверки, что конкретный проект действительно не использует пропущенный модуль — обнаружение такой ошибки происходит обычно только на этапе линковки готового приложения, что требует повторной (долгой) пересборки Qt с включённым модулем; список модулей для -skip стоит формировать осознанно, исходя из реальных потребностей конкретного проекта.
  • Использование двух разных, несовместимых версий Qt одновременно — версии, установленной в системе через apt, и версии, собранной из исходников в отдельном префиксе (/usr/local/qt6-rpi в примере) — без явного, последовательного указания нужного CMAKE_PREFIX_PATH сборка может случайно подхватить не ту версию Qt, что приводит к трудно диагностируемым ошибкам совместимости символов или поведения во время выполнения.