先确定缺少的是哪一层
跳转到“先确定缺少的是哪一层”原记录来自一个使用正点原子方案的 ARM Qt 工程:带 OpenGL 的应用编译失败,作者当时判断目标 Qt 构建没有启用 OpenGL。它没有保留具体编译日志、Qt 版本、工具链或板卡镜像版本,因此应视为该工程的排查线索,不能推广成“所有这类镜像都缺 OpenGL”,也不能把使用虚拟机本身当成原因。
原文链接的野火 RK356x Qt 交叉编译教程是 Qt 5 的板级构建材料。阅读时应对应其开发板、系统与库路径;URL 是参考资料,不是一条 Bash 命令。Qt 6 的工具链与主机工具配置则应另看Qt 嵌入式 Linux 构建说明。
| 层次 | 需要一致的内容 | 常见表现 |
|---|---|---|
| 主机工具 | 在构建电脑上运行的 CMake、moc、rcc 等 | 错把 ARM 工具拿到 x86 主机运行,出现格式/执行错误 |
| 交叉编译器和 sysroot | 目标架构、ABI、目标头文件与库 | 链接报告文件格式不匹配或找不到目标库 |
| 目标 Qt | 版本、启用的图形功能、所需 Qt 模块 | 找不到 Qt OpenGL 组件或头文件 |
| 板端图形栈 | GPU 驱动、EGL/OpenGL ES、窗口系统或 EGLFS 后端 | 编译成功但运行时无法创建上下文/平台插件 |
| 应用的图形 API | 桌面 OpenGL 与 OpenGL ES 能力差异 | 函数、着色器版本或扩展在目标不可用 |
不要用主机的 libGL、Windows Qt 或另一个 ARM ABI 的库补进目标链接路径。“找到一个同名文件”不能证明它能被当前目标使用。
看实际配置,不靠名称猜功能
跳转到“看实际配置,不靠名称猜功能”先保存完整第一条错误及对应编译/链接命令,再核对 CMake 缓存中的 Qt 路径、工具链文件、sysroot 与编译器。更换这些基础设置后使用新的构建目录,防止旧探测结果残留。
如果重新构建 Qt,检查配置摘要的 EGL、OpenGL ES、目标窗口系统与相应平台后端是否满足需要。Qt 官方嵌入式示例说明:看到 Desktop OpenGL 为 no 不一定错误,设备可能本来使用 OpenGL ES;而 EGLFS 也不是每种 X11/Wayland 应用都必须启用。正确组合来自目标图形栈,不能仅添加一个 -opengl es2 就跳过依赖检查。
Qt 6 交叉构建需要兼容的主机 Qt 工具;QT_HOST_PATH 指向可在构建主机运行的那套工具,目标 Qt 与 sysroot 是另一组路径。不要把原 Qt 5 的 qmake device spec 配方与 Qt 6 CMake 工具链参数混用。
最小模块与链接检查
跳转到“最小模块与链接检查”下面是 Qt 6 应用探针,检查 Core/Gui/Widgets/OpenGL/OpenGLWidgets 组件能否配置、编译和链接。它不会创建 OpenGL 上下文,也不绘图;成功只说明这一级依赖成立。
CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)project(QtGraphicsProbe LANGUAGES CXX)set(CMAKE_CXX_STANDARD 17)set(CMAKE_CXX_STANDARD_REQUIRED ON)find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets OpenGL OpenGLWidgets)message(STATUS "Cross compiling: ${CMAKE_CROSSCOMPILING}")message(STATUS "System: ${CMAKE_SYSTEM_NAME}/${CMAKE_SYSTEM_PROCESSOR}")message(STATUS "Compiler: ${CMAKE_CXX_COMPILER}")message(STATUS "Sysroot: ${CMAKE_SYSROOT}")message(STATUS "Qt6_DIR: ${Qt6_DIR}")add_executable(graphics_probe main.cpp)target_link_libraries(graphics_probe PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets Qt6::OpenGL Qt6::OpenGLWidgets)main.cpp:
#include <QCoreApplication>#include <QOpenGLBuffer>#include <QOpenGLContext>#include <QOpenGLWidget>#include <QWidget>#include <QtGlobal>#include <cassert>#include <iostream>#include <type_traits>
static_assert(std::is_base_of_v<QWidget, QOpenGLWidget>);
int main(int argc, char **argv) { QCoreApplication app(argc, argv); QOpenGLBuffer buffer(QOpenGLBuffer::VertexBuffer); assert(!buffer.isCreated()); // No context or GPU allocation requested. assert(QOpenGLContext::currentContext() == nullptr); std::cout << "Qt " << qVersion() << ": graphics modules linked; no GL context tested\n";}交叉配置时使用目标 SDK 提供或验证过的工具链文件及目标 Qt 安装位置;这里没有编造通用于所有开发板的绝对路径。目标程序应在对应 ARM 系统上运行,不能用“构建电脑无法直接运行 ARM 可执行文件”判断 OpenGL 功能错误。
本页整理时只在 Windows Qt 6 主机 Kit 上验证了这份探针的配置、编译、链接和无上下文执行;没有进行 ARM 交叉构建或板端 GPU 验证。原现场缺失的版本和错误日志仍然未知。
链接通过之后仍需板端检查
跳转到“链接通过之后仍需板端检查”确认目标 Qt 与板上部署的库版本匹配,平台插件及其依赖齐全,再用最小实际图形程序检查上下文、渲染和驱动。QT_DEBUG_PLUGINS=1 可用于观察 Qt 插件加载诊断;这些输出能帮助定位依赖,不能单独证明 GPU 加速生效。Qt 插件排错
如果应用只画普通 QWidget 图形,先确认它是否真的依赖 OpenGL;若使用 QOpenGLWidget、图形库的 OpenGL 加速或对应渲染后端,则应沿实际依赖链检查。跨板移植时分别验证桌面 GL/GLES API、上下文版本和着色器,避免用编译成功替代运行能力确认。
来源:原工程记录、Qt 6 交叉编译工具说明。