前言

版本口径(2026-10):当前正式发布版为 Flutter OH 3.47.8-ohos-1.0.0(atomgit.com/oh-flutter/flutter_flutter,oh-3.47-dev 线),配套 DevEco Studio 26.0.0 Release 与 OpenHarmony SDK / API 26。本篇记录的是 2026-09 的 3.44.9 → 3.47.4 历史同步批次,为保留批次现场而保留当时的坐标与数字;方法论与验证门对 3.47.8 同样适用。环境搭建见Flutter OH 环境搭建指导。

消费侧四篇到第 4 篇闭环:用别人的分叉 SDK,并把签名这一步也自动化。从本篇开始切换视角,进入生产侧(fork 维护者)——上游 Flutter 发了新版,如何把鸿蒙分叉同步上去、适配掉差异、构建发布出新的 SDK 工件。

本篇是整个生产侧六篇的总图:以 2026-09 的「3.44.9 → 3.47.4 上游同步批次」为标本,解剖一次完整同步批次的全部关键决策——为什么要同步、版本基线怎么定、2263 个适配文件由什么构成、3.47 的 Breaking Changes 有哪些、五阶段方案怎么切、风险在哪。后面的第 6-10 篇就是这张总图上逐个 Phase 的放大,本篇第七章则把整套打法压成下一批次可直接执行的 SOP。

材料口径:本篇所有数字与结论来自 2026-09-12 ~ 09-15 批次的实操留档,
路径已归一化为 $ROOT(旧工作机路径,照做时替换成自己的)。

一、为什么同步:批次的背景与目标

1.1 版本墙与版本差距

消费侧第 1、3 篇反复出现过版本墙:第三方包声明最低 Flutter ≥ 3.41,而分叉落后上游多个版本时,生态包集体不可用。版本墙的根因不在任何单个包,而在分叉落后上游。

本批次的版本差距:

  • 鸿蒙分叉最新:oh-3.44.9-dev(HEAD=fe316cf7,2026-09-11),tag 3.44.9+ohos-0.0.1-canary1;
  • 上游最新稳定版:3.47.4(9584c671,2026-08-12 发布);
  • 官方 README 版本表预计 3.47 鸿蒙版 2026/12 才跟进——间隔约 4 个月。

这 4 个月里,上游 3.45/3.46/3.47 的生态包、新特性全部被挡在鸿蒙门外。本工程的选择是抢先同步,不等官方跟进:

在这里插入图片描述

上图四个象限就是本批次决策的完整逻辑:左上是版本墙的真实 pub get 报错(升分叉版本,不是去找上游安装包);右上是上游 3.44.9→3.47.4 的漂移规模——合计 2750 个文件变动,每一处都可能撞上鸿蒙适配;左下是「不同步」的代价(生态包用不上、特性代差、用户被迫降依赖版本)与「同步」的回报(一整条版本线与生态入口);底部一句话点题:风险面 = 上游改动 ∩ 鸿蒙适配的交集文件;同步不是搬代码,是重放一套「适配集」。

1.2 批次的三项交付物

  1. 同步:编译通过、测试通过,能用该 SDK 把 Flutter 项目编译成鸿蒙 HAP 包;
  2. 文档:本系列文章,边适配边写(你正在读的就是);
  3. Skill:适配成功后沉淀为可复用的自动化 skill,下一批次直接调用。

三项交付物里,第 1 项是目标,第 2、3 项是杠杆——没有文档,踩过的坑下一批还会再踩一遍;没有 skill,每次同步都是手工作坊。

二、版本基线:批次的四个坐标

2.1 基线表

一次同步批次由四个坐标完全确定,开跑前先钉死在纸上:

项值
鸿蒙适配仓库atomgit.com/oh-flutter/flutter_flutter(当前主线;批次起点为 oh-3.44.9-dev)
鸿蒙最新分支oh-3.44.9-dev(HEAD=fe316cf7,2026-09-11);tag 3.44.9+ohos-0.0.1-canary1
上游同步目标tag 3.47.4 = 9584c6713b324636289d067944a46fd6b49df14b(2026-08-12 稳定版)
上游 3.44.9 基线tag 3.44.9 = 6b182d2c7585eba26d4edce0f97630effd256c33(2026-08-05)

四个坐标里最容易忽略的是第四个:上游旧基线 tag(3.44.9)。它是「适配清单」的 diff 起点——没有它,就算不出鸿蒙侧到底改了哪些文件(第三章的 2263 文件清单就来自这个 diff)。

2.2 上游变化规模:2750 文件

3.44.9 → 3.47.4,上游自身的变化规模:

变化文件 2750:engine 1123 · packages 804 · dev 578 · examples 138 · docs 27
Dart revision:d684a576a6 → 1d1a730ef9(Dart 3.13.3)
engine revision:5a2a6a42 → 06a2e2a1

两个直接推论:

  • engine 层是最大变化面(1123 文件)——适配工作重心必然落在 engine 嵌入层,这就是 Phase 3 要重打 826 个 engine 文件的由来;
  • Dart 大版本跳了(3.12.2 → 3.13.3)——定制 Dart SDK 不能沿用旧的,必须从源码重建(第 6 篇 Phase 2 的最大发现)。

2.3 为什么选「全新分支」方案(不 merge)

拿到 3.47.4 基线后的第一个方案决策:不 merge 旧分支,而是开全新分支 + 适配集重放。

# 基线 = 上游 tag,全新分支
git checkout -b oh-3.47.4-dev 3.47.4
# 适配集 = 旧基线树级 diff 恢复的清单(第 6 篇 Phase 1 产出)
git apply --3way <适配集 diff>

不 merge 的三个理由:

  1. 历史干净、无合并债:新分支的每个提交都可审计,不存在 merge commit 里的「混合状态」;
  2. 冲突一次性暴露:三方重放时所有 API 漂移当场撞出来(Phase 2 的 13 处 flutter_tools 漂移就是这么暴露的),而不是散在后续 merge 里慢慢炸;
  3. 同一套打法可重放到下个版本:下一批次(3.47.4 → 3.5x)复用完全相同的「基线 + 清单 + 重放」流程——这是端到端同步 SOP 能参数化的前提。

2.4 基线核验:开跑前先验四个坐标

开跑前把四个坐标逐个从远端验一遍(不信任记忆里的值):

# 验上游目标 tag 与旧基线 tag
git ls-remote https://github.com/flutter/flutter.git refs/tags/3.47.4 refs/tags/3.44.9
# 验鸿蒙分叉分支的 HEAD
git ls-remote https://atomgit.com/oh-flutter/flutter_flutter.git refs/heads/oh-3.44.9-dev

返回的 SHA 与 2.1 节基线表逐一对账(本批次:3.47.4 = 9584c671... ✅、3.44.9 = 6b182d2c... ✅、oh-3.44.9-dev HEAD = fe316cf7 ✅)。任何一个对不上,先停下来查清——后面的 diff、重放、验证全部建立在这四个坐标上,坐标错一分,结果错一片。

三、适配点构成:2263 文件的全景

3.1 总盘:+192740 行与顶层分布

「鸿蒙侧到底改了什么」不是拍脑袋,而是从树上 diff 出来的。用旧基线树级 diff 恢复适配清单(命令见第 6 篇 Phase 1):

git diff --name-status 3.44.9 oh-3.44.9-dev > sync-data/ohos_adapt_list.txt

实测结果(与旧机调研值逐项对得上,清单即权威版本):

指标值
总文件2263
新增 A / 修改 M / 删除 D1738 / 522 / 3
+行 / -行+192740 / -2018
顶层分布engine 826 · dev 633 · packages 421 · examples 265 · ci 41 · 其他 ~80

读这张表的方式:engine 826 + packages 421 是适配主体(约 65%),dev 633 主要是 flutter_tools 的 ohos 工具链与模板,examples 265 是示例工程,ci 41 是持续集成配置。这个分布直接决定了五阶段方案的切法(第六章)。

3.2 Framework 侧:421 文件的两种模式

packages/ 下 421 文件(251 改 + 151 增),核心是两种重复模式:

模式一:TargetPlatform 加 ohos 值,全部 switch 补 case。 平台判断的入口在 packages/flutter/lib/src/foundation/platform.dart,加一个枚举值之后,框架里所有 switch (TargetPlatform) 都要补 case TargetPlatform.ohos:(对齐 android 的行为)。这是数量最大、最机械的一类改动:

// 模式示意:上游的 switch 通常只有 android/ios/fuchsia/linux/macos/windows
switch (defaultTargetPlatform) {
  case TargetPlatform.android:
  case TargetPlatform.ohos:   // 鸿蒙侧补的 case,行为对齐 android
    // ...
}

模式二:flutter_tools 新增独立的 lib/src/ohos/ 目录(12 个文件),把鸿蒙做成工具链的一等公民:

ohos_builder / hvigor / hvigor_utils / hdc_server
ohos_device / ohos_device_discovery / ohos_doctor
ohos_plugins_manager / ohos_sdk / ohos_workflow
application_package / build_env

这两个文件清单与第 1 篇 L6 层(工具链层 13 源文件)是同一件事的两个视角:L6 按「层」数,这里按「文件」数。

3.3 Engine 侧:826 文件 = 新增平台目录 + 构建体系

engine/src/flutter/ 下 826 文件(207 改 + 589 增),主体是新增:

shell/platform/ohos/     # 完整平台实现:BUILD.gn、napi、accessibility、
                         # external_view_embedder、flutter_embedding 等
testing/ohos/            # 引擎单测的鸿蒙运行端
run_ohos_unittest.py     # 单测驱动脚本

注意「新增为主」这个结构:引擎适配不是重写公共逻辑,而是给引擎补一个 ohos 平台目录(第 1 篇「三层复用、一层重写」的引擎侧体现)。真正撞上公共引擎逻辑的改动是少数——而那少数,正是 Phase 3 里 15 个真冲突的高发区(第 7 篇)。

3.4 构建/发布体系:root 级文件

还有一类不显眼但缺一不可的适配点,散在仓库根级:

  • 版本锁:bin/internal/engine.ohos.version、engine.ohos.har.version——ohos 引擎与 HAR 的坐标,与上游 engine.version 平行存在;
  • 依赖与 CI:DEPS_ohos(ohos 依赖锁定)、.ci_ohos.yaml(鸿蒙 CI 配置);
  • 变更日志:CHANGELOG_OHOS.md——消费侧升级决策的权威清单(第 2 篇 5.2 节);
  • 合规:OAT.xml、LICENSE_HW、LICENSE_KHZG——开源合规与许可声明。

3.5 勘误:OBS 地址的真实身份

原文档里有一句「artifacts 下载源华为云 OBS」,2026-09-15 补了勘误批注,口径更新为:

OBS 现仅为默认回退地址。 本分支实际由 bin/internal/dart-sdk-url.ohos 的覆盖行改指 atomgit Release;
OBS 上那套工件是 3.44.9 / dart 3.12.2 时代产物,与本分支 kernel 138 不配套。

这条勘误的教训:工件下载源「名义地址」和「实际生效地址」可能是两套东西,判断 SDK 行为前先看覆盖行。完整的发布链路(版本锁、覆盖行、工件布局)是第 9 篇的主题。

3.6 清单文件解剖:2263 行怎么读

2263 文件清单本体是 sync-data/ohos_adapt_list.txt 一个纯文本文件,每行 git diff --name-status 格式(动作类型 + 路径):

M	packages/flutter/lib/src/foundation/platform.dart
A	packages/flutter_tools/lib/src/ohos/ohos_builder.dart
A	engine/src/flutter/shell/platform/ohos/BUILD.gn
...

三个常用读法:

  1. 按顶层过滤:awk '{print $2}' | cut -d/ -f1 | sort | uniq -c 得到各顶层目录分布——3.1 节那张表就是这么算出来的;
  2. 按动作类型过滤:grep '^A' / grep '^M' / grep '^D' 分别看新增/修改/删除——新增文件与修改文件的重放策略不同(新增多为整文件,修改走三方合并);
  3. 按目录圈定工作集:grep -E '^[AMD].*packages/' 圈出 Phase 2 工作集(421 文件)——第 6 篇用的就是这条过滤。

清单是整批次的「单一事实源」:该重放多少、已重放多少、还差哪些,都拿它做差集。
清单丢了,批次等于失控——所以 G1 验证门的第一件事就是清单校验。

四、3.47 Breaking Changes:三个影响鸿蒙

4.1 影响鸿蒙的三项

3.47 的 Breaking Changes 里,有 3 项直接落在鸿蒙适配的交集文件上(⚠️ 标记):

  1. ⚠️ OpenGL ES render-to-texture 内容改为 top-down 存储——关联 ohos render/surface/texture 路径,「编译过 ≠ 渲染对」,方向正确性必须上真机/模拟器验证;
  2. ⚠️ semantics header/headingLevel 在 iOS/Android 行为变更——影响 ohos accessibility 的取数路径,语义朗读正确性同样挂真机验证;
  3. ⚠️ 移除 describeEnum——鸿蒙代码若引用需迁移,全仓替换为 enum.name 类取法,编译期即可验证,是本批最干脆的一项。

4.2 待稳定项:不引入

另有三项上游尚未稳定的变更,本批次的决策是不引入(跟随上游稳定后再说):

  • DropdownButton enabled 语义调整;
  • material_ui / cupertino_ui 拆包;
  • Android prebuilt flags。

「不引入」本身是一个需要记录的决策——否则下一批次的维护者会疑惑「为什么这三项没做」。

五、BC 适配表:5+7 项实测明细

上一章是「发现了哪些 BC」,这一章是「每一项怎么适配、验证到什么程度」。本表是 3.44→3.47 迁移期已实测确认的适配档案(非预测清单):Framework 侧条目在 Phase 2/3 迁移(编译链验证),Engine 侧条目全部来自 M2/M3 本地构建实测撞坑并修复。

5.1 Framework 侧(5 项)

#Breaking Change鸿蒙侧对策状态
1OpenGL ES render-to-texture 改为 top-down 存储ohos/skia 纹理路径翻转逻辑已随同步迁移;方向正确性待真机/模拟器验证(编译过 ≠ 渲染对)已适配/验证挂起
2semantics header/headingLevel 行为变更ohos accessibility 取数路径随同步迁移,语义朗读正确性同挂真机已适配/验证挂起
3移除 describeEnum全仓迁移到 enum.name 类取法,编译通过完成
4DropdownButton enabled 等(上游待稳定)不引入不适用
5material_ui/cupertino_ui 拆包(上游待稳定)不引入不适用

前两行「已适配/验证挂起」是最需要警惕的状态:代码迁了,但渲染/朗读正确性还没被真机证明。这类条目的销项只能发生在 Phase 5 的设备侧验证里(第 10 篇)。

5.2 Engine 侧(E1-E7,全部修复并验证)

#API 漂移修法出处
E1Paint::CreateContents 扩参(ContentContext& + Geometry* + std::optional<Matrix>)测试 TU 重写为产物契约断言(MockContext 链上不可构造)06 P27b
E2FenceWaiterVK::AddFence 插入 submit_callback 参数测试补占位 lambda06 P27b
E3impeller::Context 新增纯虚 FinishQueue()测试 fake 补 return false06 P27b
E4PlatformView::Delegate 新增纯虚 OnPlatformViewHitTestfake 补 {.has_platform_view = false}(上游 ios test 同款)06 P27b
E5DlImage 抽象基类化,工厂迁到子类 DlImageSkia::Make两处调用点迁移 + 显式 include dl_image_skia.h(dl_sk_canvas.h 只给前向声明)06 P21/P27b
E6#define private public hack × libc++ <ranges> 硬错误(工具链升级放大,非上游 API 变更)宏前 #include <ranges> 预热;私有成员少走 friend+tunnel06 P22/P27b
E7fontmgr_ohos 端口被整端口移除(官方有意清理)2026-09-14 反转:采用华为 skia 方案恢复端口(见 5.3)06 P28/P29

E1-E4 有一个共同规律:全是测试文件的 API 契约漂移(fake/mock 跟不上上游接口变化),生产代码侧的漂移编译期即暴露、相对好修。这条规律被写进了下一批次的预判(5.3 节末尾)。

5.3 E7 反转:字体端口的故事

E7 是本批次最有戏剧性的一条,因为它反转了一次已作出的决策:

  1. 同步过程中发现 fontmgr_ohos(Skia 的鸿蒙字体管理端口)在 3.47 里被整端口移除,官方口径是有意清理;
  2. 初判「不做恢复」——反正官方清理了,跟着清理省事;
  3. 2026-09-14 反转:不恢复 = 文字/图标全不可见(编译零报错的静默故障),「省事」变成「不可用」。最终采用华为 skia 方案恢复端口:端口源码经 attachment 机制托管落盘(skia 树零 tracked 文件、不能就地改),GN 开关 + freetype + 引擎侧胶水一并恢复,jsoncpp 仍走独立代理 target;端口源取自 CPF-Flutter/fluttertpc_skia 镜像,含 4 处必需的 include 适配。

这个反转直接催生了第 10 篇(字体图标静默故障诊断 SOP)——每个批次、每次发布都要单独跑字体检查,就是这条教训的制度化。

5.4 下一批次的预判

从 E1-E7 提炼的三条预判,供下一同步批次直接使用:

  1. 引擎侧漂移集中在测试 TU 的 API 契约面(E1-E4 全是测试文件)——先把测试 fake 的接口对齐排进 Phase 3 清单;
  2. DlImage 工厂迁移是「抽象类化」趋势的一部分——下一批次开跑前先 grep DlImage::Make 与 dl_image 相关 include;
  3. 伏笔:jsoncpp 代理 target 引用 spirv 自带的 amalgamated 1.6.2,若上游 jsoncpp 版本升级,需同步确认 vsync 代码的 API 兼容。
# 下一批次开跑前的两条预备 grep(预判 2 的落地)
grep -rn "DlImage::Make" engine/src/flutter/
grep -rln "dl_image" engine/src/flutter/ --include="*.h" --include="*.cc"

5.5 十二条目的记忆锚点

5+7 共 12 条 BC 适配档案,按「状态」分三堆记,比逐条背有效得多:

  1. 已销项(3 条):Framework #3(describeEnum 移除,编译期验证)+ E5、E6(DlImage 工厂迁移、private public hack,M2/M3 实测修复);
  2. 挂真机验证(2 条):Framework #1(top-down 纹理翻转)、#2(semantics 行为变更)——代码迁了,渲染/朗读正确性等设备侧裁决;
  3. 不适用(2 条)+ 测试契约漂移(4 条)+ 静默故障专项(1 条):两条「不引入」是决策记录;E1-E4 全是测试 fake 跟接口;E7 单独立项成第 10 篇。

下一批次的 BC 表照这个三堆结构填:先问「销项没有」,再问「挂在哪」,最后问「要不要专项」。

六、五阶段同步方案:分工与验证门

6.1 Phase 0-5 总表

在这里插入图片描述

上图是完整作战图:上半是「全新分支 + 适配集三方重放(不 merge)」的打法与适配 delta 实测;下半是五阶段与各自的验证门。展开成表:

Phase内容工作量验证门
0环境准备(新机 arm64、88GB、ninja/DevEco/hdc、代理)已完工具链连通
1基线:fetch 上游 tag,checkout -b oh-3.47.4-dev,恢复适配清单低G1 清单全对上(2263 文件校验)
2Framework:platform.dart → switch 补 case → 移植 flutter_tools/ohos → Dart 源码构建高G2 flutter analyze 0 error
3Engine:移植 shell/platform/ohos → BC 适配 → testing/ohos → 构建 har最高G3 契约 16 项通过
4构建/发布:版本锁、cache.dart 接线、覆盖行、CHANGELOG、合规中G4 工件 URL 可达
5验证:framework 单测 + engine 单测 + flutter build hap 真机冒烟中G5 真机 1723/1723 全绿

6.2 验证门:不过门不进门

五阶段方案的灵魂不是「分五步」,而是每阶段一道验证门,不过门不进下一阶段,问题就地止损:

  • G1(清单):适配清单 2263 文件与旧机调研值逐项对上——清单错,后面全错,所以它是第一道门;
  • G2(analyze):flutter analyze 全量 0 error——Dart 层没绿,engine 层开工没有意义;
  • G3(契约):engine 与 framework 的 16 项契约对齐检查——接口不对齐,构建出来也是坏的;
  • G4(URL):发布工件的下载 URL 实测可达——工件挂了,消费侧全部白搭(第 9 篇的主题);
  • G5(全绿):真机引擎单测 1723/1723 + 三档 HAP 冒烟——设备侧证据是最终裁决(第 10 篇的主题)。

验证门是该阶段「过/不过」的判据,不是「尽量做到」的建议。
本批次 29 个编号坑(P1-P29)里,相当一部分是「没等门绿就往下走」的代价。

6.3 Phase 与本系列篇目的对照

五个 Phase 与生产侧后续篇目一一对应,阅读时可以按需跳转:

Phase篇目核心内容
1 基线建立06代理 HTTP/1.1 修障、浅克隆、清单恢复校验
2 Framework + Dart06421 文件三方重打、Dart SDK 源码构建(6 补丁)
3 Engine07826 文件重打、15 个真冲突裁决、契约对齐 16 项
4 构建/发布09版本锁、cache.dart 接线、覆盖行、11 个工件(引擎 5 + Dart SDK 4 + patched_sdk 2)
跨批次方法论05(本篇 §七)端到端 SOP、G0-G5 验证门、P1-P29 索引、错误签名查表
5 验证与冒烟10M1-M5 验证门、三档引擎、设备侧证据;P1-P29 明细散在 07/08/10,权威索引见本篇 §7.9
专题:字体10静默故障分层诊断、三层证据链

6.4 第二条编号轴:里程碑 M0-M5

本篇之外,第 8、9、10 篇还有一条里程碑(Milestone)轴在用它,读者会看到「M2 实录」「M5 追加」这类说法。它和 Phase 是两个不同的轴:Phase 是计划视角(这一阶段交付什么),Milestone 是执行视角(一个可验证的状态点,达成即冻结证据)。同批次实测对照:

Milestone状态点判据对应 Phase明细篇目
M0Dart SDK 就位源码构建的 dart-sdk + 打补丁的 frontend_server 可用206
M1构建图完整gn gen 通过 + 三档 out/ 目录成型308 §二
M2引擎编得出来ninja 0 FAILED,四 target 齐备308
M3端到端跑得起来flutter build hap 出包 + 设备侧安装启动 + 单测跑通510 §二、§三
M4发得出去11 个工件上 Release、11 条覆盖键生效、用户零操作装到409
M5验得干净真机单测全绿 + 三档引擎 + 字体端口三档在位510 §三、§四、§六

两个轴故意不重合:M4(发布)排在 M3(冒烟)之后,但 Phase 4 排在 Phase 5 之前——因为本批次实际是先冒烟确认引擎可用,才敢发布,发布后又回到设备侧做 M5 全量复核。这个错位是真实执行顺序,不是笔误。

引用规则:说"该交付什么"用 Phase,说"做到了哪一步"用 M。第 8/9/10 篇的小结都标了自己对应的 M 段(M2 / M4 / M5)。

七、端到端同步 SOP:可参数化的执行序

7.1 为什么第六章之外还要一节

第六章回答的是「谁在什么阶段交付什么、过不过门」;本节回答「下一批次照着敲什么命令」。同一批 Phase,两个视角:

  • 第六章是分工表——给评审和排期看;
  • 本节是执行序——给实际操作的人看,每一步带验证门,且全部变量参数化。

3.44.9 → 3.47.4 那一次的现场记录在第 6、7 篇;本节把它们的做法抽出来,去掉批次特有的数字。Phase 编号与 §6.1 完全一致(0-5),不另起一套。

7.2 新批次变量表:先填这张表,再动手

变量从哪取3.47.4 批次的实例值
{{UPSTREAM_TAG}}上游 release 页 / git ls-remote --tags upstream3.47.4 = 9584c6713b324636289d067944a46fd6b49df14b
{{PREV_TAG}}上一批用的上游 tag3.44.9 = 6b182d2c7585eba26d4edce0f97630effd256c33
{{PREV_OHOS_BRANCH}}上一批的鸿蒙分支oh-3.44.9-dev
{{NEW_OHOS_BRANCH}}命名惯例 oh-<tag>-devoh-3.47.4-dev
{{DART_REV}}新 tag 的 DEPS 里 dart_revision1d1a730ef9(= Dart 3.13.3)
{{ENGINE_REV}}新 tag 的 bin/internal/engine.version06a2e2a1

工作根目录:本 SOP 的相对路径一律以 $ROOT(flutter_flutter/ 的父目录)为基准。注意 docs/、scripts/、sync-data/ 都在 $ROOT 下、不在 git 仓库里——只在仓库里搜会看不见它们。

7.3 Phase 0 预检:第一道门是「tag 真的存在」

cd $ROOT/flutter_flutter

# ① 先确认目标 tag 真实存在 —— 这一步不能省
git ls-remote --tags upstream | grep -F "{{UPSTREAM_TAG}}"

# ② 网络:本地代理会杀死 HTTP/2 大包(上批最大坑)
git config --global http.version HTTP/1.1

# ③ 磁盘:engine/src/out/ 三档 + dart 源码构建 + 全量对象,上批实测 88GB 空闲起步
df -h /System/Volumes/Data

# ④ 工具链
export PATH="$ROOT/depot_tools:/opt/homebrew/opt/llvm@19/bin:$PATH"
export DEVECO_SDK_HOME=/Applications/DevEco-Studio.app/Contents/sdk

⚠️ 这是本 SOP 的第一道门,也是实测踩过的坑:曾在未验证的情况下按「3.48.0 已发布」整批作业,实际上游当时只有 3.48.0-0.x.pre 预发布版——照着不存在的目标做,全部结论作废。ls-remote 无输出就停下来,向人要准目标版本。

验证门 G0:ls-remote 命中目标 tag ✅;git config --get http.version = HTTP/1.1 ✅;磁盘 ≥ 80GB ✅;python3 / ninja / gn / llvm@19 可用 ✅。

7.4 Phase 1 基线:浅克隆 + 三方 diff 出风险面

git fetch --depth 1 upstream "refs/tags/{{UPSTREAM_TAG}}:refs/tags/{{UPSTREAM_TAG}}"
git checkout -b {{NEW_OHOS_BRANCH}} {{UPSTREAM_TAG}}

# 适配集打包:--binary 必须放在 -- 之前,否则被当 pathspec、二进制补丁静默残缺
git diff --binary {{PREV_TAG}} {{PREV_OHOS_BRANCH}} -- packages/ > /tmp/adapt_packages.patch
git diff --binary {{PREV_TAG}} {{PREV_OHOS_BRANCH}} -- engine/   > /tmp/adapt_engine.patch

# 适配 delta 与交集清单(决定后面的工作量与风险面)
git diff --name-only {{PREV_TAG}} {{PREV_OHOS_BRANCH}} | sort > $ROOT/sync-data/fork_delta.txt
git diff --name-only {{PREV_TAG}} {{UPSTREAM_TAG}}     | sort > /tmp/upstream_delta.txt
comm -12 $ROOT/sync-data/fork_delta.txt /tmp/upstream_delta.txt > /tmp/intersection.txt
wc -l $ROOT/sync-data/fork_delta.txt /tmp/intersection.txt

验证门 G1:git rev-parse {{UPSTREAM_TAG}} 与 ls-remote 的值一致 ✅;工作树 clean ✅;适配清单 2263 文件与调研值逐项对上(§3.1 的 --name-status 口径)✅;交集清单已落盘 ✅。

两个口径别混:--name-status 的适配清单是 2263 文件(第三章,含 dev/ examples/ ci/);而 git diff --name-only {{PREV_TAG}} {{NEW_OHOS_BRANCH}} 只数当前分支实际落地的 delta,上批是 1263 文件(engine 836 / packages 423 / bin 4)。同口径量级对不上,就要查是不是 fetch 不完整。

交集清单才是本轮真正的风险面:只有双方都改过的文件才可能真冲突。

7.5 Phase 2 Framework 重打:unmerged ≠ 内容错误

git apply --3way /tmp/adapt_packages.patch
git diff --diff-filter=U          # 停在 unmerged 索引态的文件

3-way 以当前 HEAD(= 新上游 tag)为 “ours”:鸿蒙单侧改动自动干净落入,只有双方都改同一区域才留冲突。上批 421 文件重打后磁盘上 0 冲突标记、但有 14 个文件停在 unmerged 索引态,内容已正确,git add 即清。

重点裁决面是 flutter_tools——上批实测 13 处漂移的重灾区(完整表见第 6 篇):reporting/ 目录删除、LinkHooks / combinedResult 类名迁移、_getPrebuiltTarget 穷尽匹配补 ohos case、build_system/targets/native_assets.dart 变量改名。新批次先读上游文件再移植,不要盲打补丁。

# 改过 flutter_tools 源码后必须删快照,否则跑的还是旧工具
rm -f bin/cache/flutter_tools.snapshot bin/cache/flutter_tools.stamp

验证门 G2:./bin/flutter --version 横幅完整输出(新版本号 + Dart 版本)✅;flutter analyze 全量 error = 0 ✅。

7.6 Phase 2 尾:Dart SDK 必须从源码构建

注意顺序:Dart SDK 必须先就位,否则 flutter_tools 编译时报 ohosArm / isOhos Member not found。机理见第 6 篇,这里只给执行序。

官方 dart JIT 二进制内嵌 platform kernel,往 bin/cache/dart-sdk 的 lib/ 里打补丁对运行时零影响——必须从源码构建。

# 1) 检出 {{DART_REV}}(.gclient 必须在父目录,checkout 目录名必须恰为 "sdk")
gclient sync
# 2) 应用 ohos 补丁集(可重跑脚本已固化;上批为 6 文件)
bash $ROOT/scripts/patch_and_build_dart_ohos.sh
# 产物:xcodebuild/ReleaseARM64/dart-sdk → 替换 bin/cache/dart-sdk(原版另存)
# 3) frontend_server 同树重编,product 配对部署到 bin/cache/dart-sdk-ohos/

验证门:dart --version 为新版本 ✅;import 'dart:ffi'; print(Abi.ohosArm) 通过 ✅;frontend_server --target-os=ohos 不再报白名单错误 ✅。

⚠️ 两个名字极易混(都在 bin/cache/,只差一个下划线):

  • bin/cache/engine.stamp ← 引擎版本 SHA,由 update_engine_version.sh 从 bin/internal/engine.version 生成,同步上游时自动更新,别手改;
  • bin/cache/engine_stamp.stamp ← 另一个 cache 工件的标记文件,与它无关。

另注:bin/internal/ 下没有 engine.stamp 这个文件(实测不存在),别去那里找。

换 Dart 版本时还要记住第 9 篇 §6.5 那条:bin/cache/dart-sdk-ohos 不会被覆盖机制自动更新(判据是"文件不存在",与引擎工件行为相反),必须手工 rm -rf。

7.7 Phase 3 Engine 重打与构建:工作量主体

git apply --3way /tmp/adapt_engine.patch
git diff --diff-filter=U

冲突裁决的两分法(上批 15 个真冲突定型,判据与逐条裁决见第 7 篇):

类别判据处置
格式吸收类上游自己完成了同名重构,鸿蒙侧改动被吸收取 OURS(新上游),用双向归零验证器确认:git diff --cached <鸿蒙侧> -- f 与 git diff --cached <新上游> -- f 双向跑,吸收文件对上游侧必须 = 0 行
手合类双方改的是不同语义,都要保留逐项 API 移植(上批 7 个:allocator 的 OH_RESTRACE、capabilities 的 OHOS 扩展、mock_vulkan 记账、typographer 整函数重建…)

典型陷阱:git diff3 的行对齐启发式会把只属于一侧的标识符混进"公共区",逐 hunk 拼装不可行 → 遇到这种要整函数重建并与两侧原始版本逐行比对(上批 typographer 即此)。补丁"改写原语句"时要对上游 diff 做结构性检查,防括号吞并(P11)。

构建(规范化入口是 engine/ohos wrapper,不是手搓 gn/ninja):

cd $ROOT/flutter_flutter/engine    # cwd 必须是引擎编译根,ohos.py 会强制检查

./ohos -n config  -t debug profile release    # gn gen
./ohos -n compile -t debug profile release    # ninja
./ohos -n har     -t debug profile release    # 产 har

三条硬规则(详见第 8、9 篇):

  1. --llvm18 不要用——它把 toolchain 指到 DevEco 的 clang 15,编不过 zlib;args.gn 必须落到 custom_toolchain = "/opt/homebrew/opt/llvm@19";
  2. args.gn 在未跟踪的 out/ 里,换机即丢,且 out/ 已存在时增量 gn gen 不会补新 args;
  3. 新批次会撞的坑先查 §7.9 的索引表,别从头排。

验证门 G3:三档 out/ohos_<mode>_arm64/libflutter.so 产出 ✅;ninja 0 FAILED ✅;契约对齐 16 项通过 ✅。

7.8 Phase 4 发布 / Phase 5 验证 / 收尾

Phase 4(构建发布) 的完整流程在第 9 篇:引擎侧打包 5 个 zip(3 个 har + 2 个宿主 gen_snapshot)、连同 2 个平台 dill、再备齐 Dart SDK 侧 4 个包(macOS / Windows 各一套),共 11 个附件 → 新建 tag → 传附件 → 改 bin/internal/dart-sdk-url.ohos 的 11 条覆盖键 → 提交推送。发布动作不改三个 *.version 锁文件,推进信号是覆盖行 URL。

Phase 5(验证) 的判据在第 10 篇,两个数别混:

  • 真机 1723 全绿(基线用这个数);
  • 模拟器 1703 通过 / 20 失败——那 20 项已查明是纯环境性(无 Vulkan 设备 / QoS 差异),与适配无关。拿模拟器数字当基线会误判成回归。

字体端口在不在是 Phase 3-4 最容易被静默丢掉的东西——它丢了编译不会报错,只是所有字形消失。每次同步后都要走一遍第 10 篇 §五 的分诊流程,别等出 HAP 才发现。

收尾:Breaking-changes 分析归档进本系列的 §五 那张表;更新版本基线与当前状态文档;新踩的坑按 Pxx 编号追加进 §7.9 索引表,并把"错误签名 → 修复"一行加进自己的 pitfalls 速查。

⚠️ release-notes/changelog/ 在当前分支已不存在(实测 git ls-files release-notes/ = 0 行,目录也没有)——照着旧路径建目录会白做。

7.9 P1-P29 全索引:生产侧坑的一站式归属

本批次 29 个编号坑的权威索引(明细在指向的篇目里,本表只做归属与一句话定性):

编号一句话类别明细
P1旧 obj/*.ninja 与 build.ninja 组成 stale 混合图(症状最迷惑)依赖树08 §2.1
P2SkLog_ohos.cpp 悬空引用——同步产物,非事故依赖树08 §2.2
P3esbuild 预编译组件缺失(CIPD 少装)依赖树08 §2.3
P4libcxx 缺 shared/fp_bits.h:漏拉一个子依赖依赖树08 §2.4
P5libcxx 的 Clang 18 硬门槛(本轮最关键)工具链08 §3.1
P6LLVM 23 太新:-Wdeprecated-attributes 毒化老第三方代码工具链08 §3.2
P7diff 为零的文件仍引用被上游删掉的 SampleCount::kCount2源码适配07 §6.1
P8同步新写文件缺尾换行,-Werror,-Wnewline-eof源码适配07 §6.6
P9重命名类变更:先认上游新语义再决定去留源码适配07 §6.2
P10私仓 pin 差异 + vendored 头缺失(最长的一战)源码适配07 §6.3
P11OHOS 补丁吞括号(#ifdef 配平错,报错点离根因很远)源码适配07 §6.6
P12GetRenderTargetView 上游加参,fork override 未跟随(虚函数)源码适配07 §6.7
P13QueueSignalReleaseImageOHOS 失去调用方,按上游删除源码适配07 §6.7
P14device_holder 重复定义——补丁贴在新版析构前面源码适配07 §6.7
P15sysroot 的 CMSG_NXTHDR 宏触发 -Wsign-compare源码适配07 §6.7
P16VK_USE_PLATFORM_OHOS 的 include-guard 时序(同批有的 TU 正常)源码适配07 §6.7
P17华为 develop 分支私有依赖 SkGlyphRasterWorkerSlot.h源码适配07 §6.7
P18SliceViews 上游加参漏跟随(自由函数版,含级联假象)源码适配07 §6.7
P19字体端口"半同步"残骸的整链清理(7 文件)源码适配07 §6.4
P20删多了:GPU 栅栏路径的 Queue 方法被误删源码适配07 §6.5
P21没跟上:FenceWaiterVK::AddFence 扩参源码适配07 §6.5
P22测试面 #define private public 撞上 libc++ <ranges>源码适配07 §6.8 / 08 §5.2
P23flatbuffers × _GNU_SOURCE × musl strto*_l 函数面构建体系08 §4.1
P24链接三件套:host clang 驱动 + DevEco runtime 桥接构建体系08 §4.2
P25wasm-opt 缺异常运行时:libcxxabi 的 OHOS 分支必须编真身构建体系08 §4.3
P26har 双修复:SDK 扫描层级 + API 26 面签名差异构建体系08 §4.4
P27libflutter.so 的 Json::* 未定义——jsoncpp 幽灵依赖收尾08 §5.1
P27b测试面漂移的五个规律(最便宜的上游 API 探测器)收尾08 §5.2
P28字体端口恢复(P19/E7 方向反转,编译期零报错)发布/验收10 §四
P29三档引擎:a 装错包 / b marker 冲突 / c AOT 缓存在 .dart_tool/发布/验收10 §六、09 §6.6

消费侧另有 CP1-CP14 一套编号(用别人发好的 SDK 时踩的坑),权威总表在第 3 篇 §六。两套编号不互相复用。

7.10 错误签名 → 出处:按报错文字查表

错误签名出路
全量 clone curl 18 transfer closed / early EOF§7.4 前置:代理杀 HTTP/2,http.version=HTTP/1.1(第 6 篇)
--binary 补丁打上去二进制文件残缺§7.4:--binary 误放 -- 之后被当 pathspec
git apply 后大批文件停在 unmerged 索引态§7.5:内容可能已对,先看 git diff --diff-filter=U 再决定
Member not found(Abi.ohosArm)§7.6:dart JIT 内嵌 platform kernel,必须从源码构建 SDK
Platform.isOhos undefined 但 SDK 正常第 6 篇:sky_engine/lib 是独立镜像,也要补补丁
flutter_tools 报 LinkHooks / combinedResult第 6 篇 13 处漂移表;先确认 Dart SDK 已就位
改 flutter_tools 后行为没变§7.5:删 bin/cache/flutter_tools.snapshot + .stamp
no member named 'kCount2' 一类符号缺失P7 / P11 / P17:符号级同步 ≠ 文件级同步(第 7 篇 §六)
gn gen 报 SwiftShader / zlib / libcxx 类错第 8 篇 §二、§三(依赖树 + 工具链定版)
链接报 undefined symbol 且来自系统库第 8 篇 §四(musl 函数面与交叉链接三件套)
compatibleSdkVersion ... cannot be lower than第 10 篇 §2.2:读 DevEco sdk-pkg.json 取精确串,别猜
--target-os=ohos 被拒第 10 篇 §2.2:frontend_server snapshot 三段式重编,product 配对
Unexpected Kernel Format Version 130 (expected 138)第 9 篇 §1.3 / §6.1:覆盖行未生效
三档产物正常但 profile 一启动就 FATAL第 9 篇 §6.6 / 第 10 篇 §6.1:patched_sdk 装成产品档 dill
反复重下 patched_sdk第 9 篇 §6.7:两个条目共用一个 .ohos-override-url 标记
清了 build/ohos/ 但 AOT 没重建第 10 篇 §6.3:AOT 快照缓存在 .dart_tool/flutter_build/
文字 / 图标全不可见第 10 篇 §五(专属诊断流程,编译期无任何报错)
改了覆盖行但已装机器没反应第 9 篇 §5.3:重传了同名附件,必须换新 tag

7.11 流程通过判据与未验证项

七个 ✅ 全满足才算这批同步做完:

  1. Phase 0 的 tag 存在性已验证(不是假设);
  2. 适配集重打完成,冲突全部裁决且吸收类经双向归零验证;
  3. flutter analyze error = 0;./bin/flutter --version 横幅正常;
  4. 三档引擎构建 0 FAILED;字体端口三档均在位(分诊见第 10 篇);
  5. 设备侧单测与三档 HAP 渲染通过(基线用真机数字);
  6. 第 9 篇的发布前回归清单全过;
  7. 文档与坑索引已更新。

本 SOP 的未验证项(不要当成已确认的步骤):

  • scripts/resolve_conflicts.py / merge7.py 的 ours/theirs 语义是 3.47.4 批次写死的,冲突清单不同就要小改,未在新批次验证过;
  • scripts/patch_and_build_dart_ohos.sh 的补丁锚点以 Dart 3.13.3 树为准,换 Dart 版本要改锚点;
  • package_ohos_engine_artifacts.sh 的目录名与 LICENSE 源路径未在新批次验证;
  • 「354 个未碰撞文件一键落盘」上批属实但本轮未跑。

7.12 大批次之后:3.47.5 → 3.47.8 的小批次长什么样

本篇正文的 2263 文件是「跨三个 minor 版本的大批次」。真实节奏里更多是一两个文件的小批次——3.47.4 之后到 3.47.8 一共发了 4 个正式 tag,实际形态如下(数字取自 bin/internal/dart-sdk-url.ohos 的批次注释、各 tag 的覆盖文件原文,以及 Release 的 assets 清单):

批次 tag发布时刻上游区间本分支实际动作自传附件 / 覆盖键
3.47.5-ohos-1.0.009-23 23:573.47.4 → 3.47.5Dart 升到 3.13.4(kernel 仍 138);引擎 C++ 层在该区间无变化11 / 9
—(3.47.6 未独立发布)—3.47.5 → 3.47.6上游全为 iOS 改动,与 OHOS 无关,并入下一批— / —
3.47.7-ohos-1.0.010-13 20:093.47.6 → 3.47.7上游仅 iOS(SemanticsObject 无障碍修复 + iOS PlatformView 测试),engine/src 无 OHOS 变更 → 附件逐字节重挂载;覆盖文件首次加两条 Windows Dart SDK 键11 / 11
3.47.7-ohos-1.0.110-21 15:56—纯框架:flutter_tools 新增 OHOS 自动签名 lib/src/ohos/signing/(第 4 篇,提交 f2651e0b91 同日 11:00)11(重挂载)/ 11
3.47.8-ohos-1.0.010-24 20:593.47.7 → 3.47.8纯框架:上游合并 6 文件 +221/−79 + 本分支「设备未连接分级排查」11(重挂载)/ 11

「附件 11 / 键 9」这个差值本身值得记一条:Windows 的 Dart SDK 包早就传上 Release 了,覆盖文件里却还没有键——上传了但没人能下到。第 9 篇 §5.7 把这类失配列成了发布前的必查项。

3.47.8 这一批的全部代码改动(可逐条核对,原文见 Flutter 3.47.8-ohos 1.0.0 ReleaseNote.md):

  • 上游两处修复:packages/flutter_tools/lib/src/resident_runner.dart(117 行,debugDumpFocusTree / debugDumpLayerTree 在 vmService 或 uiIsolate 为 null 时不再抛异常,上游 #194740);packages/flutter_tools/lib/src/flutter_plugins.dart(22 行,插件软链接损坏时安全处理,避免 FileSystemException,上游 #194578);
  • 两个版本锁随上游动:bin/internal/engine.version → cf636b1dfb818dd6a3ff16e390e93b1a036969c8,DEPS 的 dart_revision → 416e33b0ffaef062a60ec966bb8c82ed2b83f128(只影响引擎源码构建,不改已发布工件);
  • 本分支新增:鸿蒙设备未连接时的分级排查提示——OhosDeviceIssue(hdcNotAvailable / noDevices / connectFailed)、DeviceDiscovery.noDevicesHint(默认 null,纯 Android/iOS 工程不受影响)、flutter doctor 增加 hdc list targets: N 台鸿蒙设备 一行,并补 8 个单测(ohos_device_discovery_test.dart 6 个 + ohos_doctor_test.dart 2 个);
  • 引擎侧零变更:engine.ohos.version(10a8d012d8)、engine.ohos.har.version(e068c218c3)、Dart 3.13.4 全都没动,11 个附件与 3.47.7-ohos-1.0.1 逐字节相同,只是重挂到新 tag。

于是小批次的 SOP 会塌缩成三步:合上游 → 跑框架侧验证门(flutter analyze + 上游改动涉及的 plugins_test.dart / terminal_handler_test.dart 共 181 个用例 + 本分支新增 8 个单测)→ 开新 tag、重挂载 11 个附件、把 11 条覆盖键指过去。三方重放、冲突裁决、三档 ninja 这些重型环节全部跳过,唯一不能跳的还是"换新 tag"(原因见第 9 篇 §5.3:同名重传对已装机器静默无效)。

八、环境与风险

8.1 执行环境:为什么换了新机器

本批次没有沿用旧机,而是迁移到全新设备——旧机 x86_64 只剩 48GB 磁盘,扛不住大仓库克隆与构建:

macOS 15.4.1 arm64(迁移自 x86_64 旧机,交叉编译顾虑解除)
磁盘:88GB 空闲
工具:git 2.39.5 · python3 3.9.6 · clang 17 · ninja 1.13.2 · node 20 · brew
鸿蒙:DevEco Studio 26.0.0 Release + hdc(OpenHarmony SDK / API 26)· fvm ohos = 3.44.9(批次基线)
代理:http 127.0.0.1:1087 / socks5 127.0.0.1:1080
连通性:github / atomgit / 华为云 OBS 均通

arm64 这一点值得单独提:旧机 x86_64 构建 arm64 目标要走交叉编译,多一类无谓故障;换机后「本机架构 = 目标架构」,构建路径直接简化。

8.2 三大风险与对冲

开跑前记录在案的风险(含事后看是否兑现):

  1. engine 1123 文件变化,embedder API 兼容性待排(主要风险)——兑现:E1-E7 全部是这类漂移,被 Phase 3 的契约对齐与 15 个真冲突裁决接住(第 7 篇);
  2. 全新分支 = 2263 文件适配重打,需清单驱动避免遗漏——兑现方式:G1 验证门(清单逐项校验),重打后磁盘 0 冲突 + 14 个 unmerged 索引态文件全部 git add 销账(第 6 篇);
  3. 官方 2026/12 跟进可能先发布,存在版本竞争——对本工程无实质影响,目标是对齐上游而非抢时间窗。

九、常见问题 FAQ

9.1 这篇写的是 3.47.4,现在安装该用哪个版本?

当前正式发布版是 3.47.8-ohos-1.0.0,新项目安装与验收都用它;本篇的 3.47.4 是 2026-09 的历史同步批次,保留它是为了讲清一次完整同步的决策链。两者同属 3.47 线,Phase 划分、验证门与踩坑模型通用。消费侧安装见第 2 篇(fvm 不认 tag,需把 tag 浅克隆到 ~/fvm/versions/ohos/);生产侧换批次时只需替换四个坐标:旧基线 tag、上游目标 tag、分叉分支、engine / Dart revision。

9.2 为什么不直接 merge 上游,而要用「全新分支 + 三方重放」?

merge 会把「上游 2750 个变化」和「鸿蒙 2263 个适配」揉进一个巨大的合并提交,冲突散落在后续提交里慢慢爆,且无法逐项审计。全新分支 + git apply --3way 重放的好处是:冲突一次性暴露、每个提交可审计、适配清单可复用。代价是要自己维护清单和补丁集——这正是本篇(§6.2 的 G1 验证门 + §7.4 的清单恢复)与第 6 篇要解决的部分。

9.3 上游 2750 文件、鸿蒙适配 2263 文件,是什么关系?

2750 是上游 3.44.9→3.47.4 自身的变化文件数;2263 是鸿蒙分叉相对上游旧基线改过的文件数(+192740 行)。两者不是同一批文件:真正的工作量是交集——上游改过、且鸿蒙也改过的文件,必须逐个三方重放并裁决冲突;不相交的部分按清单直接搬。engine 层交集最大(826 文件),所以 Phase 3 最重。

9.4 Breaking Changes 那 12 条怎么验证,能直接照抄结论吗?

不能照抄。BC 表是本批次实测档案:5 条已销项、2 条挂真机、其余是决策记录、测试漂移或静默故障专项。换版本后要按同样口径重跑:flutter analyze 全量 0 error(G2)、framework 单测、engine 契约对齐(G3)、HAP 冒烟(M1-M5),并保留设备侧证据。验证门的具体清单见第 10 篇 §七。

9.5 复现这个批次需要什么环境?

  • Flutter OH 基线:3.44.9(批次起点),目标上游 3.47.4,当前发布版为 3.47.8-ohos-1.0.0;
  • DevEco Studio 26.0.0 Release,OpenHarmony SDK / API 26(提供 hvigor / ohpm / hdc / JBR);
  • macOS arm64、≥88GB 空闲磁盘、git / python3 / clang / ninja / node;
  • 有代理时先 git config --global http.version HTTP/1.1,否则大包 clone 会断。

完整的环境变量与工具链配置见Flutter OH 环境搭建指导。

9.6 仓库地址统一用哪个?

当前统一用 atomgit.com/oh-flutter/flutter_flutter。早期文章里的 CPF-Flutter、openharmony-tpc 链接是历史仓库,只用于追溯旧提交;新克隆、新 CI 配置不要再指向它们。

十、本篇小结与系列导航

把本篇的总图压缩成五句话:

  • 同步的动机是版本墙:分叉落后上游约 4 个月,生态包集体不可用;
  • 批次的规模是上游 2750 文件变化 × 鸿蒙 2263 文件适配集,交集才是风险面;
  • 打法是全新分支 + 三方重放(不 merge),清单驱动、五阶段、每阶段一道验证门(G1-G5);
  • BC 的口径是已实测档案:12 条里 5 条销项、2 条挂真机、其余是决策记录/测试漂移/静默故障专项;
  • 最大的单项教训是 E7 字体端口反转——「编译零报错 ≠ 可用」,字体检查从此是每个批次的固定动作;
  • 第七章把这套打法参数化成可执行 SOP:变量表 + G0-G5 验证门 + P1-P29 权威索引 + 错误签名查表,下一批次照着敲即可。

「鸿蒙Flutter框架 0day适配实战」全系列 10 篇,本篇为第 5 篇(生产侧开篇):

#篇目侧一句话主题
01背景、分叉谱系、版本命名与 fvm fork 安装消费三层架构、三个接缝、七层工作量、路径 A、版本墙
02手动 bootstrap tag 版本与三层核验消费tag 探测、浅克隆、首次初始化、SSH 修复、异常分诊
03鸿蒙模拟器/真机跑 Flutter + 消费侧踩坑集消费工具链三件套、HAP 构建/安装/运行、占位签名、截图取证、CP1-CP14
04flutter build hap 自动签名消费P12/CSR、AGC 证书与 Profile、纯 Dart AES-GCM、C0-C10 复用
05上游同步总览、BC 全景与端到端 SOP(本篇)生产批次解剖、五阶段验证门、12 项适配表、端到端 SOP 与 P1-P29 索引
06Phase 1+2:基线建立与 Framework 适配生产代理 HTTP/1.1 修障、421 文件重打、Dart SDK 源码构建
07Phase 3 Engine:三方重放与冲突裁决生产826 文件、15 真冲突两分法、契约对齐 16 项
08引擎构建链攻防生产依赖树、工具链版本、链接与测试面 27 坑
09构建发布与产物分发生产版本锁、11 个工件(Dart SDK 双宿主)、11 条覆盖键、换新 tag 铁律
10验证与真机验收生产三档引擎、设备侧单测、字体图标静默故障

配套仓库与文档:

总结

本篇用「3.44.9 → 3.47.4」这个真实批次,把生产侧的全貌讲完了一次:为什么要同步(版本墙 + 4 个月版本差)、同步的四个基线坐标、2263 文件适配集由什么构成(engine 826 / dev 633 / packages 421 为主体)、3.47 的 12 条 BC 适配档案(5 销项 / 2 挂真机 / 其余为决策与专项)、五阶段方案与 G1-G5 验证门、可直接执行的端到端 SOP 与 P1-P29 权威索引,以及开跑前的环境准备与三大风险。一句话总纲:同步不是搬代码,是清单驱动地重放一套适配集,每过一道门才进下一阶段。

下一篇(第 6 篇)进入 Phase 1+2 的实操细节:代理 HTTP/2 大包断裂的修障、浅克隆建基线、2263 文件清单恢复校验,以及 421 文件三方重打与「Dart SDK 必须从源码构建」这个本阶段最大发现。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

环境与版本

本文的示例与截图基于以下环境组合(2026-10 实测):

组件版本说明
上游 Flutter SDK3.47.8github.com/flutter/flutter
Flutter SDK(OH 适配版)3.47.8-ohos-1.0.0oh-flutter/flutter_flutter,oh-3.47-dev 分支
DevEco Studio26.0.0 Release提供 hvigor / ohpm / hdc / JBR 等工具链
OpenHarmony SDK / APIAPI 26(26.0.0)模拟器与 SDK 均为 API 26
运行设备OpenHarmony 模拟器API 26,1280×2832

环境搭建(分叉获取、DevEco Studio 与 SDK 配置、模拟器创建)请按官方指导操作:OpenHarmony-flutter 环境搭建指导。

本文正文是 2026-09 3.44.9 → 3.47.4 同步批次的实录:其中的版本号、提交号与实测数字(适配清单文件数、构建边数、单测用例数、工件字节数等)都是那一批的现场值,不随上表更新;上表是当前可复现、可照做的环境组合。方法论、验证门与坑模型对 3.47.8 线同样适用。

Logo

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

更多推荐