fix(ios): load RCTDefines.h first in React umbrella + drop submodule wildcard so RCT_* macros stay visible#56862
Closed
wneel wants to merge 1 commit into
Closed
Conversation
…wildcard so RCT_* macros stay visible
This was referenced May 16, 2026
cipolleschi
approved these changes
May 18, 2026
Contributor
cipolleschi
left a comment
There was a problem hiding this comment.
Thanks for fixing this
|
@cipolleschi has imported this pull request. If you are a Meta employee, you can view this in D105582598. |
Contributor
Author
|
Thanks for the quick review and import! Happy this one lands cleanly :) |
cortinico
approved these changes
May 18, 2026
Contributor
cortinico
left a comment
There was a problem hiding this comment.
Review automatically exported from Phabricator review in Meta.
|
@cipolleschi merged this pull request in 90c303f. |
Collaborator
|
This pull request was successfully merged by @wneel in 90c303f When will my fix make it into a release? | How to file a pick request? |
This was referenced May 18, 2026
react-native-bot
pushed a commit
that referenced
this pull request
May 21, 2026
…wildcard so RCT_* macros stay visible (#56862) Summary: When `RCT_USE_PREBUILT_RNCORE=1` (the 0.84+ default) and a consumer pod builds under `use_frameworks!`, RCT macros like `RCT_EXTERN`, `RCT_EXTERN_C_BEGIN`, `RCT_EXPORT_METHOD`, `RCT_REMAP_METHOD` fail to propagate. The `.m` files using these macros hit cascading parse errors like : - `unknown type name 'RCT_EXTERN_C_BEGIN'` in `<React/RCTBridgeModule.h>` line 51, - `unknown type name 'RCT_EXTERN'` in `<React/RCTEventDispatcherProtocol.h>` line 17, - and `type specifier missing, defaults to 'int'` on every `RCT_EXPORT_METHOD(...)` call site. Root cause is in two places in `packages/react-native/scripts/ios-prebuild/templates/`: 1. `React-umbrella.h` orders `RCTBridgeConstants.h` (line 56) before `RCTDefines.h` (line 84). `RCTBridgeConstants.h` uses `RCT_EXTERN` at its first declaration but the macro is only defined later in `RCTDefines.h`. When the umbrella is loaded as a single parse context, the `RCT_EXTERN` use is unresolvable. 2. `module.modulemap` declares `module * { export * }` inside both `framework module` blocks, which creates an inferred submodule per header. That isolates macro `#define`s into per-header parse scopes. Even fixing the umbrella order, sibling submodules don't share macros: macros defined in the `RCTDefines.h` submodule are invisible to the `RCTBridgeConstants.h` submodule, and to consumers of the `React` module. This PR fixes both: - Move `#import <React/RCTDefines.h>` to the very top of the umbrella (right after the prologue and before any other `<React/...>` import), with a comment explaining why ordering matters. - Remove the `module * { export * }` wildcard from both `framework module` blocks in the modulemap. The umbrella header alone is sufficient to declare the module's contents, and dropping the wildcard means the whole module shares one parse context where macros propagate. The combination of `use_frameworks!` + prebuilt RNCore is the path of least resistance today: `use_frameworks!` is the Expo default and is required by `firebase-ios-sdk` for its Swift bridges. Prebuilt RNCore is the 0.84+ default. The colliding defaults break native-module ecosystems like `react-native-firebase` that consume the RCT macros. Producer-side fix is in flight at invertase/react-native-firebase#9024; this PR closes the consumer side. ## Changelog: [IOS] [FIXED] - Load `RCTDefines.h` first in the prebuilt React umbrella and drop the `module *` submodule wildcard so RCT_* macros propagate to consumer pods under `use_frameworks!`. Pull Request resolved: #56862 Test Plan: Reproduced on RN 0.85.3 (latest stable at time of writing) on macOS 26.3.1 / Xcode 26.5 / iOS 26.5 Simulator (iPhone 17 Pro). **Reproducer setup** Fork of `mikehardy/rnfbdemo` with these adjustments in `make-demo.sh`: - `RN_VER=0.85.3` - `RNFB_VER=24.0.0` - `FB_IOS_VER=12.10.0` - Remove `react-native-firebase/dynamic-links` from the bulk yarn add (deprecated and removed in RNFB 24.x). Default Podfile mods produced by `make-demo.sh` are preserved: `use_frameworks! :linkage => :static` + `$RNFirebaseAsStaticFramework = true`. No `RCT_USE_PREBUILT_RNCORE` override (stays at the `1` default). Public reproducer: https://github.com/wneel/rnfbdemo (see its `REPRO.md` for the two-stage flow). The reproducer also has invertase/react-native-firebase#9024 (producer-side podspec fixes) applied as an overlay. Without those, the build fails earlier at `-Wnon-modular-include-in-framework-module`. With them applied, the build progresses to the consumer side and surfaces the macro propagation bug this PR fixes. **Before this PR** Same reproducer config. iOS build fails on consumer pods (RNFBAuth, RNFBStorage, RNFBMessaging) with: ``` .../Pods/Headers/Public/React-Core/React/RCTEventDispatcherProtocol.h:17:1: error: unknown type name 'RCT_EXTERN' .../Pods/Headers/Public/React-Core/React/RCTEventDispatcherProtocol.h:17:27: error: expected ';' after top level declarator .../node_modules/react-native-firebase/messaging/ios/RNFBMessaging/RNFBMessaging+AppDelegate.h:26:21: error: declaration of 'RCTPromiseRejectBlock' must be imported from module 'RNFBApp.RNFBAppModule' before it is required ``` **After this PR** Same reproducer config builds cleanly: `pod install` clean, `xcodebuild` Debug build produces the app, zero `RCT_EXTERN` macro errors anywhere in the log. Verified by editing `packages/react-native/scripts/ios-prebuild/templates/React-umbrella.h` and `packages/react-native/scripts/ios-prebuild/templates/module.modulemap` in place (the diff in this PR), regenerating the prebuilt React.xcframework artifact, and re-running the reproducer. **Output of `npx react-native-community/cli info` from the reproducer environment:** ``` System: OS: macOS 26.3.1 CPU: (10) arm64 Apple M2 Pro Memory: 466.16 MB / 16.00 GB Shell: version: "5.9" path: /bin/zsh Binaries: Node: version: 22.14.0 path: /usr/local/bin/node Yarn: version: 3.6.4 path: /usr/local/bin/yarn npm: version: 11.12.1 path: /usr/local/bin/npm Watchman: version: 2026.05.11.00 path: /opt/homebrew/bin/watchman Managers: CocoaPods: version: 1.16.2 path: /opt/homebrew/bin/pod SDKs: iOS SDK: Platforms: - DriverKit 25.5 - iOS 26.5 - macOS 26.5 - tvOS 26.5 - visionOS 26.5 - watchOS 26.5 IDEs: Xcode: version: 26.5/17F42 path: /usr/bin/xcodebuild Languages: Java: version: 21.0.9 path: /usr/bin/javac ``` **Cross-references** - `react-native-firebase` producer-side fix in flight: invertase/react-native-firebase#9024 - `react-native-firebase` `.m` import hygiene follow-up: invertase/react-native-firebase#9026 - Original RNFB user-facing issue: invertase/react-native-firebase#8883 Reviewed By: cortinico Differential Revision: D105582598 Pulled By: cipolleschi fbshipit-source-id: ab364d46fc94d64274197cdd717a06e425a9324f
Collaborator
|
This pull request was successfully merged by @wneel in ff2562e When will my fix make it into a release? | How to file a pick request? |
qq382724935
added a commit
to unif-design/react-native-umeng
that referenced
this pull request
May 27, 2026
CI build-ios 一直挂 'memory' file not found,本地复现也一致。 根因:RN 0.85.3 默认开 RCT_USE_PREBUILT_RNCORE 时,React-umbrella.h 把 RCTBridgeConstants.h 放在 RCTDefines.h 之前,且 module.modulemap 用 wildcard 把每个 header 隔离成 sub-module —— ReactCodegen 编译 .cpp 时找不到 <memory> 等 C++ stdlib header(facebook/react-native#56862)。 修复路径 —— 临时禁掉 prebuilt(从源码编译 React-Core),等 0.85.4 含 PR #56862 后再恢复: - ci.yml build-ios: RCT_USE_RN_DEP=0 + RCT_USE_PREBUILT_RNCORE=0 - example/ios/Podfile: 撤销之前加的 CLANG_CXX_LIBRARY workaround (根因找到后不再需要 hack) 本地用 RCT_USE_PREBUILT_RNCORE=0 重 pod install 后跑 build:ios 通过, 生成 ReactNativeUmengExample.app 成功。 参考: - facebook/react-native#56862 (fix backport to 0.84/0.85) - invertase/react-native-firebase#8883 (workaround 推荐) - expo/expo#35517 (同问题,同根因)
qq382724935
added a commit
to unif-design/react-native-umeng
that referenced
this pull request
May 27, 2026
之前禁 prebuilt(RCT_USE_PREBUILT_RNCORE=0) 绕开 'memory' file not found, 代价是 CI 每次从源码编译 React-Core 慢 5-10 分钟。改成原地 patch prebuilt xcframework 里的 React-umbrella.h + module.modulemap (facebook/react-native#56862 改的 ios-prebuild/templates/)。 变更: - example/ios/Podfile post_install: ruby patch 把 RCTDefines.h 移到 RCTBridgeConstants.h 之前 + 删 modulemap wildcard sub-module - ci.yml build-ios: RCT_USE_PREBUILT_RNCORE=1, RCT_USE_RN_DEP=1 恢复 本地验证: prebuilt+patch 模式 yarn build:ios 成功生成 .app,零 'memory' file not found 报错。 清理时机: RN 0.86.0 stable (rc.2 已验证含 fix) → 升 RN + 删 patch。
qq382724935
added a commit
to unif-design/react-native-umeng
that referenced
this pull request
May 27, 2026
只升 example 端的 react-native + @react-native/* 配套包,library peerDependencies 仍写 *,不影响下游用户的 RN 版本选择。 RN 0.86.0-rc.2 已含 facebook/react-native#56862 fix(prebuilt xcframework 里 React-umbrella.h 把 RCTDefines.h 提前 + 删 modulemap wildcard sub-module),所以可以直接走 prebuilt 不再 需要 post_install patch。 变更: - example/package.json: react-native + 4 个 @react-native/* 从 0.85.3 升 0.86.0-rc.2 - example/ios/Podfile: 删 PR #56862 ruby patch 整段 - example/ios/...pbxproj: pod install 自动加 PODFILE_DIR build setting 本地验证: - yarn typecheck 干净, 38/38 jest 测试通过 - pod install 成功, prebuilt umbrella + modulemap 自带 fix - yarn build:ios (RCT_USE_PREBUILT_RNCORE=1) 成功生成 ReactNativeUmengExample.app,零 'memory' file not found 清理时机: RN 0.86 stable 出来后,把 example 升到 0.86.x (去掉 -rc.2 后缀)。
qq382724935
added a commit
to unif-design/react-native-umeng
that referenced
this pull request
May 28, 2026
* feat(types): export PLATFORM_BRAND_COLORS for ShareSheet leading tile 把微信 (#07C160) 和钉钉 (#2595E8) 品牌色从 PlatformLeading hardcode 抽出, 作为 PLATFORM_BRAND_COLORS 公开导出。消费者 (宿主 App / 自定义 UI) 也能复用 品牌色与 ShareSheet 视觉一致。 * chore: release-it 启用 changelog 落盘到 CHANGELOG.md * fix(build): wire codegen on Android library + workaround C++ stdlib on iOS - android/build.gradle: apply 'com.facebook.react' plugin 让 example app autolinking 时触发 codegen 生成 NativeUmengXxxSpec 抽象基类,否则 compileDebugKotlin 报 Unresolved reference 'NativeUmengCommonSpec' 等 - example/ios/Podfile: post_install 强制设 CLANG_CXX_LIBRARY=libc++ + c++20 + -stdlib=libc++,绕开 Xcode 26 + RN 0.85.3 ReactCodegen .cpp 文件找不到 <memory> 的环境兼容问题 * fix(ci): disable prebuilt RNCore on iOS — RN 0.85.3 + Xcode 26 incompat CI build-ios 一直挂 'memory' file not found,本地复现也一致。 根因:RN 0.85.3 默认开 RCT_USE_PREBUILT_RNCORE 时,React-umbrella.h 把 RCTBridgeConstants.h 放在 RCTDefines.h 之前,且 module.modulemap 用 wildcard 把每个 header 隔离成 sub-module —— ReactCodegen 编译 .cpp 时找不到 <memory> 等 C++ stdlib header(facebook/react-native#56862)。 修复路径 —— 临时禁掉 prebuilt(从源码编译 React-Core),等 0.85.4 含 PR #56862 后再恢复: - ci.yml build-ios: RCT_USE_RN_DEP=0 + RCT_USE_PREBUILT_RNCORE=0 - example/ios/Podfile: 撤销之前加的 CLANG_CXX_LIBRARY workaround (根因找到后不再需要 hack) 本地用 RCT_USE_PREBUILT_RNCORE=0 重 pod install 后跑 build:ios 通过, 生成 ReactNativeUmengExample.app 成功。 参考: - facebook/react-native#56862 (fix backport to 0.84/0.85) - invertase/react-native-firebase#8883 (workaround 推荐) - expo/expo#35517 (同问题,同根因) * chore(deps): bump @unif/react-native-design ^0.2.0 -> ^0.3.0 * ci: align github actions automation with @unif/react-native-design 0.3.0 - 加 .github/workflows/pr-agent.yml: PR Agent + DeepSeek 自动 review (走 org 级 reusable workflow unif-design/.github/.github/workflows/pr-agent.yml) - 加 .pr_agent.toml: umeng 项目特有 review 规则 (TurboModule 三端同步 / PIPL / 错误码 / 友盟拼写陷阱 / U-Share UI thread) - ci.yml + release.yml 升级 actions 版本: - actions/checkout v5.0.0 -> v6.0.2 - actions/cache v4.2.3 -> v5.0.5 - actions/setup-java v4.7.1 -> v5.2.0 需要 repo secret: DEEPSEEK_API_KEY (从 design 同款配置) * perf(ci): patch prebuilt RNCore instead of disabling — saves 5-10 min 之前禁 prebuilt(RCT_USE_PREBUILT_RNCORE=0) 绕开 'memory' file not found, 代价是 CI 每次从源码编译 React-Core 慢 5-10 分钟。改成原地 patch prebuilt xcframework 里的 React-umbrella.h + module.modulemap (facebook/react-native#56862 改的 ios-prebuild/templates/)。 变更: - example/ios/Podfile post_install: ruby patch 把 RCTDefines.h 移到 RCTBridgeConstants.h 之前 + 删 modulemap wildcard sub-module - ci.yml build-ios: RCT_USE_PREBUILT_RNCORE=1, RCT_USE_RN_DEP=1 恢复 本地验证: prebuilt+patch 模式 yarn build:ios 成功生成 .app,零 'memory' file not found 报错。 清理时机: RN 0.86.0 stable (rc.2 已验证含 fix) → 升 RN + 删 patch。 * chore(example): bump RN 0.85.3 -> 0.86.0-rc.2 (drops Podfile patch) 只升 example 端的 react-native + @react-native/* 配套包,library peerDependencies 仍写 *,不影响下游用户的 RN 版本选择。 RN 0.86.0-rc.2 已含 facebook/react-native#56862 fix(prebuilt xcframework 里 React-umbrella.h 把 RCTDefines.h 提前 + 删 modulemap wildcard sub-module),所以可以直接走 prebuilt 不再 需要 post_install patch。 变更: - example/package.json: react-native + 4 个 @react-native/* 从 0.85.3 升 0.86.0-rc.2 - example/ios/Podfile: 删 PR #56862 ruby patch 整段 - example/ios/...pbxproj: pod install 自动加 PODFILE_DIR build setting 本地验证: - yarn typecheck 干净, 38/38 jest 测试通过 - pod install 成功, prebuilt umbrella + modulemap 自带 fix - yarn build:ios (RCT_USE_PREBUILT_RNCORE=1) 成功生成 ReactNativeUmengExample.app,零 'memory' file not found 清理时机: RN 0.86 stable 出来后,把 example 升到 0.86.x (去掉 -rc.2 后缀)。 * docs: add docusaurus website + lefthook + align org automation 同步 design 仓库 #13/#14/#15/#16: - website/: docusaurus 3.10 workspace (intro + share-sheet), RNW plugin alias @unif/react-native-umeng -> ../src/index.ts - .github/workflows/deploy-docs.yml: build + deploy 到 https://unif-design.github.io/react-native-umeng/ - lefthook.yml + devDep: pre-commit eslint/tsc + commit-msg commitlint - CONTRIBUTING.md: 链接到 org AUTOMATION.md,删冗余 - tsconfig.json + eslint.config.mjs: exclude / ignore website - .gitignore: website/.docusaurus + website/build 本地验证: yarn workspace ...-website build 成功生成 static files, yarn typecheck + 38/38 jest 通过。 * docs: 把 homepage / readme 指向 docs 站 - package.json#homepage: github repo readme -> 文档站 https://unif-design.github.io/react-native-umeng/ npm registry 包页面 'Homepage' 链接自动用这个(下次发版生效) - README.md 顶部加显眼链接到文档站 + npm * fix(ci): tsconfig.build exclude website + restore Podfile RNCore patch build-library CI 挂: tsconfig.build.json 自己的 exclude 覆盖了父 tsconfig 的 exclude (TypeScript 不合并),没把 website 排除 → bob build typescript target 扫到 website/src/*.tsx 报 22 个 type 错。 build-ios CI 挂: RN 0.86.0-rc.2 prebuilt 自带 PR #56862 fix,但 CI macos-latest Xcode 26 上仍报 ReactCodegen .cpp 'memory' file not found, 本地 Xcode 26.5 复现不出。先恢复 Podfile post_install 的 umbrella + modulemap 二次 patch 兜底,带 marker idempotent,RN 已含 fix 时自动跳过。 修复: - tsconfig.build.json: exclude 加 'website' (对齐 design) - example/ios/Podfile post_install: 加回 React-umbrella.h + modulemap patch,带 marker 检测避免重复修 * fix(ci): disable prebuilt RNCore on iOS — Xcode 26.3 stdlib incompat GitHub macos-15 runner 上 Xcode 26 系列最高 26.3,本地 Xcode 26.5 能跑 prebuilt 模式,CI 26.3 上 ReactCodegen .cpp 仍报 'memory' file not found —— C++ stdlib include path 在 26.3 配置不全 (跟 React umbrella / modulemap 无关,PR #56862 patch 治不了)。 回到从源码编译 React-Core 方案 (commit e996bb2 已验证过): CI 多 5-10 分钟但 100% 稳。本地开发保留 prebuilt=1 + Podfile patch 走 快路径,patch 带 marker 在 RN ≥ 0.86 自带 fix 时自动跳过。 清理时机: GitHub runner 出 Xcode 26.5(或 stdlib 配置补全的子版本) 后,把 ci.yml 改回 RCT_USE_PREBUILT_RNCORE=1。 * fix(example): 把 library 显式加为 workspace dep build-android 一直挂 'Unresolved reference NativeUmengCommonSpec' 等 —— codegen 没生成抽象基类。根因: example/node_modules 下没 @unif/react-native-umeng 软链,RN 0.86 autolinking 找不到 library 的 codegenConfig 就不触发 codegen 任务。 example/react-native.config.js 里 'dependencies.{pkg.name}.root' 这种显式 配置在 0.86 不再被 codegen 流程读 —— 0.86 走标准 node_modules 解析。 修复: example/package.json dependencies 加 '@unif/react-native-umeng: workspace:*',让 yarn workspace 建软链 example/node_modules/@unif/react-native-umeng -> ../../.. → autolinking 能扫到 → codegen 任务被 wire 进 :unif_react-native-umeng:preBuild → Native*Spec 正确生成 → compileDebugKotlin 不再报 Unresolved reference。 本地 yarn install 后软链已生成,push 等 CI 验证。 * chore(example): revert RN 0.86.0-rc.2 -> 0.85.3 按用户决定回到 RN 0.85.3 stable。example/package.json 把 react-native + 4 个 @react-native/* 改回 0.85.3。 forward 改不撤之前 commits (7976424 升 0.86 / ac56bc7 恢复 Podfile patch / d8b6d5c CI 禁 prebuilt) —— 各项 commit 历史保留作为 timeline 记录。 当前组合: - example RN 0.85.3 (stable) - ci.yml RCT_USE_PREBUILT_RNCORE=0 (CI Xcode 26.3 stdlib bug 兜底) - example/ios/Podfile post_install: PR #56862 patch 保留 (本地 prebuilt=1 走快路径时给 0.85.3 prebuilt umbrella 加 fix) * fix(android): codegenConfig 加 android.javaPackageName + 删 sourceSets 手抄 build-android 一直挂 Unresolved reference NativeUmeng{Common,Share,Analytics}Spec —— codegen 根本没生成抽象基类。 根因(对比 npx create-react-native-library 标准 turbo-module 模板): 1. package.json codegenConfig 缺 'android.javaPackageName' 字段。 RN 0.85+ codegen 需要这个告诉它 Native*Spec 生成到哪个 Java/Kotlin package。没这字段 Android 端 codegen 直接跳过 → import 报 Unresolved。 plan task 1 写 codegenConfig 时漏了这一段(iOS 不需要,看不出来)。 2. android/build.gradle 删 'sourceSets.main.java.srcDirs += [generated/...]' —— 标准模板没有这一段,RN gradle plugin apply 后自动注册 generated dirs, 我们手抄反而可能干扰路径。 修复参考: /tmp/ref-turbo (npx create-react-native-library 0.62 现跑的 turbo-module-kotlin-objc 模板) * chore(android): build.gradle 全面对齐 npx create-react-native-library 0.62 模板 对照本地 /Users/liulijun/tongyi/kj (npx create-react-native-library@latest --type turbo-module --languages kotlin-objc 现跑的模板) 把 library 的 android/build.gradle 对齐: - 用 ext.ReactNativeUmeng = [kotlinVersion: '2.0.21', minSdk: 24, compileSdk: 36, targetSdk: 36] 集中默认值,getExtOrDefault 兜底 - apply 顺序: com.android.library → kotlin-android → com.facebook.react (之前 react 放第一个,kj 放最后) - 加 buildTypes { release { minifyEnabled false } } - 加 lint { disable 'GradleCompatible' } - compileOptions JavaVersion.VERSION_1_8 (跟模板一致,RN 0.85 example 会 在 root project 注入 VERSION_17,这里 1_8 不影响 example build) - 删 def reactNativeArchitectures() —— dead code,模板没用 - 删 kotlinOptions { jvmTarget = '17' } —— 模板没显式声明 namespace + 友盟/微信/钉钉 deps 保留为业务特有部分。 实际触发 build-android 修复的关键是上一个 commit 17894d2 加的 codegenConfig.android.javaPackageName,这次的 build.gradle 对齐是 进一步消除潜在不一致风险。 * chore(example): 删 workspace dep 多余引用 example 找 library 走 react-native.config.js (autolinking) + metro 的 withMetroConfig({ root: '..' }) (JS resolve),不需要 example/node_modules 软链。npx create-react-native-library 标准模板 (kj 对照) 的 example/package.json deps 也只列 react + react-native。 之前 commit 46ece37 误加 '@unif/react-native-umeng: workspace:*' 是基于 'autolinking 走 node_modules 标准路径' 的错误诊断 —— 实际 RN 走 config.js 显式 dependencies。删除该行后 example/node_modules/@unif 只剩 react-native-design 软链。 * docs(plan): 加 Errata 段记录 plan task 1/3/23 偏差与教训 在 implementation plan 顶部 (Spec 链接和 File Structure 之间) 加 Errata 段: 1. 列出已知漏抄/改坏 (task 1 codegenConfig 漏 android.javaPackageName, task 3 build.gradle 手抄简化, task 11 注释误导, task 23 后期误加 workspace dep) 和对应修复 commit 2. 根因分析: 9 处 Kotlin Unresolved reference 全部串错指向同一个根因 —— codegenConfig.android.javaPackageName 缺失 3. 下次类似项目的 plan 写法教训: - 'patch 模板字段' 而非 '整段重写新内容' - 不在 plan 里贴整段新文件内容 - task 完成后 git diff initial-commit 校对模板字段保留 - native build 验证不能跳 不动后面 task 1-26 原文 —— 保留历史决策记录。Errata 给将来跑同样 plan 的人 / agent 看,提前避雷。 * chore(ios): podspec 对齐 npx create-react-native-library 0.62 模板 对照 /Users/liulijun/tongyi/kj (npx 现跑模板) iOS podspec 清理本 plan task 2 自加的非模板内容: - 删 pod_target_xcconfig 整段 (DEFINES_MODULE / SWIFT_VERSION=5.0 / CLANG_ENABLE_MODULES / OTHER_LDFLAGS): kj 模板没这段,RN 默认 + install_modules_dependencies(s) 帮设。我们手设的 SWIFT_VERSION=5.0 尤其可疑 (RN 0.85 默认 Swift 5.10+,强制降级潜在风险),其它三个跟 install_modules_dependencies 重复设。 - 加 s.private_header_files = 'ios/**/*.h': 把 .h 标 private,不暴露到 framework umbrella,避免污染消费者 import 空间 + 跟 RN modulemap 冲突。 保留: 友盟/微信/钉钉 deps (业务必需) + install_modules_dependencies。 本地 pod install + yarn build:ios (RCT_USE_PREBUILT_RNCORE=1) 验证通过, ReactNativeUmengExample.app 生成,零 'memory' file not found。 这是 Android task 1/3 同性质的 'plan 改坏模板' 问题在 iOS 端的修复。 Plan task 2 详见 docs/superpowers/plans/...md。 * docs(plan): 补 errata task 2 iOS podspec 偏差 补 plan Errata 段: - 表格加 task 2 行: ReactNativeUmeng.podspec 手加 pod_target_xcconfig 4 字段 + 缺 s.private_header_files,跟 install_modules_dependencies(s) 重复且 SWIFT_VERSION=5.0 强制降级有风险 - 教训章节加 'Task 2 应这样写' 段(原 task 3 改成 task 2/3 两段) - 编号 3→4 / 4→5 / 5→6 顺延 - '当前修复路径' 加 124b354 * chore: 加 dependabot automerge + security policy + feature request 模板 补齐 GitHub 标准开源仓库的 3 项配置: 1) .github/workflows/dependabot-automerge.yml: 自动批准 + auto-merge dependabot patch / minor PR,跳过人审。major bump 仍走人审。 - 用 pull_request_target 拿 base branch 上下文 (GITHUB_TOKEN 有 write) - 双 if 检查 actor + PR user = dependabot[bot] 防伪 - 所有外部输入走 env 注入,不在 run 命令体展开 expr (防 injection) - --auto 配合 ruleset required_status_checks 一起工作,等 CI 全绿才合 2) SECURITY.md: 漏洞报告流程,指向 GitHub Private vulnerability reporting 入口,列了范围 (不包含友盟 / 微信 / 钉钉 SDK 本身)、回复 SLA、致谢规则。 3) .github/ISSUE_TEMPLATE/feature_request.yml: 跟现有 bug_report.yml 同 风格的功能请求模板,加自检 / 用户故事 / API 提案 / 备选方案 / 影响范围 / 是否破坏兼容 字段。 CodeQL 已通过 GitHub Default Setup 跑 (b6af026 check-runs 有 Analyze (javascript-typescript/ruby/actions) 都 success),不需要 yml。 * docs: readme 顶部加 4 个 shields.io badges (同步 design #18) npm version / CI status / license / docs 链接,提升 repo 第一印象。 badges 已包含 npm + docs 链接,所以原来 emoji 链接段去掉。 * fix(android): onEvent map value 类型改 Any? 适配 ReadableMap.toHashMap() RN 0.85 ReadableMap.toHashMap() 返回 HashMap<String, Any?>(value 可空), 之前声明 MutableMap<String, Any> 不接受 → compileDebugKotlin 报 'Type mismatch: inferred type is Any?, but Any was expected.' 修复: MutableMap<String, Any?> —— 友盟 MobclickAgent.onEventObject 是 Java Map<String, Object> 接受 Any?,行为不变。JS 层 src/analytics.ts 已经 stringify 所有 value,实际 null 不会进来,只是类型上对齐。 注: 这是上一轮 commit 17894d2 修 codegenConfig 后真正暴露出来的代码 错(在 codegen 修之前,父类都不存在,这种 type mismatch 被遮蔽)。 codegen 修后只剩这一处真实编译错,其它 9 处 Unresolved reference 全消。 * chore(website): 删 design-only 演示组件 (IconCatalog/Swatches/LiveDemo) 这些是从 design 仓库 copy 来的 UI 组件演示工具,展示 design 的图标库 / 颜色 token / 组件库,umeng 文档站 (sidebar: intro + share-sheet) 完全 不用。 顺手解决 PR Agent (DeepSeek) review 的 2 条真 issue: - IconCatalog.tsx onKeyDown 没处理 Space 浏览器默认滚动 (a11y) - IconCatalog 按钮缺 aria-label (a11y) 第 3 条 review "process.env.NODE_ENV / JEST_WORKER_ID 安全风险" 是 误判 —— DefinePlugin 字面量替换是 webpack 标准模式做 dead-code elimination,JEST_WORKER_ID=undefined 是 docusaurus 浏览器跑 RN 库 内部 jest 分支 short-circuit 的标准 workaround,不是安全风险。 docusaurus-rnw plugin 那段保持不变,PR 上驳回。 验证: yarn workspace ...-website build 成功生成 static files。 * refactor(ios): swift adapter → 纯 objc++ (跟 rn 官方 + 友盟生态对齐) 调研结论: 1) RN 官方明确推荐 turbo-module iOS 端用 Objective-C++ (.mm),不推荐 Swift 2) 友盟 UMShare 6.11.1 用旧式 .framework 不带 Modules/ 目录,非 Clang module。友盟 Swift 集成指南只针对 App target 用 bridging header, library framework 不支持 bridging header,Swift adapter 是孤儿路径 3) GitHub 搜 react-native umeng 找到 67 个桥库,全部 ObjC,零 Swift 实现 4) Plan task 16/17/18 选 Swift Adapter Pattern 是过度设计 改造内容: - 新建 ios/UmengBootstrap.h + .mm 替代原 UmengBootstrap.swift - 重写 ios/UmengCommon.mm: 合并 UmengCommonImpl.swift 逻辑 - 重写 ios/UmengAnalytics.mm: 合并 UmengAnalyticsImpl.swift 逻辑 - 重写 ios/UmengShare.mm: 合并 UmengShareImpl.swift 逻辑 - 删 ios/Umeng{Bootstrap,CommonImpl,AnalyticsImpl,ShareImpl}.swift - ReactNativeUmeng.podspec 撤回 pod_target_xcconfig (Swift 才需要) - example/ios/Podfile 撤回 'UMShare', :modular_headers (Swift 才需要) 业务逻辑零损失 — Swift 实现全部是 ObjC API 包装,机械翻译 ObjC++。 错误码映射 / 友盟拼写陷阱 / PIPL 合规 / Universal Link 处理 全部保留。 本地验证: yarn build:ios (RCT_USE_PREBUILT_RNCORE=1) 成功生成 .app, 零 'memory file not found' / 'Unable to find module' 错误。 修复 PR #10 build-ios 长期挂的 'Unable to find module dependency: UMShare' 根因 — Swift import UMShare 在非 modular pod 上找不到 Clang module。改 ObjC++ 后根本不依赖 module 机制。 * docs(plan): 补 errata task 16/17/18 swift adapter 偏差 完成 plan errata 全闭环。补 task 16/17/18 (iOS Swift Adapter Pattern) 的过度设计偏差记录: - Errata 表格加 task 16/17/18 行,详述 3 条事实链: 1) RN 官方原文推 ObjC++ 而非 Swift 2) 友盟 UMShare 6.11.1 非 modular framework,library 不支持 bridging header,Swift adapter 在友盟生态是孤儿路径 3) GitHub 67 个 RN 友盟桥库零 Swift - 教训章节加第 4 条 'Task 16/17/18 不要选 Swift Adapter Pattern' 写法 - '当前修复路径' commit 列表加 9003025 / 289cd8a - 移除 d8b6d5c 注释里关于 'iOS Xcode stdlib bug' 的早期误判残留 (改写 说明真根因是 Swift 路径,不是 stdlib) * fix(ios): umengshare 用显式 *weakSelf 类型替代 typeof 扩展 CI Xcode 26.3 clang 报: ##[error]expected unqualified-id ##[error]use of undeclared identifier 'weakSelf' 3 处 `__weak typeof(self) weakSelf = self;` 的 `typeof` 是 GCC 扩展, 某些 ObjC++ 严格模式下 parser 不识别。本地 Xcode 26.5 容错过。 最稳的修法是显式类型 `__weak UmengShare *weakSelf = self;` —— 不依赖 任何 typeof 变体 (typeof / __typeof / __typeof__),跨 clang 版本通用。 本地 yarn build:ios 通过 (.app 生成,零 error)。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
When
RCT_USE_PREBUILT_RNCORE=1(the 0.84+ default) and a consumer pod builds underuse_frameworks!, RCT macros likeRCT_EXTERN,RCT_EXTERN_C_BEGIN,RCT_EXPORT_METHOD,RCT_REMAP_METHODfail to propagate.The
.mfiles using these macros hit cascading parse errors like :unknown type name 'RCT_EXTERN_C_BEGIN'in<React/RCTBridgeModule.h>line 51,unknown type name 'RCT_EXTERN'in<React/RCTEventDispatcherProtocol.h>line 17,type specifier missing, defaults to 'int'on everyRCT_EXPORT_METHOD(...)call site.Root cause is in two places in
packages/react-native/scripts/ios-prebuild/templates/:React-umbrella.hordersRCTBridgeConstants.h(line 56) beforeRCTDefines.h(line 84).RCTBridgeConstants.husesRCT_EXTERNat its first declaration but the macro is only defined later inRCTDefines.h. When the umbrella is loaded as a single parse context, theRCT_EXTERNuse is unresolvable.module.modulemapdeclaresmodule * { export * }inside bothframework moduleblocks, which creates an inferred submodule per header. That isolates macro#defines into per-header parse scopes. Even fixing the umbrella order, sibling submodules don't share macros: macros defined in theRCTDefines.hsubmodule are invisible to theRCTBridgeConstants.hsubmodule, and to consumers of theReactmodule.This PR fixes both:
#import <React/RCTDefines.h>to the very top of the umbrella (right after the prologue and before any other<React/...>import), with a comment explaining why ordering matters.module * { export * }wildcard from bothframework moduleblocks in the modulemap. The umbrella header alone is sufficient to declare the module's contents, and dropping the wildcard means the whole module shares one parse context where macros propagate.The combination of
use_frameworks!+ prebuilt RNCore is the path of least resistance today:use_frameworks!is the Expo default and is required byfirebase-ios-sdkfor its Swift bridges. Prebuilt RNCore is the 0.84+ default. The colliding defaults break native-module ecosystems likereact-native-firebasethat consume the RCT macros. Producer-side fix is in flight at invertase/react-native-firebase#9024; this PR closes the consumer side.Changelog:
[IOS] [FIXED] - Load
RCTDefines.hfirst in the prebuilt React umbrella and drop themodule *submodule wildcard so RCT_* macros propagate to consumer pods underuse_frameworks!.Test Plan:
Reproduced on RN 0.85.3 (latest stable at time of writing) on macOS 26.3.1 / Xcode 26.5 / iOS 26.5 Simulator (iPhone 17 Pro).
Reproducer setup
Fork of
mikehardy/rnfbdemowith these adjustments inmake-demo.sh:RN_VER=0.85.3RNFB_VER=24.0.0FB_IOS_VER=12.10.0@react-native-firebase/dynamic-linksfrom the bulk yarn add (deprecated and removed in RNFB 24.x).Default Podfile mods produced by
make-demo.share preserved:use_frameworks! :linkage => :static+$RNFirebaseAsStaticFramework = true. NoRCT_USE_PREBUILT_RNCOREoverride (stays at the1default).Public reproducer: https://github.com/wneel/rnfbdemo (see its
REPRO.mdfor the two-stage flow).The reproducer also has invertase/react-native-firebase#9024 (producer-side podspec fixes) applied as an overlay. Without those, the build fails earlier at
-Wnon-modular-include-in-framework-module. With them applied, the build progresses to the consumer side and surfaces the macro propagation bug this PR fixes.Before this PR
Same reproducer config. iOS build fails on consumer pods (RNFBAuth, RNFBStorage, RNFBMessaging) with:
After this PR
Same reproducer config builds cleanly:
pod installclean,xcodebuildDebug build produces the app, zeroRCT_EXTERNmacro errors anywhere in the log.Verified by editing
packages/react-native/scripts/ios-prebuild/templates/React-umbrella.handpackages/react-native/scripts/ios-prebuild/templates/module.modulemapin place (the diff in this PR), regenerating the prebuilt React.xcframework artifact, and re-running the reproducer.Output of
npx @react-native-community/cli infofrom the reproducer environment:Cross-references
react-native-firebaseproducer-side fix in flight: fix(ios): wire add_rncore_dependency + allow non-modular includes for RN 0.84+ prebuilt RNCore (#8883) invertase/react-native-firebase#9024react-native-firebase.mimport hygiene follow-up: fix(ios): import RCTBridgeModule.h directly in .m files using RCT_EXPORT_* macros invertase/react-native-firebase#9026