diff --git a/scripts/cocoapods/__tests__/test_utils/InstallerMock.rb b/scripts/cocoapods/__tests__/test_utils/InstallerMock.rb index f10a6109b69483..7c1c95de4d4116 100644 --- a/scripts/cocoapods/__tests__/test_utils/InstallerMock.rb +++ b/scripts/cocoapods/__tests__/test_utils/InstallerMock.rb @@ -152,16 +152,17 @@ class TargetMock attr_reader :name attr_reader :build_configurations attr_reader :product_type - attr_reader :received_resolved_build_setting_parameters + attr_reader :dependencies - def initialize(name, build_configurations = [], product_type = nil) + def initialize(name, build_configurations = [], product_type = nil, dependencies = []) @name = name @build_configurations = build_configurations unless product_type.nil? @product_type = product_type end @received_resolved_build_setting_parameters = [] + @dependencies = dependencies end def resolved_build_setting(key, resolve_against_xcconfig: false) @@ -211,3 +212,11 @@ def initialize(target = TargetMock, native_target = TargetMock, @app_resource_bundle_targets = app_resource_bundle_targets end end + +class DependencyMock + attr_reader :name + + def initialize(name) + @name = name + end +end diff --git a/scripts/cocoapods/__tests__/utils-test.rb b/scripts/cocoapods/__tests__/utils-test.rb index 765c3426db35e5..5fac9c1ed4dcca 100644 --- a/scripts/cocoapods/__tests__/utils-test.rb +++ b/scripts/cocoapods/__tests__/utils-test.rb @@ -541,7 +541,13 @@ def test_updateSearchPaths_whenUseFrameworks_addsSearchPaths # Arrange ENV['USE_FRAMEWORKS'] = 'static' first_target = prepare_target("FirstTarget") - second_target = prepare_target("SecondTarget") + second_target = prepare_target("SecondTarget", nil, [ + DependencyMock.new("RCT-Folly"), + DependencyMock.new("React-Codegen"), + DependencyMock.new("ReactCommon"), + DependencyMock.new("React-RCTFabric"), + DependencyMock.new("React-ImageManager"), + ]) third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") user_project_mock = UserProjectMock.new("a/path", [ prepare_config("Debug"), @@ -563,9 +569,23 @@ 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/react/nativemodule/core/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples" + expected_search_path = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios" assert_equal(expected_search_path, received_search_path) end + + installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result| + if pod_name == "SecondTarget" + target_installation_result.native_target.build_configurations.each do |config| + received_search_path = config.build_settings["HEADER_SEARCH_PATHS"] + expected_Search_path = "$(inherited) \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/boost\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.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-Fabric/React_Fabric.framework/Headers/react/renderer/imagemanager/platform/ios\"" + assert_equal(received_search_path, expected_Search_path) + end + else + target_installation_result.native_target.build_configurations.each do |config| + assert_nil(config.build_settings["HEADER_SEARCH_PATHS"]) + end + end + end end def test_updateSearchPaths_whenNotUseFrameworks_addsSearchPaths @@ -595,71 +615,70 @@ def test_updateSearchPaths_whenNotUseFrameworks_addsSearchPaths assert_nil(config.build_settings["HEADER_SEARCH_PATHS"]) end end -end -# ============================= # -# Test - Apply Flags For Fabric # -# ============================= # -def test_applyFlagsForFabric_whenFabricEnabled_addsTheFlag - # Arrange - first_target = prepare_target("FirstTarget") - second_target = prepare_target("SecondTarget") - third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") - user_project_mock = UserProjectMock.new("a/path", [ - prepare_config("Debug"), - prepare_config("Release"), - ], - :native_targets => [ - first_target, - second_target - ] - ) - pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) - installer = InstallerMock.new(pods_projects_mock, [ - AggregatedProjectMock.new(user_project_mock) - ]) + # ============================= # + # Test - Apply Flags For Fabric # + # ============================= # + def test_applyFlagsForFabric_whenFabricEnabled_addsTheFlag + # Arrange + first_target = prepare_target("FirstTarget") + second_target = prepare_target("SecondTarget") + third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") + user_project_mock = UserProjectMock.new("a/path", [ + prepare_config("Debug"), + prepare_config("Release"), + ], + :native_targets => [ + first_target, + second_target + ] + ) + pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) + installer = InstallerMock.new(pods_projects_mock, [ + AggregatedProjectMock.new(user_project_mock) + ]) - # Act - ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: true) + # Act + ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: true) - # Assert - user_project_mock.build_configurations.each do |config| - received_cflags = config.build_settings["OTHER_CFLAGS"] - expected_cflags = "$(inherited) -DRN_FABRIC_ENABLED" - assert_equal(received_cflags, expected_cflags) - end + # Assert + user_project_mock.build_configurations.each do |config| + received_cflags = config.build_settings["OTHER_CFLAGS"] + expected_cflags = "$(inherited) -DRN_FABRIC_ENABLED" + assert_equal(received_cflags, expected_cflags) + end -end + end -def test_applyFlagsForFabric_whenFabricDisabled_doNothing - # Arrange - first_target = prepare_target("FirstTarget") - second_target = prepare_target("SecondTarget") - third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") - user_project_mock = UserProjectMock.new("a/path", [ - prepare_config("Debug"), - prepare_config("Release"), - ], - :native_targets => [ - first_target, - second_target - ] - ) - pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) - installer = InstallerMock.new(pods_projects_mock, [ - AggregatedProjectMock.new(user_project_mock) - ]) + def test_applyFlagsForFabric_whenFabricDisabled_doNothing + # Arrange + first_target = prepare_target("FirstTarget") + second_target = prepare_target("SecondTarget") + third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") + user_project_mock = UserProjectMock.new("a/path", [ + prepare_config("Debug"), + prepare_config("Release"), + ], + :native_targets => [ + first_target, + second_target + ] + ) + pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) + installer = InstallerMock.new(pods_projects_mock, [ + AggregatedProjectMock.new(user_project_mock) + ]) - # Act - ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: false) + # Act + ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: false) - # Assert - user_project_mock.build_configurations.each do |config| - assert_nil(config.build_settings["OTHER_CFLAGS"]) + # Assert + user_project_mock.build_configurations.each do |config| + assert_nil(config.build_settings["OTHER_CFLAGS"]) + end end end - # ===== # # UTILS # # ===== # @@ -679,11 +698,11 @@ def prepare_config(config_name) ]}) end -def prepare_target(name, product_type = nil) +def prepare_target(name, product_type = nil, dependencies = []) return TargetMock.new(name, [ prepare_config("Debug"), prepare_config("Release") - ], product_type) + ], product_type, dependencies) end def prepare_Code_Signing_build_configuration(name, param) diff --git a/scripts/cocoapods/utils.rb b/scripts/cocoapods/utils.rb index b8d29042d9c81a..d7a54cb8d18e32 100644 --- a/scripts/cocoapods/utils.rb +++ b/scripts/cocoapods/utils.rb @@ -54,14 +54,10 @@ def self.turn_off_resource_bundle_react_core(installer) end def self.exclude_i386_architecture_while_using_hermes(installer) - projects = installer.aggregate_targets - .map{ |t| t.user_project } - .uniq{ |p| p.path } - .push(installer.pods_project) - + projects = self.exrtract_projects(installer) # Hermes does not support `i386` architecture - excluded_archs_default = ReactNativePodsUtils.has_pod(installer, 'hermes-engine') ? "i386" : "" + excluded_archs_default = self.has_pod(installer, 'hermes-engine') ? "i386" : "" projects.each do |project| project.build_configurations.each do |config| @@ -74,10 +70,7 @@ def self.exclude_i386_architecture_while_using_hermes(installer) def self.set_node_modules_user_settings(installer, react_native_path) Pod::UI.puts("Setting REACT_NATIVE build settings") - projects = installer.aggregate_targets - .map{ |t| t.user_project } - .uniq{ |p| p.path } - .push(installer.pods_project) + projects = self.exrtract_projects(installer) projects.each do |project| project.build_configurations.each do |config| @@ -89,18 +82,15 @@ def self.set_node_modules_user_settings(installer, react_native_path) end def self.fix_library_search_paths(installer) - projects = installer.aggregate_targets - .map{ |t| t.user_project } - .uniq{ |p| p.path } - .push(installer.pods_project) + projects = self.exrtract_projects(installer) projects.each do |project| project.build_configurations.each do |config| - ReactNativePodsUtils.fix_library_search_path(config) + self.fix_library_search_path(config) end project.native_targets.each do |target| target.build_configurations.each do |config| - ReactNativePodsUtils.fix_library_search_path(config) + self.fix_library_search_path(config) end end project.save() @@ -135,10 +125,7 @@ def self.apply_flags_for_fabric(installer, fabric_enabled: false) return if !fabric_enabled fabric_flag = "-DRN_FABRIC_ENABLED" - projects = installer.aggregate_targets - .map{ |t| t.user_project } - .uniq{ |p| p.path } - .push(installer.pods_project) + projects = self.exrtract_projects(installer) projects.each do |project| project.build_configurations.each do |config| @@ -211,26 +198,145 @@ def self.detect_use_frameworks(target_definition) def self.update_search_paths(installer) return if ENV['USE_FRAMEWORKS'] == nil - projects = installer.aggregate_targets - .map{ |t| t.user_project } - .uniq{ |p| p.path } - .push(installer.pods_project) + projects = self.exrtract_projects(installer) projects.each do |project| project.build_configurations.each do |config| + header_search_paths = config.build_settings["HEADER_SEARCH_PATHS"] ||= "$(inherited)" - if !header_search_paths.include?("${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios") - header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios" - header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core" - header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples/platform/ios" - header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples" - end + header_search_paths = self.add_search_path_if_not_included(header_search_paths, "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples") + header_search_paths = self.add_search_path_if_not_included(header_search_paths, "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core") + header_search_paths = self.add_search_path_if_not_included(header_search_paths, "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples/platform/ios") + header_search_paths = self.add_search_path_if_not_included(header_search_paths, "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios") + header_search_paths = self.add_search_path_if_not_included(header_search_paths, "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios") config.build_settings["HEADER_SEARCH_PATHS"] = header_search_paths end project.save() end + + installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result| + if self.react_native_pods.include?(pod_name) || pod_name.include?("Pod") || pod_name.include?("Tests") + next + end + + self.set_rctfolly_search_paths(target_installation_result) + self.set_codegen_search_paths(target_installation_result) + self.set_reactcommon_searchpaths(target_installation_result) + self.set_rctfabric_search_paths(target_installation_result) + self.set_imagemanager_search_path(target_installation_result) + end + end + + def self.exrtract_projects(installer) + return installer.aggregate_targets + .map{ |t| t.user_project } + .uniq{ |p| p.path } + .push(installer.pods_project) + end + + def self.add_search_path_if_not_included(current_search_paths, new_search_path) + if !current_search_paths.include?(new_search_path) + current_search_paths << " #{new_search_path}" + end + return current_search_paths + end + + def self.update_header_paths_if_depends_on(target_installation_result, dependency_name, header_paths) + depends_on_framework = target_installation_result.native_target.dependencies.any? { |d| d.name == dependency_name } + if depends_on_framework + target_installation_result.native_target.build_configurations.each do |config| + header_search_path = config.build_settings["HEADER_SEARCH_PATHS"] != nil ? config.build_settings["HEADER_SEARCH_PATHS"] : "$(inherited)" + header_paths.each { |header| header_search_path = ReactNativePodsUtils.add_search_path_if_not_included(header_search_path, header) } + config.build_settings["HEADER_SEARCH_PATHS"] = header_search_path + end + end + end + + def self.set_rctfolly_search_paths(target_installation_result) + ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "RCT-Folly", [ + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"$(PODS_ROOT)/DoubleConversion\"", + "\"$(PODS_ROOT)/boost\"" + ]) + end + + def self.set_codegen_search_paths(target_installation_result) + ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "React-Codegen", [ + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"", + ]) + end + + def self.set_reactcommon_searchpaths(target_installation_result) + ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "ReactCommon", [ + "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"", + ]) + + end + + def self.set_rctfabric_search_paths(target_installation_result) + ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "React-RCTFabric", [ + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.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\"", + ]) + end + + def self.set_imagemanager_search_path(target_installation_result) + ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "React-ImageManager", [ + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/imagemanager/platform/ios\"" + ]) + end + + def self.react_native_pods + return [ + "DoubleConversion", + "FBLazyVector", + "RCT-Folly", + "RCTRequired", + "RCTTypeSafety", + "React", + "React-Codegen", + "React-Core", + "React-CoreModules", + "React-Fabric", + "React-ImageManager", + "React-RCTActionSheet", + "React-RCTAnimation", + "React-RCTAppDelegate", + "React-RCTBlob", + "React-RCTFabric", + "React-RCTImage", + "React-RCTLinking", + "React-RCTNetwork", + "React-RCTPushNotification", + "React-RCTSettings", + "React-RCTText", + "React-RCTTest", + "React-RCTVibration", + "React-callinvoker", + "React-cxxreact", + "React-graphics", + "React-jsc", + "React-jsi", + "React-jsiexecutor", + "React-jsinspector", + "React-logger", + "React-perflogger", + "React-rncore", + "React-runtimeexecutor", + "ReactCommon", + "Yoga", + "boost", + "fmt", + "glog", + "hermes-engine", + "libevent", + "React-hermes", + ] end end