鸿蒙Qt 5.12 框架源码 + 高API版本的鸿蒙 SDK 编译失败:新枚举 + OHOS mkspec -Werror
错误信息
# 典型形态(任一模块的 switch over OHOS SDK 枚举):
<module>/src/.../foo.cpp:NN: error: enumeration values '<NEW_ENUM_A>', '<NEW_ENUM_B>',
and '<NEW_ENUM_C>' not handled in switch [-Werror,-Wswitch]
switch (nativeErrorCode) { ^~~~~~~~~~~~~~~
mingw32-make[5]: *** [Makefile:NNNN: .obj/foo.obj] Error 1
...
mingw32-make: *** [Makefile:NN: module-<name>-make_first] Error 2
本页是其通用根因 + 全局修复版本:适用于 Qt 5.12 框架源码构建中任一被新 OHOS SDK 枚举咬到的模块。
判定本页(而非模块专项页)的两个标志:①报错来自编译 Qt 框架源码本身(mingw32-make module-<name> 或整树 build),不是编译业务应用;②编译命令行里的 -Werror 来自 OHOS mkspec 的 OHOS_C_CXX_COMMON_FLAGS(见下「根因」),而不是 Qt 的 warning_clean。
场景
开发者从源码交叉编译 Qt 5.12 框架到 OHOS(构建 Qt SDK,不是编应用)。Qt 5.12 源码是按较低版本 OHOS SDK 编写的;当本地 OHOS SDK 是更高版本(如 API 26,随 DevEco Studio 自带,OHOS_SDK_NATIVE_VERSION_MAJOR=26)时,新 SDK 给若干枚举追加了新值,Qt 源码里 switch 语句没有覆盖这些新值 → -Wswitch 报警 → 被 -Werror 升级为硬错 → 模块编不过 → make 返回 Error 2 → make install 被跳过 → 该模块不入 SDK。换回低版 SDK 不复现。
反例(已验证):用
-release且未开-Werror的构建树不会咬(见下「验证」对照)。咬人的关键是 OHOS mkspec 里的-Werror,它 release 也生效。
根因
两层叠加,主因是 OHOS mkspec 的全局 -Werror:
-
OHOS-clang mkspec 把
-Werror硬编码进OHOS_C_CXX_COMMON_FLAGS(${QT5_12_SRC_FULL}\qtbase\mkspecs\ohos-clang\qmake.conf,HEAD 上游版本):OHOS_C_CXX_COMMON_FLAGS = \ $$OHOS_TOOLCHAIN_COMMON_FLAGS \ -fdata-sections \ -ffunction-sections \ -funwind-tables \ -fstack-protector-strong \ -no-canonical-prefixes \ -fno-addrsig \ -Wformat \ -Werror # ← 这一行 ... QMAKE_CFLAGS += $$OHOS_C_CXX_COMMON_FLAGS QMAKE_CXXFLAGS += $$OHOS_C_CXX_COMMON_FLAGS # -Werror 因此对 OHOS 全树 C/C++ 全局生效这个
-Werror独立于 Qt 自身的warning_clean+warnings_are_errors闸门(qt_common.prf:114),由 OHOS 团队直接加在 mkspec 里,不论 release/developer-build 都生效。后果:OHOS SDK 升级带来的任何新警告(不只是 -Wswitch)都会被它升级为硬错。 -
高版 OHOS SDK 给枚举加了新值:API 26 的媒体/相机/图像错误码与格式枚举比 Qt 5.12 编写时多了若干值(如
AV_ERR_SUPER_RESOLUTION_*、IMAGE_GET_IMAGE_DATA_FAILED、CAMERA_FORMAT_DNG/HEIC等)。Qt 5.12 源码里对这些枚举的switch没有覆盖新增值 → clang-Wswitch报警 → 被上面那个-Werror升级为硬错 → 框架构建中断。 -
5.12 上游
qt_common.prf的 clang 分支没有-Wno-switch:上游qt_common.prfclang 分支只加了 unguarded-availability 相关的-Werror=...,没有-Wno-switch -Wno-switch-enum(5.12/5.15 HEAD 均如此,已核对)。所以 switch 警告不会被上游抑制,直接撞上 OHOS mkspec 的-Werror。
注意区分两个 -Werror 来源:OHOS mkspec 的
-Werror(本页主因,全局、release 也生效)≠ Qtwarning_clean+warnings_are_errors的-Werror(qt_common.prf:114,仅 developer-build 或显式-warnings-are-errors/-Werror时生效)。./configure -no-warnings-are-errors只关后者,关不掉本页的 OHOS mkspec -Werror——所以本页必须改 mkspec,configure 标志不能替代。
解决方案
两处改动配套(用户已在 5.12 qtbase 工作树实测,git diff 见「证据」):
改动 A(主修复,对应"去掉 OHOS 平台 qmake.conf 的 -Werror")
在 ${QT5_12_SRC_FULL}\qtbase\mkspecs\ohos-clang\qmake.conf,从 OHOS_C_CXX_COMMON_FLAGS 删掉 -Werror 行:
OHOS_C_CXX_COMMON_FLAGS = \
$$OHOS_TOOLCHAIN_COMMON_FLAGS \
-fdata-sections \
-ffunction-sections \
-funwind-tables \
-fstack-protector-strong \
-no-canonical-prefixes \
-fno-addrsig \
- -Wformat \
- -Werror
+ -Wformat
效果:OHOS 全树 C/C++ 不再带全局 -Werror,新枚举的 -Wswitch 退回普通警告(非致命),框架构建放行。
改动 B(配套,抑制 switch 警告噪声 + 双保险)
在 ${QT5_12_SRC_FULL}\qtbase\mkspecs\features\qt_common.prf 的 clang { } 分支,unarded-availability 块之后补一行:
clang {
...
versionAtLeast(clang_ver, 5.0)|versionAtLeast(apple_ver, 9.0): \
QMAKE_CXXFLAGS_WARN_ON += \
-Werror=unguarded-availability \
-Werror=unguarded-availability-new \
-Werror=unsupported-availability-guard
}
+ QMAKE_CXXFLAGS_WARN_ON += -Wno-switch -Wno-switch-enum
} else: gcc:!intel_icc {
效果:clang 下 Qt 各模块的 switch 不再因新枚举报警(连警告都不出),即使将来某路径仍残留 -Werror 也不会被 -Wswitch 咬到。与 5.15 构建树里已存在的 -Wno-switch 行为对齐(5.15 不需此补丁即有同等效果,见下「验证」)。
更多推荐


所有评论(0)