欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/

欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper

鸿蒙PC适配mpd 0.24.12:从交叉编译到合入实录

项内容
对象mpd 0.24.12(Music Player Daemon,上游官方源 musicpd.org,2026-05-15 发布)
环境HUAWEI MateBook Pro(HAD-W32)/ HarmonyOS 6.1.0(6.1.0.117 SP68C00E100R13P3,HongMeng Kernel 1.12.0)/ aarch64 / Conan 2.29.1(OHOS 适配版)
仓库OpenHarmonyPCDeveloper/build_in_harmonyos(AtomGit)
PR#13375
发布mpd/0.24.12 配方已入制品仓(2026-10-03 上传;2026-10-04 conan download 实测可达)

摘要

mpd 0.24.12 适配鸿蒙 PC aarch64:mpd(Music Player Daemon)是开源世界最老牌的独立音乐服务器之一(HTTP/JSON API + 曲库 + 解码/编码后端),上游以 meson 构建。核心难点不是"换个编译器再编一遍":OHOS libcxx-ohos(LLVM 15.0.4 基线)缺失多项 C++23 标准库 API,而上游源码无条件使用——40 个文件的源码级 portable 补丁,分 4 类(其中 1 个文件属双类修改);meson 交叉编译需自包含交叉文件(host_machine=linux/aarch64 + identity exe_wrapper + 全局 -I/-L 注入);conan 2.29 的 PkgConfigDeps .pc prefix 缺陷与 find_library 型依赖用 8 个 shim 收口。上游测试 18 个 test() 注册,本配置启用 16 个、全量实测 Ok 16 / Fail 0(其中 15 个 gtest 套件共 170 例 [OK],1 个 bzip2 shell 套件 0.20s 通过;2 个未注册因上游环境依赖缺失,非适配裁剪);test_package 消费者测试 C1-C4 共 9 条真实断言,含 null 输出 + 协议状态机的无头播放闭环(play→stop);CI 7 轮构建 4 绿 3 作废(作废轮均为基础设施原因,逐轮附证据);3 份知识草稿(E429/E430/E1003)随 PR 入仓。PR #13375 已合并入 main,mpd/0.24.12 配方已入制品仓。

mpd 0.24 起上游切换到 C++20(官方推荐 clang 14+),而源码树又无条件使用 C++23 的 make_unique_for_overwrite——OHOS 的 clang 版本号 15.0.4 能过上游要求,但其标准库基线(LLVM 15)缺的正是这批 C++23 API,任何 option 组合都会命中;而在没有音频硬件的环境下,音乐服务器"真的能播"这个核心功能如何验证,同样没有现成答案。本文给出 40 个可移植补丁、8 个 pkg-config shim 与一条 null 输出播放闭环的完整实证过程。

诚实声明(结论边界):

  • 18 个上游测试套件中 2 个未注册:test_archive_iso9660(需 libiso9660 + mkisofs 程序,依赖未入制品仓)与 test_archive_zzip(需 libzzip + zip 程序,zziplib 不在本图)——上游环境依赖缺失,不是适配裁剪;点亮路径见 4.7。
  • 播放闭环经 null 输出插件验证(协议→队列→解码→输出线程全链路,play→stop 状态机实测迁移);ALSA/JACK 输出仅构建期启用(enabled),未在本设备验证真实音频设备出声路径。
  • JACK 符号探测 jack_set_info_function = NO,JACK 运行时行为未验证;inotify 本配置关闭。
  • 全部结论限定于:HarmonyOS PC aarch64 真机(本设备)+ 本构建配置。

1. 背景:为什么值得做

  • 生态价值:mpd 是开源世界最老牌的独立音乐服务器之一(源码树 NEWS 追溯至 0.5 初始发布,最早带日期条目为 2003-05-25)——守护进程 + 客户端分离架构,通过网络协议(文本命令协议 + HTTP/JSON API)暴露曲库管理、播放控制与解码/编码后端(flac/vorbis/opus/wavpack/mp3/ffmpeg 等)。它是 Linux 音频生态的事实标准组件:应用与脚本可通过其网络协议直接调度本地播放,而不依赖任何厂商私有框架。把它带到鸿蒙 PC,等于给平台补上"本地音频服务器"这一基础件。
  • 版本选择:0.24 系列是上游当前维护线(源码树 NEWS:ver 0.24 发布 2025/03/11,其后持续出补丁版至 ver 0.24.12 发布 2026/05/15)。0.24 的构建要求(NEWS 逐字):switch to C++20(GCC 12 或 clang 14+ 推荐)、require Meson 1.0、require libfmt 9 or later、remove Boost dependency,另有 ffmpeg≥4.0、alsa-lib≥1.1、libwavpack 5 等依赖底线——本配方 17 个依赖版本全部满足。0.24.12 修复 0.24.11 引入的回归:0.24.11 修复 path traversal 后误伤 lsinfo/add 的空 URI,0.24.12 放开(NEWS 逐字:allow empty URI in "lsinfo", "add" etc. (0.24.11 regression))。
  • 制品仓现状:适配前 W0 预检确认制品仓无 mpd 记录(无先例可复用);依赖链 17 个 host 包 + 1 个构建工具包全部已发布(逐包 conan download 核验,2026-09-27)——“依赖齐、本体空白”,适合直接做本体适配。
  • 路径C 高难度定性:mpd 同时命中四类深度集成面——多媒体解码/编码(归档格式 bz2/iso9660/zzip 等 + 主流标签格式 + ffmpeg 全家桶)、音频输出(ALSA/JACK)、网络服务(HTTP/ICY/WebDAV 输入)、系统存储(sqlite 曲库);源码树又无条件使用 C++23 标准库 API,在 OHOS LLVM 15.0.4 基线工具链上构成系统性缺口——不是"改两三个平台分支"能解决的量级。

2. 环境与差异前置

环境表全部值为当事机器实测(或标注来源):

项值测量来源
设备HUAWEI MateBook Pro(HAD-W32)param get const.product.model 实测
系统HarmonyOS 6.1.0(版本串 6.1.0.117 SP68C00E100R13P3;HongMeng Kernel 1.12.0)param get const.product.software.version / uname -a
架构aarch64uname -m
Conan2.29.1(OHOS 适配版,os=OHOS 为有效枚举值)conan --version
编译器clang 15.0.4(HNP 工具链,/data/service/hnp/bin/clang)conan profile conf + 构建笔记
conan profileos=OHOS / arch=armv8 / compiler clang 15 / libcxx=libc++ / cppstd=17 / Releaseci/conan/profiles/ohos-aarch64(仓库内文件)
构建工具meson 1.12.0 + ninja构建树实测 / 构建笔记
上游源https://www.musicpd.org/download/mpd/0.24/mpd-0.24.12.tar.xzconandata.yml;本机 curl -I 实测 HTTP 200(2026-10-04)
SHA-25614223ca883c35fbf711994bcf745726cecc9d898e3d3964265cf3a2c7519a360conandata.yml(下载时校验通过)

两个直接影响适配形态的环境事实:

  • profile 声明 cppstd=17,但 MPD 0.24 强制 C++20(meson 自报 cpp_std=c++20)——编译器"版本号"达标不保证"能力"达标,C++20/23 特性实际由标准库实现决定,这正是第 3 节 4 类源码缺口的根因。
  • 本机 = 目标机(aarch64 HarmonyOS 原生环境,不是"x86 host + 远端目标"的远程交叉布局)——这决定了交叉文件的形态(host_machine=linux + identity exe_wrapper),也决定了上游测试二进制可以在真机上直接实跑(见 4.2)。

差异表(先列全 13 项,第 3 节逐项展开;每行对应一个坑位或验证边界):

#差异点上游假设鸿蒙 PC 实际情况对应
1C++ 标准库能力现代 libc++(C++23 P2325/P2652 等可用)libcxx-ohos 基于 LLVM 15.0.4,缺失多项 C++23 API3.3 坑 2(4 类补丁)
2fmt 头文件布局fmt <11(core.h 暴露全量 API)图内解析 fmt/12.2.0,core.h 精简布局3.3 坑 2(第 3 类,29 文件)
3构建模式原生 meson 构建meson 交叉文件(host_machine=linux/aarch64)+ identity exe_wrapper3.2 坑 1
4pkg-config 生态系统 .pc 前缀有效conan PkgConfigDeps .pc prefix 指向不存在的槽 + 个别模块缺失3.5 坑 4(8 shim)
5find_library 型依赖系统 /usr/include 默认可见mad/lame/bzip2 需显式 -I/-L 注入3.5 坑 4
6ICU 形态动态或静态均可纯静态包,数据符号 -licudata 必链 + meson 缓存 .pc 结果3.6 坑 5
7cross 测试执行无需 wrappermeson 1.12 cross 构建无 exe_wrapper → 全部测试 SKIP3.7 坑 6
8CLI/配置格式0.22 时代习惯(–config / 等号)0.24 重构:配置路径是位置参数、无等号格式3.8 坑 7
9ELF 链接后处理strip/install 常规操作已落盘 ELF 的 in-place 字节改动 = 不可执行(完整性封印)3.9 坑 8
10构建缓存独占 .conan2多 worker 共享缓存,槽位漂移/遗留3.10 坑 9
11依赖版本图单版本 bzip2host 图 1.0.8(ffmpeg 传递)与程序需求(1.0.8.2 才有 bindirs)3.11 坑 10
12conan 2.29 依赖引用传递可达即可用package_info 使用直接依赖必须显式声明3.12 坑 11
13音频输出ALSA/JACK 设备可用构建期 enabled,运行时无设备;验证走 null 输出3.14 坑 13 + 4.4 C4 边界

3. 适配过程

3.0 侦察(动手前)

  1. W0 依赖预检:17 个 host 依赖 + 1 个工具依赖逐一 conan download <pkg> -r=ohpcd --only-recipe 核验制品仓,全部已发布(2026-09-27)→ 无需自编译依赖。测试清点阶段另发现 TestIcu 需要 icu/76.1(制品仓已有,补入 requires,初始依赖清单外)。
  2. 构建系统判定:meson + ninja(源码声明 meson_version >= 1.0;0.24 主程序无 autotools/CMake 路径)。交叉三元组口径:meson 无 ohos 系统名,host_machine 用 linux/aarch64。
  3. 测试策略:R51 三步法(清点 → 全量实跑 → 回填)。清点:test/ 目录 86 个 .cxx + 8 个 .hxx + 3 个 .sh,GoogleTest 框架,18 个 test() 注册;其中 3 个受"上游环境依赖"门控(bzip2 程序 / mkisofs 程序 / zip 程序 + 对应库),轮 A 预期本配置启用 15/18。
  4. 语言预检误报(误判 ①):lang-preflight 初判 mixed(exit 2)——3 个 build.gradle.kts + 6 个 .java 全部位于 android/ 可选 Android 客户端目录(不在 meson 构建图内);主体 1671 个 .cpp 占 99.4% → 经源码统计复核改判 cpp 继续。教训:多客户端目录工程的主体判定要按"实际适配目标",不能按全仓文件统计。
  5. 开关基线:22 个 -D 开关 = 1 显式(default_library=static)+ 15 特性开关 + 6 背景 OFF(shout/ao/oss/pulse/sndfile/faad)+ inotify=false;背景 ON 清单 11 项逐项与 meson configure 自报值核对(ALSA/JACK/SQLITE/FLAC/VORBIS+VORBISENC/MAD/WAVPACK/OPUS/FFMPEG;CDIR 因 libcdio_paranoia 不在制品仓 auto→off,PORTAUDIO 在 0.24.12 无对应输出插件不被消费);auto 族按"依赖在图内默认启用、缺省关闭"处理(curl/expat/webdav/pcre/lame/ipv6 转 ON,34 项缺依赖族 off)。

3.1 依赖树

mpd/0.24.12(meson 交叉构建,host_machine=linux/aarch64)
├── alsa-lib/1.2.16.1      音频输出(OHOS 运行时无设备,构建期 enabled)
├── jack/1.9.22            JACK 输出(符号探测 NO,运行时未验证)
├── sqlite3/3.53.4         曲库
├── zlib/1.3.1.1           ffmpeg 图冲突下唯一可解版本
├── flac/1.5.0             flac 解码
├── vorbis/1.3.7           ogg/vorbis 解码+编码(vorbis+vorbisenc 双模块)
├── mad/0.16.4             mp3 解码(find_library 型,-I/-L 注入)
├── wavpack/5.9.0          wavpack 解码
├── opus/1.5.2.1           opus 解码
├── ffmpeg/6.1.6           通用解码(libavformat 60.16.101 等,.pc Version 自 SONAME 修正)
├── icu/76.1               Unicode(纯静态包,-licudata 必链)
├── fmt/12.2.0             格式化(29 文件 core.h→format.h)
├── libcurl/8.5.0          HTTP/WebDAV 输入 + test_icy_parser(shim 收口)
├── lame/4.0               mp3 编码(find_library 型)
├── bzip2/1.0.8            .bz2 档案解码(host 图版本,与 ffmpeg 传递一致)
├── gtest/1.17.0           单元测试(gmock 代码实装于本包内,shim 收口)
├── gmock/1.17.0           单元测试(shim 收口)
└── tool_requires: bzip2/1.0.8.2   bzip2 程序(test_archive_bzip2 shell 套件;1.0.8 包无 bindirs)

传递/图内(不在 requires 主清单):expat 2.8.2.1 / libpcre2-8 10.48 /
libiso9660 2.3.0 / ogg 1.1.1(libvorbis 传递)/ fontconfig·freetype·harfbuzz·libxml2·xz(ffmpeg 传递)

3.2 坑 1:交叉文件自包含(三件套 + 两个易错点)

  • 现象:交叉构建需要 [binaries](编译器绝对路径——OHOS posix_spawn 无法经 PATH 解析裸命令)、[host_machine] 与代码生成器的 native file;本地探索期的机器特定配置若直接进配方,CI clean 环境不可复现。
  • 定位:meson 1.12 交叉三元组口径(host_machine=linux/aarch64);源码 GenParseName.cxx 是 native:true 构建期代码生成器,需要 build machine 编译器的 native file。实测 ar 必须写入 native file——缺失时 meson 对 build machine archiver 回退 PATH 查找(llvm-ar-15/llvm-ar/ar/gar 全部 ENOENT),报 “Unknown linker(s)” 误报。
  • 方案:conanfile build() 自包含生成三个文件——cross-ohos.ini([binaries] 绝对路径 + exe_wrapper + [host_machine] system=linux + [built-in options] 全局 c/cpp_args 与 c/cpp_link_args)、native-build.ini(c/cpp/ar 三件套)、mpd-exe-wrapper.sh(identity wrapper,见坑 6)。编译器路径优先取 profile conf(tools.build:compiler_executables,R33 合规),回退 HNP 绝对路径;机器环境 CFLAGS 原值(-fPIC -O2)显式保留([built-in options] 会覆盖环境 CFLAGS)。
  • 经验:meson 1.12 位置参数序是 [builddir] [sourcedir](builddir 在前);遇到 “Unknown linker(s)” 先查 archiver 探测链,而不是怀疑链接器缺失。

3.3 坑 2:OHOS libcxx-ohos 的 C++23 标准库缺口(4 类 40 文件,全部 portable)

共同根因:OHOS 工具链的 libc++ 基于 LLVM 15.0.4,上游 MPD 0.24 源码无条件使用更新的标准库 API;clang 版本号 15.0.4 能过上游推荐(clang 14+),但"标准库实现"落后于"编译器版本号"。四类:

类现象(首个命中)根因(标准缺口)portable 修法范围
1. span range 构造src/util/SpanCast.hxx:53 string_view→span 初始化无匹配构造缺 C++23 P2652(span-from-range,libc++ 18 才并入);上游 guard 仅覆盖 __clang_major__ < 15,本机 clang 15.0.4 恰好落在 guard 之外guard 改特征宏 #if __cpp_lib_span < 202306L(1 行),两分支产生等价 span1 文件
2. make_unique_for_overwrite全树编译错(首命中 FileCommands.cxx)缺 C++23 P2325R3(libc++ 19 才并入);源码树无条件使用,任何 option 组合都会命中统一替换 std::make_unique(语义差异仅值初始化多一次零填充;13 处使用点均写后才读,无副作用)10 文件 13 处(含双类文件 0024)
3. fmt 头布局29 文件 no member named 'format' in namespace 'fmt'(首命中 ToString.cxx)fmt 11+ 将 <fmt/core.h> 改精简布局(format/to_string/join 移入 <fmt/format.h>);图内 fmt/12.2.0;任何平台 fmt≥11 均会命中#include <fmt/core.h> 统一替换 <fmt/format.h>(严格超集、幂等、fmt 9-12 全兼容)29 文件(含 1 个 win32 专属文件,统一替换保任意平台可构建)
4. chrono time_point <=>src/event/TimerList.hxx:22 regular_invocable<compare_three_way, time_point, time_point> = false(一次命中 6 个 TU)缺 std::chrono::time_point::operator<=>,默认 Compare=std::compare_three_way 不可调用增加显式比较器 CompareDue(返回 strong_ordering,仅用 C++11 关系符)并传入;树逻辑以 weak_ordering 接收(strong→weak 标准隐式转换),语义完全一致1 文件
  • 文件数口径(包含关系):类别计 1+10+29+1 = 41 个"类-文件"计次,其中 0024 属双类修改文件(同时计在第 2 类与第 3 类),去重后共 40 个文件(0001–0040),与 conandata.yml 声明的补丁文件数逐一对应;notes.md 中的"41 文件"是未去重的类别计次口径。
  • W0b 历史比对:历史同类适配曾用 defined(__OHOS__) 平台宏(R8 违规),本次不复用——4 类修法均为特征宏/等价 API/显式比较器/头替换,零平台宏、零行为差异、任意平台可构建;历史补丁仅覆盖 make_unique_for_overwrite 10 文件中的 3 个,本次全树补全(含本配置对应 option 关闭的 4 个文件:Sidplay/io_uring/Win32/nfs,保证任意 option 组合可构建)。
  • 经验:“编译器版本号达标” ≠ “标准库能力达标”——现代 C++ 工程适配旧基线标准库的工具链时,先做一次"特征宏 vs 版本宏"清点;上游 guard 用版本宏写死的,改特征宏永远是最 portable 的修法。

3.4 坑 3:meson 1.12.0 对同一 dep 的 cflags 传递不一致(alsa)

  • 现象:编译错 fatal error: 'alsa/asoundlib.h' file not found(仅 input_plugins 目标)——同一 alsa_dep 对象在 libalsa/output_plugins 目标正常,唯独 input_plugins 漏掉 alsa 的 pkg-config cflags;直接 pkg-config --cflags alsa 输出正常(可复现)。
  • 定位:meson 1.12.0 对同一 dep 对象在不同 executable 目标的 cflags 传递行为不一致(疑似 dep 对象共享/缓存问题);现象可复现,内部机制未完全定位——如实记录,不假装已定位。
  • 方案:交叉文件 [built-in options] 全局注入 -I <alsa-lib include>(workaround,conanfile build() 复现;CI clean 环境同 meson 版本必现)。
  • 经验:依赖问题"部分目标成功、部分失败"时,先用 pkg-config 直查排除 .pc 文件本身,再怀疑构建系统的 dep 传递层;机制未定位的 workaround 在台账中写明"可复现 + 影响范围 + 同版本必现",供后续升级构建系统时复核。

3.5 坑 4:PkgConfigDeps .pc prefix 缺陷 + find_library 无 include(8 个 shim + -I/-L 注入)

  • 现象(同族两个问题):
    1. broken .pc 三处来源:PkgConfigDeps 生成的 mad.pc/lame.pc 等 prefix 指向 recipe 槽的 p/(路径不存在,真实产物在另一 package_id 槽);gtest 包自带 4 个 .pc 硬编码原构建期 build-context 绝对路径(本机不存在);共享缓存遗留 curl 8.15.0 包的 libcurl.pc prefix 指向跨机路径。
    2. find_library 型依赖:MPD 对 mad/lame/bzip2 走 compiler.find_library——find_library 只给链接探测(认 -L),不给 include(上游假设系统 /usr/include 默认可见),mad.h/lame/lame.h not found + 链接缺库。
  • 定位:① conan 2.29.1 PkgConfigDeps 的 .pc prefix 解析到 recipe 槽而非 package 槽(缺陷在 conan 侧,CI clean 环境同样必现);② find_library 型依赖不携带 include 路径是上游设计,非缺陷。
  • 方案:8 个 shim 收口(PKG_CONFIG_PATH 最前:shims:generators,shim prefix 一律取 conan API package_folder 真实产物槽,不依赖 .pc 自带 prefix)——
    shim收口对象原因
    icu-uc / icu-i18nICU 双模块PkgConfigDeps 只生成单一 icu.pc,MPD 按 icu-i18n/icu-uc 两模块名查询
    libcurllibcurl 8.5.0包自带 .pc prefix 跨机损坏
    gtest / gtest_main / gmock / gmock_main测试框架 4 模块包自带 .pc prefix 损坏 + 模块缺失;gmock 代码实装在 gtest 包内(conan gmock 包为无产物标记包),shim 统一指向 gtest 包
    bzip2bzip2 1.0.8轮 B 新增,PkgConfigDeps prefix 槽缺陷同类
    find_library 族:交叉文件 c_args 全局 -I <mad/lame/bzip2 include> + c/cpp_link_args -L <mad/lame/bzip2 lib>。
  • 经验:conan + pkg-config 生态里,.pc"由谁生成"不如"prefix 指向哪"重要——shim 目录 + prefix 权威来源(conan API)可以把 N 个来源各异的 broken .pc 一次收口;shim 在配方 build() 内自包含生成,CI clean 环境等价复现。

3.6 坑 5:纯静态 ICU 包缺数据符号 + meson coredata 缓存 .pc 结果

  • 现象:链接错 undefined symbol: icudt76_dat(mpd 主可执行文件 + 4 个测试链接)。
  • 定位:conan icu/76.1 是纯静态包(libicuuc.a/libicui18n.a/libicudata.a);icudt76_dat 数据符号由 libicudata.a 提供,.pc Libs 只写 -licuuc 即缺 -licudata。且 meson 把 pkg-config 结果缓存进 coredata,meson reconfigure 复用缓存不重查——实测踩坑:改 .pc 后连续两次 reconfigure,build.ninja 仍无 -licudata。
  • 方案:shim icu-uc.pc 的 Libs 补 -licudata(顺序 -licuuc 在前、-licudata 在后)+ meson setup --reconfigure --clearcache 强制刷新。
  • 经验:纯静态包的"数据符号"(icu 的 icudt*_dat 一类)必须显式链上;构建系统缓存了依赖探测结果(meson coredata、cmake cache)时,"改输入重跑"不生效——清缓存,并以 build.ninja 的实际内容(而不是 .pc 的内容)为验证对象。

3.7 坑 6:cross 构建测试全 SKIP(exit 77)→ identity exe_wrapper

  • 现象:meson test 15 个测试全部 SKIP(exit status 77、0.00s、无输出);手动直接运行同一测试二进制 55/55 PASSED。
  • 定位:meson 1.12 交叉构建语义——cross 构建产物运行测试必须经 exe_wrapper;交叉文件未定义 exe_wrapper → mtest.py _get_test_cmd 返回 None → complete_skip()(源码注释:“Can not run test on cross compiled executable because there is no execute wrapper”)。
  • 方案:交叉文件 [binaries] exe_wrapper = ['mpd-exe-wrapper.sh']——本机 = 目标机(aarch64 HarmonyOS 原生),wrapper 为 identity 形态:注入 LD_LIBRARY_PATH(全部有 package_folder 且 lib 目录非空的依赖 + SDK llvm 库)后 exec "$@" 透传。conanfile build() 生成(CI clean 环境等价;CI worker 同为目标机)。
  • 经验:"测试全 SKIP 且 0.00s"是 cross 构建缺 wrapper 的强信号,不是测试失败;本机 = 目标机时,identity wrapper 是成本最低且最诚实的解法(不引入 QEMU/模拟器变量)。

3.8 坑 7:0.24 CLI/配置格式重构(上游行为变化,非平台问题)

  • 现象:冒烟脚本按 0.22 时代习惯启动 mpd,立刻 '"' expected 配置解析错;--decode-file 报未知选项。
  • 定位(源码实证 4 条):① 0.24 主程序无 --config 选项(命令行仅 kill/no-config/no-daemon/systemd/stdout/stderr/verbose/version/help),配置文件路径是位置参数(src/CommandLine.cxx 首个非选项参数);② 新配置解析器(src/config/File.cxx + Tokenizer)不接受 name = "value"(NextString 要求值紧随名字,= 触发 '"' expected)——mpd.conf 必须 name "value" 格式;③ --decode-file 选项已移除(0.24 无);④ 测试工具 read_tags/run_decoder 的 URI 参数直接接受绝对路径(InputStream::Open 对 IsAbsolute 走本地打开,无需 file:// 前缀),DECODER 参数必须为具体插件名(mad/ffmpeg/opus 等,无 “all”)。
  • 方案:冒烟脚本 / test_package 按上述格式编写(mpd --no-daemon <conf>;conf 无等号);R40 实质验证改用 read_tags/run_decoder 替代 --decode-file。
  • 经验:大版本升级的 CLI/配置重构是"上游行为变化"不是"平台问题"——台账中单独成行(不标可移植性),测试脚本是这类变化的第一集中命中处;解析器报错('"' expected 这类)先核对当前版本的配置文法,再怀疑平台。

3.9 坑 8:OHOS 已落盘 ELF 的 in-place 字节改动 = 不可执行(完整性封印)

  • 现象(两条独立证据链,2026-09-27 本机实测,已入档 E430):
    1. llvm-objcopy(本机 llvm-strip 的别名,无独立 llvm-strip)输出——strip --strip-all 与零选项纯重序列化皆然,4.6KB hello world 亦复现——exec 报 EACCES/EPERM;
    2. meson install 对 builddir 产物剥 DT_RUNPATH 的 in-place patch(1195 字节改动、文件大小不变)→ 安装产物 stage 直接执行报 EPERM(cmp 证明 stage ≠ builddir 原件)。
      共性:文件 mode 770、ELF ehdr/phdr 内部一致、SELinux context(hmdfs:s0)与可执行文件完全相同仍被拒——权限层面无任何异常,纯内核拒 exec。
  • 定位:推断(标注为推断)——OHOS 内核/FS 对已落盘文件做完整性封印(与 lld 生成的 .note.ohos.ident 标识段相关,与 SKILL gotchas"ELF 签名:必须签名否则不可执行"同族机制):落盘后任何 in-place 字节改动破坏封印 → exec 拒绝;全新文件写入不受影响(clang/lld 原始产物可执行,cp/shutil.copy2 全新拷贝可执行)。
  • 方案:package() 禁止 meson install / strip / objcopy 一切链接后重写,一律对 builddir 原始产物做全新拷贝(conan copy = 新文件写入);builddir 产物携带的 DT_RUNPATH(指向 conan build tree 目录)异地为死路径、无害,运行时库解析由 conanrunenv 的 LD_LIBRARY_PATH 承担;瘦身/签名需求走 CI sign.sh 签名链,不做本地重写。
  • 经验:在 OHOS 上"链接后处理"与"产物搬运"必须严格分离——搬运只允许以"新文件写入"发生;仓库内 aegisub 先例同为 builddir 直拷(未走 meson install),本坑是第二个实证。

3.10 坑 9:共享 conan 缓存污染(多 worker 环境)

  • 现象:.conan2 为本机共享,被并发任务增删/清理:缓存出现空槽、跨机 prefix 的 .pc、build-context 遗留槽(p/b/ 目录消失);曾导致 libcurl 8.5.0 解析指向已消失的槽。
  • 方案:① 依赖存在性一律 conan download -r=ohpcd(W0/R36/R35 口径),不信任本地缓存的"存在";② .pc 消费一律经 SHIM 收口到实测存在的产物槽(不依赖 .pc 自带 prefix);③ PKG_CONFIG_PATH = SHIM:deps-only(排除遗留槽 .pc 干扰)。
  • 经验:共享缓存机器上,“本地有包” ≠ “包可用”;"存在性判断"与"路径引用"两个动作都应走权威源(制品仓 + conan API package_folder),不要走文件系统探测。

3.11 坑 10:bzip2 版本冲突三连坑(轮 B)

  • 现象(点亮 test_archive_bzip2 时三连命中):
    1. 版本冲突——直接 requires("bzip2/1.0.8.2") vs ffmpeg 传递 bzip2/1.0.8,conan 2 图内直接报 Version conflict;
    2. ld.lld: unable to find library -lbz2——MPD 对 bzip2 走 cc.find_library('bz2')(find_library 型只认 -L,交叉文件 c_link_args 此前仅 mad/lame);
    3. bzip2/1.0.8 包为纯库(package_info 无 bindirs),而套件另需 bzip2 程序(1.0.8.2 包才声明 bindirs=bin,含 12 个程序)。
  • 误判(②)→ 纠正:最初按"哪个包带程序就依赖哪个包"的直觉直接 requires 1.0.8.2 → 撞上硬冲突;复核 ffmpeg 的传递声明后改为分工:host 图维持 bzip2/1.0.8(与 ffmpeg 传递一致,mpd 链 libbz2.a),程序需求单独走 tool_requires(构建上下文与 host 图版本互不冲突)。
  • 方案:① tool_requires("bzip2/1.0.8.2") 仅提供程序(conan 2 直接/传递同包不同版本 = 硬冲突,无隐式升级;build/host 双上下文天然隔离);② 交叉文件 c_args 补 -I <bzip2 include>、c/cpp_link_args 补 -L <bzip2 lib>(meson-log 实证:补前链接测试缺 -L,补后 find_library 通过);③ bzip2.pc 作为第 8 个 shim 收口;④ 程序入 PATH = conan buildenv 自动注入 + 配方 shutil.which 回退注入双保险(which 未命中时读 dependencies.build["bzip2"].package_folder 的 bin 前置 PATH,带 None 判空守卫——与坑 11 同口径)。
  • 经验:conan 2 的"同包异版本"冲突,可用 host/tool 双上下文分工化解——依赖是"库 + 程序"双形态且分属两个版本包时,库走 host、程序走 tool_requires,不强行统一版本。

3.12 坑 11:conan 2.29 直接依赖引用强制(G2 第三类失败)

  • 现象:轮 B 引入 bzip2 后,G2(conan create/verify 配方复现门禁)报 bzip2 依赖引用缺失——package_info().requires 未声明 bzip2::bzip2。
  • 定位:ohpcd conan 2.29 的依赖引用检查要求 package_info 中实际消费的直接依赖必须在 requires 显式声明(依赖在图内传递可达不等于声明层可用)。
  • 方案:package_info requires 补 "bzip2::bzip2";终态 17 个直接依赖逐一声明(与 requirements() 一一对应)。
  • 经验:新增直接依赖要同步三处——requirements()、对应 meson 开关、package_info().requires;第三处最容易被漏(主构建可能不报,验证阶段才暴露)。

3.13 坑 12:W3 “Already installed” 缓存跳过与构建等价判定

  • 现象:W3 本地验证(conan create)阶段出现 “Already installed”——包被判定已在缓存中,实际构建被跳过,验证形同虚设。
  • 定位:共享缓存(坑 9)中留有前一轮产物(同包名版本、同依赖图、同 profile 命中同一 package_id),conan create 缓存命中即短路——这是 conan 的缓存语义,不是配方缺陷。
  • 方案:做构建等价判定——残留包须满足"同配方 revision + 同依赖图 + 同 profile"三要素才可视为等价于本轮构建,判定依据写入台账;最终由 CI clean 环境(无残留缓存)的绿轮做独立复验兜底。
  • 经验:“验证被跳过"要先区分"工具缓存语义"与"验证缺失”——缓存命中必须核对三要素才能接受,且必须留一轮 clean 环境的独立验证,不能拿缓存命中当验证完成。

3.14 坑 13:无头播放协议坑(null 输出播放闭环,已入档 E1003)

  • 背景:OHOS 无 ALSA/JACK 音频设备,R40 实质验证(“真的能播”)不能依赖真实出声;mpd 的 null 输出插件无条件编译(output_plugins_sources 初始值),配置 audio_output { type "null" name "X" } 即得一条零新增依赖的播放链路。
  • 协议坑(两条直觉误用,实测报错,2026-10-01):
    1. play N = 播放列表索引(不是数据库 ID);启动时列表为空 → Bad song index;
    2. add <uri> 用 music_directory 相对路径;把 listall 返回的 0: 前缀(数据库索引)传给 add → No such directory。
  • 误判(③)→ 纠正:协议读取初版按 ACK 惯例严格判定(MPD 协议中带 id 的命令回 ACK <id>),实测 MPD 0.24.12 的 add(无 id 命令)返回 OK → 脚本判全部失败;终态改为以 ERROR 为唯一失败信号(不强制 ACK/OK,跨版本兼容)。教训:协议断言必须以前置的"实测应答采样"为准,不能从协议文档惯例直接推断。
  • 方案:test_package C4 固化(详见 4.4)——python3 wave 生成 3s wav(440Hz、44100Hz mono)→ 独立配置(port 6602 + 独立 music_dir/db/log,0.24 无等号格式)→ mpd --no-daemon <conf> → python3 socket 客户端:recv greeting → listall → add 相对路径 → play 0 → 每 0.3s 轮询 status(40 次 = 12s 窗口)→ saw_play 与 saw_stop 均为真才通过(play→stop 闭环证明);失败输出 mpd 日志 tail。
  • 实测结果:2026-10-01 本机,3s 样本(440Hz wav)完整走完:协议观测到 state=play(time 0→3)→ state=stop(play→stop 闭环),脚本输出 ok: C4 playback end-to-end。
  • 经验:无音频输出的守护进程可用"协议状态机迁移"作为唯一可观测信号;两个前提——样本时长足够(≥3s,0.5s wav 可能采不到 play 状态)、断言双向(play 与 stop 都要观测到,"从未进入 play"与"播了停不下来"都算失败)。

4. 验证(分层,口径不可相加)

4.0 口径声明

本文四个口径相互独立,不可相加:

  1. 上游 meson 套件:16(本配置注册数,上游共 18);
  2. gtest 用例:170(15 个 gtest 套件的 [OK] 行;第 16 个套件 bzip2 为 shell 型,不产 gtest 行)——⊂ 口径 1;
  3. 消费者 test_package 断言:9(C1-C4 = 1+3+3+2)——鸿蒙特有验证,独立于 1/2;
  4. CI 构建轮次:7(4 绿 / 3 作废)——过程口径,不是测试通过率。

"16/16 Ok"指口径 1(套件通过率),"170/170"指口径 2(用例通过率),"9/9"指口径 3。

4.1 上游测试(R51 三步法)

第一步 清点(构建前,2026-09-27):

项值
test() 注册总数18(纯净源码树静态清点,test/meson.build,GoogleTest 框架)
本配置注册16(轮 B)
未注册 2 个test_archive_iso9660(注册条件 = libiso9660 + mkisofs 程序;轮 A 实测 libiso9660 图内可解析、构建机缺 mkisofs 程序,终报口径记为"libiso9660 未发布",两种口径结论一致:上游环境依赖缺失)/ test_archive_zzip(需 libzzip + zip 程序,zziplib 不在本图)——上游环境依赖,非适配裁剪
轮 B 点亮test_archive_bzip2(轮 A 未注册:无 bzip2 库 + 程序;轮 B 以 host bzip2/1.0.8 + tool bzip2/1.0.8.2 点亮,见 3.11 坑 10)

第二步 实跑(2026-10-01 真机,host=target 原生执行):

meson test -v -j4 -t 10    # 轮 B 配方构建树
# → Ok: 16 / Fail: 0(100%)

对归档证据文件(test-evidence.md,686 行 meson test -v 原文,未删节,随 PR 入仓)逐行计数核验:170 [ OK ] = 170 [ RUN ],15 个 [ PASSED ] 套件汇总行;TestUtil 为最大单套件(55 用例);bzip2 shell 套件 OK 0.20s(其 bzip2 程序由 tool_requires bzip2/1.0.8.2 注入 PATH)。

第三步 回填:配方 build() 内置 meson test -j4 -t 10(失败即 fail build,真门禁),CI clean 环境等价复现;全量输出与 16 套件逐条声明分别归档于 test-evidence.md 与 test_package/MANIFEST.yml。

在这里插入图片描述

图 1:上游测试复跑 Ok 16 / Fail 0

4.2 上游测试直接执行声明

本机 = 目标机(aarch64 HarmonyOS 原生):16 个上游测试二进制在目标机上真实执行(meson test 经 exe_wrapper identity 透传,见 3.7 坑 6,无 QEMU/模拟器变量),不是"x86 host 构建后回跑 host";同时未做断言级 1:1 移植——上游测试二进制本身即验证对象,gtest 套件为纯 in-process 单测,16 个套件全部可运行,0 环境受限项。

4.3 私有 API / 符号面

不适用:17 个直接依赖全部为制品仓预编译包,mpd 消费其公共 API(pkg-config + 公共头文件),无私有符号或内部头文件依赖。mpd 自身产物形态见 4.5(主可执行文件 + 2 个测试工具,default_library=static 为主)。

4.4 消费者测试 C1-C4(9 条真实断言)

test_package/test_mpd.sh(bash + python3 socket,由 test_package/conanfile.py 显式经 bash 调用;set -euo pipefail,任一断言不满足即非零退出、输出失败分支与 mpd 日志 tail,无硬编码通过):

用例层断言数断言内容(逐条)实测关键输出
C1L1 版本/身份1mpd --version 输出含 0.24.12Music Player Daemon 0.24.12 (0.24.12) + Copyright 两行(脚本打印 head -3,断言仅版本行)
C2L2 真实 API3① 守护进程启动后存活;② 协议握手:直连 127.0.0.1:6601 读 greeting(0.24 绑定成功无日志,端口连通即"实际监听"证明);③ 曲库导入:日志含 added + sample.wavgreeting OK MPD(banner 0.24.0 为上游 GitVersion 烘焙值,与 --version 的 0.24.12 不同,故仅断言 OK MPD 前缀);ok: C2 library import (scan added sample.wav)
C3L2 解码后端3① run_decoder 在包内且可执行;② run_decoder ffmpeg sample.wav(0.5s wav)退出码 0;③ 输出首行含 audio_format=(解码后端初始化并报告格式)dec.out 首行 audio_format=… 报告
C4L2 核心功能(播放闭环)2① 守护进程以 null 输出配置启动存活(独立端口 6602 + 独立 music_dir/db/log);② 协议状态机:add 相对路径 → play 0 → 12s 窗口轮询中 play 与 stop 均观测到ok: C4 playback end-to-end (play -> stop state machine observed)

C4 的 null 输出边界(与摘要诚实声明一致):验证的是协议→队列→解码→输出线程全链路(null 插件真实消费解码帧),不验证真实音频设备出声。

另(不计入 9 断言,属适配期手工 R40 验证,notes 留档):read_tags mad 解 mp3 → audio_format=44100:24:1、read_tags ffmpeg 解 opus → audio_format=48000:f:1、run_decoder mad/opus 解码帧正常(2026-09-28 本机实测)——mad 与 ffmpeg 两条独立解码路径均有实证。

在这里插入图片描述

图 2:适配产物 mpd --version 真机运行

4.5 产物验证

项值来源
包内容bin/mpd(主可执行文件)+ bin/read_tags + bin/run_decoder(测试工具)+ licenses/(COPYING/LICENCE,GPL-2.0-or-later)conanfile package() 终态
mpd 可执行文件大小37,857,984 字节(~37.9MB,构建树实测)2026-10-04 ls -la
产物搬运方式对 builddir 原始产物的全新拷贝(禁用 meson install/strip/objcopy,见 3.9 坑 8)conanfile 注释 + E430
构建规模737 个编译目标(轮 A 实测;轮 B 增加 bzip2 档案插件目标),本地 ninja 构建 ~13 minPR 正文
CI 构建时长#67013 全程 7 min 27 s(14:00:42 building → 14:08:09 passed,含 clone+构建+测试)PR 评论时间戳
命令声明软件级 commands.json(type=tool, binary=true, ref mpd/0.24.12),CI L0k 通过archives/m/mpd/commands.json
签名CI sign.sh GPG 签名链(合并后发布流水线,不在本地做链接后重写)ci/artifacts/sign.sh

4.6 CI 与评审

CI 7 轮完整表(全部轮次的证据行来自 PR #13375 评论,无删节):

轮buildheadworker结果备注
1#643950ad5ec04CI-038作废(基础设施)09-29 12:02,fork failed: out of memory(worker OOM)
2#643970ad5ec04CI-021作废(基础设施)09-29 12:03,OOM
3#643980ad5ec04CI-021作废(基础设施)09-29 12:04,OOM
4#644080ad5ec04CI-006✅ 通过09-29 12:09 → 12:50
5#644490ad5ec04CI-006✅ 通过09-29 12:51 → 13:12
6#66995148c173eCI-023作废(基础设施)10-02 13:54,SSH bridge connection refused(exit -1)
7#67013148c173eCI-019✅ 通过10-02 14:00:42 → 14:08:09(最终头)

口径:作废轮不计为失败(均为基础设施原因,证据行如上);最终头 148c173ec 有独立绿轮(#67013),不是沿用旧头的绿。

评审记录:

  • 平台 AI 检视:09-29 12:51"AI 代码检视已完成,未发现问题"(对 0ad5ec04);此后 3 次因基础设施失败跳过(09-29 21:11 / 09-30 14:58 / 09-30 20:19,共享盘拥堵/工具超时)——对最终头 148c173ec 的平台 AI 检视未成功,如实记录。
  • 真人评审:Septest(Jiuxi.)rule 评审 09-29 12:15(rule6 AI 检视未覆盖最新提交 / rule7 CI 未通过 → 后续轮次满足);Clancy_Xie 行级意见(feedback 运行时文件不应入 PR → 0ad5ec04f 移除 129 行,保 PR 原子性)。
  • 本地 AI 检视 2 轮(独立子任务执行,两轮报告均在 PR 讨论区留痕):轮 1(对 8cb8b5975)4 项发现——修 3(P1:bzip2 tool_requires 路径的 package_folder=None 守卫回归,E429 同类;P2:read_reply partial-read 竞态致状态偶发漏采;P3:add 应答判定改 ERROR 唯一失败信号)+ 弃 1(误报,附理由)→ 形成 148c173ec;轮 2(对 148c173ec)2×P3 非阻断(说明性回复,无代码改动)。

合并记录:PR #13375 于 2026-10-02 23:24 合并入 main(merged_by Clancy_Xie,approval_reviewer 已 approved;PR 属性 squash_merge=true;close_related_issue=true → 关联 Issue #3527 自动关闭,已核验为 closed)。合并后约 36 分钟,发布流水线将配方上传制品仓(见元信息表"发布"行)。

在这里插入图片描述

图 3:PR #13375 已合并入 main

4.7 复现速查

三条命令(① 为 CI 规范调用,与 ci/conan/build_and_test.sh 同形;②③ 为本文章节引用的本机实测命令):

# ① 配方全量重建 + 上游测试 + 消费者测试 C1-C4(构建期约 13 min,CI 口径见 4.5)
conan create archives/m/mpd/0.24.12 \
  -pr:h=ci/conan/profiles/ohos-aarch64 \
  -pr:b=ci/conan/profiles/ohos-aarch64 \
  --build=missing
# 期望:构建成功 + meson test Ok: 16 / Fail: 0 + "PASS: all C1-C4 checks passed"

# ② 上游测试套件复跑(用既有构建树,不重新编译;bzip2 程序入 PATH)
BZBIN=$(ls ~/.conan2/p/bzip2*/p/bin/bzip2 | head -1); export PATH="$(dirname "$BZBIN"):$PATH"
meson test -C ~/.conan2/p/b/mpd8f22b09807afb/b/build-release/meson-build -j4 -t 10
# 期望:Ok: 16 / Fail: 0(见图 1)

# ③ 产物直接运行(秒级)
bash ~/.conan2/p/b/mpd8f22b09807afb/b/build-release/mpd-exe-wrapper.sh \
  ~/.conan2/p/b/mpd8f22b09807afb/b/build-release/meson-build/mpd --version
# 期望:Music Player Daemon 0.24.12(见图 2)

口径对应:① = 配方自包含性 + 上游 16 套件 + 消费者 9 断言(三口径一次跑完);② = 口径 1 独立复验;③ = 产物可执行性。

配方直接取用:conan download mpd/0.24.12 -r=ohpcd --only-recipe(2026-10-04 实测可达,revision 180e9359c5166e2cf71eca0042278f70)。

点亮 18/18 的路径(后续工作):先适配发布 libiso9660、zziplib 及其工具程序(mkisofs/zip)到制品仓(R36 依赖先行)→ 启用对应特性开关(-Diso9660 / -Dzzip)→ test_archive_iso9660 / test_archive_zzip 注册,预期 18/18。

5. 知识沉淀

编号知识(一行)来源坑位复用价值
E429(草稿)conan 2.29 不可见传递依赖 package_folder=None → 直接遍历抛 TypeError;使用前一律判空3.12 坑 11(轮 B 在 bzip2 tool_requires 路径复发,被本地检视轮 1 P1 拦下)所有遍历 self.dependencies 的 conan 配方
E430(草稿)OHOS 已落盘 ELF 的任何 in-place 字节改动 = 不可执行(objcopy 重序列化 / meson install RUNPATH 剥离双证据链);package() 只允许"新文件写入"3.9 坑 8所有含可执行文件的 OHOS 配方
E1003(草稿)MPD headless 播放闭环:null 输出 + 独立端口/目录 + 协议状态机双向断言(play→stop)+ 协议坑(play=索引 / add=相对路径 / ERROR 唯一失败信号)3.14 坑 13无音频设备的守护进程播放/流媒体验证

3 份草稿随 PR #13375 入仓(knowledge/drafts/,kv+md 配套),待主编 promote 为正式条目;编号均与正式库无冲突(草稿态命名)。

另如实记录一起:适配期发生 E430 正式条目误写事件(覆盖了另一库的知识条目),当轮恢复原条目,OHOS 故事保留在草稿 E430——知识库写入本身也要如实留痕。

6. FAQ

Q1:为什么是 16/18 而不是 18/18?是不是裁剪了测试?
没有裁剪。2 个未注册套件的注册条件都是"库 + 程序"双依赖:test_archive_iso9660 需 libiso9660 + mkisofs 程序(轮 A 实测 libiso9660 图内可解析、构建机缺 mkisofs 程序;终报口径记为"libiso9660 未发布",两种口径结论一致),test_archive_zzip 需 libzzip + zip 程序(zziplib 不在本图)。属上游环境依赖缺失,非适配缺陷;点亮路径见 4.7。bzip2 套件轮 A 同样未注册,轮 B 被点亮(库走 host + 程序走 tool),证明"缺依赖→点亮"的路径可行。

Q2:null 输出播放闭环算"播放验证"吗?
算真链路验证,但边界明确:null 是 mpd 真实输出插件,播放链路(协议→队列→解码→输出线程)真实执行,3s 样本的 play→stop 状态迁移由协议观测;不验证的是真实音频设备出声(本机无 ALSA 节点)。本文在摘要诚实声明与 4.4 中写明边界,不声称"出声"。

Q3:bzip2 为什么依赖两个不同版本(host 1.0.8 + tool 1.0.8.2)?
mpd 需要 bzip2 库(链 libbz2.a)与 bzip2 程序(test_archive_bzip2 shell 套件)两种形态;制品仓 bzip2/1.0.8 为纯库,1.0.8.2 包才声明 bindirs 含程序。直接 requires 1.0.8.2 会与 ffmpeg 传递的 1.0.8 硬冲突(conan 2 无隐式升级)。解法 = host 图保持 1.0.8(库)、tool_requires 1.0.8.2(程序),build/host 双上下文天然版本隔离。详见 3.11 坑 10(含误判自曝过程)。

Q4:CI 7 轮作废 3 轮,可信吗??
7 轮全表列在 4.6,无删节;作废轮均有基础设施证据行(worker OOM ×3、SSH bridge refused ×1),与代码无关;绿轮是完整 conan create(构建+上游测试+消费者测试,与 CI 规范调用同一命令)。"作废轮不计失败"与社区 CI 对基础设施故障的通行处理一致;最终头 148c173ec 有独立绿轮(#67013)。

Q5:消费者测试 C1-C4 是空壳测试(print-only)吗?
不是。9 条断言逐条不满足即非零退出(set -euo pipefail + fail 计数 + fail 非零 exit 1),无硬编码通过;C4 通过条件 = 12s 窗口内 play 与 stop 都观测到(只见到一个也算失败);失败输出 mpd 日志 tail 便于事后定位。脚本源码在仓库(test_package/test_mpd.sh),CI 侧另有破坏性反向验证门禁确认断言有效。

Q6:40 个文件还是 41 个文件?
40。"41"是"类-文件"计次(1+10+29+1),其中 0024 是双类修改文件(fmt include 与 make_unique_for_overwrite 都改),被计了两次;去重后共 40 个文件(0001–0040),与 conandata.yml 的补丁声明逐一对应。口径见 3.3。

Q7:170 个 gtest 用例和 16 个套件能相加吗?
不能(4.0 口径声明)。170 是 15 个 gtest 套件内的 [OK] 用例数(⊂ 16 套件);第 16 个套件(bzip2)是 shell 型套件,不产 gtest 行。"16/16"是套件通过率,"170/170"是用例通过率,两者是包含关系不是并列关系。

7. 总结

7.1 量化盘点

维度值
源码补丁40 文件 / 4 类(0024 双类,类别计次 41)
差异点13(§2 差异表)
坑位(含流程坑)13(3.2–3.14);误判 3(语言预检 / bzip2 冲突直觉 / ACK 强制)+ 构建等价判定 1(W3 缓存)
直接依赖17 host + 1 tool(全部制品仓预编译)
PkgConfig shim8(轮 A 7 个 + 轮 B bzip2)
构建目标737(轮 A 实测)
上游测试18 注册 / 本配置 16 启用 / 16 Ok(15 gtest 套件 170 例 + 1 bzip2 shell 套件)
消费者断言9(C1-C4 = 1+3+3+2)
知识草稿3(E429/E430/E1003,随 PR 入仓,kv+md 配套)
CI7 轮:4 绿 / 3 作废(基础设施)
提交与合入4 提交(52/1/8/2 文件变更),2026-10-02 23:24 合并入 main

7.2 可复用方法(不限 mpd)

  1. PkgConfigDeps 缺陷收口:shim 目录 + prefix 取 conan API package_folder + PKG_CONFIG_PATH 排序 + meson coredata 清缓存验证(以 build.ninja 为验证对象)。
  2. find_library 型依赖三件套:交叉文件 [built-in options] 注入 -I include + -L lib + .pc shim(若经 pkg-config 查询)。
  3. host/tool 双上下文分工:依赖"库 + 程序"双形态且跨版本时,库走 host、程序走 tool_requires,conan 2 同包异版本硬冲突天然隔离。
  4. 无头播放闭环验证(E1003):null 输出 + 独立端口/目录 + 协议状态机双向断言(play 与 stop)+ 3s 样本 + 协议应答先实测后断言(ERROR 唯一失败信号)。
  5. CI 轮次口径:基础设施失败逐轮标作废附证据行;最终头必须独立绿轮;缓存命中验证须核对三要素(recipe/图/profile)+ clean 环境独立轮。

7.3 Checklist

  • 依赖发布检查(W0:17 host + 1 tool 全部已发布)
  • 语言预检(mixed 误报 → 源码统计复核改判 cpp)
  • R51 上游测试三步法(18 注册 → 16 启用 → 16 Ok,全量证据入仓)
  • R40 实质验证(消费者 9 断言,含播放闭环)
  • conan-verify + W2/W3(含构建等价判定)
  • W4 Pre-PR 独立审计(本地 AI 检视 2 轮 + 平台/真人评审闭环)
  • PR 原子性(单包目录 + 知识草稿,框架文件零混入)
  • CI 绿(最终头 #67013)+ 合并 + 入制品仓
  • 知识沉淀(3 草稿 + notes 13 项台账)
  • 18/18 点亮(被 libiso9660/zziplib 发布阻塞,路径已给)
  • 真实音频设备出声路径验证(被硬件阻塞,边界已声明)

7.4 后续工作

  • 适配发布 libiso9660、zziplib(+mkisofs/zip 程序)→ 18/18 点亮(4.7 路径)。
  • ALSA 真实输出路径验证(需有音频节点的设备)。
  • inotify 真机确认支持后 -Dinotify=auto。
  • JACK 符号探测(jack_set_info_function=NO)后续跟进与运行时行为验证。
  • meson 升级时复核 1.12.0 的 alsa cflags 传递问题(坑 3,机制未完全定位)。

参考链接

  • PR #13375(已合并):https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos/merge_requests/13375
  • 关联 Issue #3527(已关闭):https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos/issues/3527
  • 仓库:https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos
  • mpd 官网(源码下载目录,截至发稿,2026-10-04 curl 实测 HTTP 200):https://www.musicpd.org
  • 发布与版本要求信息:mpd 0.24.12 源码树自带 NEWS 文件(源码 tarball 内;源 URL 与 SHA-256 见 conandata.yml)
Logo

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

更多推荐