Skip to content

Commit fecb129

Browse files
russellwheatleymikehardy
authored andcommitted
fix(ios): warn when Expo linkage restore cannot run
Surface unsupported CocoaPods hook drift instead of silently allowing the duplicate-symbol regression to return.
1 parent 09e39ba commit fecb129

4 files changed

Lines changed: 78 additions & 2 deletions

File tree

okf-bundle/ios-spm-native-imports.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,11 @@ targets to dynamic linkage and eliminating the embedded SPM duplicate. Bare
457457
CocoaPods (no SPM), source-built Expo, non-Expo apps, and already-dynamic
458458
targets are unaffected.
459459

460+
If CocoaPods no longer exposes `generate_pods_project`, RNFB cannot install
461+
the restore at the required boundary. Expo-precompiled installs warn once per
462+
installer class and continue without the restore; non-Expo and source-built
463+
Expo paths do not warn.
464+
460465
### Regression check
461466

462467
The documented Podfile configuration does not change: SPM on,
@@ -466,6 +471,9 @@ Link success confirms both RNFB framework products are in dynamic form and
466471
duplicate Firebase symbols are absent, while still validating the app target's
467472
own FirebaseCore dependency (the original purpose of that fixture). See
468473
[Maintainer check of the Expo documented path](#app-target-firebasecore-link-package-dependency-alone-is-not-enough).
474+
The [#9202](https://github.com/invertase/react-native-firebase/issues/9202)
475+
regression signature is duplicate `_FIRFirebaseVersion` symbols from
476+
`libRNFBApp.a` and `libRNFBMessaging.a`.
469477

470478
## Review invariants
471479

okf-bundle/packages/app/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ Knowledge for the core app package: Firebase app lifecycle, Expo config plugin,
1212

1313
**Policy:** [OKF documentation and commit policy](../../documentation-policy.md). Agent shell commands: [agent command policy](../../testing/agent-command-policy.md) only.
1414

15-
The workspace Expo documented-path iOS **link** fixture (`test-expo/`) is not Detox e2e. Canonical command: `yarn test-expo:ios:link` ([agent command policy](../../testing/agent-command-policy.md)). App-target FirebaseCore linking and CocoaPods hook order: [iOS SPM native integration](../../ios-spm-native-imports.md#app-target-firebasecore-link-package-dependency-alone-is-not-enough). Expo precompiled RNCore linkage repair: [iOS SPM native integration § Expo precompiled module linkage repair](../../ios-spm-native-imports.md#expo-precompiled-module-linkage-repair). Do not treat duplicate `_FIRFirebaseVersion` ([#9202](https://github.com/invertase/react-native-firebase/issues/9202)) as that closer.
15+
The workspace Expo documented-path iOS **link** fixture (`test-expo/`) is not Detox e2e. Canonical command: `yarn test-expo:ios:link` ([agent command policy](../../testing/agent-command-policy.md)). App-target FirebaseCore linking and CocoaPods hook order: [iOS SPM native integration](../../ios-spm-native-imports.md#app-target-firebasecore-link-package-dependency-alone-is-not-enough). Expo precompiled RNCore linkage repair and duplicate-symbol regression: [iOS SPM native integration § Expo precompiled module linkage repair](../../ios-spm-native-imports.md#expo-precompiled-module-linkage-repair).
1616

1717
## Documents
1818

19-
* Cross-cutting durable SPM decisions: [iOS SPM native integration](../../ios-spm-native-imports.md) ([app-target FirebaseCore link](../../ios-spm-native-imports.md#app-target-firebasecore-link-package-dependency-alone-is-not-enough))
19+
* Cross-cutting durable SPM decisions: [iOS SPM native integration](../../ios-spm-native-imports.md) ([app-target FirebaseCore link](../../ios-spm-native-imports.md#app-target-firebasecore-link-package-dependency-alone-is-not-enough); [Expo precompiled linkage repair](../../ios-spm-native-imports.md#expo-precompiled-module-linkage-repair))
2020

2121
## Related repository files
2222

packages/app/__tests__/firebase_spm_test.rb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,6 +1632,58 @@ def test_generate_pods_project_hook_is_idempotent_across_repeated_podspec_requir
16321632
assert_equal [instance], restore_calls
16331633
end
16341634

1635+
def test_hook_warns_once_when_generate_pods_project_is_unavailable_for_expo
1636+
load_firebase_spm
1637+
stub_expo_precompiled_modules(enabled: true, linkage: :dynamic)
1638+
klass = new_fake_cocoapods_installer_class
1639+
klass.send(:remove_method, :generate_pods_project)
1640+
1641+
rnfirebase_hook_cocoapods_post_install!(klass)
1642+
rnfirebase_hook_cocoapods_post_install!(klass)
1643+
instance = klass.new
1644+
1645+
result = instance.send(:run_podfile_post_install_hooks)
1646+
1647+
assert_equal :original_result, result
1648+
assert_equal 1, instance.original_hook_calls
1649+
warnings = Pod::UI.warnings.select { |warning| warning.include?('generate_pods_project') }
1650+
assert_equal 1, warnings.length
1651+
assert_includes warnings[0], 'Expo prebuilt RNFB dynamic-linkage restoration was not hooked'
1652+
end
1653+
1654+
def test_hook_does_not_warn_when_generate_pods_project_is_unavailable_and_expo_prebuilt_is_disabled
1655+
load_firebase_spm
1656+
stub_expo_precompiled_modules(enabled: false, linkage: :dynamic)
1657+
klass = new_fake_cocoapods_installer_class
1658+
klass.send(:remove_method, :generate_pods_project)
1659+
1660+
rnfirebase_hook_cocoapods_post_install!(klass)
1661+
1662+
refute(Pod::UI.warnings.any? { |warning| warning.include?('generate_pods_project') })
1663+
end
1664+
1665+
def test_hook_does_not_warn_when_generate_pods_project_is_unavailable_outside_expo
1666+
load_firebase_spm
1667+
klass = new_fake_cocoapods_installer_class
1668+
klass.send(:remove_method, :generate_pods_project)
1669+
1670+
rnfirebase_hook_cocoapods_post_install!(klass)
1671+
1672+
refute(Pod::UI.warnings.any? { |warning| warning.include?('generate_pods_project') })
1673+
end
1674+
1675+
def test_hook_does_not_warn_when_expo_precompiled_enabled_api_is_unavailable
1676+
load_firebase_spm
1677+
ensure_expo_module!
1678+
Expo.const_set(:PrecompiledModules, Module.new)
1679+
klass = new_fake_cocoapods_installer_class
1680+
klass.send(:remove_method, :generate_pods_project)
1681+
1682+
rnfirebase_hook_cocoapods_post_install!(klass)
1683+
1684+
refute(Pod::UI.warnings.any? { |warning| warning.include?('generate_pods_project') })
1685+
end
1686+
16351687
# The generate_pods_project wrapper must not call the original generate method
16361688
# after a restore failure: it must warn with a directed message identifying
16371689
# Expo prebuilt dynamic-linkage restoration and re-raise the original error.

packages/app/firebase_spm.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,22 @@ def rnfirebase_hook_cocoapods_post_install!(installer_class = (Pod::Installer if
715715
integrate_was_private = installer_class.private_method_defined?(integrate_hook_method)
716716
post_integrate_available = integrate_was_private || installer_class.method_defined?(integrate_hook_method)
717717

718+
generate_unavailable_warning = :@rnfirebase_generate_pods_project_unavailable_warning
719+
if !already_hooked_generate &&
720+
!generate_available &&
721+
defined?(Expo::PrecompiledModules) &&
722+
Expo::PrecompiledModules.respond_to?(:enabled?) &&
723+
Expo::PrecompiledModules.enabled? &&
724+
defined?(Pod::UI) &&
725+
!installer_class.instance_variable_defined?(generate_unavailable_warning)
726+
Pod::UI.warn '[react-native-firebase] `Pod::Installer#generate_pods_project` does not exist ' \
727+
'(a CocoaPods release may have renamed or removed it) -- Expo prebuilt RNFB ' \
728+
'dynamic-linkage restoration was not hooked into `pod install`. Use the CocoaPods ' \
729+
'version required by your Expo SDK and report this version combination if the app ' \
730+
'links duplicate Firebase symbols.'
731+
installer_class.instance_variable_set(generate_unavailable_warning, true)
732+
end
733+
718734
# Already hooked -- e.g. a second RNFB podspec also `require`d this same
719735
# file within one `pod install` process. Expected and idempotent.
720736
return if (already_hooked_generate || !generate_available) &&

0 commit comments

Comments
 (0)