Files
react-native/scripts/react_native_pods.rb
T
Héctor Ramos aaa01f7710 Hermes: Use prepare-hermes-for-build in CocoaPods (#33825)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/33825

Updates the CocoaPods build scripts to consume the prepare-hermes-for-build script, replacing the now redundant set of Ruby code that would previously set the filesystem up.

Changelog:

[iOS] [Changed] - When building Hermes from source, the filesystem will now be prepared using the new hermes-utils.js scripts, outside of CocoaPods

Reviewed By: cortinico

Differential Revision: D36336633

fbshipit-source-id: a4506db80c039529b14b0290d2f0b54fae78dcf2
2022-05-12 20:42:16 -07:00

678 lines
27 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 'pathname'
require_relative './react_native_pods_utils/script_phases.rb'
require_relative './cocoapods/flipper.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'
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
# Include DevSupport dependency
production = options[:production] ||= false
# Include Hermes dependencies
hermes_enabled = options[:hermes_enabled] ||= false
if `/usr/sbin/sysctl -n hw.optional.arm64 2>&1`.to_i == 1 && !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
# 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}/"
install_flipper_dependencies(production, 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 ENV['RCT_NEW_ARCH_ENABLED'] == '1'
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)
pod 'React-Fabric', :path => "#{prefix}/ReactCommon"
pod 'React-rncore', :path => "#{prefix}/ReactCommon"
pod 'React-graphics', :path => "#{prefix}/ReactCommon/react/renderer/graphics"
pod 'React-jsi/Fabric', :path => "#{prefix}/ReactCommon/jsi"
pod 'React-RCTFabric', :path => "#{prefix}/React", :modular_headers => true
pod 'RCT-Folly/Fabric', :podspec => "#{prefix}/third-party-podspecs/RCT-Folly.podspec"
end
if hermes_enabled
system("(cd #{prefix} && node scripts/hermes/prepare-hermes-for-build)")
pod 'React-hermes', :path => "#{prefix}/ReactCommon/hermes"
pod 'hermes-engine', :path => "#{prefix}/sdks/hermes/hermes-engine.podspec"
pod 'libevent', '~> 2.1.12'
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()
flags = {
:fabric_enabled => false,
:hermes_enabled => false,
}
if ENV['RCT_NEW_ARCH_ENABLED'] == '1'
flags[:fabric_enabled] = true
flags[:hermes_enabled] = true
end
return flags
end
def use_flipper!(versions = {}, configurations: ['Debug'])
use_flipper_pods(versions, :configurations => configurations)
end
def has_pod(installer, name)
installer.pods_project.pod_group(name) != nil
end
def exclude_architectures(installer)
projects = installer.aggregate_targets
.map{ |t| t.user_project }
.uniq{ |p| p.path }
.push(installer.pods_project)
# Hermes does not support `i386` architecture
excluded_archs_default = has_pod(installer, 'hermes-engine') ? "i386" : ""
projects.each do |project|
project.build_configurations.each do |config|
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = excluded_archs_default
end
project.save()
end
end
def fix_library_search_paths(installer)
def fix_config(config)
lib_search_paths = config.build_settings["LIBRARY_SEARCH_PATHS"]
if lib_search_paths
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 M1)
# 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)\"")
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
end
end
projects = installer.aggregate_targets
.map{ |t| t.user_project }
.uniq{ |p| p.path }
.push(installer.pods_project)
projects.each do |project|
project.build_configurations.each do |config|
fix_config(config)
end
project.native_targets.each do |target|
target.build_configurations.each do |config|
fix_config(config)
end
end
project.save()
end
end
def set_node_modules_user_settings(installer, react_native_path)
puts "Setting REACT_NATIVE build settings"
projects = installer.aggregate_targets
.map{ |t| t.user_project }
.uniq{ |p| p.path }
.push(installer.pods_project)
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 react_native_post_install(installer, react_native_path = "../node_modules/react-native")
if has_pod(installer, 'Flipper')
flipper_post_install(installer)
end
exclude_architectures(installer)
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)
set_node_modules_user_settings(installer, react_native_path)
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 build_codegen!(react_native_path)
relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)
codegen_repo_path = "#{relative_installation_root}/#{react_native_path}/packages/react-native-codegen";
codegen_npm_path = "#{relative_installation_root}/#{react_native_path}/../react-native-codegen";
codegen_cli_path = ""
if Dir.exist?(codegen_repo_path)
codegen_cli_path = codegen_repo_path
elsif Dir.exist?(codegen_npm_path)
codegen_cli_path = codegen_npm_path
else
raise "[codegen] Couldn't not find react-native-codegen."
end
if !Dir.exist?("#{codegen_cli_path}/lib")
Pod::UI.puts "[Codegen] building #{codegen_cli_path}."
system("#{codegen_cli_path}/scripts/oss/build.sh")
end
end
# This is a temporary supporting function until we enable use_react_native_codegen_discovery by default.
def checkAndGenerateEmptyThirdPartyProvider!(react_native_path)
return if ENV['RCT_NEW_ARCH_ENABLED'] == '1'
relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)
output_dir = "#{relative_installation_root}/#{$CODEGEN_OUTPUT_DIR}"
provider_h_path = "#{output_dir}/RCTThirdPartyFabricComponentsProvider.h"
provider_cpp_path ="#{output_dir}/RCTThirdPartyFabricComponentsProvider.cpp"
if(!File.exist?(provider_h_path) || !File.exist?(provider_cpp_path))
# build codegen
build_codegen!(react_native_path)
# Just use a temp empty schema list.
temp_schema_list_path = "#{output_dir}/tmpSchemaList.txt"
File.open(temp_schema_list_path, 'w') do |f|
f.write('[]')
f.fsync
end
Pod::UI.puts '[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider'
Pod::Executable.execute_command(
'node',
[
"#{relative_installation_root}/#{react_native_path}/scripts/generate-provider-cli.js",
"--platform", 'ios',
"--schemaListPath", temp_schema_list_path,
"--outputDir", "#{output_dir}"
])
File.delete(temp_schema_list_path) if File.exist?(temp_schema_list_path)
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 were 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 = []
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
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