开源鸿蒙PC移植 Mesa 适配 HarmonyOS PC:从 EGL 符号治理到真机消费者验证
欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper/
欢迎加入开源鸿蒙PC社区:Harmony PC 开发者社区
欢迎在PC社区平台申请新建项目:OpenHarmony PC Developer - 开源代码托管,代码协作 - AtomGit
本文记录 Mesa 24.3.4.1.1 在 HarmonyOS PC AArch64 上的适配、Conan 制品交付和消费者验证。上游源码版本是 Mesa 24.3.4,
24.3.4.1.1是本项目的 Conan 交付版本。测试数字只采用实际回报和日志中已经验证的口径,不把未完成的跨平台测试写成全量通过。
一、先看结论

Mesa 是图形栈的核心项目,涉及 EGL、GLES、GBM、OSMesa、Gallium 和多个软件渲染后端。HarmonyOS PC 适配的难点不只是把代码编译出来,还要让共享库导出表、动态加载、无显示器软件渲染和 ELF 运行时约束同时成立。
本轮交付的关键结果:
| 项目 | 结果 |
|---|---|
| 上游项目 | Mesa |
| 上游源码版本 | 24.3.4 |
| Conan 交付版本 | 24.3.4.1.1 |
| 官方源码地址 | https://archive.mesa3d.org/mesa-24.3.4.tar.xz |
| 源码 SHA-256 | e641ae27...(以配方和证据日志中的完整值为准) |
| 目标平台 | HarmonyOS PC / AArch64 |
| 分支 | fix/mesa-24.3.4.1.1 |
| PR | MR #11116 |
| 最新交付提交 | da7d9cfe95f7ac42746f271631593e35f3c17731 |
| 交付状态 | PR 已更新并触发 /rebuild,以页面最终状态为准 |
本轮最终修复集中在两个问题:
libdrm静态库通过link_whole被并入共享libEGL,导致 137 个drm*符号泄漏到 EGL 导出表。llvm-nm将三个 libc weak-UND 符号按 4 字段输出,触发egl-symbols-check的误报。
最终使用正式交付补丁 0011 和 0012,conan create 返回 0,test_mesa、EGL 动态加载、GBM/EGL/GLES 消费者和 OHOS 专项测试均通过。
图 1:MR #11116 显示 Mesa 高难度交付已合入,页面展示版本、分支、测试统计和审核状态。
二、Mesa 在图形栈中的位置
可以把本次适配理解为下面这条链路:
Mesa 源码
-> Meson 构建 EGL/GLES/GBM/OSMesa/Gallium
-> Conan 配方打包 include/ lib/ bin/
-> ohpcd 制品仓发布 mesa/24.3.4.1.1
-> 下游通过 EGL/GLES/GBM 或 OSMesa 消费
-> HarmonyOS PC 上动态加载、渲染并运行
这里有三个容易混淆的版本号:
| 名称 | 含义 |
|---|---|
mesa-24.3.4 | 官方上游 tarball/tag 的源码版本 |
mesa/24.3.4.1.1 | 本项目 Conan 配方使用的交付版本 |
fix/mesa-24.3.4.1.1 | AtomGit 交付分支 |
Conan 版本增加修订号,不代表伪造了一个上游 Mesa 版本;它用于承载 HarmonyOS PC 的配方、补丁和制品修订。
三、为什么这是高难度适配
3.1 共享 EGL 的导出表不是“能链接”就结束
Mesa 的 libEGL 会链接多个静态和共享组件。在本项目中,libdrm 通过 link_whole 进入链接闭包。普通链接成功只能说明符号能被解析,却不能说明共享库的公开导出表符合 EGL 的接口边界。
第一次检查时,egl-symbols-check 发现 137 个 drm* 符号从 libEGL 泄漏出去。这个问题会带来两个风险:
- 下游可能误以为这些 DRM 符号是 EGL 的稳定公开 API;
- 同名符号与系统
libdrm或其他图形组件发生意外绑定。
3.2 weak-UND 符号会造成测试误报
egl-symbols-check 使用 llvm-nm 检查导出符号。HarmonyOS libc 中的 pthread_mutexattr_destroy、pthread_mutexattr_init、pthread_mutexattr_settype 以 weak-UND 形式出现,llvm-nm 的输出字段形态与检查脚本默认假设不同。
这三个符号不是 Mesa 把错误 API 导出到 EGL,而是平台 libc 的弱未定义引用。如果不区分 weak-UND 和真实导出,检查会把平台 ABI 特征误报成 Mesa 导出错误。
3.3 图形库必须面对无显示器环境
HarmonyOS PC 适配不能假定存在 X11、Wayland 或真实 DRM 设备。Mesa 的软件渲染路径、EGL surfaceless、GLES 最小调用和 OSMesa 离屏上下文,是更适合在设备上验证的路径。
本轮消费者验证覆盖 eglInitialize、eglQueryString、GLES2 调用、OSMesa 固定管线,以及 GBM/EGL/GLES 公开头文件的编译链接。它们验证的是可消费性,不等价于真实 GPU 驱动或窗口系统已经支持。
四、难度拆解:Mesa 为什么不是普通 C/C++ 库适配
很多库的 HarmonyOS PC 适配,只需要解决“编译器不认识某个宏”“缺一个头文件”或“测试 ELF 需要签名”。Mesa 不一样:它是一个把图形 API、动态链接 ABI、软件渲染器、硬件驱动接口、编译器工具链和窗口系统适配层组合在一起的图形栈。一个库的构建成功,并不代表另一个层面的接口边界正确。
4.1 难点一:一个源码树同时生成多类用户可见库
本次包不只生成一个 libmesa.so。交付物中至少涉及:
| 组件 | 下游用途 | 验证重点 |
|---|---|---|
libEGL.so.1 | 上下文、显示连接、surfaceless 初始化 | SONAME、动态加载、导出符号表 |
libGLESv2.so | GLES2 渲染 API | 公开头文件、链接和运行时依赖 |
libGLESv1_CM.so | 兼容固定管线接口 | 包内布局和消费链路 |
libgbm.so.1 | 图形缓冲区管理接口 | gbm.h、pkg-config、链接边界 |
libOSMesa.so.8 | 无窗口系统离屏软件渲染 | 上下文创建、像素缓冲区和 GL 版本 |
这意味着“一个二进制跑起来”不够。任何一个组件遗漏安装、SONAME 错误、导出表污染或运行时加载到系统同名库,都会让下游得到错误的结论。因此文章必须同时给出制品内容图、SONAME 图和真实 dlopen 图。
4.2 难点二:Meson 交叉编译和图形依赖不是普通静态链接
Mesa 使用 Meson 构建,且依赖链中包含 LLVM、libdrm、expat 以及生成阶段的 bison/flex/m4。这里同时存在 build-machine 工具和 host-machine 图形库:
构建机工具:bison / flex / m4
目标机库:libdrm / LLVM / expat / Mesa EGL-GLES-GBM
运行时组件:Gallium driver / libEGL / libGLAPI / 系统 libc
如果把这些角色混在一起,常见结果是“配置阶段找到的是宿主工具,运行时加载的是目标库的错误版本”,或者 Conan 根据 ABI 计算出另一个 package ID。本次真机安装时必须固定 OHOS / armv8 / clang 15 / C++17 / libc++,正是为了让消费者获得与已发布 Mesa 包相同的二进制身份。
4.3 难点三:共享库 ABI 比链接成功更严格
静态库通过 link_whole 进入共享库时,链接器并不会自动判断哪些符号应该成为对外 ABI。libEGL 在修复前泄漏 137 个 drm* 符号就是典型例子:生成 libEGL.so 没有失败,dlopen 也未必立即失败,但共享库已经暴露了不应公开的实现细节。
这类问题难在它通常只会被符号质量门禁或复杂下游发现。为此,本项目把检查从“库是否存在”提升为:
共享库文件存在
-> SONAME 正确
-> EGL 声明 API 存在
-> 静态 libdrm 内部符号不泄漏
-> dlopen 和 eglInitialize 可运行
--exclude-libs,ALL 的意义也在这里:它处理 ABI 边界,而不是一次普通的编译兼容补丁。
4.4 难点四:平台工具行为会改变测试结论
本轮不仅要面对 Mesa 自身代码,还要面对 llvm-nm、Meson、LLVM 工具链和 HMDFS 文件系统的行为差异。
llvm-nm对 weak-UND 的输出字段形态,使 EGL 符号检查把 libc 弱引用误判为非法导出;- HMDFS 对某些权限、缓存和临时文件操作的语义与常规 Linux 文件系统不同;
- HarmonyOS PC 没有可假定存在的 X11、Wayland、
/dev/dri或桌面 GPU 驱动路径; - SDK clang 在链接阶段会调用自身的 lld,运行时还需要正确的 LLVM/libxml2 搜索路径。
这些问题都不能靠把测试直接跳过解决。项目采用的是“明确平台边界 + 最小独立复验”的方式:对 weak-UND 只忽略三项已经解释的符号;对无 GPU 场景使用 surfaceless EGL 和 llvmpipe;对 SDK linker 运行时缺库问题显式设置 SDK LLVM 库路径。
4.5 难点五:软件渲染成功与硬件驱动成功必须分开
Mesa 的软件渲染路径可以在没有 GPU 驱动、没有显示服务器的条件下产生有效结果。图 5 的 EGL 1.5 初始化和 llvmpipe/OSMesa 测试证明的是:
Mesa 包可加载
+ EGL API 可初始化
+ 软件渲染路径可用
+ Conan 消费者能在真机运行
它不证明以下结论:
真实 GPU 驱动已加载
X11/Wayland 已支持
DRM 设备节点可用
所有 Gallium 硬件后端均可用
高难度适配的价值不是把结论写大,而是精确划分“已经验证的软件栈能力”和“仍依赖设备图形基础设施的能力”。
4.6 难点六:上游测试规模大,不能用一个通过率掩盖差异
MR 页面记录的上游审查口径达到 3264 项。Mesa 测试不仅有普通单元断言,还包括驱动专属、IR、缓存、反汇编、图像比较和平台工具依赖。OHOS 上某个 GTest 未完成,可能是 HMDFS、GLSL IR、字节序、外部工具、后端模块或网络来源阻塞,并不必然说明 EGL/GLES 基础链路损坏。
因此,本项目把测试结果拆成三层:
| 层次 | 本轮回答的问题 | 结论表达 |
|---|---|---|
| 上游测试台账 | 哪些原始测试和平台边界存在 | 保留未完成项、首错和恢复条件 |
| 包级门禁 | 配方、补丁、共享 ABI、test_package 是否闭环 | conan create、符号检查和审计通过 |
| 真机消费者 | 发布制品能否被真实下游加载和调用 | dlopen、EGL 1.5、退出码 0 |
只有三层都呈现,读者才能区分“完成了软件图形栈可消费交付”和“尚未具备全部硬件驱动矩阵”。这也是 Mesa 适配相较普通库最容易被误报、也最需要严谨说明的地方。
五、适配前的环境和源码固定
5.1 固定官方源码
配方使用官方 Mesa 归档地址:
https://archive.mesa3d.org/mesa-24.3.4.tar.xz
适配前至少保存以下信息:
curl -fL -o mesa-24.3.4.tar.xz \
https://archive.mesa3d.org/mesa-24.3.4.tar.xz
sha256sum mesa-24.3.4.tar.xz
实际配方证据确认官方 URL 和 e641ae27... 源码摘要一致。发布文章时应把完整 SHA-256 从最终日志复制过来,不要只保留省略值。
5.2 目标配置
本次构建以 OHOS AArch64 为目标,核心设置为:
os=OHOS
os.version=6.0
arch=armv8
build_type=Release
compiler=clang
compiler.version=15
compiler.cppstd=17
compiler.libcxx=libc++

图 2:真机终端显示 HarmonyOS、AArch64、Conan 2.29.1,以及 clang 和 binary-sign-tool 的实际路径。
Mesa 是 Meson 项目,Conan 配方负责把目标编译器、工具链、依赖路径和安装布局传入构建过程。不要把服务器上的 Linux Mesa 包路径直接复制到真机;最终验证必须从 Conan 包的 include/、lib/ 和实际运行环境取得文件。
5.3 依赖边界
Mesa 可以包含很多可选驱动和窗口系统后端。HarmonyOS PC 本轮的验证重点是:
- EGL 共享库及其 SONAME;
- GLESv1/GLESv2 公开接口;
- GBM 接口和链接闭包;
- OSMesa 软件渲染;
- Gallium softpipe/llvmpipe 离屏路径;
- OHOS 专项进程名和离屏渲染测试。
X11、Wayland、真实 GPU 内核驱动、系统 DRM 设备等能力如果没有在设备上成立,必须作为边界说明,而不是从测试分母中悄悄删除。
六、两项正式修复
6.1 补丁 0011:收敛 libEGL 的静态符号泄漏
问题表现:
egl-symbols-check: drm* leaked symbols = 137
根因是 libdrm 静态库通过 link_whole 被整体带入共享 libEGL。整体链接能保证内部符号可用,但也可能把不属于 EGL 公开接口的符号带入动态导出表。
解决方式是在 libEGL 的链接参数中增加:
-Wl,--exclude-libs,ALL
这个选项不删除 EGL 自己的公开 API,而是限制静态库成员符号向共享库外部导出。修复后,检查结果从 137 个 drm* 泄漏降为 0。
需要注意:--exclude-libs,ALL 是链接边界控制,不是“把 libdrm 从 Mesa 删除”。EGL 内部仍可以使用所需实现,只是不把静态依赖的内部符号伪装成 EGL 公共 API。
6.2 补丁 0012:处理平台 libc 的 weak-UND 检查误报
问题表现是 egl-symbols-check 将三个 weak-UND 符号当作异常:
pthread_mutexattr_destroy
pthread_mutexattr_init
pthread_mutexattr_settype
解决方式是在测试注册时增加三个明确的 --ignore-symbol:
--ignore-symbol pthread_mutexattr_destroy
--ignore-symbol pthread_mutexattr_init
--ignore-symbol pthread_mutexattr_settype
这不是把真实 EGL 符号检查关闭,而是把已经确认属于平台 libc weak-UND 的三项从误报集合中排除。其他未列出的异常符号仍会让检查失败。
两个补丁均已注册到 conandata.yml,并同步更新 manifest.yaml 和 notes.md。它们不是只存在于执行端临时目录的测试副本,Conan 干净创建时会实际应用。
七、构建、打包和门禁
在真机消费前,先使用 conan download "mesa/24.3.4.1.1:*" -r=ohpcd 从 ohpcd 获取对应 OHOS AArch64 二进制包。下载输出中的 package ID、revision、shared=True 和 ABI settings 是制品来源的可复核身份,不应以本地源码构建目录替代。

图 3:真机从 ohpcd 获取 Mesa 二进制包,输出包含 package revision、OHOS / armv8 / clang 15 / C++17 / libc++ 设置与共享库选项。
典型的 Conan 构建入口如下:
conan create archives/m/mesa/24.3.4.1.1 \
-pr:h=ci/conan/profiles/ohos-aarch64 \
-pr:b=ci/conan/profiles/ohos-aarch64 \
-r=ohpcd \
--build=missing \
-c tools.build:jobs=8
本轮 conan create 返回 0,并在包内执行 test_mesa。消费者输出包含:
GL_VERSION 4.5 Compatibility Profile Mesa 24.3.4 (llvmpipe)
test_mesa ALL PASS
构建门禁关注的不是单一退出码,而是下面几项是否同时成立:
| 门禁 | 关注内容 | 本轮结果 |
|---|---|---|
| 配方门禁 | 源码、补丁、构建和打包逻辑完整 | 通过 |
conan create | 干净构建、安装和 test_package | 通过 |
| EGL 符号检查 | drm* 泄漏、weak-UND 误报 | 通过,泄漏 137→0 |
| 消费者测试 | EGL/GLES/GBM/OSMesa 真实调用 | 通过 |
| OHOS 专项 | softpipe 离屏渲染与进程名检查 | 通过 |
| 原子性审计 | 仅 Mesa 白名单文件变化 | 通过 |
八、消费者验证:证明包真的能用
8.1 OSMesa test_package
test_package/test.c 通过 Conan 创建流程编译并运行,实际调用 OSMesaCreateContextExt、OSMesaMakeCurrent 等公开 API,并检查 OpenGL 版本。它验证的是 Mesa 包的头文件、库文件、链接关系和运行时加载,而不是仅检查包目录是否存在。
8.2 libEGL.so.1 动态加载
另一个消费者使用 dlopen 和 dlsym:
dlopen libEGL.so.1
-> dlsym eglGetDisplay
-> dlsym eglInitialize
-> dlsym eglQueryString
-> surfaceless EGL/GLES2
实际结果为 dlopen OK,并初始化出 EGL 1.5。这一步尤其重要,因为共享库的 SONAME 和动态加载路径是很多下游项目真正关心的接口。

图 4:从完整 package reference 定位缓存目录,确认包内含 libEGL、libGLESv1_CM、libGLESv2、libOSMesa 和 libgbm,且 libEGL 的 SONAME 为 libEGL.so.1。
8.3 GBM/EGL/GLES 最小公开头消费
本轮还分别使用 GBM、EGL、GLESv2 和 GLESv1_CM 的公开头文件编译最小程序,并链接对应库。四项消费者均返回 0。它们证明了包的 include/lib 布局和公开链接关系,但不声称设备存在真实 DRM 节点或 GPU 加速。
8.4 OHOS 专项离屏测试
OHOS 专项 ohos_adapt_test 覆盖进程名获取和 softpipe 离屏渲染,运行结果为 ALL PASS。该测试的价值是验证 Mesa 在没有窗口系统的 HarmonyOS 环境下仍可走软件渲染路径。

图 5:消费者程序编译成功后,通过包内库路径 dlopen libEGL.so.1,在 surfaceless 软件渲染环境初始化 EGL 1.5,并以退出码 0 结束。
九、测试结果如何如实表达
本轮没有宣称 Mesa 的全量 GTest 全部通过。证据中明确保留以下未完成项:
| 未完成集合 | 数量 | 原因边界 |
|---|---|---|
util_tests Cache | 7 | HMDFS 平台阻塞 |
general_ir_test | 7 | 上游 GLSL IR 差异 |
valhall_disasm_test | 244 | 反汇编器字节序/工具差异 |
| 未实例化驱动 GTest | 未统一计数 | libclc、AMDGPU LLVM 模块或网络条件阻塞 |
因此正确表述是:
当前 OHOS 配置下,Mesa 核心包构建、EGL 符号质量门禁、Conan 消费者、EGL/GLES/GBM/OSMesa 最小验证和 OHOS 专项测试通过;部分依赖特定 GPU 后端、反汇编工具、GLSL 行为或 HMDFS 语义的上游 GTest 保留未完成项及恢复条件。
不应写成“Mesa 上游全部测试通过”或“所有 GPU 驱动均已适配”。
十、常见失败与排查方法
10.1 drm* 符号仍然泄漏
先检查实际使用的 libEGL.so.1.0.0 是否来自当前 Conan 包,再确认 --exclude-libs,ALL 已进入正式配方补丁并在干净 conan create 中应用。只在临时构建目录手工加链接参数,不能作为交付修复。
10.2 egl-symbols-check 报 pthread 符号
先用 llvm-nm 查看符号类型和字段数,确认是 libc weak-UND,而不是 EGL 真正导出的强符号。只有确认属于这三个已知平台弱引用时,才能使用对应的 --ignore-symbol;不能扩大忽略名单来掩盖新的符号污染。
10.3 dlopen libEGL.so.1 失败
检查三个方面:
libEGL.so.1的 SONAME 是否正确;LD_LIBRARY_PATH或 rpath 是否指向 Conan 包的lib/;- 依赖的 GLES、GLAPI、LLVM 或系统库是否来自同一套 ABI。
本项目的质量警告明确要求下游使用显式包路径区分系统 /lib64/libEGL.so,不能让系统同名库抢先加载。
10.4 为什么没有真实 GPU 画面
本轮验证的重点是 HarmonyOS PC 上的可消费软件渲染和动态库接口。没有 /dev/dri、真实 GPU 驱动或窗口系统时,EGL surfaceless、OSMesa、softpipe/llvmpipe 仍然可以验证编译、链接、加载和离屏渲染;这不等价于硬件加速已经启用。
十一、截图证据说明
本文已经按下面顺序嵌入图片。发布到 CSDN 时,依次上传本目录对应 JPG,并将本地相对图片链接替换为 CSDN 自动生成的在线链接:
- PR 交付图:显示 MR #11116、分支
fix/mesa-24.3.4.1.1、最新提交和评审状态。 - 真机环境图:完整 HarmonyOS PC 桌面和终端,显示
uname -a、uname -m、conan --version。 - 制品下载图:显示
conan download "mesa/24.3.4.1.1:*" -r=ohpcd成功,以及os=OHOS、arch=armv8的包设置。 - 包内消费者图:显示 Conan 安装成功、
conan cache path、libEGL.so.1或libOSMesa.so的实际路径。 - 运行验证图:显示
eglInitialize EGL 1.5、OSMesa GL_VERSION ... llvmpipe、ALL PASS和退出码 0。
截图中没有 token、密码、私钥或不必要的内网地址。发布时保留图注,避免审核人员需要从终端内容自行推断每张图证明的结论。
十二、可复用流程
后续适配其他图形库时,可以复用以下顺序:
- 固定官方源码 URL、版本和 SHA-256。
- 列出需要交付的组件、共享库、SONAME 和公开头文件。
- 先验证平台工具链和依赖制品是否可消费,再开始大规模测试。
- 将每个修复写入正式补丁、
conandata.yml和 manifest,禁止只改临时 build 目录。 - 对共享库同时做链接、导出符号、SONAME、
dlopen和真实 API 消费验证。 - 区分软件渲染、窗口系统和真实 GPU 驱动能力,不扩大测试结论。
- 以
conan create、test_package、OHOS 专项和 W3/W4 门禁作为交付闭环。 - 文章中同时呈现 PR 事实、制品来源、真机路径和运行输出。
十三、结语
Mesa 24.3.4.1.1 的 HarmonyOS PC 适配重点不是“把 Mesa 编译出来”,而是把图形栈的边界说清楚并验证清楚:
官方 Mesa 24.3.4 源码
-> OHOS AArch64 Meson/Conan 构建
-> libEGL 导出表收敛(drm* 137 -> 0)
-> weak-UND 平台误报修正
-> Conan 制品安装
-> EGL/GLES/GBM/OSMesa 消费
-> surfaceless/llvmpipe 真机验证
这条证据链证明的是:Mesa 的核心共享库和软件渲染消费者可以在 HarmonyOS PC AArch64 上构建、打包、加载和运行;平台专属 GTest、真实 GPU 驱动和窗口系统能力仍按日志中记录的边界保留。
十四、FAQ
Q1:为什么源码是 24.3.4,Conan 却是 24.3.4.1.1?
24.3.4 是上游源码版本,24.3.4.1.1 是 HarmonyOS PC 适配后的 Conan 交付版本。后缀用于表达配方和补丁修订,不改变上游源码身份。
Q2:为什么必须关注 libEGL 的导出符号?
共享库的导出表就是下游可见接口。静态依赖通过 link_whole 泄漏 137 个 drm* 符号,会污染 ABI 边界,甚至引发同名符号冲突。--exclude-libs,ALL 用于收敛静态库内部符号。
Q3:--ignore-symbol 会不会掩盖真实问题?
只有三个已经确认属于 HarmonyOS libc weak-UND 的符号被忽略,其他符号仍由检查脚本校验。忽略项必须记录原因、来源和恢复条件,不能用通配符关闭检查。
Q4:为什么 dlopen 要设置包的库路径?
系统可能已有同名 /lib64/libEGL.so。显式设置 Conan 包的 LD_LIBRARY_PATH 或 rpath,才能确认加载的是本次交付的 Mesa,而不是系统库。
Q5:llvmpipe 通过是否代表 GPU 驱动通过?
不是。llvmpipe 是软件渲染器。本轮只证明软件渲染和图形 API 消费链路可用,不宣称 Intel、AMD、NVIDIA 或其他硬件驱动已经完成适配。
更多推荐



所有评论(0)