mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
4f732ba9ee
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/33982 This Diff moves another part of the utilities from the `react_native_pods` file to a specific `utils.rb` file. It adds tests for these utils and improve our test mocks. The goal is to simplify the `react_native_pods.rb` so it's easier to work with it. I decided to split this diff in 2 because it was becoming quite big. ## Changelog [iOS][Changed] - Refactoring part of the react_native_pods.rb script Reviewed By: cortinico Differential Revision: D37006265 fbshipit-source-id: ffaac3270cb098fa30b73c97ce7cd350dfb8d7d6
569 lines
24 KiB
Ruby
569 lines
24 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/flipper.rb'
|
||
require_relative './cocoapods/fabric.rb'
|
||
require_relative './cocoapods/codegen.rb'
|
||
require_relative './cocoapods/utils.rb'
|
||
|
||
$CODEGEN_OUTPUT_DIR = 'build/generated/ios'
|
||
$CODEGEN_COMPONENT_DIR = 'react/renderer/components'
|
||
$CODEGEN_MODULE_DIR = '.'
|
||
$REACT_CODEGEN_PODSPEC_GENERATED = false
|
||
$REACT_CODEGEN_DISCOVERY_DONE = false
|
||
DEFAULT_OTHER_CPLUSPLUSFLAGS = '$(inherited)'
|
||
NEW_ARCH_OTHER_CPLUSPLUSFLAGS = '$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1'
|
||
|
||
$START_TIME = Time.now.to_i
|
||
|
||
def use_react_native! (options={})
|
||
# The prefix to react-native
|
||
prefix = options[:path] ||= "../node_modules/react-native"
|
||
|
||
# Include Fabric dependencies
|
||
fabric_enabled = options[:fabric_enabled] ||= false
|
||
|
||
# New arch enabled
|
||
new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'
|
||
|
||
# Include DevSupport dependency
|
||
production = options[:production] ||= false
|
||
|
||
# Include Hermes dependencies
|
||
hermes_enabled = options[:hermes_enabled] ||= false
|
||
|
||
flipper_configuration = options[:flipper_configuration] ||= FlipperConfiguration.disabled
|
||
|
||
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"
|
||
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-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-bridging', :path => "#{prefix}/ReactCommon/react/bridging"
|
||
pod 'React-cxxreact', :path => "#{prefix}/ReactCommon/cxxreact"
|
||
pod 'React-jsi', :path => "#{prefix}/ReactCommon/jsi"
|
||
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
|
||
|
||
if new_arch_enabled
|
||
app_path = options[:app_path]
|
||
config_file_dir = options[:config_file_dir]
|
||
use_react_native_codegen_discovery!({
|
||
react_native_path: prefix,
|
||
app_path: app_path,
|
||
fabric_enabled: fabric_enabled,
|
||
config_file_dir: config_file_dir,
|
||
})
|
||
else
|
||
# Generate a podspec file for generated files.
|
||
# This gets generated in use_react_native_codegen_discovery when codegen discovery is enabled.
|
||
react_codegen_spec = get_react_codegen_spec(fabric_enabled: fabric_enabled)
|
||
generate_react_codegen_podspec!(react_codegen_spec)
|
||
end
|
||
|
||
pod 'React-Codegen', :path => $CODEGEN_OUTPUT_DIR, :modular_headers => true
|
||
|
||
if fabric_enabled
|
||
checkAndGenerateEmptyThirdPartyProvider!(prefix, new_arch_enabled, $CODEGEN_OUTPUT_DIR)
|
||
setup_fabric!(prefix)
|
||
end
|
||
|
||
if hermes_enabled
|
||
prepare_hermes = 'node scripts/hermes/prepare-hermes-for-build'
|
||
react_native_dir = Pod::Config.instance.installation_root.join(prefix)
|
||
prep_output, prep_status = Open3.capture2e(prepare_hermes, :chdir => react_native_dir)
|
||
prep_output.split("\n").each { |line| Pod::UI.info line }
|
||
abort unless prep_status == 0
|
||
|
||
pod 'React-hermes', :path => "#{prefix}/ReactCommon/hermes"
|
||
pod 'libevent', '~> 2.1.12'
|
||
pod 'hermes-engine', :podspec => "#{prefix}/sdks/hermes/hermes-engine.podspec"
|
||
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(options)
|
||
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
|
||
|
||
def get_default_flags()
|
||
return ReactNativePodsUtils.get_default_flags()
|
||
end
|
||
|
||
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
|
||
|
||
def react_native_post_install(installer, react_native_path = "../node_modules/react-native")
|
||
if ReactNativePodsUtils.has_pod(installer, 'Flipper')
|
||
flipper_post_install(installer)
|
||
end
|
||
|
||
ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer)
|
||
ReactNativePodsUtils.fix_library_search_paths(installer)
|
||
|
||
cpp_flags = DEFAULT_OTHER_CPLUSPLUSFLAGS
|
||
if ENV['RCT_NEW_ARCH_ENABLED'] == '1'
|
||
cpp_flags = NEW_ARCH_OTHER_CPLUSPLUSFLAGS
|
||
end
|
||
modify_flags_for_new_architecture(installer, cpp_flags)
|
||
|
||
ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path)
|
||
|
||
puts "Pod install took #{Time.now.to_i - $START_TIME} [s] to run"
|
||
end
|
||
|
||
def modify_flags_for_new_architecture(installer, cpp_flags)
|
||
# Add RCT_NEW_ARCH_ENABLED to Target pods xcconfig
|
||
installer.aggregate_targets.each do |aggregate_target|
|
||
aggregate_target.xcconfigs.each do |config_name, config_file|
|
||
config_file.attributes['OTHER_CPLUSPLUSFLAGS'] = cpp_flags
|
||
xcconfig_path = aggregate_target.xcconfig_path(config_name)
|
||
Pod::UI.puts xcconfig_path
|
||
config_file.save_as(xcconfig_path)
|
||
end
|
||
end
|
||
|
||
# Add RCT_NEW_ARCH_ENABLED to generated pod target projects
|
||
installer.target_installation_results.pod_target_installation_results
|
||
.each do |pod_name, target_installation_result|
|
||
if pod_name == 'React-Core'
|
||
target_installation_result.native_target.build_configurations.each do |config|
|
||
config.build_settings['OTHER_CPLUSPLUSFLAGS'] = cpp_flags
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
def get_react_codegen_spec(options={})
|
||
fabric_enabled = options[:fabric_enabled] ||= false
|
||
script_phases = options[:script_phases] ||= nil
|
||
|
||
package = JSON.parse(File.read(File.join(__dir__, "..", "package.json")))
|
||
version = package['version']
|
||
|
||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||
if version == '1000.0.0'
|
||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
|
||
else
|
||
source[:tag] = "v#{version}"
|
||
end
|
||
|
||
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
||
folly_version = '2021.06.28.00-v2'
|
||
boost_version = '1.76.0'
|
||
boost_compiler_flags = '-Wno-documentation'
|
||
|
||
spec = {
|
||
'name' => "React-Codegen",
|
||
'version' => version,
|
||
'summary' => 'Temp pod for generated files for React Native',
|
||
'homepage' => 'https://facebook.com/',
|
||
'license' => 'Unlicense',
|
||
'authors' => 'Facebook',
|
||
'compiler_flags' => "#{folly_compiler_flags} #{boost_compiler_flags} -Wno-nullability-completeness -std=c++17",
|
||
'source' => { :git => '' },
|
||
'header_mappings_dir' => './',
|
||
'platforms' => {
|
||
'ios' => '11.0',
|
||
},
|
||
'source_files' => "**/*.{h,mm,cpp}",
|
||
'pod_target_xcconfig' => { "HEADER_SEARCH_PATHS" =>
|
||
[
|
||
"\"$(PODS_ROOT)/boost\"",
|
||
"\"$(PODS_ROOT)/RCT-Folly\"",
|
||
"\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"",
|
||
"\"$(PODS_ROOT)/Headers/Private/React-Fabric\"",
|
||
"\"$(PODS_ROOT)/Headers/Private/React-RCTFabric\"",
|
||
].join(' ')
|
||
},
|
||
'dependencies': {
|
||
"FBReactNativeSpec": [version],
|
||
"React-jsiexecutor": [version],
|
||
"RCT-Folly": [folly_version],
|
||
"RCTRequired": [version],
|
||
"RCTTypeSafety": [version],
|
||
"React-Core": [version],
|
||
"React-jsi": [version],
|
||
"ReactCommon/turbomodule/core": [version]
|
||
}
|
||
}
|
||
|
||
if fabric_enabled
|
||
spec[:'dependencies'].merge!({
|
||
'React-graphics': [version],
|
||
'React-rncore': [version],
|
||
});
|
||
end
|
||
|
||
if script_phases
|
||
Pod::UI.puts "[Codegen] Adding script_phases to React-Codegen."
|
||
spec[:'script_phases'] = script_phases
|
||
end
|
||
|
||
return spec
|
||
end
|
||
|
||
def get_codegen_config_from_file(config_path, config_key)
|
||
empty = {'libraries' => []}
|
||
if !File.exist?(config_path)
|
||
return empty
|
||
end
|
||
|
||
config = JSON.parse(File.read(config_path))
|
||
return config[config_key] ? config[config_key] : empty
|
||
end
|
||
|
||
def get_react_codegen_script_phases(options={})
|
||
app_path = options[:app_path] ||= ''
|
||
if !app_path
|
||
Pod::UI.warn '[Codegen] error: app_path is requried to use codegen discovery.'
|
||
exit 1
|
||
end
|
||
|
||
# We need to convert paths to relative path from installation_root for the script phase for CI.
|
||
relative_app_root = Pathname.new(app_path).realpath().relative_path_from(Pod::Config.instance.installation_root)
|
||
|
||
config_file_dir = options[:config_file_dir] ||= ''
|
||
relative_config_file_dir = ''
|
||
if config_file_dir != ''
|
||
relative_config_file_dir = Pathname.new(config_file_dir).relative_path_from(Pod::Config.instance.installation_root)
|
||
end
|
||
|
||
fabric_enabled = options[:fabric_enabled] ||= false
|
||
|
||
# react_native_path should be relative already.
|
||
react_native_path = options[:react_native_path] ||= "../node_modules/react-native"
|
||
|
||
# Generate input files for in-app libaraies which will be used to check if the script needs to be run.
|
||
# TODO: Ideally, we generate the input_files list from generate-artifacts.js and read the result here.
|
||
# Or, generate this podspec in generate-artifacts.js as well.
|
||
config_key = options[:config_key] ||= 'codegenConfig'
|
||
app_package_path = File.join(app_path, 'package.json')
|
||
app_codegen_config = get_codegen_config_from_file(app_package_path, config_key)
|
||
file_list = []
|
||
if app_codegen_config['libraries'] then
|
||
Pod::UI.warn '[Deprecated] You are using the old `libraries` array to list all your codegen.\nThis method will be removed in the future.\nUpdate your `package.json` with a single object.'
|
||
app_codegen_config['libraries'].each do |library|
|
||
library_dir = File.join(app_path, library['jsSrcsDir'])
|
||
file_list.concat (`find #{library_dir} -type f \\( -name "Native*.js" -or -name "*NativeComponent.js" \\)`.split("\n").sort)
|
||
end
|
||
elsif app_codegen_config['jsSrcsDir'] then
|
||
codegen_dir = File.join(app_path, app_codegen_config['jsSrcsDir'])
|
||
file_list.concat (`find #{codegen_dir} -type f \\( -name "Native*.js" -or -name "*NativeComponent.js" \\)`.split("\n").sort)
|
||
else
|
||
Pod::UI.warn '[Error] Codegen not properly configured. Please add the `codegenConf` entry to your `package.json`'
|
||
exit 1
|
||
end
|
||
|
||
input_files = file_list.map { |filename| "${PODS_ROOT}/../#{Pathname.new(filename).realpath().relative_path_from(Pod::Config.instance.installation_root)}" }
|
||
|
||
# Add a script phase to trigger generate artifact.
|
||
# Some code is duplicated so that it's easier to delete the old way and switch over to this once it's stabilized.
|
||
return {
|
||
'name': 'Generate Specs',
|
||
'execution_position': :before_compile,
|
||
'input_files' => input_files,
|
||
'show_env_vars_in_log': true,
|
||
'output_files': ["${DERIVED_FILE_DIR}/react-codegen.log"],
|
||
'script': get_script_phases_with_codegen_discovery(
|
||
react_native_path: react_native_path,
|
||
relative_app_root: relative_app_root,
|
||
relative_config_file_dir: relative_config_file_dir,
|
||
fabric_enabled: fabric_enabled
|
||
),
|
||
}
|
||
|
||
end
|
||
|
||
def set_react_codegen_podspec_generated(value)
|
||
$REACT_CODEGEN_PODSPEC_GENERATED = value
|
||
end
|
||
|
||
def has_react_codegen_podspec_generated()
|
||
return $REACT_CODEGEN_PODSPEC_GENERATED
|
||
end
|
||
|
||
def generate_react_codegen_podspec!(spec)
|
||
# This podspec file should only be create once in the session/pod install.
|
||
# This happens when multiple targets are calling use_react_native!.
|
||
if has_react_codegen_podspec_generated()
|
||
Pod::UI.puts "[Codegen] Skipping React-Codegen podspec generation."
|
||
return
|
||
end
|
||
relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)
|
||
output_dir = "#{relative_installation_root}/#{$CODEGEN_OUTPUT_DIR}"
|
||
Pod::Executable.execute_command("mkdir", ["-p", output_dir]);
|
||
|
||
podspec_path = File.join(output_dir, 'React-Codegen.podspec.json')
|
||
Pod::UI.puts "[Codegen] Generating #{podspec_path}"
|
||
|
||
File.open(podspec_path, 'w') do |f|
|
||
f.write(spec.to_json)
|
||
f.fsync
|
||
end
|
||
|
||
set_react_codegen_podspec_generated(true)
|
||
|
||
return {
|
||
"spec" => spec,
|
||
"path" => $CODEGEN_OUTPUT_DIR, # Path needs to be relative to `Podfile`
|
||
}
|
||
end
|
||
|
||
|
||
def use_react_native_codegen_discovery!(options={})
|
||
return if ENV['DISABLE_CODEGEN'] == '1'
|
||
|
||
if $REACT_CODEGEN_DISCOVERY_DONE
|
||
Pod::UI.puts "[Codegen] Skipping use_react_native_codegen_discovery."
|
||
return
|
||
end
|
||
|
||
Pod::UI.warn '[Codegen] warn: using experimental new codegen integration'
|
||
react_native_path = options[:react_native_path] ||= "../node_modules/react-native"
|
||
app_path = options[:app_path]
|
||
fabric_enabled = options[:fabric_enabled] ||= false
|
||
config_file_dir = options[:config_file_dir] ||= ''
|
||
relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)
|
||
|
||
if !app_path
|
||
Pod::UI.warn '[Codegen] Error: app_path is required for use_react_native_codegen_discovery.'
|
||
Pod::UI.warn '[Codegen] If you are calling use_react_native_codegen_discovery! in your Podfile, please remove the call and pass `app_path` and/or `config_file_dir` to `use_react_native!`.'
|
||
exit 1
|
||
end
|
||
|
||
# Generate React-Codegen podspec here to add the script phases.
|
||
script_phases = get_react_codegen_script_phases(options)
|
||
react_codegen_spec = get_react_codegen_spec(fabric_enabled: fabric_enabled, script_phases: script_phases)
|
||
generate_react_codegen_podspec!(react_codegen_spec)
|
||
|
||
out = Pod::Executable.execute_command(
|
||
'node',
|
||
[
|
||
"#{relative_installation_root}/#{react_native_path}/scripts/generate-artifacts.js",
|
||
"-p", "#{app_path}",
|
||
"-o", Pod::Config.instance.installation_root,
|
||
"-e", "#{fabric_enabled}",
|
||
"-c", "#{config_file_dir}",
|
||
])
|
||
Pod::UI.puts out;
|
||
|
||
$REACT_CODEGEN_DISCOVERY_DONE = true
|
||
end
|
||
|
||
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",
|
||
"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: $CODEGEN_OUTPUT_DIR,
|
||
codegen_module_dir: $CODEGEN_MODULE_DIR,
|
||
codegen_component_dir: $CODEGEN_COMPONENT_DIR,
|
||
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
|
||
|
||
# Monkeypatch of `Pod::Lockfile` to ensure automatic update of dependencies integrated with a local podspec when their version changed.
|
||
# This is necessary because local podspec dependencies must be otherwise manually updated.
|
||
module LocalPodspecPatch
|
||
# Returns local podspecs whose versions differ from the one in the `react-native` package.
|
||
def self.pods_to_update(react_native_options)
|
||
prefix = react_native_options[:path] ||= "../node_modules/react-native"
|
||
@@local_podspecs = Dir.glob("#{prefix}/third-party-podspecs/*").map { |file| File.basename(file, ".podspec") }
|
||
@@local_podspecs = @@local_podspecs.select do |podspec_name|
|
||
# Read local podspec to determine the cached version
|
||
local_podspec_path = File.join(
|
||
Dir.pwd, "Pods/Local Podspecs/#{podspec_name}.podspec.json"
|
||
)
|
||
|
||
# Local podspec cannot be outdated if it does not exist, yet
|
||
next unless File.file?(local_podspec_path)
|
||
|
||
local_podspec = File.read(local_podspec_path)
|
||
local_podspec_json = JSON.parse(local_podspec)
|
||
local_version = local_podspec_json["version"]
|
||
|
||
# Read the version from a podspec from the `react-native` package
|
||
podspec_path = "#{prefix}/third-party-podspecs/#{podspec_name}.podspec"
|
||
current_podspec = Pod::Specification.from_file(podspec_path)
|
||
|
||
current_version = current_podspec.version.to_s
|
||
current_version != local_version
|
||
end
|
||
@@local_podspecs
|
||
end
|
||
|
||
# Patched `detect_changes_with_podfile` method
|
||
def detect_changes_with_podfile(podfile)
|
||
changes = super(podfile)
|
||
@@local_podspecs.each do |local_podspec|
|
||
next unless changes[:unchanged].include?(local_podspec)
|
||
|
||
changes[:unchanged].delete(local_podspec)
|
||
changes[:changed] << local_podspec
|
||
end
|
||
changes
|
||
end
|
||
end
|