Настройка встраиваемого устройства 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, продолжат использовать традиционный, специфичный для поставщика GPU подход для подключения поверхностей окон 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, прежде чем начнется конфигурация. Именно в этом файле происходит настройка в отношении флагов компилятора и линковщика, а также специфических для цепочки инструментов и sysroot особенностей.
В следующих разделах мы представим файл цепочки инструментов, который можно использовать во многих случаях с минимальной настройкой. Он основан на подходе, представленном в этой статье блога.
Примечание: Файл цепочки инструментов, представленный ниже, является примером, который часто потребует дальнейшей настройки для данного устройства. Пользователи и системные интеграторы также могут создавать свои собственные файлы цепочки инструментов любым удобным им способом.
Хотя CMake — единственная поддерживаемая система сборки для создания самого Qt, приложения всё ещё могут быть собраны с помощью qmake в Qt 6.0. Для получения функциональной настройки qmake с кросс-компиляцией потребуется указать некоторые устаревшие аргументы для CMake или configure.
Инструменты хоста
Для кросс-компиляции Qt требуется доступная сборка Qt на хосте. Во время сборки такие инструменты, как moc, rcc, qmlcachegen, qsb, и другие, вызываются оттуда. Например, если вы кросс-компилируете для ARM на машине x64, сначала необходимо создать локальную x64-сборку той же версии Qt.
Путь к этой сборке Qt будет передан в configure или cmake.
Настройка Qt
Предположим, что доступны следующие:
- цепочка инструментов и sysroot по адресу
$HOME/rpi-sdk, - распределение Qt, по меньшей мере модуль qtbase, по адресу
$HOME/qt-cross, - сборка Qt на хосте в
$HOME/qt-host.
Кроме того, перед настройкой необходимо принять решения:
- Где будет установлена сборка Qt на локальной системе после завершения сборки? В примере мы будем использовать
$HOME/qt6-rpi. - Где будет развернута сборка Qt на устройстве? В примере мы будем использовать
/usr/local/qt6.
В примере мы будем использовать Raspberry Pi 4 SDK (цепочка инструментов + sysroot), сгенерированный с помощью Yocto, но инструкции здесь полностью универсальны, без зависимости от Yocto. После создания и перехода в каталог build, шаги остаются одинаковыми при использовании любой другой цепочки инструментов и 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
На практике эта команда configure эквивалентна следующему прямому вызову 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 \ $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, которые должны работать на целевом устройстве. Инструменты, связанные со сборкой, такие как moc и uic, не строятся. Построение таких инструментов можно включить, задав QT_BUILD_TOOLS_WHEN_CROSSCOMPILING значение ON.
Примечание: При включенном QT_BUILD_TOOLS_WHEN_CROSSCOMPILING, целевые двоичные файлы инструментов, таких как qmake, будут установлены в местоположение Staging. Поэтому, если использовать qmake для сборки приложений, следует вызвать скрипт host-qmake.
После успешной конфигурации без ошибок запустите cmake --build . --parallel для сборки. После сборки выполните cmake --install . для установки результатов в $HOME/qt6-rpi. Оттуда сборку Qt можно развернуть на устройстве, используя rsync, scp или другой метод.
При сборке отдельных модулей Qt можно использовать скрипт qt-configure-module из каталога bin места Staging ($HOME/qt6-rpi в примере) для конфигурирования дополнительных модулей, таких как qtdeclarative, qtquick3d и так далее. Затем они могут быть собраны с помощью cmake --build . и установлены в местоположение Staging путём выполнения 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 в Staging, можно собирать примеры или приложения.
С помощью CMake используйте сгенерированный скрипт qt-cmake в каталоге bin места Staging ($HOME/qt6-rpi в примере) для конфигурации, затем запустите ninja. Например:
$HOME/qt6-rpi/bin/qt-cmake . cmake --build .
Полученный двоичный файл приложения можно затем развернуть на устройстве. Использование вспомогательного скрипта qt-cmake удобно, поскольку скрипт гарантирует загрузку файла цепочки инструментов, использованного для сборки Qt, поэтому нет необходимости указывать его повторно для каждого приложения.
В отличие от Qt, сборка приложений с помощью qmake всё ещё поддерживается в Qt 6.0, при условии наличия подходящей спецификации устройства и передачи соответствующих устаревших аргументов в CMake или configure при конфигурировании Qt. Если всё это верно, то запуск 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.2/configure-linux-device.html