错误信息

# 典型形态(任一模块的 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:

  1. 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)都会被它升级为硬错。

  2. 高版 OHOS SDK 给枚举加了新值:API 26 的媒体/相机/图像错误码与格式枚举比 Qt 5.12 编写时多了若干值(如 AV_ERR_SUPER_RESOLUTION_*IMAGE_GET_IMAGE_DATA_FAILEDCAMERA_FORMAT_DNG/HEIC 等)。Qt 5.12 源码里对这些枚举的 switch 没有覆盖新增值 → clang -Wswitch 报警 → 被上面那个 -Werror 升级为硬错 → 框架构建中断。

  3. 5.12 上游 qt_common.prf 的 clang 分支没有 -Wno-switch:上游 qt_common.prf clang 分支只加了 unguarded-availability 相关的 -Werror=...,没有 -Wno-switch -Wno-switch-enum(5.12/5.15 HEAD 均如此,已核对)。所以 switch 警告不会被上游抑制,直接撞上 OHOS mkspec 的 -Werror

注意区分两个 -Werror 来源:OHOS mkspec 的 -Werror(本页主因,全局、release 也生效)≠ Qt warning_clean+warnings_are_errors-Werrorqt_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.prfclang { } 分支,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 不需此补丁即有同等效果,见下「验证」)。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐