153 lines
7.0 KiB
Ruby
153 lines
7.0 KiB
Ruby
# Overrides CocoaPods `Installer`/'Podfile' classes to patch podspecs on the fly
|
|
# See: https://github.com/CocoaPods/CocoaPods/blob/master/lib/cocoapods/installer.rb
|
|
# See: https://github.com/CocoaPods/Core/blob/master/lib/cocoapods-core/podfile.rb#L160
|
|
#
|
|
# This is necessary to disable `USE_FRAMEWORKS` for specific pods that include
|
|
# React Native Core headers in their public headers, which causes issues when
|
|
# building them as dynamic frameworks with modular headers enabled.
|
|
|
|
module Pod
|
|
class Podfile
|
|
public
|
|
|
|
def framework_modules_to_patch
|
|
@framework_modules_to_patch ||= ['ExpoModulesCore', 'Expo', 'ReactAppDependencyProvider', 'expo-dev-menu']
|
|
end
|
|
|
|
def expo_add_modules_to_patch(modules)
|
|
framework_modules_to_patch.concat(modules)
|
|
end
|
|
end
|
|
|
|
class Installer
|
|
private
|
|
|
|
_original_perform_post_install_actions = instance_method(:perform_post_install_actions)
|
|
_original_run_podfile_pre_install_hooks = instance_method(:run_podfile_pre_install_hooks)
|
|
_script_phase_name = '[Expo Autolinking] Run Codegen with autolinking'
|
|
|
|
public
|
|
|
|
define_method(:perform_post_install_actions) do
|
|
|
|
# Call original implementation first
|
|
_original_perform_post_install_actions.bind(self).()
|
|
|
|
# Next we'll perform an Expo workaround for Codegen in React Native where it uses the wrong output path for
|
|
# the generated files. This can be remove when the following PR is merged and released upstream:
|
|
# https://github.com/facebook/react-native/pull/54066
|
|
# TODO: chrfalch - remove when RN PR is released
|
|
# Find the ReactCodegen pod target in the pods project
|
|
react_codegen_native_target = self.pods_project.targets.find { |target| target.name == 'ReactCodegen' }
|
|
|
|
if react_codegen_native_target
|
|
# Check if the build phase already exists
|
|
already_exists = react_codegen_native_target.build_phases.any? do |phase|
|
|
phase.is_a?(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) && phase.name == _script_phase_name
|
|
end
|
|
|
|
if !already_exists
|
|
Pod::UI.puts "[Expo] ".blue + "Adding '#{_script_phase_name}' build phase to ReactCodegen"
|
|
|
|
# Create the new shell script build phase
|
|
phase = react_codegen_native_target.new_shell_script_build_phase(_script_phase_name)
|
|
phase.shell_path = '/bin/sh'
|
|
phase.shell_script = <<~SH
|
|
# Remove this step when the fix is merged and released.
|
|
# See: https://github.com/facebook/react-native/pull/54066
|
|
|
|
# This re-runs Codegen without the broken "scripts/react_native_pods_utils/script_phases.sh" script, causing Codegen to run without autolinking.
|
|
# Instead of using "script_phases.sh" which always runs inside DerivedData, we run it in the normal "/ios" folder
|
|
# See: https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods_utils/script_phases.sh
|
|
pushd "$PODS_ROOT/../" > /dev/null
|
|
RCT_SCRIPT_POD_INSTALLATION_ROOT="$PODS_ROOT/.."
|
|
popd >/dev/null
|
|
|
|
export RCT_SCRIPT_RN_DIR="$REACT_NATIVE_PATH" # This is set by Expo
|
|
export RCT_SCRIPT_APP_PATH="$RCT_SCRIPT_POD_INSTALLATION_ROOT/.."
|
|
export RCT_SCRIPT_OUTPUT_DIR="$RCT_SCRIPT_POD_INSTALLATION_ROOT"
|
|
export RCT_SCRIPT_TYPE="withCodegenDiscovery"
|
|
|
|
# This is the broken script that runs inside DerivedData, meaning it can't find the autolinking result in `ios/build/generated/autolinking.json`.
|
|
# Resulting in Codegen running with it's own autolinking, not discovering transitive peer dependencies.
|
|
# export SCRIPT_PHASES_SCRIPT="$RCT_SCRIPT_RN_DIR/scripts/react_native_pods_utils/script_phases.sh"
|
|
export WITH_ENVIRONMENT="$RCT_SCRIPT_RN_DIR/scripts/xcode/with-environment.sh"
|
|
|
|
# Start of workaround code
|
|
|
|
# Load the $NODE_BINARY from the "with-environment.sh" script
|
|
source "$WITH_ENVIRONMENT"
|
|
|
|
# Run this script directly in the right folders:
|
|
# https://github.com/facebook/react-native/blob/3f7f9d8fb8beb41408d092870a7c7cac58029a4d/packages/react-native/scripts/react_native_pods_utils/script_phases.sh#L96-L101
|
|
pushd "$RCT_SCRIPT_RN_DIR" >/dev/null || exit 1
|
|
set -x
|
|
"$NODE_BINARY" "scripts/generate-codegen-artifacts.js" --path "$RCT_SCRIPT_APP_PATH" --outputPath "$RCT_SCRIPT_OUTPUT_DIR" --targetPlatform "ios"
|
|
set +x
|
|
popd >/dev/null || exit 1
|
|
|
|
# End of workaround code
|
|
SH
|
|
|
|
# Find the index of the "Compile Sources" phase (PBXSourcesBuildPhase)
|
|
compile_sources_index = react_codegen_native_target.build_phases.find_index do |p|
|
|
p.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase)
|
|
end
|
|
|
|
if compile_sources_index
|
|
# Remove the phase from its current position (it was added at the end)
|
|
react_codegen_native_target.build_phases.delete(phase)
|
|
# Insert it before the "Compile Sources" phase
|
|
react_codegen_native_target.build_phases.insert(compile_sources_index, phase)
|
|
else
|
|
Pod::UI.puts "[Expo] ".yellow + "Could not find 'Compile Sources' phase, build phase added at default position"
|
|
end
|
|
end
|
|
else
|
|
Pod::UI.puts "[Expo] ".yellow + "ReactCodegen target not found in pods project"
|
|
end
|
|
end
|
|
|
|
define_method(:run_podfile_pre_install_hooks) do
|
|
# Call original implementation first
|
|
_original_run_podfile_pre_install_hooks.bind(self).()
|
|
|
|
return unless should_disable_use_frameworks_for_core_expo_pods?()
|
|
|
|
# Disable USE_FRAMEWORKS in core targets when USE_FRAMEWORKS is set
|
|
# This method overrides the build_type field to always use static_library for
|
|
# the following pod targets:
|
|
# - ExpoModulesCore, Expo, ReactAppDependencyProvider, expo-dev-menu
|
|
# These are all including files from React Native Core in their public header files,
|
|
# which causes their own modular headers to be invalid.
|
|
Pod::UI.puts "[Expo] ".blue + "Disabling USE_FRAMEWORKS for modules #{@podfile.framework_modules_to_patch.join(', ')}"
|
|
self.pod_targets.each do |t|
|
|
if @podfile.framework_modules_to_patch.include?(t.name)
|
|
def t.build_type
|
|
Pod::BuildType.static_library
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
# We should only disable USE_FRAMEWORKS for specific pods when:
|
|
# - RCT_USE_PREBUILT_RNCORE is not '1'
|
|
# - USE_FRAMEWORKS is not set
|
|
def should_disable_use_frameworks_for_core_expo_pods?()
|
|
return false if ENV['RCT_USE_PREBUILT_RNCORE'] != '1'
|
|
return true if get_linkage?() != nil
|
|
false
|
|
end
|
|
|
|
# Returns the linkage type if USE_FRAMEWORKS is set, otherwise returns nil
|
|
def get_linkage?()
|
|
return nil if ENV["USE_FRAMEWORKS"] == nil
|
|
return :dynamic if ENV["USE_FRAMEWORKS"].downcase == 'dynamic'
|
|
return :static if ENV["USE_FRAMEWORKS"].downcase == 'static'
|
|
nil
|
|
end
|
|
end
|
|
end
|