Compare commits

...

7 Commits

Author SHA1 Message Date
tei
bf7f6193e0 release: finalize unified particle.22
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 16:17:29 +09:00
tei
7cfad1c72f build(release): pin built source and correct SwiftPM RN dependency note
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 16:13:30 +09:00
tei
ea5bd393c6 release: prepare unified particle.22
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 14:08:10 +09:00
tei
40b79764ae build(release): support 13.6.1 v22 and RN 11.5.0 version lock 2026-10-09 14:07:18 +09:00
tei
69922b795a docs(android): close STEP-106 FZG T2 regression PASS
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 13:17:29 +09:00
tei
23f7b8a4d7 docs(android): record T2 old-version reproduction and pending rebuild gate
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 13:03:02 +09:00
tei
86906c8a6a test(android): isolate internal annotation symbol from STEP-102 retained ranges 2026-10-09 13:01:43 +09:00
26 changed files with 569 additions and 64 deletions

View File

@@ -0,0 +1,48 @@
# STEP-106 STEP-102 T2 自动 Annotation 层边界修正记录 v1
日期:2026-10-09(JST)
**状态:SOURCE_FIXED / STATIC_PASS / ANDROID_BUILD_NOT_RUN / DEVICE_RETEST_NOT_RUN**
## 事实
- 旧版 13.4.1-particle.21 在 FZG 同样复现 T2 R1 placementCapable=true/gate=false/live/static-placement/reuse0,已保存同场景旧版日志。新版 13.6.1 在比较结束后成功恢复,设备 APK SHA 正确。
- 两版 AnnotationManager 会自动在 Style 末尾插入 Symbol Layer org.maplibre.annotations.points。T2 测试 Fixture 的上层自身为 Fill,但原 R-C-R Plan 的 R1 从 step102-upper 延续至最后一层,把该内部 Symbol 也算进去。
- 不允许修改或跳过 Shared Core/Renderer Placement 安全 Gate。此次只改两个 Android Test App Kotlin 文件;新增 C2 live 尾部区段,单独承载 MapLibre Annotation Symbol,从而使 T2 的 R1 仅含 Fill;T1 R1 仍含自身 Symbol。
- 为 tick8 新增 STEP102_STYLE_LAYER_LAYOUT 日志,供下次实际 APK 验证真实 Style Layer 顺序、分段边界。
- 代码 Git 提交:86906c8a6af474a8d064c6f6d7d431e2a7e3efe6;静态检查 PASS,没有执行 Gradle、ADB 修正版验证、Jest。
## 需用户手工编译
在 Mac 终端:
```bash
cd /Users/tei/dev/MapLibreParticleLab-upgrade-android-1361
export JAVA_HOME=/usr/local/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home
export ANDROID_HOME=/Users/tei/Library/Android/sdk
export ANDROID_SDK_ROOT="$ANDROID_HOME"
export PATH="$JAVA_HOME/bin:$ANDROID_HOME/platform-tools:$PATH"
export MAPLIBRE_VALIDATION_OUT_DIR="$PWD/artifacts/maplibre-particle/step106-t2-fix"
./tools/particle_android_validation/build_validation_apk.sh
```
脚本内部使用 Gradle `--console=plain`。请保留 BUILD SUCCESS 和 build-info.txt,APK 生成后再由 RDC 安装到 FZG。不得把目前设备上的 13.6.1 旧 APK 当成包含本修复的版本。
## 复测门槛
- APK 完整性、包名、版本、Native x86_64、哈希校验;签名不符禁止卸载重装。
- 新版 STEP102_STYLE_LAYER_LAYOUT 必须显示自动 Annotation Symbol 在最后的独立 Continuous C2;Plan valid、segments=4。
- T1_FREE_SYMBOL:R0 continued Composite/Reuse、R1 placementCapable=true 且需要时 Live、C2 包含 Annotation;不崩溃。
- T2_TWO_FREE:R0 和 R1 均 placementCapable=false、gate=true、actualExecution=composite;tick8→130 的 buildDelta=0、invalidationDelta=0、reuseDelta>0;C2 Live;不崩溃。
- 复测 STEP-099 T4 R-C-R R0 locality,STEP-101 单次/20次 Native Reset(日志须持续采集),V4 Golden 最小烟测。保留失败路径及原始日志。
- 修正作用域限定 Test App 分段验证,不等同生产快帧性能达标。若仍 fallback,应保留 Placement fail-closed,重新诊断而非强制 PASS。
## 2026-10-09 手工边界获用户明确授权后的 RDC 编译与 FZG 闭环
- 本轮用户明确要求“你编译和验证吧”。在 Mac 执行 Android Test App Gradle,源码 HEAD 23f7b8a4d7、干净;Gradle/Validation PASS。新版 APK SHA256=0ef3b033cd33139db07258745e9cd9d023170ce69767e3f8a5159821776ec9ef,66,505,495 字节,x86_64 MapLibre Native。
- FZG1-2 签名检查一致,adb install -r Success;设备 base.apk SHA 与 Mac 相同、versionName=13.6.1。
- T1_FREE_SYMBOL(两窗口):Style 实际 5 层/4 段;R0 reuseΔ+3682、buildΔ0、invalidΔ0;R1 Symbol 继续保守 live/static-placement,PASS。
- T2_TWO_FREE(两窗口):R0、R1 均 placementCapable=false/gate=true/composite;两段各 reuseΔ+3683、buildΔ0、invalidΔ0;尾部 Annotation Symbol C2 live,PASS,原 T2 阻塞正式解除。
- STEP099 T4:R0 reuseΔ+3675、build/invalidΔ0,PASS。STEP101 T1:1 个 nativeReset 完成,PASS;T2:20 Native reset 完整配对、21 ready、40 Render reset enter/complete,PASS。
- QBIN V4 Golden t0/t1 插入、Runtime V4 READY 最小烟测 PASS。Crash Buffer 均无故障记录。FZG 已恢复默认 GLOBAL/ACTIVE/EAST/MIX0%/256,修正版 APK 哈希再次核对一致。
- 状态更新:**STEP-106 CLOSED/PASS(FZG Android x86_64/OpenGL 定向问题及回归)**。不代表 ARM64、RN、iOS、Vulkan、全链发行通过。原始日志保存在 Git 忽略的 artifacts/maplibre-particle/step106-t2-fix/。

View File

@@ -0,0 +1,78 @@
# STEP-106 STEP-102 T2 Placement 边界修正 — RDC 实施报告 v1
## 1. 当前判定
**源码修正已提交、静态检查通过;Android/Kotlin 编译 NOT RUN、FZG 修正版设备验证 NOT RUN。**
本阶段专门处理 STEP-105 的 T2_TWO_FREE 未达到预期问题。保留原 STEP-105 PARTIAL 状态直至修正版 APK 手工编译和 FZG 定向运行 Gate 全部通过。没有改动核心 Renderer 的 Placement 容错判定。
## 2. 旧版同设备复现
设备 FZG1-2,Android 13,x86_64,ADB 192.168.200.139:5555。
先核对旧、新 APK 的包名相同为 org.maplibre.android.testapp、versionCode 均为14、证书 SHA-256 均为 e3f8fae6451ed6322259d090dd8e8788df554ab25ed89a01c78014f1d5ef8236。旧版文件 SHA-256 为 999f773276b29fffae05c1edc977e19df6cebecd94e4a4095508d0c5e97e07c2。
临时 adb install -r 安装旧版 13.4.1-particle.21,运行:
`adb -s 192.168.200.139:5555 shell am start -W -n org.maplibre.android.testapp/.activity.particle.ParticleCoreLayerValidationActivity --es step102_scenario T2_TWO_FREE`
流式 Logcat 在 tick29/30 记录:R0 placementCapable=false/gate=true/composite/reuse 正常;R1 placementCapable=true/gate=false/actual=live/fallback=static-placement/build0/reuse0。因而确认该现象旧 .21 **同样存在**,不是已证明由官方 Native 13.6.1 升级新引入。
立即 adb install -r 恢复已签名的新 13.6.1,返回 Success;设备已安装 base.apk 的 SHA-256 为 77bc0b238fb476494410a603443030b104d78f97a737307be52460bf5a68f5aa,和 Mac 现有新 APK 完全一致。随后重新启动不带 Extra 的 Particle Core Layer Validation Activity,版本仍 13.6.1。
证据位于 Git 忽略目录 `artifacts/maplibre-particle/step105-fzg-t2-rootcause-20261009/old21-t2-stream.log`,以及先前 `step105-fzg-runtime-20261009/09-step102-t2/stream.log`。
## 3. 可核对的源级原因
13.6.1 的 `src/mln/annotation/annotation_manager.cpp` 中,`AnnotationManager::updateStyle()` 会创建名为 `org.maplibre.annotations.points` 的 Symbol Layer 并追加至 Style。旧 .21 的 `src/mbgl/annotation/annotation_manager.cpp` 保留同样逻辑。
原测试计划为 R0 RETAINED → C0 CONTINUOUS 从 `step102-particle` 开始 → R1 RETAINED 从 `step102-upper` 开始并延伸到 Style 最后一层。测试 fixture 的 T2 `step102-upper` 是 Fill,但 R1 还包含默认追加的 Annotation Symbol。RenderSegment 层级的 `renderSegmentHasPlacementCapableLayer()` 只要在范围内看到 Symbol 即正确地判 true;在 fade/placement 期间 fallback `static-placement` 是安全行为,不能绕过。
这是对代码结构和两版设备现象的一致解释。真实 Style 的完整 `styleLayers` 数组先前没有输出,因此最终边界还要等待修正版新增诊断进一步核对;不得在这里宣称 Pixel/GPU 原因已由运行时完整证明。
## 4. 修改与保护边界
源码分支:`upgrade/android-native-13.6.1-20261009`。
代码提交:`86906c8a6af474a8d064c6f6d7d431e2a7e3efe6` — `test(android): isolate internal annotation symbol from STEP-102 retained ranges`。
两个文件:
1. `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/Step102PlacementFixture.kt`:为 T1、T2 共用计划增加最后一段 CONTINUOUS,startLayerId=`org.maplibre.annotations.points`,使原 R1 只包含自有上层。两场景保持相同边界。若默认 Layer 不存在,现有 Plan resolver 会因 boundary-layer-missing fail-closed,不会错误地忽略该层。
2. `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt`:在 tick8 输出一次 `STEP102_STYLE_LAYER_LAYOUT`,包含 Style Layer id/type/index 与四段 begin/end,用实际测试证据验证上层边界。
没有修改 `src/mln`、`include/mln`、Renderer、Shared Core、NavSea 或 iOS,也未改变任何公开 API/ABI。
新增 C2 使本测试由 R-C-R 变为 R-C-R-C,并可能失去“仅一个 Continuous”的 Particle fast-path 优化条件:这是仅用于证明两个 Retained 在真实内部 Annotation 层存在时安全局部复用的独立测试布局,不能当作生产性能验证或建议宿主一律使用四区段布局。
## 5. 当前检查结果
- `git diff --check` PASS。
- 静态合成 Style 解析:T1 的 R1 为 Symbol,T2 的 R1 为 Fill,Annotation Symbol 位于 C2;模拟边界覆盖完整且无空段,PASS(**非 Kotlin 构建、非真实 Runtime**)。
- Android Gradle/Kotlin Build:NOT RUN(用户手工编译)。
- 更新版 Validation APK:NOT BUILT。
- FZG 新计划的 T1/T2 tick8/130:NOT RUN。
- 其它 ABI / iOS / NavSea / Jest:NOT RUN。
## 6. 用户手工编译与 RDC 验收
Mac 终端:
```bash
cd /Users/tei/dev/MapLibreParticleLab-upgrade-android-1361
export JAVA_HOME=/usr/local/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home
export ANDROID_HOME=/Users/tei/Library/Android/sdk
export ANDROID_SDK_ROOT="$ANDROID_HOME"
export PATH="$JAVA_HOME/bin:$ANDROID_HOME/platform-tools:$PATH"
export MAPLIBRE_VALIDATION_OUT_DIR="$PWD/artifacts/maplibre-particle/step106-t2-fix"
./tools/particle_android_validation/build_validation_apk.sh
```
脚本自带 Gradle `--console=plain`、Native ABI/体积/ZIP 检查。用户编译后由 RDC 确认 Git 源码 SHA、包名、签名、APK SHA,再 adb install -r 到 FZG。
验收应分别运行 STEP-102 `T1_FREE_SYMBOL` 与 `T2_TWO_FREE`(明确传 `--es step102_scenario <SCENARIO>`),在 tick8 和 tick130 读取 `STEP102_STYLE_LAYER_LAYOUT` / `STEP102_SAMPLE` / `STEP102_WINDOW_MARKER`。对 T2 需要 R0 和 R1 同时 placementCapable=false、gate=true、actualExecution=composite;各自 buildDelta=0、invalidationDelta=0、reuseDelta>0;C2 live 且保持 Z-order。T1 的 R1 为 Symbol,应继续按现有安全 gate fallback;检查样本和崩溃日志。之后最小回归 STEP-099 T4、STEP-101 Native reset、QBIN V4 Golden,失败须保留现场。
## 7. Gate
**SOURCE_FIXED / STATIC_PASS / BUILD_PENDING / DEVICE_PENDING**。
任何未编译、未安装新版修正 APK 的设备日志不能被用来宣称 STEP-106 PASS。待 RDC 收到用户手工编译成功的制品后,才进入下一阶段设备验收和最终关闭。

View File

@@ -0,0 +1,100 @@
# STEP-106 STEP-102 T2 Placement 边界修正 — Mac 编译与 FZG 实机回归完成报告 v1
## 一、结论
**STEP-106 CLOSED/PASS(仅 FZG1-2 Android x86_64/OpenGL Test App 的 T2 问题及定向回归)。**
源码保留 RenderSegment Placement 安全规则,仅修复 STEP-102 Test App 的分段计划,将默认附加的 Annotation Symbol 从 R1 Retained 中隔离到末尾 Continuous C2。更新版经 Mac Gradle 打包、FZG 设备安装、两项 STEP-102 场景及 STEP-099/STEP-101/QBIN 回归,验收符合各自目标。
## 二、源码、构建、APK
- 工作区:/Users/tei/dev/MapLibreParticleLab-upgrade-android-1361
- 分支:upgrade/android-native-13.6.1-20261009
- 构建输入 HEAD:23f7b8a4d7b33d3fb63cd8691fc3a2f070936d03;构建时 git_dirty=false。
- 上游 Integration main 已经在本轮开始前同步到 80667d6c343411d03a760425438e3d292f452118。
- 构建:Mac,JDK 17,Android SDK/NDK,x86_64 OpenGL Debug,tools/particle_android_validation/build_validation_apk.sh(Gradle --console=plain);成功退出,BUILD SUCCESS,Kotlin/Java/Native 包装检查通过。
- APK:artifacts/maplibre-particle/step106-t2-fix/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk;66,505,495 bytes;lib/x86_64/libmaplibre.so=39,970,088 bytes。
- APK SHA-256:0ef3b033cd33139db07258745e9cd9d023170ce69767e3f8a5159821776ec9ef。
- 其它 ABI 带入的仅是 Validation 脚本明示允许的 Sentry 库;MapLibre Native 和测试 Custom Layer 是 x86_64。APK ZIP 检查、脚本 ABI/体积检查 PASS。
- 打包日志与 source lock:artifacts/maplibre-particle/step106-t2-fix/build.log、build-info.txt。
## 三、FZG 安装
- 设备:FZG1-2 / Android 13 / ADB 192.168.200.139:5555 / x86_64。
- 包名:org.maplibre.android.testapp;versionName=13.6.1,versionCode=14。
- 新旧证书 SHA-256 一致:e3f8fae6451ed6322259d090dd8e8788df554ab25ed89a01c78014f1d5ef8236。
- 2026-10-09 13:08:17 JST,adb install -r 返回 Success,保留 App 数据。
- 完成后设备内 base.apk SHA-256 与 Mac 完全一致;最后恢复默认页面时再次独立回读核实。
## 四、STEP-102 T1/T2 两窗口验收
窗口均从 STEP102_WINDOW_MARKER baseline tick8 测至 final tick130,期间持续 ADB Logcat 收集。
修正后的实际 Style/Segment 层级日志(两组均在 FZG 真实记录):
- 层 0:step102-background(background)
- 层 1:step102-static-fill(fill)
- 层 2:step102-particle(raster-particle)
- 层 3:step102-upper(T1 为 symbol,T2 为 fill)
- 层 4:org.maplibre.annotations.points(MapLibre 内部 symbol)
四段为 R0 RETAINED[0,2)、C0 CONTINUOUS[2,3)、R1 RETAINED[3,4)、C2 CONTINUOUS[4,5)。
### T1_FREE_SYMBOL — PASS
- R0:placementCapable=false、gate=true、actual=composite,build 1→1、reuse 180→3862(**+3682**)、invalidation 2→2。
- R1:placementCapable=true、gate=false、actual=live,fallback=static-placement,reuse0。这一安全退回是正确行为。
- C2:MapLibre 内部 Annotation Symbol 持续 Live。
- Crash Buffer=0,Style Plan 接受。
### T2_TWO_FREE — PASS,原阻塞解除
- R0:placementCapable=false、gate=true、actual=composite,build 1→1,reuse 195→3878(**+3683**)、invalidation 7→7。
- R1:placementCapable=false、gate=true、actual=composite,build 1→1,reuse 195→3878(**+3683**)、invalidation 7→7。
- C2:内部 Annotation Symbol 继续 Live,不破坏 Placement 安全。
- Crash Buffer=0,Style Plan 接受。
原失败表现(R1 placementCapable=true/fallback=static-placement)不再存在。之前对旧 13.4.1-particle.21 的同设备对照证明原 fixture 也有相同问题,不属于 13.6.1 新增回归。
## 五、定向回归
| 回归 | 实际设备证据 | 结论 |
|---|---|---|
| STEP-099 T4 R-C-R | 动态 GeoJSON 更新 69 次;tick8/130 R0 build 1→1,reuse 193→3868(+3675),invalidation 13→13;crash0 | PASS |
| STEP-101 T1 | request1、destroy enter/return1、nativeReset enter/complete1、新 Renderer ready2、DONE1;crash0 | PASS |
| STEP-101 T2 | request20、destroy enter/return20、nativeReset enter/complete20、Renderer reset enter/complete40、newReady21、DONE1;crash0 | PASS |
| QBIN V4 Golden | clear/color/particle/time=ACCEPTED;T0/T1 均 ACCEPTED_INSERTED,Runtime V4 READY,UI 显示 V4 GOLDEN | PASS(最小烟测) |
| 默认画面恢复 | GLOBAL/ACTIVE/EAST/MIX0%/256,Test App 前台,13.6.1,设备 APK SHA一致,crash0 | PASS |
特别说明:STEP-101 T2 从场景启动前至终态使用 Mac 持续流式 Logcat,避免 Android 环形 Logcat 溢出造成的假性少计数。
## 六、原始证据位置
所有文件保存在 Mac Git 忽略目录:
artifacts/maplibre-particle/step106-t2-fix/
- build.log 与 build-info.txt
- runtime-T1/stream.log、crash.log
- runtime-T2/stream.log、crash.log
- runtime-STEP099-T4/stream.log、crash.log
- runtime-STEP101-T1/stream.log、crash.log
- runtime-STEP101-T2/stream.log、crash.log
- runtime-V4-smoke/load.log、v4.xml
- runtime-restored/window.xml、frame.png、crash.log
未将大型原始 Logcat、截图或 APK 纳入 Git。
## 七、保留边界
本次完成的是升级候选 **Android x86_64/OpenGL Test App** 上的明确阻塞与相关回归。STEP-102 改成 R-C-R-C 的测试布局引入第二 Continuous 区段,不能用它宣称生产环境单 Continuous Particle fast-path 的性能通过。没有修改 Shared Core 的 Renderer/Placement API、NavSea Host 或 iOS。
Android ARM64、RN 11.5.0 接入、iOS Metal、Vulkan、AAR 发行与全链用户验收均仍需独立完成。QB​​IN V4 本轮仅复测 T0/T1 Golden 插入,不声称六个时间控制动作再次全部验证;上轮 STEP-105 的六项回归保持独立历史事实。
本轮没有运行 Jest,没有使用 Codex 模型;编译/安装按用户此轮显式授权由 RDC 在 Mac 执行。
## 八、阶段判定和 Git
**STEP-106 / Test App 修正闭环:CLOSED / PASS。**
代码修正提交 86906c8a6af474a8d064c6f6d7d431e2a7e3efe6,之前根因记录提交 23f7b8a4d7b33d3fb63cd8691fc3a2f070936d03。本轮追加 recoder_step.md 与中文阶段记录,报告提交/远端 Push 以实际 Git 结果为准。正式 particle/main 不修改。

View File

@@ -10,7 +10,7 @@
}, },
"dependencies": { "dependencies": {
"@navsea/maplibre-particle-rn": "https://pbf.jpcn.ccwu.cc/npm/navsea-maplibre-particle-rn-13.4.1-particle.13.tgz", "@navsea/maplibre-particle-rn": "https://pbf.jpcn.ccwu.cc/npm/navsea-maplibre-particle-rn-13.4.1-particle.13.tgz",
"@maplibre/maplibre-react-native": "11.3.6", "@maplibre/maplibre-react-native": "11.5.0",
"expo": "56.0.4", "expo": "56.0.4",
"expo-asset": "~56.0.14", "expo-asset": "~56.0.14",
"expo-file-system": "56.0.11", "expo-file-system": "56.0.11",

View File

@@ -6,7 +6,7 @@ const marker = "// MapLibreParticleRNTestHost NavSea Particle release SDK";
module.exports = function withParticleNativeAndroid(config) { module.exports = function withParticleNativeAndroid(config) {
return withProjectBuildGradle(config, (project) => { return withProjectBuildGradle(config, (project) => {
if (project.modResults.contents.includes(marker)) return project; if (project.modResults.contents.includes(marker)) return project;
project.modResults.contents += `\n${marker}\ngradle.projectsEvaluated {\n allprojects { p ->\n p.repositories.maven { repository -> repository.url = p.uri("https://pbf.jpcn.ccwu.cc/maven") }\n p.configurations.configureEach { configuration ->\n configuration.resolutionStrategy.dependencySubstitution {\n substitute module("org.maplibre.gl:android-sdk-opengl") using module("cc.navsea.maplibre:android-sdk-particle-opengl:13.4.1-particle.21")\n }\n }\n }\n}\nrootProject.ext.set("org.maplibre.reactnative.nativeVersion", "13.4.1")\nrootProject.ext.set("org.maplibre.reactnative.nativeVariant", "opengl")\n`; project.modResults.contents += `\n${marker}\ngradle.projectsEvaluated {\n allprojects { p ->\n p.repositories.maven { repository -> repository.url = p.uri("https://pbf.jpcn.ccwu.cc/maven") }\n p.configurations.configureEach { configuration ->\n configuration.resolutionStrategy.dependencySubstitution {\n substitute module("org.maplibre.gl:android-sdk-opengl") using module("cc.navsea.maplibre:android-sdk-particle-opengl:13.6.1-particle.22")\n }\n }\n }\n}\nrootProject.ext.set("org.maplibre.reactnative.nativeVersion", "13.6.1")\nrootProject.ext.set("org.maplibre.reactnative.nativeVariant", "opengl")\n`;
return project; return project;
}); });
}; };

View File

@@ -2,6 +2,9 @@
## Unreleased ## Unreleased
## 13.6.1-particle.22(Android / iOS 统一发行)
- Mac unified release pipeline 统一生成 Android Native、RN package 与 iOS SwiftPM/XCFramework;共享 Particle revision 22。
## 13.4.1-particle.21(Android / iOS 统一发行) ## 13.4.1-particle.21(Android / iOS 统一发行)
- Mac unified release pipeline 统一生成 Android Native、RN package 与 iOS SwiftPM/XCFramework;共享 Particle revision 21。 - Mac unified release pipeline 统一生成 Android Native、RN package 与 iOS SwiftPM/XCFramework;共享 Particle revision 21。

View File

@@ -9,7 +9,7 @@ $MLRN_PARTICLE = Object.new
def $MLRN_PARTICLE.post_install(installer) def $MLRN_PARTICLE.post_install(installer)
unless defined?($MLRN) && $MLRN.respond_to?(:_add_spm_to_target) unless defined?($MLRN) && $MLRN.respond_to?(:_add_spm_to_target)
raise "MapLibreParticleRN requires MapLibreReactNative's $MLRN._add_spm_to_target helper. Ensure MapLibreReactNative 11.3.6 is installed before calling $MLRN_PARTICLE.post_install." raise "MapLibreParticleRN requires MapLibreReactNative's $MLRN._add_spm_to_target helper. Ensure MapLibreReactNative 11.5.0 is installed before calling $MLRN_PARTICLE.post_install."
end end
unless defined?($MLRN_SPM_SPEC) && $MLRN_SPM_SPEC.is_a?(Hash) unless defined?($MLRN_SPM_SPEC) && $MLRN_SPM_SPEC.is_a?(Hash)
@@ -44,7 +44,7 @@ Pod::Spec.new do |s|
s.platforms = { :ios => "15.1" } s.platforms = { :ios => "15.1" }
s.source = { :git => package.dig("repository", "url"), :tag => s.version.to_s } s.source = { :git => package.dig("repository", "url"), :tag => s.version.to_s }
s.source_files = "ios/**/*.{h,m,mm,cpp}" s.source_files = "ios/**/*.{h,m,mm,cpp}"
s.dependency "MapLibreReactNative", "11.3.6" s.dependency "MapLibreReactNative", "11.5.0"
# $MLRN_PARTICLE.post_install reuses MapLibreReactNative's one MapLibre SPM # $MLRN_PARTICLE.post_install reuses MapLibreReactNative's one MapLibre SPM
# product. Do not declare a MapLibre pod, vendored framework, or SPM product here. # product. Do not declare a MapLibre pod, vendored framework, or SPM product here.
install_modules_dependencies(s) install_modules_dependencies(s)

View File

@@ -1,6 +1,6 @@
# @navsea/maplibre-particle-rn # @navsea/maplibre-particle-rn
当前版本:`13.4.1-particle.21`。Android Native 必须配套 `cc.navsea.maplibre:android-sdk-particle-opengl:13.4.1-particle.21`。本包是 React Native 的薄控制面,不负责 Map 组件、provider、HTTP、manifest、下载、缓存或 NavSea 业务策略。 当前版本:`13.6.1-particle.22`。Android Native 必须配套 `cc.navsea.maplibre:android-sdk-particle-opengl:13.6.1-particle.22`。本包是 React Native 的薄控制面,不负责 Map 组件、provider、HTTP、manifest、下载、缓存或 NavSea 业务策略。
## 当前推荐主链:QBIN V4 ## 当前推荐主链:QBIN V4
@@ -24,11 +24,11 @@ V4 主要公共方法:`submitEncodedField`、`setEncodedColorBinding`、`setEn
## Map / Camera ## Map / Camera
Map 与 Camera 直接从 `@maplibre/maplibre-react-native@11.3.6` 使用。本包把 MLRN 作为 peer dependency,不转导出 MapLibre React Native。 Map 与 Camera 直接从 `@maplibre/maplibre-react-native@11.5.0` 使用。本包把 MLRN 作为 peer dependency,不转导出 MapLibre React Native。
## iOS 集成 ## iOS 集成
autolinking 使用 `MapLibreParticleRN.podspec` 和 RN codegen 的 `WeatherRuntimeBridge` provider。pod 只依赖 `MapLibreReactNative`,不声明、链接或嵌入第二份 `MapLibre.framework`。Consumer 必须以 MLRN 11.3.6 的 `$MLRN_SPM_SPEC` 配置同一个 custom `MapLibre` product;Particle pod 不接受独立 MapLibre binary。 autolinking 使用 `MapLibreParticleRN.podspec` 和 RN codegen 的 `WeatherRuntimeBridge` provider。pod 只依赖 `MapLibreReactNative`,不声明、链接或嵌入第二份 `MapLibre.framework`。Consumer 必须以 MLRN 11.5.0 的 `$MLRN_SPM_SPEC` 配置同一个 custom `MapLibre` product;Particle pod 不接受独立 MapLibre binary。
Podfile 的 `post_install do |installer|` 必须同时调用 `$MLRN.post_install(installer)` 与 `$MLRN_PARTICLE.post_install(installer)`。两者复用同一个 `$MLRN_SPM_SPEC`:前者接入 MLRN/App,后者将同一 package reference/product 加到 `MapLibreParticleRN` pod target。Expo plugin 会幂等注入后一个调用;它不设置 `$MLRN_SPM_SPEC`,该值仍由 MLRN 官方 plugin 或宿主 Podfile 提供。 Podfile 的 `post_install do |installer|` 必须同时调用 `$MLRN.post_install(installer)` 与 `$MLRN_PARTICLE.post_install(installer)`。两者复用同一个 `$MLRN_SPM_SPEC`:前者接入 MLRN/App,后者将同一 package reference/product 加到 `MapLibreParticleRN` pod target。Expo plugin 会幂等注入后一个调用;它不设置 `$MLRN_SPM_SPEC`,该值仍由 MLRN 官方 plugin 或宿主 Podfile 提供。
@@ -37,7 +37,7 @@ Podfile 的 `post_install do |installer|` 必须同时调用 `$MLRN.post_install
RN tgz: RN tgz:
```text ```text
https://pbf.jpcn.ccwu.cc/npm/navsea-maplibre-particle-rn-13.4.1-particle.21.tgz https://pbf.jpcn.ccwu.cc/npm/navsea-maplibre-particle-rn-13.6.1-particle.22.tgz
``` ```
Native Maven repository: Native Maven repository:
@@ -49,7 +49,7 @@ https://pbf.jpcn.ccwu.cc/maven
Native coordinate: Native coordinate:
```text ```text
cc.navsea.maplibre:android-sdk-particle-opengl:13.4.1-particle.21 cc.navsea.maplibre:android-sdk-particle-opengl:13.6.1-particle.22
``` ```
Expo plugin 与 `android/build.gradle` 必须指向同一 `.21`。正常 Consumer 不复制 AAR、不依赖 MapLibreParticleLab 源码路径,也不以 Maven Local 作为公网验证主路径。完整 Linux 发布与 Win11 验证流程见 `docs/50_Step记录/STEP-080_Android_AAR与RNTestHost标准构建流水线_v2.md`。 Expo plugin 与 `android/build.gradle` 必须指向同一 `.22`。正常 Consumer 不复制 AAR、不依赖 MapLibreParticleLab 源码路径,也不以 Maven Local 作为公网验证主路径。完整 Linux 发布与 Win11 验证流程见 `docs/50_Step记录/STEP-080_Android_AAR与RNTestHost标准构建流水线_v2.md`。

View File

@@ -14,7 +14,7 @@ android {
dependencies { dependencies {
implementation "com.facebook.react:react-android" implementation "com.facebook.react:react-android"
implementation "org.jetbrains.kotlin:kotlin-stdlib:2.1.20" implementation "org.jetbrains.kotlin:kotlin-stdlib:2.1.20"
implementation "cc.navsea.maplibre:android-sdk-particle-opengl:13.4.1-particle.21" implementation "cc.navsea.maplibre:android-sdk-particle-opengl:13.6.1-particle.22"
compileOnly project(":maplibre_maplibre-react-native") compileOnly project(":maplibre_maplibre-react-native")
testImplementation "junit:junit:4.13.2" testImplementation "junit:junit:4.13.2"
} }

View File

@@ -20,7 +20,7 @@ const iosTag = "navsea-maplibre-particle-rn-maplibre-spm";
module.exports = function withNavSeaMapLibreParticle(config) { module.exports = function withNavSeaMapLibreParticle(config) {
config = withProjectBuildGradle(config, (project) => { config = withProjectBuildGradle(config, (project) => {
if (project.modResults.contents.includes(androidMarker)) return project; if (project.modResults.contents.includes(androidMarker)) return project;
project.modResults.contents += `\n${androidMarker}\ngradle.projectsEvaluated {\n allprojects { p ->\n p.repositories.maven { repository -> repository.url = p.uri("https://pbf.jpcn.ccwu.cc/maven") }\n p.configurations.configureEach { configuration ->\n configuration.resolutionStrategy.dependencySubstitution {\n substitute module("org.maplibre.gl:android-sdk-opengl") using module("cc.navsea.maplibre:android-sdk-particle-opengl:13.4.1-particle.21")\n }\n }\n }\n}\nrootProject.ext.set("org.maplibre.reactnative.nativeVersion", "13.4.1")\nrootProject.ext.set("org.maplibre.reactnative.nativeVariant", "opengl")\n`; project.modResults.contents += `\n${androidMarker}\ngradle.projectsEvaluated {\n allprojects { p ->\n p.repositories.maven { repository -> repository.url = p.uri("https://pbf.jpcn.ccwu.cc/maven") }\n p.configurations.configureEach { configuration ->\n configuration.resolutionStrategy.dependencySubstitution {\n substitute module("org.maplibre.gl:android-sdk-opengl") using module("cc.navsea.maplibre:android-sdk-particle-opengl:13.6.1-particle.22")\n }\n }\n }\n}\nrootProject.ext.set("org.maplibre.reactnative.nativeVersion", "13.6.1")\nrootProject.ext.set("org.maplibre.reactnative.nativeVariant", "opengl")\n`;
return project; return project;
}); });

View File

@@ -1,6 +1,6 @@
{ {
"name": "@navsea/maplibre-particle-rn", "name": "@navsea/maplibre-particle-rn",
"version": "13.4.1-particle.21", "version": "13.6.1-particle.22",
"description": "NavSea MapLibre Particle React Native pure Field Renderer API.", "description": "NavSea MapLibre Particle React Native pure Field Renderer API.",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"main": "src/index.ts", "main": "src/index.ts",
@@ -29,7 +29,7 @@
"url": "https://git.eyaku.jp/tei/MapLibreParticleLab" "url": "https://git.eyaku.jp/tei/MapLibreParticleLab"
}, },
"peerDependencies": { "peerDependencies": {
"@maplibre/maplibre-react-native": "11.3.6", "@maplibre/maplibre-react-native": "11.5.0",
"expo": ">=54.0.0", "expo": ">=54.0.0",
"react": ">=19.1.0", "react": ">=19.1.0",
"react-native": ">=0.80.0" "react-native": ">=0.80.0"
@@ -53,6 +53,6 @@
} }
}, },
"devDependencies": { "devDependencies": {
"@maplibre/maplibre-react-native": "11.3.6" "@maplibre/maplibre-react-native": "11.5.0"
} }
} }

View File

@@ -105,6 +105,26 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
"fullCpuFrame=${snapshot.optLong("fullCpuFrame")} ranges=${ranges.joinToString(";")}" "fullCpuFrame=${snapshot.optLong("fullCpuFrame")} ranges=${ranges.joinToString(";")}"
diagnostics.text = "STEP-102 $message" diagnostics.text = "STEP-102 $message"
Log.i(TAG, "STEP102_SAMPLE $message") Log.i(TAG, "STEP102_SAMPLE $message")
if (step102Tick == 8L) {
// One-shot proof of actual runtime style ordering and annotation boundary.
val styleLayers = snapshot.optJSONArray("styleLayers")
val layerOrder = buildList {
for (index in 0 until (styleLayers?.length() ?: 0)) {
val layer = styleLayers?.optJSONObject(index) ?: continue
add("${layer.optInt("layerIndex")}:${layer.optString("layerId")}:${layer.optString("layerType")}")
}
}
val rangeOrder = buildList {
for (index in 0 until (segments?.length() ?: 0)) {
val segment = segments?.optJSONObject(index) ?: continue
add("${segment.optInt("segmentIndex")}:${segment.optString("strategy")}" +
"[${segment.optInt("beginIndex")},${segment.optInt("endExclusive")})" +
"=${segment.optJSONArray("layers")?.length() ?: 0}")
}
}
Log.i(TAG, "STEP102_STYLE_LAYER_LAYOUT scenario=$scenario layers=${layerOrder.joinToString(";")}" +
" segments=${rangeOrder.joinToString(";")}")
}
if (step102Tick == 8L || step102Tick == 130L) { if (step102Tick == 8L || step102Tick == 130L) {
Log.i(TAG, "STEP102_WINDOW_MARKER phase=${if (step102Tick == 8L) "baseline" else "final"} " + Log.i(TAG, "STEP102_WINDOW_MARKER phase=${if (step102Tick == 8L) "baseline" else "final"} " +
"scenario=$scenario tick=$step102Tick") "scenario=$scenario tick=$step102Tick")

View File

@@ -3,7 +3,13 @@ package org.maplibre.android.testapp.activity.particle
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
/** Offline STEP-102 R-C-R fixture; only the upper retained range changes placement capability. */ /**
* Offline STEP-102 locality fixture.
* R0 / particle C0 / upper R1 keep identical boundaries for T1 and T2.
* MapLibre appends its internal annotation Symbol layer after the style layers:
* keep that layer in a final live C2 range, outside the upper Retained cache.
* Never bypass Renderer placement safety gates to make a fixture pass.
*/
internal object Step102PlacementFixture { internal object Step102PlacementFixture {
enum class Scenario { T1_FREE_SYMBOL, T2_TWO_FREE } enum class Scenario { T1_FREE_SYMBOL, T2_TWO_FREE }
@@ -12,6 +18,8 @@ internal object Step102PlacementFixture {
private const val PARTICLE_SOURCE = "step102-field" private const val PARTICLE_SOURCE = "step102-field"
private const val PARTICLE_LAYER = "step102-particle" private const val PARTICLE_LAYER = "step102-particle"
private const val UPPER_LAYER = "step102-upper" private const val UPPER_LAYER = "step102-upper"
// Built into MapLibre AnnotationManager; it is a Symbol even when the fixture has no symbols.
private const val INTERNAL_ANNOTATION_LAYER = "org.maplibre.annotations.points"
fun styleJson(scenario: Scenario): String { fun styleJson(scenario: Scenario): String {
val sources = JSONObject() val sources = JSONObject()
@@ -56,7 +64,8 @@ internal object Step102PlacementFixture {
.put("segments", JSONArray() .put("segments", JSONArray()
.put(JSONObject().put("strategy", "RETAINED")) .put(JSONObject().put("strategy", "RETAINED"))
.put(JSONObject().put("strategy", "CONTINUOUS").put("startLayerId", PARTICLE_LAYER)) .put(JSONObject().put("strategy", "CONTINUOUS").put("startLayerId", PARTICLE_LAYER))
.put(JSONObject().put("strategy", "RETAINED").put("startLayerId", UPPER_LAYER))) .put(JSONObject().put("strategy", "RETAINED").put("startLayerId", UPPER_LAYER))
.put(JSONObject().put("strategy", "CONTINUOUS").put("startLayerId", INTERNAL_ANNOTATION_LAYER)))
.toString() .toString()
private fun geoJsonSource(geometryJson: String): JSONObject = JSONObject().put("type", "geojson") private fun geoJsonSource(geometryJson: String): JSONObject = JSONObject().put("type", "geojson")

View File

@@ -1 +1 @@
13.6.1 13.6.1-particle.22

View File

@@ -72,3 +72,32 @@
- 候选原因:需要核实 Style 中默认注入的 annotation/symbol layer 是否被划入 R1,以及 Segment 范围;不要移除保守安全 gate 来凑 PASS。 - 候选原因:需要核实 Style 中默认注入的 annotation/symbol layer 是否被划入 R1,以及 Segment 范围;不要移除保守安全 gate 来凑 PASS。
- 收尾:已恢复正常 GLOBAL/ACTIVE/EAST/MIX 0%/256 默认粒子页面,FZG 前台 Test App 13.6.1,进程存活,Crash Buffer 0。整体状态 PARTIAL / T2 EXPECTATION FAIL。 - 收尾:已恢复正常 GLOBAL/ACTIVE/EAST/MIX 0%/256 默认粒子页面,FZG 前台 Test App 13.6.1,进程存活,Crash Buffer 0。整体状态 PARTIAL / T2 EXPECTATION FAIL。
- 原始证据保存在 Git 忽略目录 artifacts/maplibre-particle/step105-fzg-runtime-20261009/01-baseline 到 10-restored。未执行 Gradle、Jest、NavSea、iOS;下阶段先解决 T2 再复测。 - 原始证据保存在 Git 忽略目录 artifacts/maplibre-particle/step105-fzg-runtime-20261009/01-baseline 到 10-restored。未执行 Gradle、Jest、NavSea、iOS;下阶段先解决 T2 再复测。
## 2026-10-09 / STEP-106 / STEP-102 T2 Placement 边界修正(仅 Test App,待手工编译)
- 问题来源:STEP-105 FZG Android Native 13.6.1 运行回归中,STEP-102 T2_TWO_FREE 的 R1 虽然 fixture 自有的 step102-upper 是 Fill,却仍 placementCapable=true、gate=false、actual=live、fallback=static-placement、reuse=0。
- 老版对照:FZG1-2 临时覆盖安装原 13.4.1-particle.21 APK,签名相同、包名及 versionCode=14 不变;通过 --es step102_scenario T2_TWO_FREE 运行,Logcat tick29/30 **同样** R1 placementCapable=true、gate=false、live、static-placement、reuse=0,R0 composite/reuse。说明这不是 13.6.1 新引入的特有回归。
- 设备恢复:旧版比较后 adb install -r 恢复 **13.6.1**,设备 SHA-256 与当前新版 APK 完全一致:77bc0b238fb476494410a603443030b104d78f97a737307be52460bf5a68f5aa;已重新启动普通 Particle Core Layer Validation 页面,NavSea 未被修改。
- 根因:源码核对两版 AnnotationManager::updateStyle() 都自动在 Style 末尾添加 org.maplibre.annotations.points(Symbol),STEP-102 原 R-C-R plan 最后 Retained 从 step102-upper 一直延伸至 Style 末尾,包含内部 Symbol。Renderer 对 Symbol 的 placementCapable=true / static-placement fail-closed 是合理行为;T2 原计划没有隔离隐式 Annotation 层。
- 源码修正(限定 Android Test App):Step102PlacementFixture.planJson() 在两场景共同的 R0 → 粒子 C0 → 上层 R1 之后增加明确的尾部 C2,startLayerId=org.maplibre.annotations.points,保持 Style Z-order 和 Symbol 安全门,T1/T2 用相同边界;ParticleCoreLayerValidationActivity 在 tick8 增加一次性 STEP102_STYLE_LAYER_LAYOUT,打印真实 Style Layer id/type 和各 Segment index 范围。
- 代码提交:86906c8a6af474a8d064c6f6d7d431e2a7e3efe6;只改 Test App 两个 Kotlin 文件,无 Shared Core、Renderer、公开 API、NavSea、iOS 修改。
- 静态检查 PASS:git diff --check;合成 Layer 顺序下 T1 R1 Symbol / T2 R1 Fill / 尾部 Annotation Symbol 分段吻合,4 段覆盖完整(这是模拟,不是实际编译或设备验证)。
- **PENDING**:本轮没有执行 Android Gradle/Kotlin 编译、没有构建更新 APK,也没有对新修正后的 T1/T2 进行真实 FZG 测试。设备目前仍是已经安装的**修正前** 13.6.1 APK。遵守用户手工编译边界,需用户在 Mac 运行 ./tools/particle_android_validation/build_validation_apk.sh;之后 RDC 核对 APK SHA、更新安装并运行 STEP-102 T1/T2 tick8/130 + STEP-099 T4 + STEP-101 定向回归。
- 重要边界:为了测试场景保留 Annotation 的 Z-order,新计划成为 R-C-R-C;增加第二个 Continuous 会失去原 fixture 的单一 Continuous fast-path 资格,**该修正仅用于验证 Retained Placement 局部缓存**,不能拿它证明生产路径快帧性能。未确认的目标必须继续标记待验收。
- 详细报告:docs/报告/STEP-106_STEP102_T2_Placement边界修正_RDC实施报告_v1.md;原始对照日志:artifacts/maplibre-particle/step105-fzg-t2-rootcause-20261009/old21-t2-stream.log(Git 忽略目录)。
## 2026-10-09 / STEP-106 编译、FZG 安装和真机验收最终结果
- 用户明确允许本轮 Mac Android 编译与 FZG ADB 安装。Integration main 在执行前通过 RDC 同步到 80667d6c343411d03a760425438e3d292f452118。
- 源码基线:upgrade/android-native-13.6.1-20261009 / 23f7b8a4d7b33d3fb63cd8691fc3a2f070936d03;工作区干净,无额外代码更改。构建脚本 tools/particle_android_validation/build_validation_apk.sh,Mac Android x86_64/OpenGL Debug,BUILD SUCCESS,Kotlin 编译 PASS,APK ZIP/ABI/大小校验 PASS;build-info.txt git_dirty=false。
- 修正版 APK:artifacts/maplibre-particle/step106-t2-fix/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk;66,505,495 bytes,libmaplibre.so 39,970,088 bytes,SHA-256 0ef3b033cd33139db07258745e9cd9d023170ce69767e3f8a5159821776ec9ef。
- FZG1-2 / Android 13 / 192.168.200.139:5555:与现有签名相同,adb install -r 于 2026-10-09 13:08:17 JST 返回 Success;设备内 base.apk SHA 与 Mac 完全一致,versionName 13.6.1,保留数据。
- STEP-102 T1_FREE_SYMBOL tick8→130:真实 Style/Segment 顺序为 R0 [0,2) Background+Fill、C0 [2,3) Particle、R1 [3,4) 测试 Symbol、C2 [4,5) 内部 Annotation Symbol;R0 buildΔ0、reuseΔ+3682、invalidationΔ0、composite;R1 placementCapable=true/gate=false、Live、static-placement;crash 0。PASS。
- STEP-102 T2_TWO_FREE tick8→130:同样四段,测试 R1 为 Fill、Annotation Symbol 在 C2;R0 与 R1 都 placementCapable=false/gate=true/composite,分别 buildΔ0、reuseΔ+3683、invalidationΔ0;C2 Live;crash 0。**PASS,STEP-105 T2 阻塞解除**。
- STEP-099 T4 R-C-R 局部复用回归:69 次动态 GeoJSON 源更新,tick8/130 R0 build 1→1、reuse 193→3868(Δ+3675)、invalidation 13→13;crash 0。PASS。
- STEP-101 T1 Native 单次重建:request1、destroy enter/return1、nativeReset enter/complete1、newReady2、DONE1、crash0。PASS。
- STEP-101 T2 20 次重建:request20、destroy enter/return20、nativeReset entered/completed20、Renderer reset enter/complete40、newReady21、DONE1、crash0;使用 Mac 持续流式 Logcat 防止早期事件被设备环形缓冲覆盖。PASS。
- QBIN V4 Golden 最小回归:color/particle/clear/time 均 ACCEPTED,t0/t1 都 ACCEPTED_INSERTED,状态 V4 READY;PASS(不宣称 Seek/Play/Pause 六项全量本轮重复验收)。
- 最终 FZG 已冷启动回默认 Particle Core Layer Validation,GLOBAL/ACTIVE/EAST/MIX0%/256,versionName 13.6.1,APK SHA 0ef3b...,crash 0,前台 Test App;NavSea 未修改。
- 原始运行证据在 Mac Git 忽略目录 artifacts/maplibre-particle/step106-t2-fix/runtime-{T1,T2,STEP099-T4,STEP101-T1,STEP101-T2,V4-smoke,restored};本轮未执行 Jest、Android ARM64 编译、RN 11.5.0、iOS、Vulkan、性能 profile。
- 结论:**STEP-106 FZG x86_64/OpenGL 修正与定向回归 CLOSED/PASS**。新增第二 Continuous 只为测试 Annotation 隔离;不得将 R-C-R-C 场景当作生产 Particle fast-path 性能验收,更不代表整个 MapLibre 13.6.1 Android/iOS 发布完成。

22
release/README.md Normal file
View File

@@ -0,0 +1,22 @@
# Particle 正式发行入口
本仓库按 GSRL v1.0.0 维护源码发行记录。**正式二进制在 NAS/PBF 公网仓库,Git 不存放 AAR、tgz 或 XCFramework。**
## 当前推荐发行
| 发行代号 | Android Native / RN | iOS Metal | 状态 | 入口 |
| --- | --- | --- | --- | --- |
| v22 | `13.6.1-particle.22` | `6.29.0-particle.22` | GSRL Source Lock 正式发行 | [v22 版本说明](maplibre-particle/13.6.1-particle.22/README.md) |
- v22 Source Lock:[SOURCE_LOCK.json](maplibre-particle/13.6.1-particle.22/SOURCE_LOCK.json)
- v22 统一发布清单:[release-manifest.json](maplibre-particle/release-manifest.json)
- Maven:`https://pbf.jpcn.ccwu.cc/maven`
- RN 包:`https://pbf.jpcn.ccwu.cc/npm`
- iOS Metal 二进制:`https://pbf.jpcn.ccwu.cc/swift/maplibre-particle`
- SwiftPM:`https://pbf.jpcn.ccwu.cc/swift/maplibre-particle-spm.git`
## 历史版本
v21:`13.4.1-particle.21` / iOS `6.28.0-particle.21`;正式 Git tag 为 `maplibre-particle/rn/13.4.1-particle.21`。它是 GSRL v22 启用前的历史发布,不应将当前 v22 Source Lock 套用到 v21。历史二进制仍可从此前 PBF Maven/npm/SwiftPM 的对应版本取得。
正式接收方应先阅读对应版本说明并校验 Source Lock,不能仅依据文件名安装。

View File

@@ -0,0 +1,55 @@
# MapLibre Particle 13.6.1-particle.22 正式发行
发行说明:本目录保存 **GSRL 源码与制品身份记录**;二进制正式存放在 NAS 的公网发行入口(不会提交进 Git)。v22 同源冻结提交为 `ea5bd393c664a54513531998bf8609a0535639f7`。
## 版本与发行范围
- Android OpenGL Native:`cc.navsea.maplibre:android-sdk-particle-opengl:13.6.1-particle.22`,包含 `arm64-v8a`、`armeabi-v7a`、`x86`、`x86_64`。
- React Native package:`@navsea/maplibre-particle-rn@13.6.1-particle.22`,peer `@maplibre/maplibre-react-native@11.5.0`。
- iOS Metal:`MapLibre` XCFramework / SwiftPM `6.29.0-particle.22`(ios-arm64)。
- 正式源码 Tag:`maplibre-particle/rn/13.6.1-particle.22`;Build Source Commit 见 `SOURCE_LOCK.json`。
## 公网制品(NAS 发布)
| 制品 | 获取地址 |
| --- | --- |
| Android AAR | https://pbf.jpcn.ccwu.cc/maven/cc/navsea/maplibre/android-sdk-particle-opengl/13.6.1-particle.22/android-sdk-particle-opengl-13.6.1-particle.22.aar |
| Android POM | https://pbf.jpcn.ccwu.cc/maven/cc/navsea/maplibre/android-sdk-particle-opengl/13.6.1-particle.22/android-sdk-particle-opengl-13.6.1-particle.22.pom |
| Android Gradle Module Metadata | https://pbf.jpcn.ccwu.cc/maven/cc/navsea/maplibre/android-sdk-particle-opengl/13.6.1-particle.22/android-sdk-particle-opengl-13.6.1-particle.22.module |
| RN tgz | https://pbf.jpcn.ccwu.cc/npm/navsea-maplibre-particle-rn-13.6.1-particle.22.tgz |
| iOS Metal XCFramework zip | https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.29.0-particle.22/MapLibre.dynamic.xcframework.zip |
| iOS XCFramework SHA-256 文件 | https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.29.0-particle.22/MapLibre.dynamic.xcframework.zip.sha256 |
完整 SHA-256 以本目录 `SOURCE_LOCK.json` 的 `files[]` 为权威记录。以上文件均已按 NAS 公网重新下载与原始构建文件逐字节比对。
## 使用方法
**Android**:Gradle Maven repository 增加 `https://pbf.jpcn.ccwu.cc/maven`,依赖:
`implementation("cc.navsea.maplibre:android-sdk-particle-opengl:13.6.1-particle.22")`
本版 AAR 采用 OpenGL,不宣称包含 Vulkan 制品。
**React Native**:从上表 RN tgz 的 HTTPS URL 安装 `@navsea/maplibre-particle-rn`;宿主需使用 `@maplibre/maplibre-react-native@11.5.0`。按 package 内 `README.md` 配置 Android Maven、Expo plugin、iOS Podspec/codegen;勿继续锁定 v21 的 `13.4.1` Native。
**iOS**:SwiftPM repository:`https://pbf.jpcn.ccwu.cc/swift/maplibre-particle-spm.git`,选择 exact tag `6.29.0-particle.22`,product `MapLibre`。将 RN iOS 依赖与该同源 Metal binary 按宿主 Post Install 说明接入。
## GSRL 来源核对与接收
1. 从此目录获取 `SOURCE_LOCK.json`,确认项目名、发行版本、Git Remote、完整 `gitCommit` 和 `gitRef`。
2. 按上述 URL 下载所需制品,重新计算各文件 SHA-256,与 `files[]` 逐项比较;确认 Gradle/RN/SwiftPM 依赖版本。
3. SHA 或来源不同不得按本版接收。已发行版本不可覆盖;修正须使用新版本。
## 验证边界
- Mac 统一源码构建、四 ABI Android Release AAR、iOS Metal ios-arm64 XCFramework、RN tgz 与公网逐字节回读:PASS。
- FZG1-2 x86_64/OpenGL Test App 的 STEP-106 粒子/RenderSegment/Renderer/QBIN 定向回归:PASS;该测试不能替代正式 Release AAR 在 NavSea 上的集成测试。
- Android ARM64 实机、RN 11.5.0 宿主整体集成、iOS Metal 真机:**本次未验证,不宣称这些运行环境 PASS**。
- GSRL PASS 仅代表源码与发行文件身份一致、可获取、依赖及说明完整。
## 溯源
- Build Source Commit:`ea5bd393c664a54513531998bf8609a0535639f7`
- 主发行清单:`release/maplibre-particle/release-manifest.json`
- GSRL Source Lock:`release/maplibre-particle/13.6.1-particle.22/SOURCE_LOCK.json`
- 原始构建与发布详细日志位于 Mac 临时工作区 `artifacts/maplibre-particle/`,**不是使用方获取入口**。

View File

@@ -0,0 +1,103 @@
{
"schemaVersion": "gsrl/source-lock/v1",
"project": "MapLibreParticleLab",
"releaseUnit": "Particle unified Android OpenGL / React Native / iOS Metal",
"version": "13.6.1-particle.22",
"versions": {
"android": "13.6.1-particle.22",
"reactNative": "13.6.1-particle.22",
"ios": "6.29.0-particle.22"
},
"source": {
"gitRemote": "https://git.eyaku.jp/tei/MapLibreParticleLab",
"gitCommit": "ea5bd393c664a54513531998bf8609a0535639f7",
"gitRef": "refs/tags/maplibre-particle/rn/13.6.1-particle.22",
"note": "gitCommit 是实际构建所用的冻结源代码提交;发行清单和 GSRL 记录在后续发行提交。发行 Tag 保留完整历史,不要求 Tag 指向的发行记录提交等于构建源码提交。"
},
"files": [
{
"releaseUnit": "android",
"name": "android-sdk-particle-opengl-13.6.1-particle.22.aar",
"location": "https://pbf.jpcn.ccwu.cc/maven/cc/navsea/maplibre/android-sdk-particle-opengl/13.6.1-particle.22/android-sdk-particle-opengl-13.6.1-particle.22.aar",
"sha256": "ed62a67a0882896d3d59f315351d6807941881333494590bc943a858b213a130",
"sizeBytes": 16541912
},
{
"releaseUnit": "android",
"name": "android-sdk-particle-opengl-13.6.1-particle.22.pom",
"location": "https://pbf.jpcn.ccwu.cc/maven/cc/navsea/maplibre/android-sdk-particle-opengl/13.6.1-particle.22/android-sdk-particle-opengl-13.6.1-particle.22.pom",
"sha256": "bf66dad234d763aa9ad7ed17576177219063cd5e2a8ff32593608913bc442b3c",
"sizeBytes": 5687
},
{
"releaseUnit": "android",
"name": "android-sdk-particle-opengl-13.6.1-particle.22.module",
"location": "https://pbf.jpcn.ccwu.cc/maven/cc/navsea/maplibre/android-sdk-particle-opengl/13.6.1-particle.22/android-sdk-particle-opengl-13.6.1-particle.22.module",
"sha256": "a64e1ac9b9562f947b38c0553679c94aba1b912147825fec6aedfa72fd843f43",
"sizeBytes": 6999
},
{
"releaseUnit": "reactNative",
"name": "navsea-maplibre-particle-rn-13.6.1-particle.22.tgz",
"location": "https://pbf.jpcn.ccwu.cc/npm/navsea-maplibre-particle-rn-13.6.1-particle.22.tgz",
"sha256": "dcd30dd64a3d140934f8ea3a042cbac5c0450e0510c017127824d6a1a53557b5",
"sizeBytes": 29008
},
{
"releaseUnit": "ios",
"name": "MapLibre.dynamic.xcframework.zip",
"location": "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.29.0-particle.22/MapLibre.dynamic.xcframework.zip",
"sha256": "79b1b8dcd6c647afc150fc33f0771ae81c3ca0c8be93a9a9fa6cce49a1776670",
"sizeBytes": 4147794
},
{
"releaseUnit": "ios",
"name": "MapLibre.dynamic.xcframework.zip.sha256",
"location": "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.29.0-particle.22/MapLibre.dynamic.xcframework.zip.sha256",
"sha256": "2b5a41897f83b1070c085d07e9e780756fbec599c826dfa3f43d2598751dcfa0",
"sizeBytes": 99
}
],
"dependencies": [
{
"name": "@maplibre/maplibre-react-native",
"version": "11.5.0",
"role": "React Native host peer, iOS MapLibreReactNative Pod"
},
{
"name": "React Native",
"version": ">=0.80.0",
"role": "RN package peer requirement"
},
{
"name": "Expo",
"version": ">=54.0.0 (optional)",
"role": "RN optional peer"
},
{
"name": "Android Native SDK",
"version": "13.6.1-particle.22",
"coordinate": "cc.navsea.maplibre:android-sdk-particle-opengl:13.6.1-particle.22",
"role": "OpenGL AAR, arm64-v8a/armeabi-v7a/x86/x86_64"
},
{
"name": "iOS SwiftPM MapLibre",
"version": "6.29.0-particle.22",
"url": "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle-spm.git",
"role": "Exact version, product MapLibre, Metal ios-arm64"
}
],
"usage": "release/maplibre-particle/13.6.1-particle.22/README.md",
"releaseManifest": "release/maplibre-particle/release-manifest.json",
"status": "RELEASED",
"validation": {
"publicReadback": "PASS",
"buildSourceCommit": "ea5bd393c664a54513531998bf8609a0535639f7",
"androidBuild": "PASS - four ABI OpenGL Release AAR",
"androidDevice": "FZG1-2 x86_64 OpenGL Test App smoke/regression PASS (STEP-106; release AAR separate)",
"androidArm64Device": "NOT_TESTED",
"reactNative115HostIntegration": "NOT_TESTED",
"iosMetalDevice": "NOT_TESTED",
"note": "GSRL verifies source and artifact identity, not runtime certification of every target."
}
}

View File

@@ -9,8 +9,8 @@ let package = Package(
targets: [ targets: [
.binaryTarget( .binaryTarget(
name: "MapLibre", name: "MapLibre",
url: "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.28.0-particle.21/MapLibre.dynamic.xcframework.zip", url: "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.29.0-particle.22/MapLibre.dynamic.xcframework.zip",
checksum: "fd78ed8f504c3d0ee969954f44501719b94e699aa5b160de849e712b32d24f72" checksum: "79b1b8dcd6c647afc150fc33f0771ae81c3ca0c8be93a9a9fa6cce49a1776670"
), ),
] ]
) )

View File

@@ -1,14 +1,14 @@
# MapLibre Particle iOS 发行 # MapLibre Particle iOS 发行
当前正式发行:6.28.0-particle.21 当前正式发行:6.29.0-particle.22
- Renderer:Metal - Renderer:Metal
- Product / Module:MapLibre - Product / Module:MapLibre
- Binary:https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.28.0-particle.21/MapLibre.dynamic.xcframework.zip - Binary:https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.29.0-particle.22/MapLibre.dynamic.xcframework.zip
- SHA-256:fd78ed8f504c3d0ee969954f44501719b94e699aa5b160de849e712b32d24f72 - SHA-256:79b1b8dcd6c647afc150fc33f0771ae81c3ca0c8be93a9a9fa6cce49a1776670
- SwiftPM:https://pbf.jpcn.ccwu.cc/swift/maplibre-particle-spm.git - SwiftPM:https://pbf.jpcn.ccwu.cc/swift/maplibre-particle-spm.git
- Exact Version:6.28.0-particle.21 - Exact Version:6.29.0-particle.22
- Source Commit:16a5d15f164dc93d220e3fac62de66a9c9527ccc - Source Commit:ea5bd393c664a54513531998bf8609a0535639f7
构建命令固定为: 构建命令固定为:

View File

@@ -1,20 +1,20 @@
{ {
"schemaVersion": 2, "schemaVersion": 2,
"status": "PUBLISHED_PUBLIC_READBACK_PASS", "status": "PUBLISHED_PUBLIC_READBACK_PASS",
"distributionVersion": "6.28.0-particle.21", "distributionVersion": "6.29.0-particle.22",
"moduleName": "MapLibre", "moduleName": "MapLibre",
"compilationMode": "opt", "compilationMode": "opt",
"artifact": { "artifact": {
"fileName": "MapLibre.dynamic.xcframework.zip", "fileName": "MapLibre.dynamic.xcframework.zip",
"sizeBytes": 4121573, "sizeBytes": 4147794,
"sha256": "fd78ed8f504c3d0ee969954f44501719b94e699aa5b160de849e712b32d24f72", "sha256": "79b1b8dcd6c647afc150fc33f0771ae81c3ca0c8be93a9a9fa6cce49a1776670",
"url": "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.28.0-particle.21/MapLibre.dynamic.xcframework.zip" "url": "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.29.0-particle.22/MapLibre.dynamic.xcframework.zip"
}, },
"sourceCommit": "16a5d15f164dc93d220e3fac62de66a9c9527ccc", "sourceCommit": "ea5bd393c664a54513531998bf8609a0535639f7",
"swiftPackage": { "swiftPackage": {
"url": "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle-spm.git", "url": "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle-spm.git",
"requirement": "exactVersion", "requirement": "exactVersion",
"version": "6.28.0-particle.21", "version": "6.29.0-particle.22",
"productName": "MapLibre" "productName": "MapLibre"
}, },
"notes": "Metal renderer optimized release built with bazel build -c opt --//:renderer=metal //platform/ios:MapLibre.dynamic" "notes": "Metal renderer optimized release built with bazel build -c opt --//:renderer=metal //platform/ios:MapLibre.dynamic"

View File

@@ -1,49 +1,49 @@
{ {
"schemaVersion": 2, "schemaVersion": 2,
"releaseState": "PUBLISHED_PUBLIC_READBACK_PASS", "releaseState": "PUBLISHED_PUBLIC_READBACK_PASS",
"particleRevision": 21, "particleRevision": 22,
"sourceCommit": "16a5d15f164dc93d220e3fac62de66a9c9527ccc", "sourceCommit": "ea5bd393c664a54513531998bf8609a0535639f7",
"generatedAtUtc": "2026-10-08T04:32:42.009872+00:00", "generatedAtUtc": "2026-10-09T07:14:50.067897+00:00",
"reactNative": { "reactNative": {
"name": "@navsea/maplibre-particle-rn", "name": "@navsea/maplibre-particle-rn",
"version": "13.4.1-particle.21", "version": "13.6.1-particle.22",
"artifact": { "artifact": {
"fileName": "navsea-maplibre-particle-rn-13.4.1-particle.21.tgz", "fileName": "navsea-maplibre-particle-rn-13.6.1-particle.22.tgz",
"sizeBytes": 28965, "sizeBytes": 29008,
"sha256": "8862dda5ad03727967465edea42053c71e59485e45afe7b99ed153d5c0a27eb5", "sha256": "dcd30dd64a3d140934f8ea3a042cbac5c0450e0510c017127824d6a1a53557b5",
"url": "https://pbf.jpcn.ccwu.cc/npm/navsea-maplibre-particle-rn-13.4.1-particle.21.tgz" "url": "https://pbf.jpcn.ccwu.cc/npm/navsea-maplibre-particle-rn-13.6.1-particle.22.tgz"
}, },
"mapLibreReactNative": "11.3.6" "mapLibreReactNative": "11.5.0"
}, },
"android": { "android": {
"version": "13.4.1-particle.21", "version": "13.6.1-particle.22",
"coordinate": "cc.navsea.maplibre:android-sdk-particle-opengl:13.4.1-particle.21", "coordinate": "cc.navsea.maplibre:android-sdk-particle-opengl:13.6.1-particle.22",
"renderer": "opengl", "renderer": "opengl",
"artifact": { "artifact": {
"fileName": "android-sdk-particle-opengl-13.4.1-particle.21.aar", "fileName": "android-sdk-particle-opengl-13.6.1-particle.22.aar",
"sizeBytes": 170777014, "sizeBytes": 16541912,
"sha256": "59248c9a80aafa03da202a2666cfefe919090a16ae21d425370fcf8b39d0898c", "sha256": "ed62a67a0882896d3d59f315351d6807941881333494590bc943a858b213a130",
"url": "https://pbf.jpcn.ccwu.cc/maven/cc/navsea/maplibre/android-sdk-particle-opengl/13.4.1-particle.21/android-sdk-particle-opengl-13.4.1-particle.21.aar" "url": "https://pbf.jpcn.ccwu.cc/maven/cc/navsea/maplibre/android-sdk-particle-opengl/13.6.1-particle.22/android-sdk-particle-opengl-13.6.1-particle.22.aar"
}, },
"ndk": "28.2.13676358", "ndk": "28.2.13676358",
"gradle": "9.5.1", "gradle": "9.5.1",
"jdk": "openjdk version \"17.0.20.1\" 2026-08-18" "jdk": "openjdk version \"17.0.20.1\" 2026-08-18"
}, },
"ios": { "ios": {
"distributionVersion": "6.28.0-particle.21", "distributionVersion": "6.29.0-particle.22",
"renderer": "metal", "renderer": "metal",
"compilationMode": "opt", "compilationMode": "opt",
"moduleName": "MapLibre", "moduleName": "MapLibre",
"artifact": { "artifact": {
"fileName": "MapLibre.dynamic.xcframework.zip", "fileName": "MapLibre.dynamic.xcframework.zip",
"sizeBytes": 4121573, "sizeBytes": 4147794,
"sha256": "fd78ed8f504c3d0ee969954f44501719b94e699aa5b160de849e712b32d24f72", "sha256": "79b1b8dcd6c647afc150fc33f0771ae81c3ca0c8be93a9a9fa6cce49a1776670",
"url": "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.28.0-particle.21/MapLibre.dynamic.xcframework.zip" "url": "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle/6.29.0-particle.22/MapLibre.dynamic.xcframework.zip"
}, },
"swiftPackage": { "swiftPackage": {
"url": "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle-spm.git", "url": "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle-spm.git",
"requirement": "exactVersion", "requirement": "exactVersion",
"version": "6.28.0-particle.21", "version": "6.29.0-particle.22",
"productName": "MapLibre" "productName": "MapLibre"
}, },
"xcode": "Xcode 26.3 Build version 17C529 ", "xcode": "Xcode 26.3 Build version 17C529 ",

View File

@@ -77,7 +77,7 @@ def main() -> None:
"name": "@navsea/maplibre-particle-rn", "name": "@navsea/maplibre-particle-rn",
"version": android_version, "version": android_version,
"artifact": tgz, "artifact": tgz,
"mapLibreReactNative": "11.3.6", "mapLibreReactNative": json.loads((ROOT / "packages/maplibre-particle-rn/package.json").read_text())["peerDependencies"]["@maplibre/maplibre-react-native"],
}, },
"android": { "android": {
"version": android_version, "version": android_version,

View File

@@ -20,14 +20,20 @@ def base_version(value: str) -> str:
return re.sub(r"-particle\.\d+$", "", value.strip()) return re.sub(r"-particle\.\d+$", "", value.strip())
def replace_current_particle(path: Path, base: str, target: str) -> None: def replace_current_particle(path: Path, previous: str, target: str) -> None:
text = path.read_text() text = path.read_text()
pattern = rf"{re.escape(base)}-particle\.\d+" updated, count = re.subn(re.escape(previous), target, text)
updated, count = re.subn(pattern, target, text)
if count == 0: if count == 0:
die(f"no particle version reference found in {path}") die(f"previous RN/Native version {previous} not found in {path}")
path.write_text(updated) path.write_text(updated)
def replace_exact(path: Path, old: str, new: str) -> None:
text = path.read_text()
if text.count(old) != 1:
die(f"expected exactly one version reference {old!r} in {path}")
path.write_text(text.replace(old, new, 1))
def update_changelog(target: str, revision: int) -> None: def update_changelog(target: str, revision: int) -> None:
path = RN_ROOT / "CHANGELOG.md" path = RN_ROOT / "CHANGELOG.md"
text = path.read_text() text = path.read_text()
@@ -64,7 +70,11 @@ def main() -> None:
package_path = RN_ROOT / "package.json" package_path = RN_ROOT / "package.json"
package = json.loads(package_path.read_text()) package = json.loads(package_path.read_text())
previous_rn_version = package["version"]
package["version"] = android_version package["version"] = android_version
# v22 upgrades the host MapLibre React Native baseline together with native.
package["peerDependencies"]["@maplibre/maplibre-react-native"] = "11.5.0"
package["devDependencies"]["@maplibre/maplibre-react-native"] = "11.5.0"
package_path.write_text(json.dumps(package, ensure_ascii=False, indent=2) + "\n") package_path.write_text(json.dumps(package, ensure_ascii=False, indent=2) + "\n")
for relative in ( for relative in (
@@ -72,15 +82,14 @@ def main() -> None:
"packages/maplibre-particle-rn/app.plugin.js", "packages/maplibre-particle-rn/app.plugin.js",
"integration/react-native/MapLibreParticleRNTestHost/plugins/withParticleNativeAndroid.js", "integration/react-native/MapLibreParticleRNTestHost/plugins/withParticleNativeAndroid.js",
): ):
replace_current_particle(ROOT / relative, android_base, android_version) replace_current_particle(ROOT / relative, previous_rn_version, android_version)
readme = RN_ROOT / "README.md" readme = RN_ROOT / "README.md"
readme_text = readme.read_text() readme_text = readme.read_text()
readme_text = re.sub( if previous_rn_version not in readme_text:
rf"{re.escape(android_base)}-particle\.\d+", die("README missing previous RN version")
android_version, readme_text = readme_text.replace(previous_rn_version, android_version)
readme_text, readme_text = readme_text.replace("11.3.6", "11.5.0")
)
readme_text = re.sub( readme_text = re.sub(
r"必须指向同一 `\.\d+`", r"必须指向同一 `\.\d+`",
f"必须指向同一 `.{revision}`", f"必须指向同一 `.{revision}`",
@@ -88,6 +97,26 @@ def main() -> None:
) )
readme.write_text(readme_text) readme.write_text(readme_text)
# Both Expo plugins must request the same upstream Native base as the new AAR.
for relative in (
"packages/maplibre-particle-rn/app.plugin.js",
"integration/react-native/MapLibreParticleRNTestHost/plugins/withParticleNativeAndroid.js",
):
replace_exact(ROOT / relative,
'nativeVersion", "13.4.1"',
f'nativeVersion", "{android_base}"')
podspec = RN_ROOT / "MapLibreParticleRN.podspec"
podtext = podspec.read_text()
if podtext.count('11.3.6') != 2:
die("podspec must contain exactly two pinned RN 11.3.6 references")
podspec.write_text(podtext.replace("11.3.6", "11.5.0"))
host_path = ROOT / "integration/react-native/MapLibreParticleRNTestHost/package.json"
host = json.loads(host_path.read_text())
host["dependencies"]["@maplibre/maplibre-react-native"] = "11.5.0"
host_path.write_text(json.dumps(host, ensure_ascii=False, indent=2) + "\n")
update_changelog(android_version, revision) update_changelog(android_version, revision)
print(f"PARTICLE_REVISION={revision}") print(f"PARTICLE_REVISION={revision}")

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations from __future__ import annotations
import json
import subprocess import subprocess
import sys import sys
from pathlib import Path from pathlib import Path
@@ -8,6 +9,7 @@ from pathlib import Path
PUBLIC_ROOT = "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle" PUBLIC_ROOT = "https://pbf.jpcn.ccwu.cc/swift/maplibre-particle"
GIT_REMOTE = "nas:/volume1/work/pbf/swift/maplibre-particle-spm.git" GIT_REMOTE = "nas:/volume1/work/pbf/swift/maplibre-particle-spm.git"
WORK = Path.home() / "dev/MapLibreParticleDistribution" WORK = Path.home() / "dev/MapLibreParticleDistribution"
ROOT = Path(__file__).resolve().parents[2]
def run(*args: str, cwd: Path | None = None) -> str: def run(*args: str, cwd: Path | None = None) -> str:
@@ -26,6 +28,8 @@ def main() -> None:
if len(sys.argv) != 3: if len(sys.argv) != 3:
raise SystemExit("usage: publish_swiftpm.py <ios-version> <zip-sha256>") raise SystemExit("usage: publish_swiftpm.py <ios-version> <zip-sha256>")
version, checksum = sys.argv[1], sys.argv[2] version, checksum = sys.argv[1], sys.argv[2]
rn_pkg = json.loads((ROOT / "packages/maplibre-particle-rn/package.json").read_text())
rn_version = rn_pkg["peerDependencies"]["@maplibre/maplibre-react-native"]
if not WORK.exists(): if not WORK.exists():
run("git", "clone", GIT_REMOTE, str(WORK)) run("git", "clone", GIT_REMOTE, str(WORK))
@@ -66,7 +70,7 @@ let package = Package(
(WORK / "README.md").write_text( (WORK / "README.md").write_text(
"# MapLibre Particle SwiftPM Distribution\n\n" "# MapLibre Particle SwiftPM Distribution\n\n"
"该仓库只保存 NavSea MapLibre Particle iOS binary distribution 的 SwiftPM manifest。\n" "该仓库只保存 NavSea MapLibre Particle iOS binary distribution 的 SwiftPM manifest。\n"
"产品和模块名固定为 MapLibre,供 MapLibre React Native 11.3.6 消费。\n\n" f"产品和模块名固定为 MapLibre,供 MapLibre React Native {rn_version} 消费。\n\n"
f"当前版本:{version}。\n" f"当前版本:{version}。\n"
f"对应 binary:{url}\n" f"对应 binary:{url}\n"
) )

View File

@@ -73,6 +73,8 @@ prepare_release() {
packages/maplibre-particle-rn/app.plugin.js \ packages/maplibre-particle-rn/app.plugin.js \
packages/maplibre-particle-rn/README.md \ packages/maplibre-particle-rn/README.md \
packages/maplibre-particle-rn/CHANGELOG.md \ packages/maplibre-particle-rn/CHANGELOG.md \
packages/maplibre-particle-rn/MapLibreParticleRN.podspec \
integration/react-native/MapLibreParticleRNTestHost/package.json \
integration/react-native/MapLibreParticleRNTestHost/plugins/withParticleNativeAndroid.js integration/react-native/MapLibreParticleRNTestHost/plugins/withParticleNativeAndroid.js
if ! git -C "$ROOT" diff --cached --quiet; then if ! git -C "$ROOT" diff --cached --quiet; then
git -C "$ROOT" commit -m "release: prepare unified particle.$REV" git -C "$ROOT" commit -m "release: prepare unified particle.$REV"
@@ -145,7 +147,10 @@ publish_release() {
local remote_aar_sha remote_rn_sha remote_ios_sha local remote_aar_sha remote_rn_sha remote_ios_sha
local pom_name module_name local pom_name module_name
source_commit="$(git -C "$ROOT" rev-parse HEAD)" source_commit="${PARTICLE_RELEASE_SOURCE_COMMIT:-$(git -C "$ROOT" rev-parse HEAD)}"
[[ "$source_commit" =~ ^[0-9a-f]{40}$ ]] || die "invalid frozen release source SHA"
git -C "$ROOT" cat-file -e "$source_commit^{commit}" || die "release source commit unavailable"
git -C "$ROOT" merge-base --is-ancestor "$source_commit" HEAD || die "release source commit is not an ancestor of current HEAD"
android_root="/volume1/work/pbf/maven/cc/navsea/maplibre/android-sdk-particle-opengl" android_root="/volume1/work/pbf/maven/cc/navsea/maplibre/android-sdk-particle-opengl"
android_final="$android_root/$ANDROID_VERSION" android_final="$android_root/$ANDROID_VERSION"
android_tmp="$android_root/.$ANDROID_VERSION.uploading" android_tmp="$android_root/.$ANDROID_VERSION.uploading"