Files
duooomi-ble-sdk/BUILD_ISSUES.md
2026-04-08 15:36:13 +08:00

194 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 构建问题记录
## 问题 1expo prebuild 报 EEXIST 目录冲突
**现象**`npx expo prebuild --platform ios` 报错 `EEXIST: file already exists, mkdir 'ios/DuooomiBleSDK'`
**原因**macOS 文件系统大小写不敏感。Expo prebuild 先创建 `ios/duooomiblesdk`(小写),然后 expo-brownfield 插件尝试创建 `ios/DuooomiBleSDK`(驼峰),被视为同一目录导致 EEXIST。
**修复**patch `expo-brownfield``plugin/build/ios/utils/filesystem.js`,将 `mkdir``recursive` 参数默认值改为 `true`
```js
// 修改前
const mkdir = (path, recursive = false) => {
// 修改后
const mkdir = (path, recursive = true) => {
```
**注意**:这是 node_modules 内的 patch`pnpm install` 后会丢失。如需持久化,使用 `pnpm patch expo-brownfield`
---
## 问题 2CocoaPods ffi_c 加载失败
**现象**`pod install` 报错 `LoadError - cannot load such file -- ffi_c`
**原因**:终端运行在 Rosetta2 x86_64 模拟环境下,导致 Ruby gem 的原生扩展ffi、nkf架构与解释器不匹配。
**修复**:强制使用 arm64 原生架构运行:
```bash
env /usr/bin/arch -arm64 /bin/bash --login -c 'source ~/.rvm/scripts/rvm && rvm use 2.7.5 && pod install --project-directory=ios'
```
---
## 问题 3Xcode 26 编译 fmt 库失败(已解决)
**现象**`BUILD FAILED`,错误为 `call to consteval function ... is not a constant expression`,出现在 `fmt/format-inl.h`
**原因**Xcode 26 的 Apple Clang 17+ 声明支持 `__cpp_consteval`fmt 11.0.2 据此启用 `consteval` 关键字,但编译器实现存在 bug 导致编译失败。
**修复**patch `ios/Pods/fmt/include/fmt/base.h`,在 consteval 检测逻辑中禁用 Apple Clang 17+
```c
// 在 __apple_build_version__ < 14000029L 判断之后添加:
#elif defined(__apple_build_version__) && __apple_build_version__ >= 17000000L
# define FMT_USE_CONSTEVAL 0 // consteval is broken in Apple clang 17+ (Xcode 26).
```
**注意**`pod install` 会重新下载 Pods此 patch 需要在每次 pod install 后重新应用。
---
## 问题 4签名错误已解决
**现象**`Signing for "duooomiblesdk" requires a development team`
**原因**Expo Brownfield 构建过程会编译宿主 App targetXcode 对 App target 强制要求签名。
**修复**xcodebuild 参数中加 `CODE_SIGNING_ALLOWED=NO`
---
## 问题 5RCTAppDependencyProvider.h 缺失(已解决)
**现象**`The file "RCTAppDependencyProvider.h" couldn't be opened because there is no such file`
**原因**React Native codegen 没有自动运行,需要手动触发。
**前置依赖**
```bash
pnpm add -D @react-native-community/cli
```
**修复**:在构建前手动运行 codegen
```bash
npx react-native codegen --platform ios --outputPath ios
```
---
## 问题 6Xcode 16 不兼容 Expo SDK 55已确认
**现象**`unknown attribute 'MainActor'` 等 Swift 编译错误
**原因**Expo SDK 55 的 `expo-modules-core` 使用了 Swift 6 特性,需要 Xcode 26 的 Swift 编译器。Xcode 16 只有 Swift 5.x无法编译。
**结论**:必须使用 Xcode 26不能降级到 Xcode 16。配合问题 3 的 fmt patch 解决 C++ 兼容性。
---
## 构建完整流程(已验证通过)
```bash
# 1. 安装依赖
pnpm install
# 2. Patch expo-brownfield mkdir每次 pnpm install 后需重做)
# 文件node_modules/.pnpm/expo-brownfield@.../plugin/build/ios/utils/filesystem.js
# 修改recursive = false → recursive = true
# 3. Prebuild
rm -rf ios
npx expo prebuild --platform ios
# prebuild 内部的 pod install 会因 ffi 失败,忽略
# 4. Pod installarm64 环境)
env /usr/bin/arch -arm64 /bin/bash --login -c 'source ~/.rvm/scripts/rvm && rvm use 2.7.5 && pod install --project-directory=ios'
# 5. Patch fmt consteval每次 pod install 后需重做)
# 文件ios/Pods/fmt/include/fmt/base.h
# 在 __apple_build_version__ < 14000029L 判断后添加 >= 17000000L 的判断
# 6. 运行 codegen
npx react-native codegen --platform ios --outputPath ios
# 7. 构建真机 + 模拟器(使用 DEVELOPER_DIR 指定 Xcode 26无需 sudo 切换)
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
# 真机
xcodebuild -workspace ios/duooomiblesdk.xcworkspace -scheme DuooomiBleSDK \
-derivedDataPath ios/build -sdk iphoneos -arch arm64 \
-configuration Release CODE_SIGNING_ALLOWED=NO
# 模拟器
xcodebuild -workspace ios/duooomiblesdk.xcworkspace -scheme DuooomiBleSDK \
-derivedDataPath ios/build -sdk iphonesimulator -arch arm64 -arch x86_64 \
-configuration Release CODE_SIGNING_ALLOWED=NO
# 8. 合并为 XCFramework
xcodebuild -create-xcframework \
-framework ios/build/Build/Products/Release-iphoneos/DuooomiBleSDK.framework \
-framework ios/build/Build/Products/Release-iphonesimulator/DuooomiBleSDK.framework \
-output artifacts/DuooomiBleSDK.xcframework
# 9. 产物(约 75MB
# artifacts/DuooomiBleSDK.xcframework (约 75MB)
# ├── ios-arm64/ ← 真机
# ├── ios-arm64_x86_64-simulator/ ← 模拟器
# └── Info.plist
```
---
## 问题 7运行时 hermesvm.framework 缺失(已解决)
**现象**App 启动 crash`dyld: Library not loaded: @rpath/hermesvm.framework/hermesvm`
**原因**`DuooomiBleSDK.framework` 动态链接 `hermesvm.framework`Hermes JS 引擎),但构建 XCFramework 时只输出了 SDK 本身,没有包含 Hermes。
**修复**:将 `hermesvm.xcframework` 也复制到产物目录,宿主 App 需要同时嵌入两个 framework
```bash
# 复制 hermesvm 到 artifacts
cp -R ios/Pods/hermes-engine/destroot/Library/Frameworks/universal/hermesvm.xcframework artifacts/
# 宿主 App 的 project.yml 中添加:
dependencies:
- framework: path/to/DuooomiBleSDK.xcframework
embed: true
- framework: path/to/hermesvm.xcframework
embed: true
```
---
## CLAUDE.md 与实际代码的偏差
CLAUDE.md 中描述的 API 设计意图与 BleSDK.ts 实际实现存在以下差异,后续需要统一:
### 状态 key 不一致
CLAUDE.md 设计为单个 `deviceState` 对象,但实际实现使用多个独立 key
- `btState` — 连接状态
- `connectedDevice` — 已连接设备
- `deviceInfo` — 设备详情
- `version` — 固件版本
- `isActivated` — 是否激活
- `transferProgress` — 传输进度
- `error` — 错误信息
- `discoveredDevices` — 发现的设备列表
### Action 名称不一致
| CLAUDE.md 描述 | 实际代码 |
|---|---|
| `init` | 无此 actionSDK 在 RN mount 时自动初始化 |
| `syncFile` | `transferFile`(参数为 `{ fileUri, commandType }`|
| connect 内自动 bind | `bind` 是独立 action |
| connect 内自动 getInfo | `getDeviceInfo` / `getVersion` 是独立 action |
### 集成注意事项
1. 必须显式调用 `ReactNativeHostManager.shared.initialize()``ExpoBrownfieldAppDelegate` 不会自动调用
2. 必须加载 `ReactNativeView`(即使隐藏),否则 JS 运行时不启动sendMessage 无人接收
3. `BrownfieldState.subscribe` 返回的 `AnyCancellable` 必须持有引用,否则订阅立即失效
4. subscribe 回调在 RN 桥接线程,更新 UI 需手动 `DispatchQueue.main.async`