为 GCC 编译器添加 OpenHarmony (OHOS) 目标支持:深度解析与实现思路

作者:sanchuanhehe
日期:2025年12月5日
地址:https://gitcode.com/sanchuanhehe/ohos-gcc
状态:施工中

引言

OpenHarmony 是一款面向全场景的开源分布式操作系统,由华为贡献给开放原子开源基金会。虽然 OpenHarmony 官方主要使用 LLVM/Clang 作为编译工具链,但为 GCC 添加 OHOS 目标支持具有重要意义:

  1. 生态兼容性:许多开源项目仍然依赖 GCC 特有的扩展和特性
  2. 工具链多样性:提供更多编译选择,便于性能对比和问题排查
  3. 移植便利性:简化现有 GCC 项目向 OpenHarmony 的移植工作

本文将深入分析为 GCC 15.2.0 添加 OpenHarmony 目标支持的补丁实现,讲解关键技术点和设计思路。

一、GCC 目标支持的整体架构

在深入补丁细节之前,我们需要理解 GCC 如何支持新的操作系统目标。GCC 的目标配置系统主要由以下几部分组成:

                    ┌─────────────────┐
                    │   config.sub    │  目标三元组识别
                    └────────┬────────┘
                             │
                    ┌────────▼────────┐
                    │    config.gcc   │  目标配置主文件
                    └────────┬────────┘
                             │
        ┌────────────────────┼────────────────────┐
        │                    │                    │
┌───────▼───────┐   ┌────────▼────────┐   ┌──────▼──────┐
│    ohos.h     │   │ arch-ohos.h     │   │   t-ohos    │
│  (通用配置)   │   │ (架构特定配置) │   │ (Makefile)  │
└───────────────┘   └─────────────────┘   └─────────────┘

1.1 目标三元组 (Target Triplet)

GCC 使用"目标三元组"来标识编译目标,格式为:架构-厂商-操作系统

对于 OpenHarmony,我们定义了以下主要目标:

架构 目标三元组 说明
AArch64 aarch64-linux-ohos ARM 64位
ARM arm-linux-ohos ARM 32位
x86_64 x86_64-linux-ohos Intel/AMD 64位
RISC-V riscv64-linux-ohos RISC-V 64位
MIPS mips64el-linux-ohos MIPS 64位小端

二、补丁核心修改分析

2.1 config.sub 修改:识别 OHOS 目标

-	     | fiwix* )
+	     | fiwix* | ohos* )
		;;

以及:

 	linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
-		   | linux-musl* | linux-relibc* | linux-uclibc* )
+		   | linux-musl* | linux-relibc* | linux-uclibc* | linux-ohos* )
 		;;

设计思路

  • ohos 添加到操作系统识别列表
  • 支持 linux-ohos 内核-操作系统组合
  • 这使得 aarch64-linux-ohos 等三元组能被正确解析

2.2 config.gcc 修改:配置构建参数

这是最核心的配置文件,需要处理多个方面:

2.2.1 C 库选择
*-*-*ohos*)
  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_MUSL"
  ;;

OpenHarmony 使用 musl libc,这一选择至关重要:

  • musl 是轻量级、符合标准的 C 库
  • 相比 glibc 更适合嵌入式场景
  • Alpine Linux 也使用 musl,提供了良好的参考
2.2.2 架构特定配置

以 AArch64 为例:

aarch64*-*-linux-ohos*)
    tm_file="${tm_file} elfos.h gnu-user.h linux.h ohos.h glibc-stdint.h"
    tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-linux.h aarch64/aarch64-ohos.h"
    tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-ohos"
    tm_defines="${tm_defines} TARGET_DEFAULT_ASYNC_UNWIND_TABLES=1"
    gas=yes gnu_ld=yes
    ;;

关键点

  1. 头文件链:按顺序加载配置头文件,后面的可以覆盖前面的定义
  2. 异步展开表:启用 .eh_frame 以支持 C++ 异常处理
  3. 工具链:指定使用 GNU as 和 GNU ld

2.3 通用 OHOS 配置头文件 (ohos.h)

这个文件定义了所有架构共享的 OHOS 配置:

2.3.1 C 库选择宏
#undef OPTION_GLIBC
#define OPTION_GLIBC 0
#undef OPTION_MUSL
#define OPTION_MUSL 1
2.3.2 预定义宏
#define OHOS_BASE_OS_CPP_BUILTINS()             \
  do {                                          \
    builtin_define ("__ohos__");                \
    builtin_define ("__OpenHarmony__");         \
    builtin_define ("__MUSL__");                \
    builtin_assert ("target=ohos");             \
    builtin_assert ("target=openharmony");      \
  } while (0)

这些宏让用户代码可以检测编译目标:

#ifdef __ohos__
  // OpenHarmony 特定代码
#endif
2.3.3 动态链接器配置
#define OHOS_DYNAMIC_LINKER OHOS_ARCH_DYNAMIC_LINKER

动态链接器路径遵循 musl 约定,由架构特定头文件定义:

架构 动态链接器路径
AArch64 /lib/ld-musl-aarch64.so.1
ARM (hard float) /lib/ld-musl-armhf.so.1
x86_64 /lib/ld-musl-x86_64.so.1
RISC-V 64 /lib/ld-musl-riscv64.so.1
2.3.4 安全特性
#define CC1_SPEC \
  "%{!fno-stack-protector:%{!fstack-protector-all:%{!fstack-protector-strong:%{!fstack-protector:-fstack-protector}}}}"

默认启用栈保护(Stack Protector),这是 OpenHarmony 的安全要求。

2.4 架构特定配置

以 AArch64 为例 (aarch64-ohos.h):

2.4.1 Cortex-A53 勘误修复
#undef TARGET_FIX_ERR_A53_835769_DEFAULT
#define TARGET_FIX_ERR_A53_835769_DEFAULT 1
#undef TARGET_FIX_ERR_A53_843419_DEFAULT
#define TARGET_FIX_ERR_A53_843419_DEFAULT 1

这修复了 Cortex-A53 处理器的已知硬件 bug。

2.4.2 库搜索路径
#define OHOS_ARCH_LIB_DIR "aarch64-linux-ohos"

#define STARTFILE_SPEC \
  "%{!shared: \
     %{pg|p|profile:%R/usr/lib/" OHOS_ARCH_LIB_DIR "/gcrt1.o%s; \
       pie:%R/usr/lib/" OHOS_ARCH_LIB_DIR "/Scrt1.o%s; \
       :%R/usr/lib/" OHOS_ARCH_LIB_DIR "/crt1.o%s}} \
   %R/usr/lib/" OHOS_ARCH_LIB_DIR "/crti.o%s \
   %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"

定义了 CRT(C Runtime)文件的搜索路径,这些文件在程序启动时执行。

2.4.3 链接规范 (LINK_SPEC)
#define LINK_SPEC                              \
  "%{mbig-endian:-EB} %{mlittle-endian:-EL} "  \
  "%{shared:-shared} "                         \
  "%{!shared: "                                \
    "%{!static: "                              \
      "%{rdynamic:-export-dynamic} "           \
      "-dynamic-linker " OHOS_DYNAMIC_LINKER "} " \
    "%{static:-static}} "                      \
  "-L%R/usr/lib/" OHOS_ARCH_LIB_DIR " "        \
  "-L%R/usr/lib "

这定义了传递给链接器的参数。

2.5 libgcc 配置

aarch64*-*-linux-ohos*)
    extra_parts="$extra_parts crtfastmath.o"
    md_unwind_def_header=aarch64/aarch64-unwind-def.h
    md_unwind_header=aarch64/linux-unwind.h
    tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
    tmake_file="${tmake_file} ${cpu_type}/t-lse t-slibgcc-libgcc"
    tmake_file="${tmake_file} t-softfp ${cpu_type}/t-softfp"
    ;;

配置了:

  • LSE (Large System Extension) 原子操作支持
  • 软浮点支持
  • 异常展开支持

2.6 线程支持修改

-#ifndef __BIONIC__
+#if !defined(__BIONIC__) && !defined(__OHOS__)
 __gthrw(pthread_cancel)
 #endif

原因:musl libc 的 pthread_cancel 实现有限制,类似 Android 的 Bionic libc。通过这个修改,避免在 OHOS 上使用 pthread_cancel

2.7 兼容性修复

// gcc/system.h
#ifndef __GLIBC_PREREQ
#define __GLIBC_PREREQ(x, y) 0
#endif

当交叉编译到 musl 目标时,host 系统可能使用 glibc,而某些代码会检查 __GLIBC_PREREQ。这个宏确保在非 glibc 环境下编译不会出错。

三、与 LLVM/Clang OHOS 支持的对比

特性 GCC (本补丁) LLVM/Clang
C 库 musl musl
运行时库 libgcc compiler-rt
C++ 标准库 libstdc++ (可选 libc++) libc++
动态链接器路径 相同 相同
默认安全特性 SSP SSP

本补丁的设计参考了 LLVM 的 OHOS 支持实现,确保两者生成的代码具有 ABI 兼容性。

四、架构支持矩阵

┌─────────────┬──────────┬──────────┬──────────┬──────────┐
│   架构      │  动态    │  软浮点  │   LSE    │  MIPS    │
│             │  链接器  │          │  原子    │  N32     │
├─────────────┼──────────┼──────────┼──────────┼──────────┤
│ AArch64     │    ✓     │    ✓     │    ✓     │    -     │
│ ARM         │    ✓     │    ✓     │    -     │    -     │
│ x86/x86_64  │    ✓     │    -     │    -     │    -     │
│ RISC-V      │    ✓     │    ✓     │    -     │    -     │
│ MIPS        │    ✓     │    -     │    -     │    ✓     │
└─────────────┴──────────┴──────────┴──────────┴──────────┘

五、构建和使用

5.1 构建交叉编译器

# 应用补丁
cd gcc-15.2.0
patch -p1 < ../patches/0001-Add-OpenHarmony-OHOS-target-support-to-GCC.patch

# 配置
mkdir build && cd build
../configure \
    --target=aarch64-linux-ohos \
    --prefix=/opt/ohos-gcc \
    --enable-languages=c,c++ \
    --with-sysroot=/path/to/ohos-sysroot \
    --disable-multilib

# 构建
make -j$(nproc)
make install

5.2 使用编译器

# 编译 C 程序
aarch64-linux-ohos-gcc -o hello hello.c

# 编译 C++ 程序
aarch64-linux-ohos-g++ -o hello hello.cpp

# 静态链接(不需要 sysroot)
aarch64-linux-ohos-gcc -static -o hello hello.c

参考资料

附录:补丁文件清单

文件 作用
config.sub 目标识别
gcc/config.gcc 主配置文件
gcc/config/ohos.h 通用 OHOS 配置
gcc/config/ohos-paths.h 路径定义
gcc/config/t-ohos Makefile 片段
gcc/config/aarch64/aarch64-ohos.h AArch64 配置
gcc/config/aarch64/t-aarch64-ohos AArch64 Makefile
gcc/config/arm/arm-ohos.h ARM 配置
gcc/config/arm/t-arm-ohos ARM Makefile
gcc/config/i386/i386-ohos.h x86 配置
gcc/config/mips/mips-ohos.h MIPS 配置
gcc/config/riscv/riscv-ohos.h RISC-V 配置
gcc/system.h 兼容性修复
libcpp/system.h 兼容性修复
libgcc/config.host libgcc 配置
libgcc/gthr-posix.h 线程支持修复
libstdc++-v3/configure.host C++ 库配置
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐