react-native-macos/scripts/react_native_pods.rb

358 строки
16 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 'json'
require 'open3'
require 'pathname'
require_relative './react_native_pods_utils/script_phases.rb'
require_relative './cocoapods/jsengine.rb'
require_relative './cocoapods/flipper.rb'
require_relative './cocoapods/fabric.rb'
require_relative './cocoapods/codegen.rb'
require_relative './cocoapods/codegen_utils.rb'
require_relative './cocoapods/utils.rb'
require_relative './cocoapods/new_architecture.rb'
require_relative './cocoapods/local_podspec_patch.rb'
$CODEGEN_OUTPUT_DIR = 'build/generated/ios'
$CODEGEN_COMPONENT_DIR = 'react/renderer/components'
$CODEGEN_MODULE_DIR = '.'
$FOLLY_VERSION = '2021.07.22.00'
$START_TIME = Time.now.to_i
# This function returns the min iOS version supported by React Native
# By using this function, you won't have to manualy change your Podfile
# when we change the minimum version supported by the framework.
def min_ios_version_supported
return '12.4'
end
# This function prepares the project for React Native, before processing
# all the target exposed by the framework.
def prepare_react_native_project!
# Temporary solution to suppress duplicated GUID error.
# Can be removed once we move to generate files outside pod install.
install! 'cocoapods', :deterministic_uuids => false
ReactNativePodsUtils.create_xcode_env_if_missing
end
# Function that setup all the react native dependencies
# 
# Parameters
# - path: path to react_native installation.
# - fabric_enabled: whether fabric should be enabled or not.
# - new_arch_enabled: whether the new architecture should be enabled or not.
# - production: whether the dependencies must be installed to target a Debug or a Release build.
# - hermes_enabled: whether Hermes should be enabled or not.
# - flipper_configuration: The configuration to use for flipper.
# - app_path: path to the React Native app. Required by the New Architecture.
# - config_file_dir: directory of the `package.json` file, required by the New Architecture.
# - ios_folder: the folder where the iOS code base lives. For a template app, it is `ios`, the default. For RNTester, it is `.`.
def use_react_native! (
path: "../node_modules/react-native",
fabric_enabled: false,
new_arch_enabled: ENV['RCT_NEW_ARCH_ENABLED'] == '1',
production: ENV['PRODUCTION'] == '1',
hermes_enabled: ENV['USE_HERMES'] && ENV['USE_HERMES'] == '0' ? false : true,
flipper_configuration: FlipperConfiguration.disabled,
app_path: '..',
config_file_dir: '',
ios_folder: 'ios'
)
# Current target definition is provided by Cocoapods and it refers to the target
# that has invoked the `use_react_native!` function.
ReactNativePodsUtils.detect_use_frameworks(current_target_definition)
CodegenUtils.clean_up_build_folder(path, app_path, ios_folder, $CODEGEN_OUTPUT_DIR)
# We are relying on this flag also in third parties libraries to proper install dependencies.
# Better to rely and enable this environment flag if the new architecture is turned on using flags.
ENV['RCT_NEW_ARCH_ENABLED'] = new_arch_enabled ? "1" : "0"
fabric_enabled = fabric_enabled || new_arch_enabled
ENV['USE_HERMES'] = hermes_enabled ? "1" : "0"
prefix = path
ReactNativePodsUtils.warn_if_not_on_arm64()
# The Pods which should be included in all projects
pod 'FBLazyVector', :path => "#{prefix}/Libraries/FBLazyVector"
pod 'FBReactNativeSpec', :path => "#{prefix}/React/FBReactNativeSpec" if !new_arch_enabled
pod 'RCTRequired', :path => "#{prefix}/Libraries/RCTRequired"
pod 'RCTTypeSafety', :path => "#{prefix}/Libraries/TypeSafety", :modular_headers => true
pod 'React', :path => "#{prefix}/"
pod 'React-Core', :path => "#{prefix}/"
pod 'React-CoreModules', :path => "#{prefix}/React/CoreModules"
pod 'React-RCTAppDelegate', :path => "#{prefix}/Libraries/AppDelegate"
pod 'React-RCTActionSheet', :path => "#{prefix}/Libraries/ActionSheetIOS"
pod 'React-RCTAnimation', :path => "#{prefix}/Libraries/NativeAnimation"
pod 'React-RCTBlob', :path => "#{prefix}/Libraries/Blob"
pod 'React-RCTImage', :path => "#{prefix}/Libraries/Image"
pod 'React-RCTLinking', :path => "#{prefix}/Libraries/LinkingIOS"
pod 'React-RCTNetwork', :path => "#{prefix}/Libraries/Network"
pod 'React-RCTSettings', :path => "#{prefix}/Libraries/Settings"
pod 'React-RCTText', :path => "#{prefix}/Libraries/Text"
pod 'React-RCTVibration', :path => "#{prefix}/Libraries/Vibration"
pod 'React-Core/RCTWebSocket', :path => "#{prefix}/"
pod 'React-rncore', :path => "#{prefix}/ReactCommon"
pod 'React-cxxreact', :path => "#{prefix}/ReactCommon/cxxreact"
if hermes_enabled
setup_hermes!(:react_native_path => prefix, :fabric_enabled => fabric_enabled)
else
setup_jsc!(:react_native_path => prefix, :fabric_enabled => fabric_enabled)
end
pod 'React-jsiexecutor', :path => "#{prefix}/ReactCommon/jsiexecutor"
pod 'React-jsinspector', :path => "#{prefix}/ReactCommon/jsinspector"
pod 'React-callinvoker', :path => "#{prefix}/ReactCommon/callinvoker"
pod 'React-runtimeexecutor', :path => "#{prefix}/ReactCommon/runtimeexecutor"
pod 'React-perflogger', :path => "#{prefix}/ReactCommon/reactperflogger"
pod 'React-logger', :path => "#{prefix}/ReactCommon/logger"
pod 'ReactCommon/turbomodule/core', :path => "#{prefix}/ReactCommon", :modular_headers => true
pod 'Yoga', :path => "#{prefix}/ReactCommon/yoga", :modular_headers => true
pod 'DoubleConversion', :podspec => "#{prefix}/third-party-podspecs/DoubleConversion.podspec"
pod 'glog', :podspec => "#{prefix}/third-party-podspecs/glog.podspec"
pod 'boost', :podspec => "#{prefix}/third-party-podspecs/boost.podspec"
pod 'RCT-Folly', :podspec => "#{prefix}/third-party-podspecs/RCT-Folly.podspec", :modular_headers => true
run_codegen!(
app_path,
config_file_dir,
:new_arch_enabled => new_arch_enabled,
:disable_codegen => ENV['DISABLE_CODEGEN'] == '1',
:react_native_path => prefix,
:fabric_enabled => fabric_enabled,
:hermes_enabled => hermes_enabled,
:codegen_output_dir => $CODEGEN_OUTPUT_DIR,
:package_json_file => File.join(__dir__, "..", "package.json"),
:folly_version => $FOLLY_VERSION
)
pod 'React-Codegen', :path => $CODEGEN_OUTPUT_DIR, :modular_headers => true
if fabric_enabled
checkAndGenerateEmptyThirdPartyProvider!(prefix, new_arch_enabled)
setup_fabric!(:react_native_path => prefix, new_arch_enabled: new_arch_enabled)
else
relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)
build_codegen!(prefix, relative_installation_root)
end
# CocoaPods `configurations` option ensures that the target is copied only for the specified configurations,
# but those dependencies are still built.
# Flipper doesn't currently compile for release https://github.com/facebook/react-native/issues/33764
# Setting the production flag to true when build for production make sure that we don't install Flipper in the app in the first place.
if flipper_configuration.flipper_enabled && !production
install_flipper_dependencies(prefix)
use_flipper_pods(flipper_configuration.versions, :configurations => flipper_configuration.configurations)
end
pods_to_update = LocalPodspecPatch.pods_to_update(:react_native_path => prefix)
if !pods_to_update.empty?
if Pod::Lockfile.public_instance_methods.include?(:detect_changes_with_podfile)
Pod::Lockfile.prepend(LocalPodspecPatch)
else
Pod::UI.warn "Automatically updating #{pods_to_update.join(", ")} has failed, please run `pod update #{pods_to_update.join(" ")} --no-repo-update` manually to fix the issue."
end
end
end
# Getter to retrieve the folly flags in case contributors need to apply them manually.
#
# Returns: the folly compiler flags
def folly_flags()
return NewArchitectureHelper.folly_compiler_flags
end
# This function can be used by library developer to prepare their modules for the New Architecture.
# It passes the Folly Flags to the module, it configures the search path and installs some New Architecture specific dependencies.
#
# Parameters:
# - spec: The spec that has to be configured with the New Architecture code
# - new_arch_enabled: Whether the module should install dependencies for the new architecture
def install_modules_dependencies(spec, new_arch_enabled: ENV['RCT_NEW_ARCH_ENABLED'] == "1")
NewArchitectureHelper.install_modules_dependencies(spec, new_arch_enabled, $FOLLY_VERSION)
end
# It returns the default flags.
def get_default_flags()
return ReactNativePodsUtils.get_default_flags()
end
# It installs the flipper dependencies into the project.
#
# Parameters
# - versions: a dictionary of Flipper Library -> Versions that can be used to customize which version of Flipper to install.
# - configurations: an array of configuration where to install the dependencies.
def use_flipper!(versions = {}, configurations: ['Debug'])
Pod::UI.warn "use_flipper is deprecated, use the flipper_configuration option in the use_react_native function"
use_flipper_pods(versions, :configurations => configurations)
end
# Function that executes after React Native has been installed to configure some flags and build settings.
#
# Parameters
# - installer: the Cocoapod object that allows to customize the project.
# - react_native_path: path to React Native.
# - mac_catalyst_enabled: whether we are running the Pod on a Mac Catalyst project or not.
def react_native_post_install(installer, react_native_path = "../node_modules/react-native", mac_catalyst_enabled: false)
ReactNativePodsUtils.turn_off_resource_bundle_react_core(installer)
ReactNativePodsUtils.apply_mac_catalyst_patches(installer) if mac_catalyst_enabled
if ReactNativePodsUtils.has_pod(installer, 'Flipper')
flipper_post_install(installer)
end
fabric_enabled = ReactNativePodsUtils.has_pod(installer, 'React-Fabric')
ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer)
ReactNativePodsUtils.fix_library_search_paths(installer)
ReactNativePodsUtils.update_search_paths(installer)
ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path)
ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: fabric_enabled)
NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer)
is_new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == "1"
NewArchitectureHelper.modify_flags_for_new_architecture(installer, is_new_arch_enabled)
Pod::UI.puts "Pod install took #{Time.now.to_i - $START_TIME} [s] to run".green
end
# === LEGACY METHOD ===
# We need to keep this while we continue to support the old architecture.
# =====================
def use_react_native_codegen!(spec, options={})
return if ENV['RCT_NEW_ARCH_ENABLED'] == "1"
# TODO: Once the new codegen approach is ready for use, we should output a warning here to let folks know to migrate.
# The prefix to react-native
react_native_path = options[:react_native_path] ||= "../.."
# Library name (e.g. FBReactNativeSpec)
library_name = options[:library_name] ||= "#{spec.name.gsub('_','-').split('-').collect(&:capitalize).join}Spec"
Pod::UI.puts "[Codegen] Found #{library_name}"
relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)
output_dir = options[:output_dir] ||= $CODEGEN_OUTPUT_DIR
output_dir_module = "#{output_dir}/#{$CODEGEN_MODULE_DIR}"
output_dir_component = "#{output_dir}/#{$CODEGEN_COMPONENT_DIR}"
codegen_config = {
"modules" => {
:js_srcs_pattern => "Native*.js",
:generated_dir => "#{relative_installation_root}/#{output_dir_module}/#{library_name}",
:generated_files => [
"#{library_name}.h",
"#{library_name}-generated.mm"
]
},
"components" => {
:js_srcs_pattern => "*NativeComponent.js",
:generated_dir => "#{relative_installation_root}/#{output_dir_component}/#{library_name}",
:generated_files => [
"ComponentDescriptors.h",
"EventEmitters.cpp",
"EventEmitters.h",
"Props.cpp",
"Props.h",
"States.cpp",
"States.h",
"RCTComponentViewHelpers.h",
"ShadowNodes.cpp",
"ShadowNodes.h"
]
}
}
# The path to JavaScript files
js_srcs_dir = options[:js_srcs_dir] ||= "./"
library_type = options[:library_type]
if library_type
if !codegen_config[library_type]
raise "[Codegen] invalid library_type: #{library_type}. Check your podspec to make sure it's set to 'modules' or 'components'. Removing the option will generate files for both"
end
js_srcs_pattern = codegen_config[library_type][:js_srcs_pattern]
end
if library_type
generated_dirs = [ codegen_config[library_type][:generated_dir] ]
generated_files = codegen_config[library_type][:generated_files].map { |filename| "#{codegen_config[library_type][:generated_dir]}/#{filename}" }
else
generated_dirs = [ codegen_config["modules"][:generated_dir], codegen_config["components"][:generated_dir] ]
generated_files = codegen_config["modules"][:generated_files].map { |filename| "#{codegen_config["modules"][:generated_dir]}/#{filename}" }
generated_files = generated_files.concat(codegen_config["components"][:generated_files].map { |filename| "#{codegen_config["components"][:generated_dir]}/#{filename}" })
end
if js_srcs_pattern
file_list = `find #{js_srcs_dir} -type f -name #{js_srcs_pattern}`.split("\n").sort
input_files = file_list.map { |filename| "${PODS_TARGET_SRCROOT}/#{filename}" }
else
input_files = [ js_srcs_dir ]
end
# Prepare filesystem by creating empty files that will be picked up as references by CocoaPods.
prepare_command = "mkdir -p #{generated_dirs.join(" ")} && touch -a #{generated_files.join(" ")}"
system(prepare_command) # Always run prepare_command when a podspec uses the codegen, as CocoaPods may skip invoking this command in certain scenarios. Replace with pre_integrate_hook after updating to CocoaPods 1.11
spec.prepare_command = prepare_command
env_files = ["$PODS_ROOT/../.xcode.env.local", "$PODS_ROOT/../.xcode.env"]
spec.script_phase = {
:name => 'Generate Specs',
:input_files => input_files + env_files, # This also needs to be relative to Xcode
:output_files => ["${DERIVED_FILE_DIR}/codegen-#{library_name}.log"].concat(generated_files.map { |filename| "${PODS_TARGET_SRCROOT}/#{filename}"} ),
# The final generated files will be created when this script is invoked at Xcode build time.
:script => get_script_phases_no_codegen_discovery(
react_native_path: react_native_path,
codegen_output_dir: output_dir,
codegen_module_dir: output_dir_module,
codegen_component_dir: output_dir_component,
library_name: library_name,
library_type: library_type,
js_srcs_pattern: js_srcs_pattern,
js_srcs_dir: js_srcs_dir,
file_list: file_list
),
:execution_position => :before_compile,
:show_env_vars_in_log => true
}
end
# This provides a post_install workaround for build issues related Xcode 12.5 and Apple Silicon (M1) machines.
# Call this in the app's main Podfile's post_install hook.
# See https://github.com/facebook/react-native/issues/31480#issuecomment-902912841 for more context.
# Actual fix was authored by https://github.com/mikehardy.
# New app template will call this for now until the underlying issue is resolved.
def __apply_Xcode_12_5_M1_post_install_workaround(installer)
# Flipper podspecs are still targeting an older iOS deployment target, and may cause an error like:
# "error: thread-local storage is not supported for the current target"
# The most reliable known workaround is to bump iOS deployment target to match react-native (iOS 11 now).
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
# ensure IPHONEOS_DEPLOYMENT_TARGET is at least 11.0
deployment_target = config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f
should_upgrade = deployment_target < 11.0 && deployment_target != 0.0
if should_upgrade
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
end
end
end
# But... doing so caused another issue in Flipper:
# "Time.h:52:17: error: typedef redefinition with different types"
# We need to make a patch to RCT-Folly - remove the `__IPHONE_OS_VERSION_MIN_REQUIRED` check.
# See https://github.com/facebook/flipper/issues/834 for more details.
time_header = "#{Pod::Config.instance.installation_root.to_s}/Pods/RCT-Folly/folly/portability/Time.h"
`sed -i -e $'s/ && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0)//' '#{time_header}'`
end