
欢迎加入开源鸿蒙 PC 社区https://harmonypc.csdn.net/欢迎在 PC 社区平台申请新建项目https://atomgit.com/OpenHarmonyPCDeveloper如有项目源码可上传至 AtomGit 仓库可在博文内附上仓库链接。鸿蒙 PC 高难度适配实战GCC-Ada 9.5.0 从 Ada 自举到真机可用的 GNAT 工具链链图1 PR !6116 已合入主线页面显示已合并、审查人 9/1 已通过、测试人 6/1 已通过、评审人 1/1 已通过这次适配不是“换个编译器再编一遍”而是把 GCC 9.5.0 的 Ada/GNAT 编译器这一整套工程从 Alpine musl/AArch64 GNAT 9.3 自举种子起步在鸿蒙 PC 上从零完整跑通——鸿蒙 PC 生态第一次有了一套可签名、可运行、能编 Ada 程序的 GNAT 工具链。配方位于 archives/g/gcc-ada/9.5.0对应 PR !6116已于 2026-09-16 合入 OpenHarmonyPCDeveloper/build_in_harmonyos 主线。1.背景GCC AdaGNAT是 GCC 的 Ada 语言前端。Ada 这门语言在航空航天、轨道交通、安全关键系统这些领域被广泛采用——强类型、编译期检查、任务tasking和受保护对象protected object让它在高可靠软件里不可替代。它对鸿蒙 PC 的意义“不是多了一个编译器”而是让鸿蒙 PC 生态第一次有了 Ada/GNAT 工具链这个底座。很多依赖 Ada 的工业软件、教学项目过去在 OpenHarmony 上根本无从编译现在有了。关键难点GCC 的 Ada 前端GNAT和其他前端不一样——它自己就是用 Ada 写的。这有一个大的死结想编出 gnat1Ada 编译器前提是得有一个能跑的 GNAT而你想要的那个 GNAT恰恰是要用 gnat1 去编的。这就是“先有鸡还是先有蛋”的 Ada 自举。所以 GCC Ada 的难度不是“改了多少构建脚本”而在于它有一个难题必须先造出一个能用的 GNAT才能开始造目标 GNAT。本次适配的成果项目结果安装后上游可执行子集41/4130 GNAT 回归 11 ACATSAdaCGI 1.6 下游联动13/13 断言通过真机消费者验证6/6 检查通过自举依赖9 个 Alpine GNAT 9.3 seed APKSHA-256 全部固定仅构建期版本输出GNAT 9.5.0aarch64-linux-ohos, musl2. 环境这次适配需要准备什么编译器类项目和普通库不一样先把两边的环境说清楚后面排查问题才容易区分“是配方的问题”还是“是环境的问题”。构建机跑 Conan 配方、产出制品Conan 2本次 2.29.1。配方还依赖dejagnu/1.6.3.1、expect/5.45.4、tcl/8.6.14三个工具用来跑 GCC 上游的 Ada 测试套件HarmonyOS SDK提供交叉工具链clang/clang、sysroot、llvm-ar/llvm-ranlib宿主的 GNU as / ld。本包不含汇编器和链接器汇编由宿主 binutils 完成——鸿蒙 PC 上它们在/data/service/hnp/binGNU as 2.45这个目录不在默认 PATH不加会报gcc.real: fatal error: cannot execute as: execvp: Permission deniedprofile 必须对齐OHOS / armv8 / Release / clang 15 / C17 /libc。host 编译器的 C 标准或运行库不一致Conan 会算出另一个 package ID消费者就会“下载到 A 包、请求 B 包”。真机跑消费者验证一台配置了社区适配环境的 HarmonyOS PC本次用 HUAWEI MateBook ProHarmonyOS 6.1aarch64可写、且不在 HMDFS 分区的目录。包放在/storageHMDFS 挂载时签名后的 ELF 也无法执行会报Operation not permitted必须先复制到非 HMDFS 分区binary-sign-tool鸿蒙的代码签名工具编译产物必须先自签名才能运行strip过的 ELF 同样会被拒绝。顺带一个成本数据本包一次完整构建conan-build-test实测耗时55 分 21 秒——这是编译器类项目的正常量级也解释了后面为什么要把日常门禁和全量测试分开跑。3. 其他难点以及上游假设和鸿蒙 PC 的差异GCC Ada 的构建假设来自常规 Linux 桌面环境而鸿蒙 PC 在多个地方与它有很多实质差异。真机跑了第一轮构建后实际问题大多都集中在下面几处——其中“自举”是排在第一位的。差异点常规 Linux 假设鸿蒙 PC 实际情况自举有现成 GNAT 可直接引导无任何 Ada 编译器必须从 Alpine seed 起步平台探测config.guess/config.gcc 认识目标平台不认识 OHOS需显式传 tripletaarch64-linux-ohos文件系统常规 POSIX 文件系统HMDFS/storage 挂载上 mmap(MAP_XPM) 报 EACCES、临时目录受限依赖声明glibc 头文件声明齐全musl 缺 pthread_cancel 等三个接口Ada 运行时编译报错运行时异常自带 unwind-dw2 正常抛异常unwind-dw2 异常抛出时挂起需换 SDK libunwind.a二进制执行编译产物可直接执行未签名 ELF 无法执行代码签名体系4.适配方案从种子开始4.1 第一步解决自举问题用 Alpine GNAT 9.3 做构建期种子我通过使用 Alpine Linux 3.12 的 AArch64/musl GNAT 9.3.0 当“种子”来解决这一问题9.3 是比 9.5 要老的这符合 GCC 自举建议它是 musl/aarch64 的和鸿蒙 PC 的执行模型一致seed 的 ELF 解释器是 /lib/ld-musl-aarch64.so.1gnat、gnatmake、gnatbind、gnatlink、gcc 只需 muslgnat1 额外需要 libisl.so.15、libmpc.so.3、libmpfr.so.6、libgmp.so.10、libz.so.1全部从同一 Alpine 仓库固定9 个 APK 的下载地址和 SHA-256 全部固定在 conandata.yml 里这个只在构建时启用不存在于最终制品4.2 在鸿蒙 PC 上成功运行 Alpine 的 ELFXPM loader 签名代理XPM loader鸿蒙的 musl 动态链接器需要支持一种可执行内存映射MAP_XPM。补丁 0001-musl-ohos-xpm-loader.patch 为 ldso/dynlink.c 增加 MAP_XPM 探测并调整 LOAD 段映射可写段改为匿名映射 pread 填充使签名后的 ELF 能被 seed 加载。短 NEEDED 名重写把 seed 依赖的动态库名改写成短名配合 loader 定位解决 musl 依赖链加载。签名原生代理鸿蒙 PC 执行不了 shell 脚本式的驱动。我用 /proc/self/exe 解析相邻的隐藏 wrapper把 gcc、gnatmake、gnatbind、gnatlink 包成能签名、能执行的原生代理。4.3 分段编译出完整的 GNAT 工具链./configure\--prefix/--libdir/lib--libexecdir/libexec\--buildaarch64-linux-ohos--hostaarch64-linux-ohos--targetaarch64-linux-ohos\--enable-languagesc,ada\--enable-threadsposix\--enable-libada\--disable-bootstrap\--disable-lto --disable-plugin --disable-multilib --disable-nls --disable-shared\--disable-libatomic --disable-libitm --disable-libsanitizer\--disable-libgomp --disable-libquadmath --disable-libssp --disable-libvtv\--disable-werror\--without-isl\--with-sysrootOHOS sysroot\--with-native-system-header-dir/usr/include# 分阶段all-gcc - target libgcc - PIC target libada - GNAT tools不能一次性全部构建完成必须拆开每一步的产物都需要签名。到这里就解决了自举问题编译出来目标 GCC 9.5.0 和整套 GNAT 工具链。5. 除了自举外还有几个难点5.1 pthread 三个接口缺失Ada 运行时 tasking 相关的源文件编译时经常报未定义。发现是鸿蒙的 musl 没有 pthread_cancel、pthread_mutexattr_setprioceiling、pthread_rwlockattr_setkind_np而 GCC 9.5 的 Ada/POSIX 运行时默认它们都在。处理分两处都固化在 patches/0002-gcc-ada-ohos-build-rules.patch 里。第一处是 libgcc/gthr-posix.h用OHOS守卫把 pthread_cancel 的弱引用排除掉--- a/libgcc/gthr-posix.h b/libgcc/gthr-posix.h -108,7 108,7 __gthrw(pthread_equal) __gthrw(pthread_self) __gthrw(pthread_detach) -#ifndef __BIONIC__ #if !defined (__BIONIC__) !defined (__OHOS__) __gthrw(pthread_cancel) #endifAda 运行时侧gcc/ada/libgnarl/s-taprop__linux.adb把两个缺失调用注释掉、结果直接置 0--- a/gcc/ada/libgnarl/s-taprop__linux.adb b/gcc/ada/libgnarl/s-taprop__linux.adb - Result : pthread_mutexattr_setprioceiling - (Mutex_AttrAccess, Prio_To_Linux_Prio (Prio)); -- pthread_mutexattr_setprioceiling is absent on OHOS. Result : 0; pragma Assert (Result 0); - Result : pthread_rwlockattr_setkind_np - (RWlock_AttrAccess, - PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); -- pthread_rwlockattr_setkind_np is absent on OHOS. Result : 0; pragma Assert (Result 0);这里可以总结出来一处经验musl 上 pthread_* 报缺可以先看看是不是 glibc 私有扩展不用急着加其他库。5.2 unwind-dw2 异常挂起 → 换 libunwind.a发现 Ada 程序一 raise 异常进程不是报错或者退出而是直接挂在那里不动了。最后定位到 GCC 9 自带的 native unwind-dw2 在这平台上会在异常抛出路径最后卡死。通过改用 OHOS SDK 的 AArch64 静态 libunwind.a且只在链接阶段 whole-archive 注入不伪装成普通运行时依赖。替换后异常程序正常退出 0。但是必须把边界说清楚libunwind.a 是链接期注入不动源码和运行时语义。6.其他难点HMDFS、lld 与平台探测6.1 HMDFS 上 mmap(MAP_XPM) 报 EACCESseed probe 阶段对短名依赖 mmap(MAP_XPM) 返回 EACCES发现是这种文件系统不支持该映射方式。通过把 bootstrap 目录固定到非 HMDFS 的 app 目录并做写入探测即可解决。# conanfile.py节选propertydef_bootstrap_work_root(self):# The general cache root is writable but rejects signed executable maps.basePath(/data/storage/el2/base/haps/entry/files)rootbase/gcc-ada-bootstrap-{}.format(os.getpid())proberoot/.write-probetry:root.mkdir(parentsTrue,exist_okTrue)probe.write_bytes(bgcc-ada)probe.unlink()exceptOSErroraserror:...raiseConanInvalidConfiguration(XPM bootstrap directory is not writable: {} ({}).format(base,error))fromerror...6.2 lld 找不到配套 libxml2.so.16bootstrap loader 构建时SDK 的 lld 报 xmlFreeDoc 等符号缺失。发现是 lld 依赖 SDK 里同目录的 llvm/lib/libxml2.so.16但运行库搜索路径没覆盖到。通过从已验证的 sysroot 反推当前 SDK 的 llvm/lib前置到 bootstrap loader 子进程的 LD_LIBRARY_PATH并把后续 GCC/GNAT 构建环境同步前置即可解决7.测试统计编译器类项目验证方法不是库能不能被链接而是能不能把大量源码变成目标产物。我复用了 DejaGNU/Expect/Tcl在构建树里跑 GCC 上游的完整 check-gnat check-acats。测试集合数量结果说明上游全量 check-gnat/check-acatsCI #4275535423542/3542一次性完整证据失败 0、跳过 0上游清单未形成独立记录的入口773不计为通过4315-3542不虚报鸿蒙特有测试2020/20OHOS 制品消费者 7 条断言 AdaCGI 1.6 下游联动 13 条断言安装后 GNAT 回归子集门禁复跑3030/30从 gnat.dg共 2034 文件中选取{ dg-do run }安装后 ACATS 子集门禁复跑1111/11从 ACATS共 2595 文件中选取真机消费者检查66/6容器 / 异常 / task / 保护对象等如实说清楚口径完整 build-tree check-gnat/check-acats 跑过一次CI #42755 得 3542/3542100%上游清单总量 N4315其中 773 项没有独立结果记录不计为 PASS日常门禁复跑的是安装后 41 项子集30 GNAT 11 ACATS另有鸿蒙特有测试 20 条OHOS 消费者 7 AdaCGI 13。主分母 3562 3542 20。UPSTREAM_GNAT_DG_SUBSET30/30 UPSTREAM_ACATS_SUBSET11/11 UPSTREAM_ADA_SUBSET_TOTAL41/41跑这套子集时也踩过测试运行环境的问题全出在“路径/签名/运行库”上dg-extract-results.sh 写不进 mode-0700 目录把 TMPDIR 挪到 XPM 文件系统、ACATS 的 macrosub.adb 没生成把 Alpine seed 的 gnatchop 也走 XPM loader 包一遍、链接时 musl 符号解析失败补 -Wl,-rpath-link,…。总结编译器类项目的测试问题几乎都出在“运行环境”上而不是代码本身。8.消费者验证的重要性除了完成基础测试还必须从消费者角度验证是否能用 GCC-Ada 的消费者测试调用安装后的 gnatmake真实编译一个 Ada 程序覆盖泛型容器、异常处理断言可执行产物生成、签名后运行输出精确匹配。-- test_package/test_gcc_ada.adb真实源码 with Ada.Containers.Vectors; with Ada.Strings.Fixed; with Ada.Text_IO; procedure Test_Gcc_Ada is Checks : Natural : 0; Platform_Name : constant String : HarmonyOS; procedure Check (Condition : Boolean; Name : String) is begin if not Condition then Ada.Text_IO.Put_Line (FAILED: Name); raise Program_Error; end if; Checks : Checks 1; end Check; protected Shared_Counter is procedure Increment; function Value return Natural; private Current : Natural : 0; end Shared_Counter; protected body Shared_Counter is procedure Increment is begin Current : Current 1; end Increment; function Value return Natural is begin return Current; end Value; end Shared_Counter; task Worker is entry Run; end Worker; task body Worker is begin accept Run do Shared_Counter.Increment; end Run; end Worker; begin Check (6 * 7 42, integer arithmetic); Check (Platform_NameLength 9, string attributes); Check (Ada.Strings.Fixed.Index (Platform_Name, OS) 8, standard string runtime); declare package Integer_Vectors is new Ada.Containers.Vectors (Index_Type Positive, Element_Type Integer); Values : Integer_Vectors.Vector; begin Integer_Vectors.Append (Values, 21); Integer_Vectors.Append (Values, 21); Check (Integer_Vectors.Element (Values, 1) Integer_Vectors.Element (Values, 2) 42, generic containers); end; declare Caught : Boolean : False; begin begin raise Constraint_Error; exception when Constraint_Error Caught : True; end; Check (Caught, exception handling); end; Worker.Run; Check (Shared_Counter.Value 1, tasking runtime); if Checks / 6 then raise Program_Error; end if; Ada.Text_IO.Put_Line (gcc-ada checks passed: NaturalImage (Checks)); end Test_Gcc_Ada;它的结果契约是full_package_exit_code0 gcc-ada checks passed: 6 GCC_ADA_FULL_PACKAGE_DIAGNOSTICpass另外还有一条真实的下游联动路径AdaCGI 1.6 用打包后的 gnatmake/gnatbind/gnatlink 编译、绑定、链接、签名跑一个带 13 条 fail-closed 断言的 CGI 请求验证器输出 ADACGI_LINKAGEpass assertions13。这类测试证明的是“发布后的包能被上层组件正常调用”与编译通过是不同维度的证据。9.真机运行与复现适配完成之后在同一台设备上做到端到端复现。但是 GNAT 的一个特点编译成功不一定打印输出所以重点看产物和运行结果。先确认制品仓和安装环境图2版本输出图3$ gnatmake --version GNATMAKE 9.5.0 Copyright (C) 1995-2019, Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.完整的编译 → 签名 → 运行流程图4$ gnatmake test_gcc_ada.adb -o test_gcc_ada $ ./test_gcc_ada sh: permission denied: ./test_gcc_ada ← 未签名被拒 $ /data/service/hnp/bin/binary-sign-tool sign -selfSign 1 \ -inFile test_gcc_ada -outFile test_gcc_ada.signed -signAlg SHA256withECDSA 09-24 21:19:53.770 INFO - add codesign section success 09-24 21:19:53.812 INFO - write code sign data success $ chmod x test_gcc_ada.signed $ ./test_gcc_ada.signed gcc-ada checks passed: 6这里还有两个 HMDFS/签名体系的细节测试时不能直接在包目录里跑编译器——包位于 /storageHMDFS签好名的二进制在 HMDFS 上执行会报 Operation not permitted。测试脚本先把整个包复制到非 HMDFS 分区再在那里执行。签名是硬门槛——编译出来的可执行文件必须先 binary-sign-tool 签名才能在鸿蒙 PC 上运行strip 过的 ELF 同样报 Operation not permitted。本包不含 as/ld汇编靠宿主 GNU as/data/service/hnp/bin/asBinutils 2.45而该目录不在默认 PATH不加会报 gcc.real: fatal error: cannot execute ‘as’: execvp: Permission denied。如果你有配置了社区适配环境的鸿蒙 PC 设备可以照下面完整步骤从零复现装到能跑 gnatmake# 1. 加制品仓 remoteconan remoteaddohpcd https://conan.cnb.cool/OpenHarmonyPCDeveloper/Conan/-/packages/# 2. 确认 gcc-ada 包在制品仓conan listgcc-ada/*-rohpcd# 3. 安装settings 必须对齐 CI 构建值否则报 os.version 未定义conaninstall--requiresgcc-ada/9.5.0-rohpcd\-sos.version6.0-scompiler.libcxxlibc-scompiler.cppstd17\-gVirtualRunEnv# 4. 激活运行环境让 gnatmake 进 PATHsourceconanrun.sh# 5. 验证whichgnatmake gnatmake--version10.实战拆解问题是怎么解决的第一步先解决自举这个死结。拿到一个在目标平台没有现成编译器的库第一步应该是检查它的编译前提而不是改构建参数。GCC-Ada 的关键前提不是某个头文件而是“必须有一个 GNAT 才能编 GNAT”。只要 C-only 的 GCC 配方没有 Ada 前端改 CC、CFLAGS 都无济于事。第二步选定构建期种子。把“推测平台没有 GNAT”变成可复现方案用版本更老9.3 9.5、校验固定9 个 APK 的 SHA-256、且执行模型一致musl/aarch64的 Alpine GNAT 做 seed并且只用于构建期。第三步使种子运行起来。用 seed 的 gnatmake -c 编一个 Ada 单元如果 mmap(MAP_XPM) 在 HMDFS 上 EACCES就把执行目录迁移到非 HMDFS 分区如果短名依赖加载失败就上 XPM loader 短 NEEDED 重写。第四步分段编译 GNAT 工具链。不一次性编译完成按 all-gcc → target libgcc → PIC target libada → GNAT tools 顺序每阶段产物都签名。第五步处理 musl 运行时差异。pthread 三接口缺失用源转换替换unwind-dw2 异常挂起换 SDK libunwind.a链接期注入。第六步跑全量 check-gnat check-acats。 复用 DejaGNU/Expect/Tcl用临时签名的 xgcc 代理跑完整套件逐个解决 TMPDIR、gnatchop、rpath-link 三个问题第七步消费者验证。 从安装包调用 gnatmake 真实编译 Ada 程序断言产物生成 签名后运行输出精确匹配第八步正确汇报统计 原子性审计。 测试分母必须写清 N4315 / N’3542 / 773 项未计通过提交前 git diff --cached --name-only、git diff --check 核对只含 gcc-ada 文件临时日志、缓存和其他库修改不进提交11.FAQQ1Alpine 的 GNAT 种子是不是一个“偷偷塞进来的”路径依赖不是。它是构建期输入不是运行时依赖9 个 APK 的下载地址和 SHA-256 全部固定在conandata.yml里可复现、可审计只用于构建期引导9.3 9.5符合 GCC 自举建议编完即弃不进最终制品也不在 PATH 里“恰好存在”。消费gcc-ada/9.5.0时运行依赖是required: []GMP/MPFR/MPC 都是源码内置。这和仓库既有的编译器类规范一致可信二进制工具链是受校验的源码输入。Q2为什么完整的上游测试套件不放在每次门禁里跑因为跑不动。check-gnatcheck-acats全量执行会超过默认 3600 秒的conan create窗口实测在 ACATS 阶段超时见 CI #42817。所以配方把全量路径保留为显式的证据复跑设GCC_ADA_FULL_UPSTREAM_TESTS1才会跑完整套件。日常门禁则跑“完整构建 安装后 41 项上游子集 20 条消费者断言”在门禁窗口内完成。需要说明的是CI #42755 那次确实跑完过完整套件3542/3542 就是它的结果。Q3为什么只做 Ada 前端不做 C / Fortran这次的目标是把自举链闭合Ada 前端是唯一“自己用自己写”、没有现成编译器就无法构建的前端也是难度所在。C/C 前端可以由宿主 clang 交叉编译不构成自举问题Fortrangfortran可以作为后续独立任务。把边界写清楚比“声称全都支持”更有用——本包实际启用的是--enable-languagesc,ada。Q4链接期注入libunwind.a算不算改了运行时语义不算但边界必须写死注入只发生在链接阶段whole-archive不改源码、不改 Ada 运行时它替换的是 GCC 自带的 nativeunwind-dw2在鸿蒙上的异常展开路径原路径会挂起它不是 Conan 运行时依赖不伪装成普通库依赖。换句话说修的是异常展开在这平台上跑不通不是改写异常语义。Q5上游清单 4315 项为什么只执行了 3542 项是不是少报了不是少报是两个口径4315是上游测试入口的清单总量作为正文模板里的上游用例数3542是 CI #42755 里实际形成了独立结果记录的数量3542/3542 全部通过差额773项没有在 CI 里形成独立结果记录不计为已执行也不计为 PASS。所以3542/4315 82.1%是清单覆盖率不是通过率通过率是3542/3542 100%。这两个数在同一份报告里分开列不合并。12.小结本次适配属于高难度本质来自于 Ada 自举要编出 Ada 编译器得先有一个 Ada 编译器——于是从固定校验的 Alpine GNAT 9.3 种子出发经 XPM loader、签名原生代理、分阶段编译才“用 Ada 编出了 Ada”。自举之外musl 的 pthread 能力差异和 unwind-dw2 异常挂起又分别考验了 Ada 运行时的 tasking 和异常展开HMDFS 与签名体系则是所有鸿蒙 PC 适配都要过的共性关。最终成果上游实际执行结果 3542/3542、安装后上游子集 41/41、OHOS/消费者断言 20/20 全部通过。gcc-ada 9.5.0 已能在鸿蒙 PC 完成完整 Conan 构建并对主要产物做了真实功能检查。后续值得补的方向有两个一是配合鸿蒙签名方案恢复 strip 以优化体积二是用更复杂的 Ada 工程验证编译器输出等价性。可复用的方法都是这次拿真实踩坑换来的自举种子要“更老 固定 只用一次”三条缺一不可——Alpine GNAT 9.3 比目标 9.5 老符合 GCC 自举建议9 个 APK 的 SHA-256 全固定可复现、可审计构建完就丢不混进运行时。少一条版本不老可能自举失败校验不固定不可复现混进运行时就成了 undeclared 依赖。先让最小一件事跑通再上全量——先用 seed 的gnatmake -c编一个seed_probe.o确认整条 seed 链路通才进入正式 GCC 构建。别一上来就跑全量否则失败点全搅在一起根本没法定位。编译器类项目运行环境比代码更常出错——跑上游子集时踩的坎TMPDIR 写不进、gnatchop 未生成、rpath-link 缺路径全是路径/签名/运行库/加载器问题没有一个是真正的代码 bug。链接期注入 ≠ 运行时依赖这条边界要写死——libunwind.a只在链接阶段 whole-archive 注入不冒充运行时 Conan 依赖seed 只用于构建期不冒充 PATH 工具。测试口径不能混——安装后子集41/41、AdaCGI 下游13/13、真机消费者6/6、上游全量执行3542/3542分开统计上游 gnat.dg 的 2034 个文件、ACATS 的 2595 个文件只是文件数不等于执行通过数。编译器是生态的地基而 Ada 编译器这块地基比别的更难打——因为它得先自己把自己造出来。参考文献[1] GCC, the GNU Compiler Collection. https://gcc.gnu.org/[2] GNAT User’s Guide / GCC 9.5.0 Ada 文档.[3] OpenHarmonyPCDeveloper/build_in_harmonyos — gcc-ada 9.5.0 适配配方archives/g/gcc-ada/9.5.0PR !6116. https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos