配置嵌入式 Linux 设备
为特定设备交叉编译 Qt 需要一套工具链和一个sysroot。该工具链应包含 gcc 或其他编译器的某个版本,以及为交叉编译构建的相关工具。 这意味着这些工具在主机系统(通常为 x64)上运行,同时生成面向目标架构(例如 32 或 64 位 ARM)的二进制文件。sysroot 包含目标系统的头文件和库文件,从而允许在主机上编译和链接库及应用程序。
本概述页面描述了一种通用方法,该方法不使用 Yocto 或 Buildroot 等发行版构建系统。只要具备合适的工具链和 sysroot,就始终可以进行交叉编译并将 Qt 部署到设备上。
警告:本 页面仅提供通用且高层次的概述。具体细节因构建环境、目标设备和工具链的不同而存在巨大差异。如有疑问,请咨询您的系统集成商。有关预构建的参考镜像和 SDK,请参阅 Boot to Qt 相关资源。
在没有 X11 或 Wayland 等窗口系统的情况下运行基于 Qt 的应用程序时,某些设备需要供应商特定的适配代码来支持 EGL 和 OpenGL ES。这些适配代码以 EGLFS 平台插件后端的形式提供。 这对于非加速平台(例如使用 LinuxFB 平台插件的平台)并不适用,因为该插件仅适用于基于软件的渲染。截至 Qt 6,许多嵌入式系统使用drm来设置视频模式、管理显示接口和图形表面。 例如,基于NXP i.MX8的设备或树莓派 4 都会采用这种方法,因此 EGLFS 最常用的后端是eglfs_kms,它通过drm 启用基于 EGL 和 OpenGL ES 的渲染,并使用gbm 进行表面和缓冲区管理。 较旧的设备(例如NXP 的i.MX6)将继续采用传统的、特定于GPU供应商的方法,通过专用eglfs后端(如eglfs_viv )将EGL窗口表面连接到帧缓冲区。
注意:请 注意,Qt 只是嵌入式设备软件栈中的一个组件。特别是在涉及图形加速时,Qt 需要一个功能正常的图形栈,其中用户空间和内核组件(如显示驱动程序)必须配置得当。 这些组件超出了 Qt 的管辖范围,确保基础系统(包括图形加速功能)完全正常运行且处于最佳状态,是系统集成商的责任。
有关嵌入式 Linux 系统图形和输入配置的更多信息,请参阅《Qt for Embedded Linux》。
工具链文件与设备规范
在 Qt 5 中,通常会使用qtbase/mkspecs/devices目录下的设备规范文件。这些文件包含针对特定设备的适当编译器和链接器标志,同时确保正确加载 EGL 和 OpenGL ES 库——以防这些库在 sysroot 中位于非标准位置。
例如,您可以使用如下所示的 configure 命令为树莓派 2 配置 Qt 5 构建:
./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注意: 如果存在ninja 可执行文件,configure 始终会使用Ninja生成器和构建工具。Ninja 具有跨平台、功能丰富、性能优异等特点,建议在所有平台上使用。使用其他生成器可能有效,但不被官方支持。
在 Qt 6 和 CMake 中,仅靠这种方法已不再足够。相反,必须在进行配置之前提供一个CMake 工具链文件。正是通过这个文件,可以对编译器和链接器标志以及工具链和 sysroot 的特定特性进行自定义设置。
在以下各节中,我们将介绍一个工具链文件,该文件在许多情况下只需极少定制即可使用。它基于本文中介绍的方法。
注意: 下文介绍的工具链文件 仅为示例,通常需要针对特定设备进行进一步定制。用户和系统集成商也可以根据自身需求,自由创建自己的工具链文件。
虽然 CMake 是构建 Qt 本身时唯一受支持的构建系统,但在 Qt 6.0 中仍可使用qmake 构建应用程序。为了使qmake 配置能够支持交叉编译,需要向 CMake 或 configure 指定一些传统参数。
主机工具
跨编译 Qt 需要可用的 Qt 主机构建版本。详情请参阅《跨编译 Qt》。
配置 Qt
假设已具备以下条件:
- 位于
$HOME/rpi-sdk下的工具链和 sysroot, - 位于
$HOME/qt-cross下的 Qt 代码库(至少包含 qtbase 模块), - 位于
$HOME/qt-host目录下的 Qt 主机构建版本。
此外,在配置之前必须确定以下事项:
- Qt 构建完成后,将在本地系统的哪个位置安装?在本示例中,我们将使用
$HOME/qt6-rpi。 - Qt 构建结果将在设备上的哪个位置部署?在本示例中,我们将使用
/usr/local/qt6。
在本示例中,我们将使用通过 Yocto 生成的 Raspberry Pi 4 SDK(工具链+sysroot),但此处的说明完全通用,不依赖于 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实际上,此 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_FORCE_BUILD_TOOLS 设置为ON 来启用此类工具的构建。
注意:当启用 QT_FORCE_BUILD_TOOLS 时, qmake 等工具的目标二进制文件将被安装到暂存位置。因此,如果使用qmake 构建应用程序,请改用host-qmake 脚本。
一旦配置完成且无错误,请运行cmake --build . --parallel 进行构建。构建完成后,运行cmake --install . 将构建结果安装到$HOME/qt6-rpi 。随后,可通过 rsync、scp 或其他方法将 Qt 构建结果部署到设备上。
如果要构建单个 Qt 模块,可以使用临时存储位置(本例中为$HOME/qt6-rpi )的bin 目录下的qt-configure-module 脚本来配置其他模块,例如 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以树莓派 4 为例,我们期望 EGL、OpenGL ES 和EGLFS GBM 均被报告为yes ,否则 EGLFS 平台插件及其eglfs_kms后端将无法在设备上正常工作。若要获得功能完备的鼠标、键盘和触摸输入,必须启用evdev 或libinput 中的任意一项。
同样地,如果计划将 X11 作为设备上的(或其中之一)窗口系统,则请确保 xcb 和 X11 相关功能被标记为yes 。
工具链文件示例
我们将假设在$HOME/rpi-sdk 下有一个可用的 sysroot 和工具链。TARGET_SYSROOT 和CROSS_COMPILER 必须根据所使用的工具链和 sysroot 进行调整。此处的示例仅适用于一个特定的、由 Yocto 生成的 SDK。CMAKE_C_COMPILER 和CMAKE_CXX_COMPILER 也是如此。
我们不依赖任何会提供 PKG_CONFIG_* 等环境变量的封装脚本。相反,.pc 文件的路径会在工具链文件中明确指定。 若使用其他 sysroot,可能需要对PKG_CONFIG_LIBDIR 进行调整。例如,若使用由 Raspberry Pi OS(原 Raspbian)镜像生成的 sysroot,则应改用/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 时,请在暂存位置的bin 目录(示例中为$HOME/qt6-rpi )中使用生成的qt-cmake 脚本进行配置,然后运行ninja 。例如:
$HOME/qt6-rpi/bin/qt-cmake .
cmake --build .生成的应用程序二进制文件随后可部署到设备上。使用qt-cmake 辅助脚本非常方便,因为该脚本会确保加载用于构建 Qt 的工具链文件,因此无需为每个应用程序反复指定该文件。
与 Qt 本身不同,只要有合适的设备规范,并且在配置 Qt 时已向 CMake 或 configure 传递了相应的兼容性参数,Qt 6.0 仍然支持使用 qmake 构建应用程序。如果上述条件均满足,那么运行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) - 默认平台插件的名称。
这些变量也可以在工具链文件中进行设置。
有关配置 Qt 的更多信息,请参阅Qt 配置选项。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.