Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
ios: {
deploymentTarget: '18.1',
useFrameworks: 'static',
// Build React Native from source instead of the prebuilt
// ReactNativeDependencies.xcframework. The prebuilt core does not
// re-export RN's preprocessor macros (RCT_EXTERN, RCT_CONCAT) across
// the static-framework module boundary, so RCT_EXPORT_MODULE() fails
// to compile in third-party Obj-C modules like @react-native-firebase.
buildReactNativeFromSource: true,
},
},
],
Expand Down
29 changes: 28 additions & 1 deletion plugins/withWebRTCFrameworkFix.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ const path = require('path');
* compatibility with use_frameworks! :linkage => :static (required by
* @react-native-firebase).
*
* Fixes three classes of errors:
* Fixes four classes of errors:
* 1. "include of non-modular header inside framework module" — sets
* CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES for all pods.
* 2. "declaration of 'X' must be imported from module 'Y' before it is required"
* — adds use_modular_headers! so #import statements resolve correctly across
* framework module boundaries.
* 3. "RCTPromiseRejectBlock must be imported from module 'RNFBApp.RNFBAppModule'"
* — patches RNFBMessaging source files to import RNFBAppModule explicitly.
* 4. "unknown type name 'RCT_EXTERN'" / "duplicate declaration of method
* 'RCT_CONCAT'" in RNFBMessagingModule.m (RCT_EXPORT_MODULE fails to expand)
* — sets $RNFirebaseAsStaticFramework = true so the @react-native-firebase
* pods build as static frameworks, letting React's macro headers resolve
* inside the Firebase module.
Comment on lines +10 to +22

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix the numbering inconsistency between the header comment and code comments.

The header comment lists fixes as 1, 2, 3, 4, but the code comments below number them as 0, 1, 2, 3 (lines 31, 53, 65, 110). Additionally, the execution order doesn't match the header order:

  • Header: 1=CLANG_ALLOW, 2=use_modular_headers, 3=RCTPromiseRejectBlock, 4=$RNFirebaseAsStaticFramework
  • Code execution: 0=$RNFirebaseAsStaticFramework, 1=use_modular_headers, 2=CLANG_ALLOW, 3=RCTPromiseRejectBlock

Consider renumbering the header to match the code's execution order (0, 1, 2, 3) for clarity.

📝 Suggested fix to align numbering
- * Fixes four classes of errors:
- * 1. "include of non-modular header inside framework module" — sets
- *    CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES for all pods.
- * 2. "declaration of 'X' must be imported from module 'Y' before it is required"
- *    — adds use_modular_headers! so `#import` statements resolve correctly across
- *    framework module boundaries.
- * 3. "RCTPromiseRejectBlock must be imported from module 'RNFBApp.RNFBAppModule'"
- *    — patches RNFBMessaging source files to import RNFBAppModule explicitly.
- * 4. "unknown type name 'RCT_EXTERN'" / "duplicate declaration of method
- *    'RCT_CONCAT'" in RNFBMessagingModule.m (RCT_EXPORT_MODULE fails to expand)
+ * Fixes four classes of errors (in execution order):
+ * 0. "unknown type name 'RCT_EXTERN'" / "duplicate declaration of method
+ *    'RCT_CONCAT'" in RNFBMessagingModule.m (RCT_EXPORT_MODULE fails to expand)
  *    — sets $RNFirebaseAsStaticFramework = true so the `@react-native-firebase`
  *    pods build as static frameworks, letting React's macro headers resolve
  *    inside the Firebase module.
+ * 1. "declaration of 'X' must be imported from module 'Y' before it is required"
+ *    — adds use_modular_headers! so `#import` statements resolve correctly across
+ *    framework module boundaries.
+ * 2. "include of non-modular header inside framework module" — sets
+ *    CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES for all pods.
+ * 3. "RCTPromiseRejectBlock must be imported from module 'RNFBApp.RNFBAppModule'"
+ *    — patches RNFBMessaging source files to import RNFBAppModule explicitly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/withWebRTCFrameworkFix.js` around lines 10 - 22, The header comment
in withWebRTCFrameworkFix.js numbers the fixes as 1, 2, 3, 4
(CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES, use_modular_headers,
RCTPromiseRejectBlock, and $RNFirebaseAsStaticFramework) but the code comments
below number them as 0, 1, 2, 3 with a different execution order. Renumber and
reorder the header comment to match the actual code execution order:
0=$RNFirebaseAsStaticFramework, 1=use_modular_headers,
2=CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES, 3=RCTPromiseRejectBlock
patch, ensuring the description order aligns with how these fixes are actually
applied in the code.

*/
const withWebRTCFrameworkFix = (config) => {
return withDangerousMod(config, [
Expand All @@ -23,6 +28,28 @@ const withWebRTCFrameworkFix = (config) => {
const podfilePath = path.join(config.modRequest.platformProjectRoot, 'Podfile');
let contents = fs.readFileSync(podfilePath, 'utf-8');

// 0. Set $RNFirebaseAsStaticFramework = true at global scope (before any
// target) so the @react-native-firebase pods build as static frameworks.
// Without this, under use_frameworks! :linkage => :static the React
// macro headers (RCT_EXTERN, RCT_CONCAT) don't resolve inside the
// Firebase module and RCT_EXPORT_MODULE() fails to compile.
if (!contents.includes('$RNFirebaseAsStaticFramework')) {
const fbAnchor = 'prepare_react_native_project!';
const fbAnchorIdx = contents.indexOf(fbAnchor);
if (fbAnchorIdx === -1) {
throw new Error(
'[withWebRTCFrameworkFix] Could not find prepare_react_native_project! in Podfile — ' +
'cannot place $RNFirebaseAsStaticFramework at global scope.'
);
}
const fbEndOfLine = contents.indexOf('\n', fbAnchorIdx);
const fbInsertAt = fbEndOfLine === -1 ? contents.length : fbEndOfLine + 1;
contents =
contents.slice(0, fbInsertAt) +
'\n$RNFirebaseAsStaticFramework = true\n' +
contents.slice(fbInsertAt);
}

// 1. Add use_modular_headers! after use_frameworks! if not already present.
if (!contents.includes('use_modular_headers!')) {
const useFrameworksPattern = /use_frameworks!.*\n/g;
Expand Down
Loading