跳转到内容
新建笔记

Qt ARM 交叉编译中的 OpenGL 依赖与运行环境

先确定缺少的是哪一层

跳转到“先确定缺少的是哪一层”

原记录来自一个使用正点原子方案的 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 交叉编译工具说明。