1# Copyright (c) Meta Platforms, Inc. and affiliates. 2# 3# This source code is licensed under the MIT license found in the 4# LICENSE file in the root directory of this source tree. 5 6require_relative "./helpers.rb" 7 8# Utilities class for React Native Cocoapods 9class ReactNativePodsUtils 10 def self.warn_if_not_on_arm64 11 if SysctlChecker.new().call_sysctl_arm64() == 1 && !Environment.new().ruby_platform().include?('arm64') 12 Pod::UI.warn 'Do not use "pod install" from inside Rosetta2 (x86_64 emulation on arm64).' 13 Pod::UI.warn ' - Emulated x86_64 is slower than native arm64' 14 Pod::UI.warn ' - May result in mixed architectures in rubygems (eg: ffi_c.bundle files may be x86_64 with an arm64 interpreter)' 15 Pod::UI.warn 'Run "env /usr/bin/arch -arm64 /bin/bash --login" then try again.' 16 end 17 end 18 19 def self.get_default_flags 20 flags = { 21 :fabric_enabled => false, 22 :hermes_enabled => true, 23 :flipper_configuration => FlipperConfiguration.disabled 24 } 25 26 if ENV['RCT_NEW_ARCH_ENABLED'] == '1' 27 flags[:fabric_enabled] = true 28 flags[:hermes_enabled] = true 29 end 30 31 if ENV['USE_HERMES'] == '0' 32 flags[:hermes_enabled] = false 33 end 34 35 return flags 36 end 37 38 def self.has_pod(installer, name) 39 installer.pods_project.pod_group(name) != nil 40 end 41 42 def self.turn_off_resource_bundle_react_core(installer) 43 # this is needed for Xcode 14, see more details here https://github.com/facebook/react-native/issues/34673 44 # we should be able to remove this once CocoaPods catches up to it, see more details here https://github.com/CocoaPods/CocoaPods/issues/11402 45 installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result| 46 if pod_name.to_s == 'React-Core' 47 target_installation_result.resource_bundle_targets.each do |resource_bundle_target| 48 resource_bundle_target.build_configurations.each do |config| 49 config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO' 50 end 51 end 52 end 53 end 54 end 55 56 def self.exclude_i386_architecture_while_using_hermes(installer) 57 projects = installer.aggregate_targets 58 .map{ |t| t.user_project } 59 .uniq{ |p| p.path } 60 .push(installer.pods_project) 61 62 63 # Hermes does not support `i386` architecture 64 excluded_archs_default = ReactNativePodsUtils.has_pod(installer, 'hermes-engine') ? "i386" : "" 65 66 projects.each do |project| 67 project.build_configurations.each do |config| 68 config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = excluded_archs_default 69 end 70 71 project.save() 72 end 73 end 74 75 def self.set_node_modules_user_settings(installer, react_native_path) 76 Pod::UI.puts("Setting REACT_NATIVE build settings") 77 projects = installer.aggregate_targets 78 .map{ |t| t.user_project } 79 .uniq{ |p| p.path } 80 .push(installer.pods_project) 81 82 projects.each do |project| 83 project.build_configurations.each do |config| 84 config.build_settings["REACT_NATIVE_PATH"] = File.join("${PODS_ROOT}", "..", react_native_path) 85 end 86 87 project.save() 88 end 89 end 90 91 def self.fix_library_search_paths(installer) 92 projects = installer.aggregate_targets 93 .map{ |t| t.user_project } 94 .uniq{ |p| p.path } 95 .push(installer.pods_project) 96 97 projects.each do |project| 98 project.build_configurations.each do |config| 99 ReactNativePodsUtils.fix_library_search_path(config) 100 end 101 project.native_targets.each do |target| 102 target.build_configurations.each do |config| 103 ReactNativePodsUtils.fix_library_search_path(config) 104 end 105 end 106 project.save() 107 end 108 end 109 110 def self.apply_mac_catalyst_patches(installer) 111 # Fix bundle signing issues 112 installer.pods_project.targets.each do |target| 113 if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle" 114 target.build_configurations.each do |config| 115 config.build_settings['CODE_SIGN_IDENTITY[sdk=macosx*]'] = '-' 116 end 117 end 118 end 119 120 installer.aggregate_targets.each do |aggregate_target| 121 aggregate_target.user_project.native_targets.each do |target| 122 target.build_configurations.each do |config| 123 # Explicitly set dead code stripping flags 124 config.build_settings['DEAD_CODE_STRIPPING'] = 'YES' 125 config.build_settings['PRESERVE_DEAD_CODE_INITS_AND_TERMS'] = 'YES' 126 # Modify library search paths 127 config.build_settings['LIBRARY_SEARCH_PATHS'] = ['$(SDKROOT)/usr/lib/swift', '$(SDKROOT)/System/iOSSupport/usr/lib/swift', '$(inherited)'] 128 end 129 end 130 aggregate_target.user_project.save() 131 end 132 end 133 134 private 135 136 def self.fix_library_search_path(config) 137 lib_search_paths = config.build_settings["LIBRARY_SEARCH_PATHS"] 138 139 if lib_search_paths == nil 140 # No search paths defined, return immediately 141 return 142 end 143 144 if lib_search_paths.include?("$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)") || lib_search_paths.include?("\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"") 145 # $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) causes problem with Xcode 12.5 + arm64 (Apple M1) 146 # since the libraries there are only built for x86_64 and i386. 147 lib_search_paths.delete("$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)") 148 lib_search_paths.delete("\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"") 149 end 150 151 if !(lib_search_paths.include?("$(SDKROOT)/usr/lib/swift") || lib_search_paths.include?("\"$(SDKROOT)/usr/lib/swift\"")) 152 # however, $(SDKROOT)/usr/lib/swift is required, at least if user is not running CocoaPods 1.11 153 lib_search_paths.insert(0, "$(SDKROOT)/usr/lib/swift") 154 end 155 end 156 157 def self.create_xcode_env_if_missing 158 relative_path = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd) 159 file_path = File.join(relative_path, '.xcode.env') 160 if File.exist?(file_path) 161 return 162 end 163 164 system("echo 'export NODE_BINARY=$(command -v node)' > #{file_path}") 165 end 166 167 # It examines the target_definition property and sets the appropriate value for 168 # ENV['USE_FRAMEWORKS'] variable. 169 # 170 # - parameter target_definition: The current target definition 171 def self.detect_use_frameworks(target_definition) 172 if ENV['USE_FRAMEWORKS'] != nil 173 return 174 end 175 176 framework_build_type = target_definition.build_type.to_s 177 178 Pod::UI.puts("Framework build type is #{framework_build_type}") 179 180 if framework_build_type === "static framework" 181 ENV['USE_FRAMEWORKS'] = 'static' 182 elsif framework_build_type === "dynamic framework" 183 ENV['USE_FRAMEWORKS'] = 'dynamic' 184 else 185 ENV['USE_FRAMEWORKS'] = nil 186 end 187 end 188end 189