Skip to content

Commit ff2562e

Browse files
wneelreact-native-bot
authored andcommitted
fix(ios): load RCTDefines.h first in React umbrella + drop submodule 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
1 parent aa91ba2 commit ff2562e

2 files changed

Lines changed: 5 additions & 3 deletions

File tree

packages/react-native/scripts/ios-prebuild/templates/React-umbrella.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
#endif
1818
#endif
1919

20+
// RCTDefines.h defines RCT_EXTERN, RCT_EXTERN_C_BEGIN/END, RCT_EXPORT_METHOD, etc.
21+
// Must be loaded first so its macros are visible to subsequent umbrella headers (e.g. RCTBridgeConstants.h).
22+
// clang-format off
23+
#import <React/RCTDefines.h>
24+
// clang-format on
2025
#import <React/CoreModulesPlugins.h>
2126
#import <React/FBXXHashUtils.h>
2227
#import <React/NSTextStorage+FontScaling.h>
@@ -81,7 +86,6 @@
8186
#import <React/RCTDebuggingOverlay.h>
8287
#import <React/RCTDebuggingOverlayManager.h>
8388
#import <React/RCTDecayAnimation.h>
84-
#import <React/RCTDefines.h>
8589
#import <React/RCTDevLoadingView.h>
8690
#import <React/RCTDevLoadingViewProtocol.h>
8791
#import <React/RCTDevLoadingViewSetEnabled.h>
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
framework module React {
22
umbrella header "React_Core/React_Core-umbrella.h"
33
export *
4-
module * { export * }
54
}
65

76

87
framework module React_RCTAppDelegate {
98
umbrella header "React_RCTAppDelegate/React_RCTAppDelegate-umbrella.h"
109
export *
11-
module * { export * }
1210
}

0 commit comments

Comments
 (0)