
欢迎加入开源鸿蒙PC社区https://harmonypc.csdn.net/欢迎在PC社区平台申请新建项目https://atomgit.com/OpenHarmonyPCDeveloper引言这次将 GNU binutils 2.46.0 适配到鸿蒙 PC在 AArch64 环境中完成了原生构建、Conan 打包和安装包测试。过程中主要处理了构建脚本兼容、Clang 与 GNU as 配合、DejaGNU 测试运行和 ELF 签名问题。PR !9025 已于 2026 年 9 月 10 日合入。最终五套 DejaGNU 测试得到3419 PASS、35 FAIL、0 UNRESOLVED普通通过率 98.99%安装包功能测试为16/16。下面介绍环境准备、构建命令、适配过程和剩余失败项的分析。上游测试数字来自 2026 年 9 月 8 日归档的final39真机记录9 月 26 日另在原设备重新执行安装包测试结果仍为16/16运行截图见第 8 节。1. binutils 包含哪些工具binutils 是一组处理二进制文件的工具常见用法如下汇编源码 → as → 目标文件 → ld → 可执行文件 ↓ readelf / objdump / nm查看结构、指令和符号 ar建立静态归档objcopy / strip处理文件副本其中as是汇编器ld是链接器ELF 是本次目标文件、动态库和可执行文件使用的文件格式。Conan 按配方获取源码、安装依赖、构建和打包test_package用来运行包内工具检查安装后的功能。这类直接使用已安装工具的测试下文称为“消费者测试”。本项目按高难度挑战申报Issue #2846 记录了技术依据binutils 包含 BFD、opcodes、gas、ld 等相互配合的组件涉及多架构汇编、重定位、符号版本和动态加载。源码归档中有 8815 个.s文件和 7 个.asm文件这些数量描述了源码与测试规模其中也包含其他架构的测试材料。本次使用鸿蒙环境中的 Clang 编译 binutils再调用生成的 GNU as、GNU ld 等工具执行测试。运行时 Conan 依赖列表为空DejaGNU、Expect、Tcl 属于测试阶段的工具依赖。2. 开发环境与设备配置本次使用 Windows 和 WSL Ubuntu 做源码整理及对照试验最终构建与验收在鸿蒙 PC 上执行。项目本次记录目标设备HarmonyOS PCAArch64本次截图复验的系统实测参数OpenHarmony-6.1.0.1152026-09-26Conan 目标配置osOHOS、os.version6.0、archarmv8编译器配置Clang 15、libc、ReleaseSDK 路径记录ohos-sdk_26.0.0.18/ohos/native包管理器社区 OHOS 适配版 Conan 2.29.1测试工具DejaGNU 1.6.3.1、Expect 5.45.4、Tcl 8.6.14上游版本binutils 2.46.0tag 为binutils-2_46本次适配提交62bd363f7a8ef6e60f5fec0393fc01c868eaa5cfConan profile 是指定操作系统、架构、编译器和环境变量的配置文件。表中的6.0是 profile 的配置值复现时还应记录设备“关于本机”中的完整系统版本和实际 SDK 版本。Conan 的armv8在这里对应 AArch64它与终端中uname -m输出的aarch64表示同一目标架构。首次准备设备可以从官方仓库 README 的部署入口和环境初始化脚本 了解所需工具。本次复现的前提是设备已经具备 HNP 命令行环境、Git、Python、make、Clang 和 OHOS 适配版 Conan。普通桌面平台上的同版本 Conan配置行为可能不同。在鸿蒙 PC 终端进入 Bash 后先检查工具/data/service/hnp/bin/bashexportPATH/data/service/hnp/bin:/system/bin:$HOME/.local/bin:$PATHexportCONFIG_SHELL/data/service/hnp/bin/bashexportSHELL$CONFIG_SHELLuname-mconan--versionpython3--version/data/service/hnp/bin/clang--versioncommand-vgitmaketest-x/data/service/hnp/bin/binary-sign-tooltest-x/data/service/hnp/bin/llvm-objcopy应能看到 AArch64 架构及各工具版本两个test命令成功时返回 0。后续原生程序测试会使用签名工具和llvm-objcopy因此这两项也要提前检查。3. 适配过程核对源码确定要运行的测试先固定 binutils 2.46.0 的上游 tag、源码归档和 SHA256再检查构建系统、组件及测试入口。binutils 使用 Autotools Make 构建使用 DejaGNU/Expect 测试。上游config.sub已接受 OHOSconfig.guess还需要补充系统名识别。本次验收检查六项内容AArch64 汇编、链接、ELF 检查、静态归档、objcopy/strip 变换后执行以及启用的上游测试驱动完整结束。gprofng 等受限组件也在这一阶段记录后续在报告中说明关闭原因。开始编写配方前先整理源码、依赖和测试要求。本次记录如下适配其他项目时也可以逐项检查调查项本次记录后续处理源码版本固定 tag 与源码哈希各轮实验使用同一份源码交付产物鸿蒙 PC 原生二进制工具包用包内工具汇编、链接并检查 ELF构建与测试工具Autotools/Make、DejaGNU/Expect检查各工具及其依赖是否齐全已有平台支持已有 OHOS triplet、平台知识条目在当前版本验证已有方案补充缺少的修改运行检查正常输入的输出、错误输入的退出码、原生程序执行在消费者脚本中加入对应断言源码地址和哈希记入conandata.yml依赖和构建步骤写入 Conan 配方test_package/MANIFEST.yml记录测试文件、执行命令和断言数量实际运行结果保存在日志和验证报告中。在 WSL 上做工具链对照本次先在 WSL 做 Clang/工具链对照并运行上游测试。主机结果为 5571 PASS、83 FAIL、1 UNRESOLVED消费者为 13/13。后续遇到编译器诊断、调试信息等问题时可以查这些日志确认 WSL 上是否有同样的失败。主机与 AArch64 设备启用的用例不同两个平台的通过率不适合直接比较高低。随后把源码版本信息、配方、补丁、profile 和测试脚本打成设备文件包在鸿蒙 PC 原生构建。文件传入设备后按清单核对哈希确认设备使用的是本轮修改后的文件。最终的 r6 文件包共核验了 46 个文件。每轮运行都记录源码版本、编译器版本、完整命令、退出码、标准输出和标准错误。失败日志同样保留修改后可以对照具体报错是否消失。用小例子复现错误遇到错误时先从日志判断出错阶段源码获取 → configure → 编译 → 链接 → 测试启动 → 程序运行 → 结果比较例如临时目录创建失败时检查配置脚本和文件系统Expect 启动报错时检查测试依赖和进程交互方式程序输出与预期不同时检查程序行为和比较规则。导致测试驱动中断的问题要先处理待驱动运行完整后再统计结果。排查.addrsig指令错误时测试代码只有int fixture(void) { return 1; }。用同一 Clang 分别生成默认汇编和加入-fno-addrsig的汇编再交给同一 GNU as比较退出码与 stderr检查加上该选项后指令错误是否消失。这个实验只需编译一个函数。排查原生程序执行错误时将同一个hello.c分别交给 SDK 默认链接器和本轮 GNU ld 链接检查两个 ELF 的段、节和执行结果随后按平台流程签名再次运行。后续分析preinit_array、符号绑定等问题时也采用 LLD/GNU ld 对照两组产物使用相同的签名步骤。做这类对照时要保留原用例的编译与链接参数。漏掉-O3、PIE、符号可见性或 DSO 替换步骤小例子的行为就可能与原用例不同。本次后续补充了 O3、libc 和重定位场景的对照实验。修复后重跑相关套件系统识别、HMDFS 临时目录、DejaGNU 传输和脚本解释器等问题参考了仓库里的已有处理方法并在 binutils 2.46.0 上逐项验证。新增的.addrsig问题也保留了最小复现代码和编译输出。补齐 SFrame 只读夹具复制和 ld 日志参数处理后先重跑对应套件libctf 明确选择 GNU ld 后定向运行得到 18 PASS原来的驱动错误消失。修改保存到补丁和配方中下一次从源码重新构建时自动应用。本次还为适配逻辑、签名辅助程序和复验脚本保留了回归检查。binutils 的工具功能由上游测试和安装包消费者测试验证。完整回归中的几次调整定向测试通过后再运行完整套件检查其他测试是否出现新的失败。下表是几次真机运行的结果和后续处理阶段观察到的结果后续处理r43223 PASS、193 FAIL、1 UNRESOLVED继续定位夹具、测试传输和运行部署问题final203393 PASS、60 FAIL定位压缩调试测试的汇编器选择及dlopen夹具漏签final343425 PASS、36 FAIL全局外部汇编器引入mbind2a/b两项新失败收窄修改范围final36设备会话中断退出码 130记录为中断运行另起完整运行final393419 PASS、35 FAIL、0 UNRESOLVED作为本次最终测试记录各轮启用的用例有所变化。final34 到 final39 之间部分驱动恢复了原来的能力探测状态PASS 总数随之变化。因此比较两轮结果时还要核对失败名称、实际执行的驱动以及修改前的测试状态。最终final39使用新的 Conan 缓存从固定版本的源码、配方和补丁重新构建测试依赖及 binutils运行五套 DejaGNU 测试、libiberty 检查与安装包消费者。归档的 138 个结果文件回传后逐项核对大小和哈希。同一份配方、补丁、测试和说明随后提交到官方任务分支通过 PR 检查并合入。GNU ld 程序执行失败的排查记录下面以 GNU ld 链接后的程序执行返回 126 为例列出当时的排查记录项目GNU ld 原生程序执行案例触发条件同一源码经 GNU ld 链接后在鸿蒙设备执行原始现象链接完成执行返回 126待验证假设产物部署环节缺少平台签名最小实验对比 SDK 默认链接器与 GNU ld 产物的 ELF 信息及执行状态单项修改对 GNU ld 产物按平台流程签名并确认执行权限观察结果同一程序随后执行成功退出码和 stdout 均留存修改位置测试签名辅助程序与native-test.py回归范围主程序、本地动态库、明确的 dlopen 夹具以及 objcopy/strip 产物排查记录还应附上完整命令、退出码和 stdout/stderr方便按相同参数重新运行。表中只列主要结果原始输出单独保存。4. 用公开配方复现构建为对应本文记录先取固定提交。以下命令在鸿蒙 PC 的 Bash 中执行选一个用于复现的新目录gitclone https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos.git binutils-2460-articlecdbinutils-2460-articlegitcheckout--detach62bd363f7a8ef6e60f5fec0393fc01c868eaa5cfRECIPE$PWD/archives/b/binutils/2.46.0PROFILE$PWD/ci/conan/profiles/ohos-aarch64cat$PROFILE配方目录里conandata.yml固定上游源码地址和 SHA256conanfile.py组织构建与验证patches/保存 25 个补丁test_package/保存安装包测试。Conan 会自动应用补丁。复现前检查 profile 中编译器及 SDK 动态库目录与本机一致目录有差异时复制一份 profile调整路径并让PROFILE指向该文件。随后使用独立缓存保存这次实验避免旧制品干扰判断set-opipefailRUN_ROOT$PWD/article-run-$(date%Y%m%d-%H%M%S)mkdir-p$RUN_ROOT/tmpexportCONAN_HOME$RUN_ROOT/conan-homeexportTMPDIR$RUN_ROOT/tmpexportMAKEFLAGS-j1 conan remoteaddohpcd\https://conan.cnb.cool/OpenHarmonyPCDeveloper/Conan/-/packages/ conan profile show-pr:h$PROFILE-pr:b$PROFILEconan create$RECIPE-tf$RECIPE/test_package\-pr:h$PROFILE-pr:b$PROFILE\--buildmissing--buildbinutils/*\21|tee$RUN_ROOT/conan-create.logbuild_rc${PIPESTATUS[0]}printfconan create exit%s\n$build_rc这里 host 和 build 都使用鸿蒙 profile因为是在目标设备上原生构建。--buildbinutils/*指定重新构建 binutils--buildmissing允许补建缺少的依赖包。pipefail与PIPESTATUS用来保留构建进程的真实退出码便于识别日志管道里的失败。本次归档运行使用独立缓存conan create返回 0任务耗时约 44 分 45 秒。这个耗时对应当时的设备和缓存条件。归档运行从设备文件包启动上面的命令使用同一提交下的公开配方目录执行时应保存自己的新日志。后文数字仍引用原始final39记录。5. 构建脚本与编译选项平台识别和临时目录Autotools 通过config.guess判断构建平台。本次在脚本里补充 HarmonyOS、OpenHarmony、OHOS 的系统名分支AArch64 对应的识别结果为aarch64-unknown-linux-ohos。同版本config.sub已接受linux-ohos因此最终方案保留了它的原有实现。本次在 HMDFS 上还遇到了config.status创建临时目录失败的问题。最终补丁调整了 14 个生成的configure脚本中临时目录的umask从077调整为022同时为脚本入口选择已配置的 Bash。这类报错发生在编译之前。排查时先看失败的是目录创建、平台探测还是 C/C 编译再决定修改位置。相关补丁保存在项目目录内复现时由配方应用其他项目采用同一办法前需要先验证自己的文件系统行为。Clang 与 GNU as 的.addrsig问题Clang 输出的文本汇编包含 LLVM 的.addrsig相关指令本次交给 GNU as 处理时出现了指令错误。配方为 Clang 的 C/C 编译标志追加-fno-addrsig让 Clang 省略这部分汇编元数据。最终配方 中的代码为ifstr(self.settings.compiler)clang:toolchain.extra_cflags.append(-fno-addrsig)toolchain.extra_cxxflags.append(-fno-addrsig)这个片段属于 Conan 配方的generate()方法完整上下文以链接中的文件为准。它解决的是本次 Clang 与 GNU as 的衔接问题采用其他编译器或版本组合时应先确认实际输出和报错。6. DejaGNU 测试与工具选择DejaGNU 与终端环境binutils 大量测试由 DejaGNU 组织Expect 负责启动进程和读取输出。原有运行方式依赖伪终端简称 PTY。本次设备环境需要使用 pipe 或文件通道完成相应交互。以 gas 测试读取gas.out为例补丁 0019 把读取方式调整为spawn -open [open gas.out r]这样仍然读取汇编器输出由原来的比较逻辑给出结果。其他修复还包括用普通文件复制部署只读测试夹具、通过指定 shell 执行辅助脚本以及给send_log加--让负退出状态按数据写入日志。在运行长测试前配方先执行传输预检完成 5 项检查和 256 次子进程循环。这些预检结果单独记录帮助判断进程启动与输出读取是否可靠。检查 Clang 实际调用的汇编器压缩调试信息测试中Clang 收到了指向测试工具目录的-B参数却仍使用自身的集成汇编器测试未调用预期的 GNU as。本次通过-fno-integrated-as让相关测试调用 GNU as并明确选择本轮生成的 GNU ld。final34 曾把外部汇编器开关扩大到全部 ld 测试导致mbind2a/b出现新的失败。最终补丁 0025 将这个开关限定在compress.exp运行期间进入前保存 C/C 标志执行相关测试结束时恢复原值。最终压缩调试组为28/28 PASSmbind2a/b回到基线的UNSUPPORTED状态。-fno-addrsig控制元数据生成-fno-integrated-as控制汇编器选择。调整参数后需要核对实际调用的工具并重跑受影响的测试驱动。7. ELF 签名与原生程序执行GNU ld 生成的程序还需要完成鸿蒙平台的签名部署随后才能验证其运行行为。排查记录中出现过未签名产物执行返回 126 的现象退出码 126 本身并不唯一对应签名问题还要结合文件权限、架构、加载器和签名记录定位。本次增加了测试签名辅助程序。它只处理当前测试套件tmpdir范围内符合条件的 AArch64 ELF并处理程序本地的DT_NEEDED依赖。DT_NEEDED可以理解为 ELF 记录的动态库需求列表。部分测试还会用dlopen在运行过程中加载动态库这些库未必出现在主程序的DT_NEEDED中。例如pr21964-2b.so就需要作为明确的测试夹具纳入签名范围。补齐后pr21964-2测试通过。objcopy和strip会改变 ELF 文件因此安装包测试在每次变换后重新签名再执行程序。包含自定义外部 RPATH/RUNPATH 的应用还需要按自身部署方式验证依赖查找和签名过程。8. 安装包测试与真机复验上游测试主要验证构建目录里的工具。交付时还需要检查 Conan 包内的工具、测试输入和运行环境是否齐全。本次通用消费者脚本 用as汇编夹具再用readelf、objdump、nm检查格式和符号用ar创建归档用ld -r链接目标文件最后用strip处理副本。它还故意读取一个不存在的文件检查工具返回非零值并在标准错误中包含缺失路径和原因。该流程共有13 个断言。原生消费者脚本 则验证 GNU ld 链接后的程序、objcopy 副本和 strip 产物三个程序签名后均在真机输出binutils native consumer: 2460这部分是3 个运行断言两类合计16/16。运行conan create时会自动执行这些入口只想复验安装包时可以使用conan test传入自己的包引用和本次 profile。2026 年 9 月 26 日在原设备保留的安装包上重新运行相同消费者脚本输入文件的 SHA256 与最终提交一致。此次实测系统参数为OpenHarmony-6.1.0.115编译器为 Clang 15.0.4。通用断言 13/13、原生运行断言 3/3 均通过三个原生程序均输出上述字符串。图 12026 年 9 月 26 日通过 HDC 获取的 3120×2080 完整屏幕保留终端窗口和系统任务栏。终端显示当次消费者测试的运行汇总原始 stdout/stderr 另行保存。9. 测试结果与剩余失败本次五套 DejaGNU 汇总如下数字来自原始.sum文件套件PASSFAILXFAILUNSUPPORTEDUNTESTEDbinutils2731282gas123900100ld172134131822libctf180030libsframe1680000合计341935152034五套汇总的UNRESOLVED和XPASS均为 0。普通通过率按PASS / (PASS FAIL UNRESOLVED)计算即3419 / 3454 98.99%。XFAIL是预期失败UNSUPPORTED表示当前配置不支持相应用例UNTESTED表示未完成测试三者都单独保留。上游共有 386 个.exp文件其中 7 个属于关闭的 gprofng 组件启用的 379 个文件包含 367 个执行驱动和 12 个支持文件。一个驱动会产生多个测试结果文件数、驱动数与 PASS 数各自统计。传输预检的 5 项检查也未并入上游五套汇总。另外libiberty 的检查为930/930包括 860 个符号解码用例、69 项输出检查和 1 项进程执行检查。gprof 因gprof_cv_sys_nativeno该环境实际发现和执行数量均为 0gprofng 的 Linux 专用采集器在配置中显式关闭。配方也显式关闭了 NLS并使用--without-zstd。35 个失败项的分析失败分析报告 保留了完整名称并记录 15 类根因。以下是其中几项的对照结果有用例要求 ELF 携带 glibc 的GLIBC_ABI_DT_RELR版本需求而本次目标使用 musl 环境预期条件存在平台差异。preinit_array场景用同一源码分别经 SDK LLD 和 GNU ld 链接、签名两种产物出现一致的运行现象相关证据指向目标加载器行为。精确诊断行号的部分用例在 WSL Clang 对照中也失败需要结合编译器调试信息分析。AArch64 PIE 重定位的部分场景中SDK LLD 与 GNU ld 结果确有差异使用这些重定位的程序需要单独验证。归档报告结合日志与对照实验未发现最终适配补丁引入的保留失败。这个结论限定于已测试场景35 个FAIL仍是实际结果。特定项目如果依赖其中的符号版本、加载顺序或重定位行为应增加自己的验证。图 22026 年 9 月 26 日在设备上读取final39原始日志并由 HDC 获取完整屏幕。画面明确标注历史记录上游全量测试对应 9 月 8 日的运行。设备日志 SHA256 与本地归档一致。10. 代码合入与发布检查本次交付包含 Conan 配方、25 个补丁、安装包测试、运行签名辅助程序和失败分析。PR 检查 #42539 通过2026 年 9 月 10 日 PR 合入后发布流水线 #6203 的公开回执记录了构建测试、制品上传和制品签名通过。11. 常见问题Windows 或 WSL 编译成功可以作为鸿蒙端成功的证据吗它们可以提供源码、编译器和测试逻辑的对照。本次最终结论来自 HarmonyOS PC 原生构建与执行主机结果在验证材料中单列。为什么使用-j1本次 HMDFS 环境对 GNU make 的 FIFO jobserver 路径有兼容问题配方采用串行构建与测试。换到其他环境后可以在确认文件系统和调度行为的基础上评估并行设置。Conan 提示OHOS不是有效的系统配置先查什么先核对是否使用社区 OHOS 适配版 Conan再检查当前CONAN_HOME的配置是否来自旧版本。独立实验缓存有助于排除历史设置影响具体配置参照官方初始化脚本。HDC 已连接为什么它的 shell 看不到 HNP 工具目录本次设备上HDC shell 与 HiShell 的目录视图不同HDC 使用/storage/media/100/local/files/Docs/传输文件HiShell 使用对应的/storage/Users/currentUser/路径并运行 HNP 工具。因此本次由 HDC 传入脚本在独立 HiShell 标签页执行再由 HDC 截图和取回日志。遇到相同情况时先核对当前 shell 的身份和目录视图再查工具路径。make check返回 2为什么最终conan create返回 0原始make check保留了 35 个失败项因此返回 2。配方另设验收条件五套汇总文件齐全、367 个驱动按清单执行、未发生指定的驱动中断错误且普通通过率至少为 90%此外还检查 gprof、libiberty 和运行预检结果最后执行安装包测试。本次通过了这些检查因此conan create返回 0。复现时要同时查看原始日志和失败分析35 个上游失败项仍保留在结果中。UNSUPPORTED可以算成通过吗统计时单列并保留它产生的条件。此次收窄compress.exp的汇编器开关后相关驱动恢复了基线状态报告据实记录。新手从哪里读源码最有效建议先看test_package/test.sh中的汇编、链接和文件检查命令再看conanfile.py如何构建和运行上游测试。遇到具体报错时查相应补丁和失败分析中的复现记录。