|
18 | 18 |
|
19 | 19 | require 'json' |
20 | 20 |
|
| 21 | +RNFIREBASE_SPM_EMBED_PHASE_NAME = '[RNFB] Embed Firebase SPM Frameworks' |
| 22 | + |
21 | 23 | # Read Firebase SPM URL from app package.json (single source of truth). |
22 | 24 | # __dir__ resolves to the directory of this file (packages/app/). |
23 | 25 | # In monorepos with hoisted dependencies or pnpm, the path from other packages |
|
46 | 48 | # https://github.com/firebase/firebase-ios-sdk/blob/main/Package.swift |
47 | 49 | # (all products use .library(type: .dynamic)) |
48 | 50 | # |
| 51 | +# Returns true only when `$RNFirebaseDisableSPM` has been explicitly set to `true`. |
| 52 | +# |
| 53 | +# We deliberately check the value (not just `defined?`), so that config generators, |
| 54 | +# Expo plugins, or env-templated Podfiles that emit `$RNFirebaseDisableSPM = false` |
| 55 | +# don't silently switch to CocoaPods. |
| 56 | +def rnfirebase_spm_disabled? |
| 57 | + defined?($RNFirebaseDisableSPM) && $RNFirebaseDisableSPM == true |
| 58 | +end |
| 59 | + |
| 60 | +def rnfirebase_spm_embed_script |
| 61 | + <<~'SCRIPT' |
| 62 | + set -euo pipefail |
| 63 | +
|
| 64 | + package_frameworks_dir="${BUILT_PRODUCTS_DIR}/PackageFrameworks" |
| 65 | + app_frameworks_dir="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" |
| 66 | +
|
| 67 | + if [ ! -d "${package_frameworks_dir}" ]; then |
| 68 | + exit 0 |
| 69 | + fi |
| 70 | +
|
| 71 | + mkdir -p "${app_frameworks_dir}" |
| 72 | +
|
| 73 | + find "${package_frameworks_dir}" -maxdepth 1 -type d -name "*.framework" -print0 | while IFS= read -r -d '' framework; do |
| 74 | + framework_name="$(basename "${framework}")" |
| 75 | + destination="${app_frameworks_dir}/${framework_name}" |
| 76 | +
|
| 77 | + if [ -e "${destination}" ]; then |
| 78 | + continue |
| 79 | + fi |
| 80 | +
|
| 81 | + echo "Embedding Firebase SPM framework ${framework_name}" |
| 82 | + rsync -av --delete \ |
| 83 | + --filter "- Headers" \ |
| 84 | + --filter "- PrivateHeaders" \ |
| 85 | + --filter "- Modules" \ |
| 86 | + "${framework}" \ |
| 87 | + "${app_frameworks_dir}" |
| 88 | +
|
| 89 | + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" ] && [ "${CODE_SIGNING_REQUIRED:-}" != "NO" ] && [ "${CODE_SIGNING_ALLOWED:-}" != "NO" ]; then |
| 90 | + /usr/bin/codesign --force --sign "${EXPANDED_CODE_SIGN_IDENTITY}" ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements "${destination}" |
| 91 | + fi |
| 92 | + done |
| 93 | + SCRIPT |
| 94 | +end |
| 95 | + |
| 96 | +def rnfirebase_add_spm_embed_phase(installer) |
| 97 | + return unless defined?(SPM) |
| 98 | + |
| 99 | + dependencies_by_pod = SPM.instance_variable_get(:@dependencies_by_pod) || {} |
| 100 | + firebase_spm_enabled = dependencies_by_pod.values.flatten.any? do |dependency| |
| 101 | + dependency[:url] == $firebase_spm_url |
| 102 | + end |
| 103 | + return unless firebase_spm_enabled |
| 104 | + |
| 105 | + installer.aggregate_targets.each do |aggregate_target| |
| 106 | + aggregate_target.user_project.native_targets.each do |target| |
| 107 | + next unless target.respond_to?(:shell_script_build_phases) |
| 108 | + next unless target.shell_script_build_phases.any? { |phase| phase.name == '[CP] Embed Pods Frameworks' } |
| 109 | + |
| 110 | + phase = target.shell_script_build_phases.find { |candidate| candidate.name == RNFIREBASE_SPM_EMBED_PHASE_NAME } |
| 111 | + phase ||= target.new_shell_script_build_phase(RNFIREBASE_SPM_EMBED_PHASE_NAME) |
| 112 | + |
| 113 | + phase.shell_script = rnfirebase_spm_embed_script |
| 114 | + phase.shell_path = '/bin/bash' |
| 115 | + phase.always_out_of_date = '1' |
| 116 | + phase.input_paths = ['${BUILT_PRODUCTS_DIR}/PackageFrameworks'] |
| 117 | + phase.output_paths = ['${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}'] |
| 118 | + end |
| 119 | + |
| 120 | + aggregate_target.user_project.save |
| 121 | + end |
| 122 | +end |
| 123 | + |
| 124 | +if defined?(SPM) && SPM.respond_to?(:apply_on_post_install) && !SPM.singleton_class.method_defined?(:rnfirebase_original_apply_on_post_install) |
| 125 | + SPM.singleton_class.alias_method :rnfirebase_original_apply_on_post_install, :apply_on_post_install |
| 126 | + |
| 127 | + def SPM.apply_on_post_install(installer) |
| 128 | + rnfirebase_original_apply_on_post_install(installer) |
| 129 | + rnfirebase_add_spm_embed_phase(installer) |
| 130 | + end |
| 131 | +end |
| 132 | + |
49 | 133 | # @param spec [Pod::Specification] The podspec object (the `s` in podspec DSL) |
50 | 134 | # @param version [String] Firebase SDK version (e.g., '12.10.0') |
51 | 135 | # @param spm_products [Array<String>] SPM product names (e.g., ['FirebaseAuth']) |
|
0 commit comments