From 5f77554b199aca9ff5046f8e96ccdde16cedd0b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ma=C5=82ecki?= Date: Tue, 22 Sep 2026 04:28:01 -0700 Subject: [PATCH] Fix framework umbrella search paths (#58622) Summary: Source-built CocoaPods frameworks do not automatically expose the directories behind stable umbrella includes. Exported and generated headers consume umbrellas owned by sibling frameworks, while consuming application and pod targets do not automatically inherit the header roots for those frameworks. Add source-only aggregate paths for the umbrella frameworks used by FabricComponents and React-perflogger, configure the React-timing dependency of React-perflogger with its framework header root, and expose React-bridging to generated module targets. Keep prebuilt RNCore unchanged so its headers continue to resolve from the prebuilt React.framework. Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D120992289 --- .../React-FabricComponents.podspec | 11 +++++++++ .../reactperflogger/React-perflogger.podspec | 2 +- .../cocoapods/__tests__/codegen_utils-test.rb | 2 +- .../__tests__/new_architecture-test.rb | 11 +++++++++ .../scripts/cocoapods/__tests__/utils-test.rb | 24 ++++++++++++++++++- .../scripts/cocoapods/new_architecture.rb | 1 + .../react-native/scripts/cocoapods/utils.rb | 15 ++++++++++++ .../generate-artifacts-executor-test.js.snap | 2 ++ .../templates/ReactCodegen.podspec.template | 1 + 9 files changed, 66 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactCommon/React-FabricComponents.podspec b/packages/react-native/ReactCommon/React-FabricComponents.podspec index 6f550a031b57..ae7adc6ace19 100644 --- a/packages/react-native/ReactCommon/React-FabricComponents.podspec +++ b/packages/react-native/ReactCommon/React-FabricComponents.podspec @@ -33,6 +33,17 @@ if ENV['USE_FRAMEWORKS'] "\"$(PODS_TARGET_SRCROOT)/react/renderer/components/text/platform/cxx\"", "\"$(PODS_TARGET_SRCROOT)/react/renderer/components/view/platform/cxx\"", ] + + if ReactNativeCoreUtils.build_rncore_from_source() + # Stable umbrellas consumed by exported component headers. + header_search_path = header_search_path + [ + "\"$(PODS_TARGET_SRCROOT)/react/debug\"", + "\"$(PODS_TARGET_SRCROOT)/react/renderer/components/view\"", + "\"$(PODS_TARGET_SRCROOT)/react/renderer/core\"", + "\"$(PODS_TARGET_SRCROOT)/react/renderer/debug\"", + "\"$(PODS_TARGET_SRCROOT)/react/utils\"", + ] + end end Pod::Spec.new do |s| diff --git a/packages/react-native/ReactCommon/reactperflogger/React-perflogger.podspec b/packages/react-native/ReactCommon/reactperflogger/React-perflogger.podspec index 75f6d5f2c0b1..4dada48f356f 100644 --- a/packages/react-native/ReactCommon/reactperflogger/React-perflogger.podspec +++ b/packages/react-native/ReactCommon/reactperflogger/React-perflogger.podspec @@ -41,7 +41,7 @@ Pod::Spec.new do |s| add_rncore_dependency(s) s.dependency "React-cxxstableapi" - s.dependency "React-timing" + add_dependency(s, "React-timing") mark_as_react_native_build(s) end diff --git a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb index 3dde2a593588..8822d7e7b922 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb @@ -298,7 +298,7 @@ def get_podspec_when_use_frameworks specs = get_podspec_no_fabric_no_script() specs["pod_target_xcconfig"]["FRAMEWORK_SEARCH_PATHS"].concat([]) - specs["pod_target_xcconfig"]["HEADER_SEARCH_PATHS"].concat(" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-featureflags/React_featureflags.framework/Headers\"") + specs["pod_target_xcconfig"]["HEADER_SEARCH_PATHS"].concat(" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-bridging/React_bridging.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-featureflags/React_featureflags.framework/Headers\"") specs[:dependencies].merge!({ 'React-graphics': [], diff --git a/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb b/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb index fc1fa036be4b..9cb7ca410bfa 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb @@ -23,6 +23,7 @@ def teardown Pod::UI.reset() FileMock.reset() ENV["RCT_NEW_ARCH_ENABLED"] = nil + ENV["USE_FRAMEWORKS"] = nil NewArchitectureHelper.reset() end @@ -180,6 +181,16 @@ def test_installModulesDependencies_whenNewArchEnabledAndNewArchAndNoSearchPaths ) end + def test_installModulesDependencies_whenUseFrameworks_addsReactBridgingSearchPath + spec = SpecMock.new + ENV["USE_FRAMEWORKS"] = "dynamic" + + NewArchitectureHelper.install_modules_dependencies(spec, true, '2024.10.14.00') + + header_search_paths = Array(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"]).join(" ") + assert(header_search_paths.include?("${PODS_CONFIGURATION_BUILD_DIR}/React-bridging/React_bridging.framework/Headers")) + end + def test_installModulesDependencies_whenNewArchDisabledAndSearchPathsAndCompilerFlagsArePresent_itInstallDependenciesAndPreserveOtherSettings # Arrange spec = SpecMock.new diff --git a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb index 44e0e3bcaa9c..445a2455e0aa 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb @@ -5,6 +5,7 @@ require "test/unit" require_relative "../utils.rb" +require_relative "../rncore.rb" require_relative "./test_utils/PodMock.rb" require_relative "./test_utils/InstallerMock.rb" require_relative "./test_utils/EnvironmentMock.rb" @@ -33,6 +34,7 @@ def teardown Environment.reset() Xcodeproj::Plist.reset() XcodebuildMock.reset() + ReactNativeCoreUtils.class_variable_set(:@@build_from_source, true) ENV['RCT_NEW_ARCH_ENABLED'] = '0' ENV['USE_FRAMEWORKS'] = nil ENV['RCT_REMOVE_LEGACY_MODULE_INTEROP'] = nil @@ -741,7 +743,7 @@ def test_updateSearchPaths_whenUseFrameworks_addsSearchPaths # Assert user_project_mock.build_configurations.each do |config| received_search_path = config.build_settings["HEADER_SEARCH_PATHS"] - expected_search_path = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core ${PODS_CONFIGURATION_BUILD_DIR}/React-runtimeexecutor/React_runtimeexecutor.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-runtimeexecutor/React_runtimeexecutor.framework/Headers/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx ${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/React-featureflags/React_featureflags.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-renderercss/React_renderercss.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-cxxstableapi/React_cxxstableapi.framework/Headers" + expected_search_path = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core ${PODS_CONFIGURATION_BUILD_DIR}/React-runtimeexecutor/React_runtimeexecutor.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-runtimeexecutor/React_runtimeexecutor.framework/Headers/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-timing/React_timing.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/React-featureflags/React_featureflags.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-renderercss/React_renderercss.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-cxxstableapi/React_cxxstableapi.framework/Headers" assert_equal(expected_search_path, received_search_path) end @@ -921,6 +923,26 @@ def test_creatHeaderSearchPathForFrameworks_whenMultiplePlatformsAndExtraPath_cr ], result) end + def test_createHeaderSearchPathsForStableUmbrellas_whenBuildingFromSource_addsOwningFrameworks + result = ReactNativePodsUtils.create_header_search_paths_for_stable_umbrellas("PODS_CONFIGURATION_BUILD_DIR") + + assert_equal([ + "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-timing/React_timing.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers", + ], result) + end + + def test_createHeaderSearchPathsForStableUmbrellas_whenUsingPrebuiltCore_addsNothing + ReactNativeCoreUtils.class_variable_set(:@@build_from_source, false) + + result = ReactNativePodsUtils.create_header_search_paths_for_stable_umbrellas("PODS_CONFIGURATION_BUILD_DIR") + + assert_equal([], result) + end + # ================================= # # TEST - Add RN_BUILDING definition # # ================================= # diff --git a/packages/react-native/scripts/cocoapods/new_architecture.rb b/packages/react-native/scripts/cocoapods/new_architecture.rb index 6ce3f92fc15b..86fa4d47e92e 100644 --- a/packages/react-native/scripts/cocoapods/new_architecture.rb +++ b/packages/react-native/scripts/cocoapods/new_architecture.rb @@ -85,6 +85,7 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version = He if ENV['USE_FRAMEWORKS'] ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-graphics", "React_graphics", ["react/renderer/graphics/platform/ios"]) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-Fabric", "React_Fabric", ["react/renderer/components/view/platform/cxx"])) + .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-bridging", "React_bridging", [])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-FabricImage", "React_FabricImage", [])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-FabricComponents", "React_FabricComponents", [])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-Mapbuffer", "React_Mapbuffer", [])) diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 3038897c8545..2140b3013b0c 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -355,6 +355,20 @@ def self.create_header_search_path_for_frameworks(base_folder, pod_name, framewo return search_paths end + def self.create_header_search_paths_for_stable_umbrellas(base_folder) + return [] unless ReactNativeCoreUtils.build_rncore_from_source() + + [ + ["React-Fabric", "React_Fabric"], + ["React-debug", "React_debug"], + ["React-rendererdebug", "React_rendererdebug"], + ["React-timing", "React_timing"], + ["React-utils", "React_utils"], + ].flat_map { |pod_name, framework_name| + self.create_header_search_path_for_frameworks(base_folder, pod_name, framework_name, []) + } + end + # Add a new dependency to an existing spec, configuring also the headers search paths def self.add_dependency(spec, dependency_name, base_folder_for_frameworks, framework_name, additional_paths: [], version: nil, subspec_dependency: nil) # Update Search Path @@ -397,6 +411,7 @@ def self.update_search_paths(installer) "react/renderer/components/scrollview/platform/cxx", "react/renderer/components/scrollview/platform/ios", ], false)) + .concat(ReactNativePodsUtils.create_header_search_paths_for_stable_umbrellas("PODS_CONFIGURATION_BUILD_DIR")) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-FabricComponents", "React_FabricComponents", [ "react/renderer/textlayoutmanager/platform/ios", "react/renderer/components/text/platform/cxx", diff --git a/packages/react-native/scripts/codegen/__tests__/__snapshots__/generate-artifacts-executor-test.js.snap b/packages/react-native/scripts/codegen/__tests__/__snapshots__/generate-artifacts-executor-test.js.snap index 9ce1c901040e..6bc79e6875e4 100644 --- a/packages/react-native/scripts/codegen/__tests__/__snapshots__/generate-artifacts-executor-test.js.snap +++ b/packages/react-native/scripts/codegen/__tests__/__snapshots__/generate-artifacts-executor-test.js.snap @@ -426,6 +426,7 @@ header_search_paths = [ if use_frameworks ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-Fabric\\", \\"React_Fabric\\", [\\"react/renderer/components/view/platform/cxx\\"]) + .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-bridging\\", \\"React_bridging\\", [])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-FabricImage\\", \\"React_FabricImage\\", [])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-graphics\\", \\"React_graphics\\", [\\"react/renderer/graphics/platform/ios\\"])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"ReactCommon\\", \\"ReactCommon\\", [\\"react/nativemodule/core\\"])) @@ -909,6 +910,7 @@ header_search_paths = [ if use_frameworks ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-Fabric\\", \\"React_Fabric\\", [\\"react/renderer/components/view/platform/cxx\\"]) + .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-bridging\\", \\"React_bridging\\", [])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-FabricImage\\", \\"React_FabricImage\\", [])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-graphics\\", \\"React_graphics\\", [\\"react/renderer/graphics/platform/ios\\"])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"ReactCommon\\", \\"ReactCommon\\", [\\"react/nativemodule/core\\"])) diff --git a/packages/react-native/scripts/codegen/templates/ReactCodegen.podspec.template b/packages/react-native/scripts/codegen/templates/ReactCodegen.podspec.template index 5909a466ee82..ff57a460ffd1 100644 --- a/packages/react-native/scripts/codegen/templates/ReactCodegen.podspec.template +++ b/packages/react-native/scripts/codegen/templates/ReactCodegen.podspec.template @@ -30,6 +30,7 @@ header_search_paths = [ if use_frameworks ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-Fabric", "React_Fabric", ["react/renderer/components/view/platform/cxx"]) + .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-bridging", "React_bridging", [])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-FabricImage", "React_FabricImage", [])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-graphics", "React_graphics", ["react/renderer/graphics/platform/ios"])) .concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "ReactCommon", "ReactCommon", ["react/nativemodule/core"]))