Настройка встраиваемого устройства 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, подобной следующей:
./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
Предположим, что доступны:
- цепочка инструментов и 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
На практике эта команда 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 \ -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 можно использовать скрипт 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, если доступна подходящая спецификация устройства, и соответствующие устаревшие аргументы были переданы в 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.1/configure-linux-device.html