- App.tsx: full navigation (Auth stack + Main tabs with 5 screens) - Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen - HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors - MapScreen: interactive map with layer toggles (6 layers) - MarketplaceScreen: categories (6), products (5), search - ChatScreen: AI chat with quick prompts (4), bot responses - ProfileScreen: user info, stats, menu (9 items), logout - AlertsScreen: alert list with severity, acknowledge - SensorsScreen: sensor list with type filters (6 types), search - ZonesScreen: zone cards with stats - SettingsScreen: language picker (FR/EN/ES/DE), privacy, about - Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n - Hooks: useSensors, useAlerts, useNotifications, useLocation - Components: Card, Button, LoadingSpinner, ErrorBoundary, Header - Services: iotService, notificationService (with axios API client) - Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN) - Theme: colors.ts with full design system (Blue Ocean palette) - Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
733 lines
33 KiB
Ruby
733 lines
33 KiB
Ruby
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
#
|
|
# This source code is licensed under the MIT license found in the
|
|
# LICENSE file in the root directory of this source tree.
|
|
|
|
require_relative "./helpers.rb"
|
|
|
|
# Utilities class for React Native Cocoapods
|
|
class ReactNativePodsUtils
|
|
def self.warn_if_not_on_arm64
|
|
if SysctlChecker.new().call_sysctl_arm64() == 1 && !Environment.new().ruby_platform().include?('arm64')
|
|
Pod::UI.warn 'Do not use "pod install" from inside Rosetta2 (x86_64 emulation on arm64).'
|
|
Pod::UI.warn ' - Emulated x86_64 is slower than native arm64'
|
|
Pod::UI.warn ' - May result in mixed architectures in rubygems (eg: ffi_c.bundle files may be x86_64 with an arm64 interpreter)'
|
|
Pod::UI.warn 'Run "env /usr/bin/arch -arm64 /bin/bash --login" then try again.'
|
|
end
|
|
end
|
|
|
|
# deprecated. These checks are duplicated in the react_native_pods function
|
|
# and we don't really need them. Removing this function will make it easy to
|
|
# move forward.
|
|
def self.get_default_flags
|
|
flags = {
|
|
:fabric_enabled => false,
|
|
:hermes_enabled => true,
|
|
}
|
|
|
|
if ENV['RCT_NEW_ARCH_ENABLED'] == '1'
|
|
flags[:fabric_enabled] = true
|
|
flags[:hermes_enabled] = true
|
|
end
|
|
|
|
if ENV['USE_HERMES'] == '0'
|
|
flags[:hermes_enabled] = false
|
|
end
|
|
|
|
return flags
|
|
end
|
|
|
|
def self.has_pod(installer, name)
|
|
installer.pods_project.pod_group(name) != nil
|
|
end
|
|
|
|
def self.set_gcc_preprocessor_definition_for_React_hermes(installer)
|
|
self.add_build_settings_to_pod(installer, "GCC_PREPROCESSOR_DEFINITIONS", "HERMES_ENABLE_DEBUGGER=1", "React-hermes", "Debug")
|
|
self.add_build_settings_to_pod(installer, "GCC_PREPROCESSOR_DEFINITIONS", "HERMES_ENABLE_DEBUGGER=1", "hermes-engine", "Debug")
|
|
end
|
|
|
|
def self.turn_off_resource_bundle_react_core(installer)
|
|
# this is needed for Xcode 14, see more details here https://github.com/facebook/react-native/issues/34673
|
|
# we should be able to remove this once CocoaPods catches up to it, see more details here https://github.com/CocoaPods/CocoaPods/issues/11402
|
|
installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result|
|
|
if pod_name.to_s == 'React-Core'
|
|
target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
|
|
resource_bundle_target.build_configurations.each do |config|
|
|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.set_use_hermes_build_setting(installer, hermes_enabled)
|
|
Pod::UI.puts("Setting USE_HERMES build settings")
|
|
projects = self.extract_projects(installer)
|
|
|
|
projects.each do |project|
|
|
project.build_configurations.each do |config|
|
|
config.build_settings["USE_HERMES"] = hermes_enabled
|
|
end
|
|
|
|
project.save()
|
|
end
|
|
end
|
|
|
|
def self.set_node_modules_user_settings(installer, react_native_path)
|
|
Pod::UI.puts("Setting REACT_NATIVE build settings")
|
|
projects = self.extract_projects(installer)
|
|
|
|
projects.each do |project|
|
|
project.build_configurations.each do |config|
|
|
config.build_settings["REACT_NATIVE_PATH"] = File.join("${PODS_ROOT}", "..", react_native_path)
|
|
end
|
|
|
|
project.save()
|
|
end
|
|
end
|
|
|
|
def self.set_ccache_compiler_and_linker_build_settings(installer, react_native_path, ccache_enabled)
|
|
projects = self.extract_projects(installer)
|
|
|
|
ccache_path = `command -v ccache`.strip
|
|
ccache_available = !ccache_path.empty?
|
|
|
|
message_prefix = "[Ccache]"
|
|
|
|
if ccache_available
|
|
Pod::UI.puts("#{message_prefix}: Ccache found at #{ccache_path}")
|
|
end
|
|
|
|
# Using scripts wrapping the ccache executable, to allow injection of configurations
|
|
ccache_clang_sh = File.join("$(REACT_NATIVE_PATH)", 'scripts', 'xcode', 'ccache-clang.sh')
|
|
ccache_clangpp_sh = File.join("$(REACT_NATIVE_PATH)", 'scripts', 'xcode', 'ccache-clang++.sh')
|
|
|
|
if ccache_available and ccache_enabled
|
|
Pod::UI.puts("#{message_prefix}: Setting CC, LD, CXX & LDPLUSPLUS build settings")
|
|
|
|
projects.each do |project|
|
|
project.build_configurations.each do |config|
|
|
# Using the un-qualified names means you can swap in different implementations, for example ccache
|
|
config.build_settings["CC"] = ccache_clang_sh
|
|
config.build_settings["LD"] = ccache_clang_sh
|
|
config.build_settings["CXX"] = ccache_clangpp_sh
|
|
config.build_settings["LDPLUSPLUS"] = ccache_clangpp_sh
|
|
end
|
|
|
|
project.save()
|
|
end
|
|
elsif ccache_available and !ccache_enabled
|
|
Pod::UI.puts("#{message_prefix}: Pass ':ccache_enabled => true' to 'react_native_post_install' in your Podfile or set environment variable 'USE_CCACHE=1' to increase the speed of subsequent builds")
|
|
elsif !ccache_available and ccache_enabled
|
|
Pod::UI.warn("#{message_prefix}: Install ccache or ensure your neither passing ':ccache_enabled => true' nor setting environment variable 'USE_CCACHE=1'")
|
|
else
|
|
Pod::UI.puts("#{message_prefix}: Removing Ccache from CC, LD, CXX & LDPLUSPLUS build settings")
|
|
|
|
projects.each do |project|
|
|
project.build_configurations.each do |config|
|
|
# Using the un-qualified names means you can swap in different implementations, for example ccache
|
|
config.build_settings["CC"] = config.build_settings["CC"] ? config.build_settings["CC"].gsub(/#{Regexp.escape(ccache_clang_sh)}/, '') : ""
|
|
config.build_settings["LD"] = config.build_settings["LD"] ? config.build_settings["LD"].gsub(/#{Regexp.escape(ccache_clang_sh)}/, "") : ""
|
|
config.build_settings["CXX"] = config.build_settings["CXX"] ? config.build_settings["CXX"].gsub(/#{Regexp.escape(ccache_clangpp_sh)}/, "") : ""
|
|
config.build_settings["LDPLUSPLUS"] = config.build_settings["LDPLUSPLUS"] ? config.build_settings["LDPLUSPLUS"].gsub(/#{Regexp.escape(ccache_clangpp_sh)}/, "") : ""
|
|
end
|
|
|
|
project.save()
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.fix_library_search_paths(installer)
|
|
projects = self.extract_projects(installer)
|
|
|
|
projects.each do |project|
|
|
project.build_configurations.each do |config|
|
|
self.fix_library_search_path(config)
|
|
end
|
|
project.native_targets.each do |target|
|
|
target.build_configurations.each do |config|
|
|
self.fix_library_search_path(config)
|
|
end
|
|
end
|
|
project.save()
|
|
end
|
|
end
|
|
|
|
def self.apply_mac_catalyst_patches(installer)
|
|
# Fix bundle signing issues
|
|
installer.pods_project.targets.each do |target|
|
|
if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle"
|
|
target.build_configurations.each do |config|
|
|
config.build_settings['CODE_SIGN_IDENTITY[sdk=macosx*]'] = '-'
|
|
end
|
|
end
|
|
end
|
|
|
|
installer.aggregate_targets.each do |aggregate_target|
|
|
aggregate_target.user_project.native_targets.each do |target|
|
|
target.build_configurations.each do |config|
|
|
# Explicitly set dead code stripping flags
|
|
config.build_settings['DEAD_CODE_STRIPPING'] = 'YES'
|
|
config.build_settings['PRESERVE_DEAD_CODE_INITS_AND_TERMS'] = 'YES'
|
|
# Modify library search paths
|
|
config.build_settings['LIBRARY_SEARCH_PATHS'] = ['$(SDKROOT)/usr/lib/swift', '$(SDKROOT)/System/iOSSupport/usr/lib/swift', '$(inherited)']
|
|
end
|
|
end
|
|
aggregate_target.user_project.save()
|
|
end
|
|
end
|
|
|
|
def self.apply_xcode_15_patch(installer, xcodebuild_manager: Xcodebuild)
|
|
projects = self.extract_projects(installer)
|
|
|
|
other_ld_flags_key = 'OTHER_LDFLAGS'
|
|
xcode15_compatibility_flags = '-Wl -ld_classic '
|
|
|
|
projects.each do |project|
|
|
project.build_configurations.each do |config|
|
|
# fix for weak linking
|
|
self.safe_init(config, other_ld_flags_key)
|
|
if self.is_using_xcode15_0(:xcodebuild_manager => xcodebuild_manager)
|
|
self.add_value_to_setting_if_missing(config, other_ld_flags_key, xcode15_compatibility_flags)
|
|
else
|
|
self.remove_value_from_setting_if_present(config, other_ld_flags_key, xcode15_compatibility_flags)
|
|
end
|
|
end
|
|
project.save()
|
|
end
|
|
|
|
end
|
|
|
|
private
|
|
|
|
def self.add_build_settings_to_pod(installer, settings_name, settings_value, target_pod_name, configuration)
|
|
installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result|
|
|
if pod_name.to_s == target_pod_name
|
|
target_installation_result.native_target.build_configurations.each do |config|
|
|
if configuration == nil || (configuration != nil && config.name.include?(configuration))
|
|
config.build_settings[settings_name] ||= '$(inherited) '
|
|
config.build_settings[settings_name] << settings_value
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.fix_library_search_path(config)
|
|
lib_search_paths = config.build_settings["LIBRARY_SEARCH_PATHS"]
|
|
|
|
if lib_search_paths == nil
|
|
# No search paths defined, return immediately
|
|
return
|
|
end
|
|
|
|
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)\"")
|
|
# $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) causes problem with Xcode 12.5 + arm64 (Apple Silicon)
|
|
# since the libraries there are only built for x86_64 and i386.
|
|
lib_search_paths.delete("$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)")
|
|
lib_search_paths.delete("\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"")
|
|
end
|
|
|
|
if !(lib_search_paths.include?("$(SDKROOT)/usr/lib/swift") || lib_search_paths.include?("\"$(SDKROOT)/usr/lib/swift\""))
|
|
# however, $(SDKROOT)/usr/lib/swift is required, at least if user is not running CocoaPods 1.11
|
|
lib_search_paths.insert(0, "$(SDKROOT)/usr/lib/swift")
|
|
end
|
|
end
|
|
|
|
def self.create_xcode_env_if_missing(file_manager: File)
|
|
relative_path = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)
|
|
file_path = file_manager.join(relative_path, '.xcode.env')
|
|
|
|
if !file_manager.exist?(file_path)
|
|
system("echo 'export NODE_BINARY=$(command -v node)' > #{file_path}")
|
|
end
|
|
|
|
if !file_manager.exist?("#{file_path}.local")
|
|
node_binary = `command -v node`
|
|
system("echo 'export NODE_BINARY=#{node_binary}' > #{file_path}.local")
|
|
end
|
|
end
|
|
|
|
# It examines the target_definition property and sets the appropriate value for
|
|
# ENV['USE_FRAMEWORKS'] variable.
|
|
#
|
|
# - parameter target_definition: The current target definition
|
|
def self.detect_use_frameworks(target_definition)
|
|
if ENV['USE_FRAMEWORKS'] != nil
|
|
return
|
|
end
|
|
|
|
framework_build_type = target_definition.build_type.to_s
|
|
|
|
Pod::UI.puts("Framework build type is #{framework_build_type}")
|
|
|
|
if framework_build_type === "static framework"
|
|
ENV['USE_FRAMEWORKS'] = 'static'
|
|
elsif framework_build_type === "dynamic framework"
|
|
ENV['USE_FRAMEWORKS'] = 'dynamic'
|
|
else
|
|
ENV['USE_FRAMEWORKS'] = nil
|
|
end
|
|
end
|
|
|
|
def self.create_header_search_path_for_frameworks(base_folder, pod_name, framework_name, additional_paths, include_base_path = true)
|
|
platforms = $RN_PLATFORMS != nil ? $RN_PLATFORMS : []
|
|
search_paths = []
|
|
|
|
if platforms.empty?() || platforms.length() == 1
|
|
base_path = File.join("${#{base_folder}}", pod_name, "#{framework_name}.framework", "Headers")
|
|
self.add_search_path_to_result(search_paths, base_path, additional_paths, include_base_path)
|
|
else
|
|
platforms.each { |platform|
|
|
base_path = File.join("${#{base_folder}}", "#{pod_name}-#{platform}", "#{framework_name}.framework", "Headers")
|
|
self.add_search_path_to_result(search_paths, base_path, additional_paths, include_base_path)
|
|
}
|
|
end
|
|
return search_paths
|
|
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
|
|
optional_current_search_path = spec.to_hash["pod_target_xcconfig"]["HEADER_SEARCH_PATHS"]
|
|
current_search_paths = (optional_current_search_path != nil ? optional_current_search_path : "")
|
|
.split(" ")
|
|
create_header_search_path_for_frameworks(base_folder_for_frameworks, dependency_name, framework_name, additional_paths)
|
|
.each { |path|
|
|
wrapped_path = "\"#{path}\""
|
|
current_search_paths << wrapped_path
|
|
}
|
|
current_pod_target_xcconfig = spec.to_hash["pod_target_xcconfig"]
|
|
current_pod_target_xcconfig["HEADER_SEARCH_PATHS"] = current_search_paths.join(" ")
|
|
spec.pod_target_xcconfig = current_pod_target_xcconfig
|
|
|
|
actual_dependency = subspec_dependency != nil ? "#{dependency_name}/#{subspec_dependency}" : dependency_name
|
|
# Set Dependency
|
|
if !version
|
|
spec.dependency actual_dependency
|
|
else
|
|
spec.dependency actual_dependency, version
|
|
end
|
|
end
|
|
|
|
def self.update_search_paths(installer)
|
|
return if ENV['USE_FRAMEWORKS'] == nil
|
|
|
|
projects = self.extract_projects(installer)
|
|
|
|
projects.each do |project|
|
|
project.build_configurations.each do |config|
|
|
|
|
header_search_paths = config.build_settings["HEADER_SEARCH_PATHS"] ||= "$(inherited)"
|
|
|
|
ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "ReactCommon", "ReactCommon", ["react/nativemodule/core"])
|
|
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "ReactCommon-Samples", "ReactCommon_Samples", ["platform/ios"]))
|
|
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-Fabric", "React_Fabric", ["react/renderer/components/view/platform/cxx"], false))
|
|
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-NativeModulesApple", "React_NativeModulesApple", []))
|
|
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-graphics", "React_graphics", ["react/renderer/graphics/platform/ios"]))
|
|
.each{ |search_path|
|
|
header_search_paths = self.add_search_path_if_not_included(header_search_paths, search_path)
|
|
}
|
|
|
|
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.updateOSDeploymentTarget(installer)
|
|
installer.target_installation_results.pod_target_installation_results
|
|
.each do |pod_name, target_installation_result|
|
|
target_installation_result.native_target.build_configurations.each do |config|
|
|
old_iphone_deploy_target = config.build_settings["IPHONEOS_DEPLOYMENT_TARGET"] ?
|
|
config.build_settings["IPHONEOS_DEPLOYMENT_TARGET"] :
|
|
Helpers::Constants.min_ios_version_supported
|
|
config.build_settings["IPHONEOS_DEPLOYMENT_TARGET"] = [Helpers::Constants.min_ios_version_supported.to_f, old_iphone_deploy_target.to_f].max.to_s
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.set_dynamic_frameworks_flags(installer)
|
|
installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result|
|
|
|
|
# Set "RCT_DYNAMIC_FRAMEWORKS=1" if pod are installed with USE_FRAMEWORKS=dynamic
|
|
# This helps with backward compatibility.
|
|
if pod_name == 'React-RCTFabric' && ENV['USE_FRAMEWORKS'] == 'dynamic'
|
|
Pod::UI.puts "Setting -DRCT_DYNAMIC_FRAMEWORKS=1 to React-RCTFabric".green
|
|
rct_dynamic_framework_flag = " -DRCT_DYNAMIC_FRAMEWORKS=1"
|
|
target_installation_result.native_target.build_configurations.each do |config|
|
|
prev_build_settings = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "$(inherithed)"
|
|
config.build_settings['OTHER_CPLUSPLUSFLAGS'] = prev_build_settings + rct_dynamic_framework_flag
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# ========= #
|
|
# Utilities #
|
|
# ========= #
|
|
|
|
def self.extract_projects(installer)
|
|
return installer.aggregate_targets
|
|
.map{ |t| t.user_project }
|
|
.uniq{ |p| p.path }
|
|
.push(installer.pods_project)
|
|
end
|
|
|
|
def self.safe_init(config, setting_name)
|
|
old_config = config.build_settings[setting_name]
|
|
if old_config == nil
|
|
config.build_settings[setting_name] ||= '$(inherited) '
|
|
end
|
|
end
|
|
|
|
def self.add_value_to_setting_if_missing(config, setting_name, value)
|
|
old_config = config.build_settings[setting_name]
|
|
if old_config.is_a?(Array)
|
|
old_config = old_config.join(" ")
|
|
end
|
|
|
|
trimmed_value = value.strip()
|
|
if !old_config.include?(trimmed_value)
|
|
config.build_settings[setting_name] = "#{old_config.strip()} #{trimmed_value}".strip()
|
|
end
|
|
end
|
|
|
|
def self.remove_value_from_setting_if_present(config, setting_name, value)
|
|
old_config = config.build_settings[setting_name]
|
|
if old_config.is_a?(Array)
|
|
old_config = old_config.join(" ")
|
|
end
|
|
|
|
trimmed_value = value.strip()
|
|
if old_config.include?(trimmed_value)
|
|
new_config = old_config.gsub(trimmed_value, "")
|
|
config.build_settings[setting_name] = new_config.strip()
|
|
end
|
|
end
|
|
|
|
def self.is_using_xcode15_0(xcodebuild_manager: Xcodebuild)
|
|
xcodebuild_version = xcodebuild_manager.version
|
|
|
|
if version = self.parse_xcode_version(xcodebuild_version)
|
|
return version["major"] == 15 && version["minor"] == 0
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
def self.parse_xcode_version(version_string)
|
|
# The output of xcodebuild -version is something like
|
|
# Xcode 15.0
|
|
# or
|
|
# Xcode 14.3.1
|
|
# We want to capture the version digits
|
|
match = version_string.match(/(\d+)\.(\d+)(?:\.(\d+))?/)
|
|
return nil if match.nil?
|
|
|
|
return {"str" => match[0], "major" => match[1].to_i, "minor" => match[2].to_i};
|
|
end
|
|
|
|
def self.check_minimum_required_xcode(xcodebuild_manager: Xcodebuild)
|
|
version = self.parse_xcode_version(xcodebuild_manager.version)
|
|
if (version.nil? || !Gem::Version::correct?(version["str"]))
|
|
Pod::UI.warn "Unexpected XCode version string '#{xcodebuild_manager.version}'"
|
|
return
|
|
end
|
|
|
|
current = version["str"]
|
|
min_required = Helpers::Constants.min_xcode_version_supported
|
|
|
|
if Gem::Version::new(current) < Gem::Version::new(min_required)
|
|
Pod::UI.puts "React Native requires XCode >= #{min_required}. Found #{current}.".red
|
|
raise "Please upgrade XCode"
|
|
end
|
|
end
|
|
|
|
def self.add_compiler_flag_to_project(installer, flag, configuration: nil)
|
|
projects = self.extract_projects(installer)
|
|
|
|
projects.each do |project|
|
|
project.build_configurations.each do |config|
|
|
self.set_flag_in_config(config, flag, configuration: configuration)
|
|
end
|
|
project.save()
|
|
end
|
|
end
|
|
|
|
def self.remove_compiler_flag_from_project(installer, flag, configuration: nil)
|
|
projects = self.extract_projects(installer)
|
|
|
|
projects.each do |project|
|
|
project.build_configurations.each do |config|
|
|
self.remove_flag_in_config(config, flag, configuration: configuration)
|
|
end
|
|
project.save()
|
|
end
|
|
end
|
|
|
|
def self.add_compiler_flag_to_pods(installer, flag, configuration: nil)
|
|
installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result|
|
|
target_installation_result.native_target.build_configurations.each do |config|
|
|
self.set_flag_in_config(config, flag, configuration: configuration)
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.set_flag_in_config(config, flag, configuration: nil)
|
|
if configuration == nil || config.name == configuration
|
|
self.add_flag_for_key(config, flag, "OTHER_CFLAGS")
|
|
self.add_flag_for_key(config, flag, "OTHER_CPLUSPLUSFLAGS")
|
|
end
|
|
end
|
|
|
|
def self.remove_flag_in_config(config, flag, configuration: nil)
|
|
if configuration == nil || config.name == configuration
|
|
self.remove_flag_for_key(config, flag, "OTHER_CFLAGS")
|
|
self.remove_flag_for_key(config, flag, "OTHER_CPLUSPLUSFLAGS")
|
|
end
|
|
end
|
|
|
|
|
|
def self.add_flag_for_key(config, flag, key)
|
|
current_setting = config.build_settings[key] ? config.build_settings[key] : "$(inherited)"
|
|
|
|
if current_setting.kind_of?(Array)
|
|
current_setting = current_setting
|
|
.map { |s| s.gsub('"', '') }
|
|
.map { |s| s.gsub('\"', '') }
|
|
.join(" ")
|
|
end
|
|
|
|
if !current_setting.include?(flag)
|
|
current_setting = "#{current_setting} #{flag}"
|
|
end
|
|
|
|
config.build_settings[key] = current_setting
|
|
end
|
|
|
|
def self.remove_flag_for_key(config, flag, key)
|
|
current_setting = config.build_settings[key] ? config.build_settings[key] : "$(inherited)"
|
|
|
|
if current_setting.kind_of?(Array)
|
|
current_setting = current_setting
|
|
.map { |s| s.gsub('"', '') }
|
|
.map { |s| s.gsub('\"', '') }
|
|
.join(" ")
|
|
end
|
|
|
|
if current_setting.include?(flag)
|
|
current_setting.slice! flag
|
|
end
|
|
|
|
config.build_settings[key] = current_setting
|
|
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)/fmt/include\"",
|
|
"\"$(PODS_ROOT)/boost\""
|
|
])
|
|
end
|
|
|
|
def self.set_codegen_search_paths(target_installation_result)
|
|
header_search_paths = ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-Codegen", "React_Codegen", [])
|
|
.map { |search_path| "\"#{search_path}\"" }
|
|
ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "React-Codegen", header_search_paths)
|
|
end
|
|
|
|
def self.set_reactcommon_searchpaths(target_installation_result)
|
|
header_search_paths = ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "ReactCommon", "ReactCommon", ["react/nativemodule/core"])
|
|
.map { |search_path| "\"#{search_path}\"" }
|
|
ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "ReactCommon", header_search_paths)
|
|
end
|
|
|
|
def self.set_rctfabric_search_paths(target_installation_result)
|
|
header_search_paths = ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-RCTFabric", "RCTFabric", [])
|
|
.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-FabricImage", "React_FabricImage", []))
|
|
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-Graphics", "React_graphics", ["react/renderer/graphics/platform/ios"]))
|
|
.map { |search_path| "\"#{search_path}\"" }
|
|
|
|
ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "React-RCTFabric", header_search_paths)
|
|
end
|
|
|
|
def self.set_imagemanager_search_path(target_installation_result)
|
|
header_search_paths = ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-Fabric", "React_Fabric", ["react/renderer/imagemanager/platform/ios"])
|
|
.map { |search_path| "\"#{search_path}\"" }
|
|
ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "React-ImageManager", header_search_paths)
|
|
end
|
|
|
|
def self.get_privacy_manifest_paths_from(user_project)
|
|
privacy_manifests = user_project
|
|
.files
|
|
.select { |p|
|
|
p.path&.end_with?('PrivacyInfo.xcprivacy')
|
|
}
|
|
return privacy_manifests
|
|
end
|
|
|
|
def self.add_privacy_manifest_if_needed(installer)
|
|
user_project = installer.aggregate_targets
|
|
.map{ |t| t.user_project }
|
|
.first
|
|
privacy_manifest = self.get_privacy_manifest_paths_from(user_project).first
|
|
if privacy_manifest.nil?
|
|
file_timestamp_reason = {
|
|
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryFileTimestamp",
|
|
"NSPrivacyAccessedAPITypeReasons" => ["C617.1"],
|
|
}
|
|
user_defaults_reason = {
|
|
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryUserDefaults",
|
|
"NSPrivacyAccessedAPITypeReasons" => ["CA92.1"],
|
|
}
|
|
boot_time_reason = {
|
|
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategorySystemBootTime",
|
|
"NSPrivacyAccessedAPITypeReasons" => ["35F9.1"],
|
|
}
|
|
privacy_manifest = {
|
|
"NSPrivacyCollectedDataTypes" => [],
|
|
"NSPrivacyTracking" => false,
|
|
"NSPrivacyAccessedAPITypes" => [file_timestamp_reason, user_defaults_reason, boot_time_reason]
|
|
}
|
|
path = File.join(user_project.path.parent, "PrivacyInfo.xcprivacy")
|
|
Xcodeproj::Plist.write_to_path(privacy_manifest, path)
|
|
Pod::UI.puts "Your app does not have a privacy manifest! A template has been generated containing Required Reasons API usage in the core React Native library. Please add the PrivacyInfo.xcprivacy file to your project and complete data use, tracking and any additional required reasons your app is using according to Apple's guidance: https://developer.apple.com/.../privacy_manifest_files. Then, you will need to manually add this file to your project in Xcode.".red
|
|
end
|
|
end
|
|
|
|
def self.react_native_pods
|
|
return [
|
|
"DoubleConversion",
|
|
"FBLazyVector",
|
|
"RCT-Folly",
|
|
"RCTRequired",
|
|
"RCTTypeSafety",
|
|
"React",
|
|
"React-Codegen",
|
|
"React-Core",
|
|
"React-CoreModules",
|
|
"React-Fabric",
|
|
"React-FabricImage",
|
|
"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",
|
|
"React-hermes",
|
|
]
|
|
end
|
|
|
|
def self.add_search_path_to_result(result, base_path, additional_paths, include_base_path)
|
|
if (include_base_path)
|
|
result << base_path
|
|
end
|
|
|
|
additional_paths.each { |extra_path|
|
|
result << File.join(base_path, extra_path)
|
|
}
|
|
return result
|
|
end
|
|
|
|
def self.add_ndebug_flag_to_pods_in_release(installer)
|
|
ndebug_flag = " -DNDEBUG"
|
|
|
|
installer.aggregate_targets.each do |aggregate_target|
|
|
aggregate_target.xcconfigs.each do |config_name, config_file|
|
|
is_release = config_name.downcase.include?("release") || config_name.downcase.include?("production")
|
|
unless is_release
|
|
next
|
|
end
|
|
self.add_flag_to_map_with_inheritance(config_file.attributes, 'OTHER_CPLUSPLUSFLAGS', ndebug_flag);
|
|
self.add_flag_to_map_with_inheritance(config_file.attributes, 'OTHER_CFLAGS', ndebug_flag);
|
|
|
|
xcconfig_path = aggregate_target.xcconfig_path(config_name)
|
|
config_file.save_as(xcconfig_path)
|
|
end
|
|
end
|
|
|
|
installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result|
|
|
target_installation_result.native_target.build_configurations.each do |config|
|
|
is_release = config.name.downcase.include?("release") || config.name.downcase.include?("production")
|
|
unless is_release
|
|
next
|
|
end
|
|
self.add_flag_to_map_with_inheritance(config.build_settings, 'OTHER_CPLUSPLUSFLAGS', ndebug_flag);
|
|
self.add_flag_to_map_with_inheritance(config.build_settings, 'OTHER_CFLAGS', ndebug_flag);
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.add_flag_to_map_with_inheritance(map, field, flag)
|
|
if map[field] == nil
|
|
map[field] = "$(inherited)" + flag
|
|
else
|
|
unless map[field].include?(flag)
|
|
map[field] = map[field] + flag
|
|
end
|
|
unless map[field].include?("$(inherited)")
|
|
map[field] = "$(inherited) " + map[field]
|
|
end
|
|
end
|
|
end
|
|
end
|