Настройка встраиваемого устройства Linux
Компиляция Qt для данного устройства требует цепочки инструментов и sysroot. Цепочка инструментов должна содержать версию gcc или другого компилятора и соответствующие инструменты, скомпилированные для кросс-компиляции. Это означает, что эти инструменты работают на системе хоста (обычно x64), создавая двоичные файлы для целевой архитектуры (например, 32 или 64-битный ARM). Sysroot содержит заголовки и библиотеки для целевой системы, позволяя компилировать и линкую библиотеки и приложения на хосте.
Эта обзорная страница описывает общий подход, где не используются системы сборки дистрибутивов, такие как Yocto или Buildroot. Всегда возможно кросс-скомпилировать и развернуть Qt на устройстве, если доступны подходящая цепочка инструментов и sysroot.
Предупреждение: Эта страница может предоставить только общий, высокоуровневый обзор. Существует множество деталей, которые могут меняться в зависимости от среды сборки, целевого устройства и цепочки инструментов. В случае сомнений обратитесь к вашему системному интегратору. Для предварительно скомпилированных образцов и SDK см. предложение Qt для создания устройств.
При запуске приложений Qt без системного окна, таких как X11 или Wayland, некоторые устройства требуют адаптационного кода, специфичного для поставщика, для поддержки EGL и OpenGL ES. Это обеспечивается бэкендами для плагина платформы EGLFS. Это не имеет значения для платформ без ускорения, таких как те, которые используют плагин платформы LinuxFB, предназначенный только для рендеринга на основе программного обеспечения. Начиная с Qt 6, многие встраиваемые системы используют drm для установки режима видео, управления разъёмами дисплея и графическими поверхностями. Например, устройство на базе NXP i.MX8 или Raspberry Pi 4 будут использовать этот подход, и, следовательно, наиболее часто используемый бэкенд для EGLFS — это eglfs_kms, который позволяет рендеринг на основе EGL и OpenGL ES с drm, используя gbm для управления поверхностями и буферами. Более старые устройства, такие как NXP i.MX6, по-прежнему будут использовать устаревший подход, специфичный для поставщика графического процессора, для подключения поверхностей окон EGL к буферу изображения, используя специализированные бэкенды eglfs, такие как eglfs_viv.
Примечание: Помните, что Qt — всего лишь один компонент в стеке программного обеспечения для встраиваемого устройства. Особенно при использовании ускоренной графики Qt ожидает функциональный графический стек с соответствующей конфигурацией для пользовательских и ядровых компонентов, таких как драйвер дисплея. Эти компоненты находятся за пределами области Qt, и системный интегратор отвечает за обеспечение полной функциональности и оптимальности базовой системы, включая ускоренную графику.
Дополнительную информацию о конфигурации графики и ввода для встраиваемых систем Linux см. в Qt для встраиваемого Linux.
Сравнение файлов цепочки инструментов и спецификаций устройства
В Qt 5 вы обычно использовали спецификацию устройства в каталоге qtbase/mkspecs/devices. Они содержат соответствующие флаги компилятора и линковщика для определённого устройства, а также обеспечивают выбор правильных библиотек EGL и OpenGL ES, в случае их расположения вне стандартного места в sysroot.
Например, вы могли бы настроить сборку Qt 5 для Raspberry Pi 2 с помощью команды конфигурации, подобной следующей:
./configure -release -opengl es2 -device linux-rasp-pi2-g++ -device-option CROSS_COMPILE=$TOOLCHAIN/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- -sysroot $ROOTFS -prefix /usr/local/qt5
В Qt 6 и CMake этот подход больше не является достаточным сам по себе. Вместо этого перед конфигурацией необходимо предоставить файл цепочки инструментов CMake CMake toolchain file. Именно в этом файле происходит настройка параметров компилятора и линковщика, а также специфических для цепочки инструментов и sysroot особенностей.
В следующих разделах мы представим файл цепочки инструментов, который может быть использован во многих случаях с минимальной настройкой. Он основан на подходе, представленном в этой статье блога.
Примечание: Представленный ниже файл цепочки инструментов — это пример, который часто требует дальнейшей настройки для данного устройства. Пользователи и системные интеграторы также могут создавать свои собственные файлы цепочки инструментов любым удобным для них способом.
Хотя CMake — единственная поддерживаемая система сборки для сборки самого Qt, приложения всё ещё могут быть скомпилированы с помощью qmake в Qt 6.0. Чтобы получить qmake установку, которая работает с кросс-компиляцией, необходимо указать некоторые устаревшие аргументы для CMake или для конфигурирования.
Инструменты хоста
Для кросс-компиляции Qt требуется хостовая сборка Qt. Во время сборки инструменты, такие как moc, rcc, qmlcachegen, qsb, и другие, вызываются из неё. Например, если вы кросс-компилируете для ARM на машине x64, сначала необходимо создать локальную x64 сборку Qt той же версии.
Настройка Qt
Предположим, что доступны:
- цепочка инструментов и sysroot по адресу
$HOME/rpi-sdk, - выгрузка Qt, как минимум модуль qtbase, по адресу
$HOME/qt-cross, - хостовая сборка Qt в
$HOME/qt-host.
Кроме того, перед настройкой необходимо принять следующие решения:
- Где будет установлена сборка Qt на локальной системе после завершения сборки? В примере мы будем использовать
$HOME/qt6-rpi. - Где будет развернута сборка Qt на устройстве? В примере мы будем использовать
/usr/local/qt6.
В примере мы будем использовать SDK Raspberry Pi 4 (цепочка инструментов + sysroot), сгенерированный с помощью Yocto, но инструкции здесь полностью общие и не зависят от Yocto. Шаги одинаковые при использовании любой другой цепочки инструментов и sysroot, как только файл цепочки инструментов будет обновлен с правильным кросс-компилятором и другими путями.
После создания и перехода в каталог build:
$HOME/qt-cross/qtbase/configure -release -opengl es2 -nomake examples -nomake tests \ -qt-host-path $HOME/qt-host \ -extprefix $HOME/qt6-rpi \ -prefix /usr/local/qt6 \ -- -DCMAKE_TOOLCHAIN_FILE=$HOME/qt-cross/toolchain.cmake \ -DQT_BUILD_TOOLS_WHEN_CROSSCOMPILING=ON
На практике эта команда конфигурации эквивалентна следующему прямому вызову CMake:
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DINPUT_opengl=es2 -DQT_BUILD_EXAMPLES=OFF -DQT_BUILD_TESTS=OFF \ -DQT_HOST_PATH=$HOME/qt-host \ -DCMAKE_STAGING_PREFIX=$HOME/qt6-rpi \ -DCMAKE_INSTALL_PREFIX=/usr/local/qt6 \ -DCMAKE_TOOLCHAIN_FILE=$HOME/qt-cross/toolchain.cmake \ -DQT_BUILD_TOOLS_WHEN_CROSSCOMPILING=ON \ $HOME/qt-cross/qtbase
С соответствующим файлом цепочки инструментов этого достаточно для создания сборки Qt, которая затем позволяет собирать приложения с помощью CMake. Чтобы также позволить сборку приложений с qmake, необходимо указать спецификацию устройства и параметры устройства в стиле Qt 5, а также все показанные выше аргументы:
$HOME/qt-cross/qtbase/configure ... ... -device linux-rasp-pi4-v3d-g++ \ -device-option CROSS_COMPILE=$HOME/rpi_sdk/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi- \ -device-option DISTRO_OPTS="hard-float" \ ...
Включение QT_BUILD_TOOLS_WHEN_CROSSCOMPILING необязательно. Если для целевого устройства требуются только библиотеки Qt без связанных инструментов, то можно его пропустить. Однако это часто хорошая идея, поскольку это приведет к созданию двоичных файлов инструментов, предназначенных для выполнения на целевом устройстве, таких как qml, qmlscene, или qmlpreview.
Примечание: При включении QT_BUILD_TOOLS_WHEN_CROSSCOMPILING, целевые двоичные файлы инструментов, таких как qmake, будут установлены в место назначения. Поэтому, если используется qmake, чтобы скомпилировать приложения, следует вызвать скрипт host-qmake.
После успешной конфигурации выполните cmake --build . --parallel, чтобы выполнить сборку. После сборки выполните cmake --install ., чтобы установить результаты в $HOME/qt6-rpi. После этого сборку Qt можно развернуть на устройстве, используя rsync, scp или другой метод.
Для сборки отдельных модулей Qt можно использовать скрипт qt-configure-module из каталога bin места назначения ($HOME/qt6-rpi в примере) для конфигурации дополнительных модулей, таких как qtdeclarative, qtquick3d и т. д. Затем их можно собрать, используя cmake --build ., и установить в место назначения, выполнив cmake --install ..
Примечание: Перед началом сборки всегда внимательно проверяйте вывод шага конфигурации: все ли ожидаемые функции включены? Бесполезно выполнять сборку и развертывание её на устройстве, если важные функции не включены на этапе конфигурации.
Например, при желании использовать ускоренную графику через OpenGL, уделите особое внимание следующим функциям:
EGL .................................... yes OpenGL: Desktop OpenGL ....................... no OpenGL ES 2.0 ........................ yes OpenGL ES 3.0 ........................ yes ... evdev .................................. yes libinput ............................... yes ... EGLFS .................................. yes EGLFS details: EGLFS OpenWFD ........................ no EGLFS i.Mx6 .......................... no EGLFS i.Mx6 Wayland .................. no EGLFS RCAR ........................... no EGLFS EGLDevice ...................... yes EGLFS GBM ............................ yes EGLFS VSP2 ........................... no EGLFS Mali ........................... no EGLFS Raspberry Pi ................... no EGLFS X11 ............................ no LinuxFB ................................ yes
В примере Raspberry Pi 4 мы ожидаем, что EGL, OpenGL ES и EGLFS GBM все будут отмечены как yes, иначе плагин платформы EGLFS и его бэкенд eglfs_kms не будут работать на устройстве. Для получения работы с функциями мыши, клавиатуры и сенсорного ввода необходимо включить либо evdev, либо libinput.
Аналогично, если планируется использовать X11 в качестве (или одной из) систем окон на устройстве, убедитесь, что функции, связанные с xcb и X11, отмечены как yes.
Пример файла цепочки инструментов
Предположим, что sysroot и цепочка инструментов доступны по адресу $HOME/rpi-sdk. TARGET_SYSROOT и CROSS_COMPILER должны быть скорректированы для используемой цепочки инструментов и sysroot. Приведённый пример подходит только для одного конкретного SDK, сгенерированного с помощью Yocto. То же самое относится к CMAKE_C_COMPILER и CMAKE_CXX_COMPILER.
Мы не полагаемся на скрипты-оболочки, которые предоставляли бы переменные среды, такие как PKG_CONFIG_*. Вместо этого путь к файлам .pc указывается в файле цепочки инструментов. Вероятно, для другого sysroot потребуются корректировки в PKG_CONFIG_LIBDIR. Например, с sysroot, сгенерированным из образа Raspberry Pi OS (ранее Raspbian), следует использовать /usr/lib/arm-gnueabihf/pkgconfig вместо этого.
Флаги компилятора и линковщика в примере не являются оптимальными. Настройте их по необходимости для целевого устройства.
Дополнительную информацию о специфике CMake в файле цепочки инструментов см. в этой статье блога и документации CMake.
cmake_minimum_required(VERSION 3.18)
include_guard(GLOBAL)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(TARGET_SYSROOT /home/user/rpi-sdk/sysroots/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi)
set(CROSS_COMPILER /home/user/rpi-sdk/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi)
set(CMAKE_SYSROOT ${TARGET_SYSROOT})
set(ENV{PKG_CONFIG_PATH} "")
set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig)
set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})
set(CMAKE_C_COMPILER ${CROSS_COMPILER}/arm-poky-linux-gnueabi-gcc)
set(CMAKE_CXX_COMPILER ${CROSS_COMPILER}/arm-poky-linux-gnueabi-g++)
set(QT_COMPILER_FLAGS "-march=armv7-a -mfpu=neon -mfloat-abi=hard")
set(QT_COMPILER_FLAGS_RELEASE "-O2 -pipe")
set(QT_LINKER_FLAGS "-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
include(CMakeInitializeConfigs)
function(cmake_initialize_per_config_variable _PREFIX _DOCSTRING)
if (_PREFIX MATCHES "CMAKE_(C|CXX|ASM)_FLAGS")
set(CMAKE_${CMAKE_MATCH_1}_FLAGS_INIT "${QT_COMPILER_FLAGS}")
foreach (config DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
if (DEFINED QT_COMPILER_FLAGS_${config})
set(CMAKE_${CMAKE_MATCH_1}_FLAGS_${config}_INIT "${QT_COMPILER_FLAGS_${config}}")
endif()
endforeach()
endif()
if (_PREFIX MATCHES "CMAKE_(SHARED|MODULE|EXE)_LINKER_FLAGS")
foreach (config SHARED MODULE EXE)
set(CMAKE_${config}_LINKER_FLAGS_INIT "${QT_LINKER_FLAGS}")
endforeach()
endif()
_cmake_initialize_per_config_variable(${ARGV})
endfunction() Сборка приложений для целевого устройства
После завершения сборки Qt и её установки в место назначения, примеры или приложения могут быть скомпилированы.
С помощью CMake используйте сгенерированный скрипт qt-cmake в каталоге bin места назначения ($HOME/qt6-rpi в примере) для конфигурирования, затем выполните ninja. Например:
$HOME/qt6-rpi/bin/qt-cmake . cmake --build .
Полученный двоичный файл приложения затем можно развернуть на устройстве. Использование вспомогательного скрипта qt-cmake удобно, потому что он загружает файл цепочки инструментов, который использовался для сборки Qt, поэтому нет необходимости указывать его повторно для каждого приложения.
В отличие от самого Qt, сборка приложений с помощью qmake всё ещё поддерживается в Qt 6.0, если доступна подходящая спецификация устройства и при конфигурировании Qt были переданы соответствующие устаревшие аргументы CMake или configure. Если это так, то выполнение qmake и make также сгенерирует двоичный файл приложения для целевого устройства.
Значения по умолчанию для плагинов платформы и EGLFS
После конфигурации выбирается плагин платформы по умолчанию. Он используется при запуске приложения без аргумента -platform и без установки переменной среды QT_QPA_PLATFORM.
Аналогично, плагин платформы EGLFS имеет несколько бэкэндов. По умолчанию выбирается бэкэнд в зависимости от доступности и предопределенного порядка приоритета. Если доступны drm и gbm, по умолчанию будет использоваться бэкэнд eglfs_kms. Это всегда можно переопределить во время выполнения, установив переменную среды QT_QPA_EGLFS_INTEGRATION.
Чтобы изменить эти значения по умолчанию для сборки, не принуждая к определенному значению во время выполнения, после выполнения CMake доступны следующие переменные кэша CMake:
-
QT_QPA_DEFAULT_PLATFORM(STRING) - Название плагина платформы по умолчанию. -
QT_QPA_DEFAULT_EGLFS_INTEGRATION(STRING) - Бэкэнд EGLFS по умолчанию.
Для получения дополнительной информации о конфигурировании Qt, см. Настройки конфигурации Qt.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.0/configure-linux-device.html