ann-flavor-cocoapods 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +61 -0
- data/lib/ann_flavor_cocoapods/podfile_helper.rb +265 -14
- data/lib/ann_flavor_cocoapods/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0b4a6fb9baad3561d14ffa73da2e419ebbaa0664edf12924875484973e5e5f21
|
|
4
|
+
data.tar.gz: a88e357ca0d0fdf957a3640229d7f98a852a058d3ea442f5333d8c6f02c1393c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a156d31659cb317a3e114adda24d44048e0a8c28bf781f23b50f3821a8e0eb84e19aabf2ac57beec9da4d3e7cc192ab3182acf8a4f95c5177eb8ff3445298df0
|
|
7
|
+
data.tar.gz: 7c4b22bba78a36cb28338c38152e2126ea9b9d92007e633d1b6684bb40b2db1a30ca5f7ac74ad0855e31a3ae65bcca98210d3e6d8c2f98cac7664dbded19ee18
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,66 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **New `[ann-flavor] Merge Entitlements` build phase composes the final
|
|
7
|
+
`.entitlements` file Xcode signs with at build time**, not sync time: copies
|
|
8
|
+
`ios/Runner/Runner.entitlements` (the generic/base layer, developer-owned —
|
|
9
|
+
if present; unlike `Runner/Info.plist`, most projects have no stock
|
|
10
|
+
entitlements file at all, so a missing base file here starts from an empty
|
|
11
|
+
plist rather than failing), then merges in every key from the current
|
|
12
|
+
flavor's `ann/Entitlements/<flavor>.entitlements` delta (see
|
|
13
|
+
`ann_flutter_flavor` 1.3.0 — that file now holds only the flavor's
|
|
14
|
+
`entitlements:` cascade, not a full copy of `Runner.entitlements`), with the
|
|
15
|
+
flavor's value winning on any key both define. Uses `PlistBuddy`, mirroring
|
|
16
|
+
`[ann-flavor] Merge Info.plist` (0.3.0) exactly — entitlements files and
|
|
17
|
+
Info.plist are both plain Apple XML property lists, so the same
|
|
18
|
+
type-preserving merge logic applies unchanged. Injected only when at least
|
|
19
|
+
one flavor actually needs entitlements (its own cascade, or a stock
|
|
20
|
+
`Runner.entitlements`); removed automatically once nothing needs it anymore.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
- **`CODE_SIGN_ENTITLEMENTS` now points at
|
|
24
|
+
`$(DERIVED_FILE_DIR)/Entitlements-merged.entitlements`** (the Merge
|
|
25
|
+
Entitlements phase's output above) instead of directly at
|
|
26
|
+
`ann/Entitlements/<flavor>.entitlements`, whenever anything needs signing —
|
|
27
|
+
extends the same `INFOPLIST_FILE` rewiring from 0.3.0 to entitlements. See
|
|
28
|
+
[plan 039](../../docs/03-planning/features/039-entitlements-build-time-merge.md)
|
|
29
|
+
and the [Entitlements](../../docs/04-userguide/ios/overview.md#entitlements)
|
|
30
|
+
section of the iOS userguide for the full design.
|
|
31
|
+
|
|
32
|
+
## 0.3.0
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
- **New `[ann-flavor] Merge Info.plist` build phase composes the final
|
|
36
|
+
Info.plist Xcode builds against at build time**, not sync time: copies
|
|
37
|
+
`ios/Runner/Info.plist` (the generic/base layer, developer-owned, always
|
|
38
|
+
present) to `$(DERIVED_FILE_DIR)/Info-merged.plist`, then merges in every
|
|
39
|
+
key from the current flavor's `ios/ann/Info/Info-<flavor>.plist` delta (see
|
|
40
|
+
`ann_flutter_flavor` 1.2.0 — that file now holds only the flavor's
|
|
41
|
+
`info_plist:` cascade, not a full copy of `Runner/Info.plist`), with the
|
|
42
|
+
flavor's value winning on any key both define. Uses `PlistBuddy`
|
|
43
|
+
(`/usr/libexec/PlistBuddy`), not `python3`/`ruby` — ships as part of Xcode
|
|
44
|
+
itself, so this phase adds no dependency on any scripting runtime beyond
|
|
45
|
+
what Xcode already requires. Every plist value type (string, bool, integer,
|
|
46
|
+
real, array, nested dict — e.g. `SKAdNetworkItems`) round-trips correctly
|
|
47
|
+
through the merge, not just strings. Prints a one-line notice to the Xcode
|
|
48
|
+
build log for any key the flavor delta actually overrides, to make an
|
|
49
|
+
unintentional override easy to spot. Found-and-updated in place on a
|
|
50
|
+
re-run, same UUID-stability guarantee as the Firebase-copy and Print Build
|
|
51
|
+
Info phases.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
- **`INFOPLIST_FILE` now points at `$(DERIVED_FILE_DIR)/Info-merged.plist`**
|
|
55
|
+
(the Merge Info.plist phase's output above) instead of directly at
|
|
56
|
+
`ios/ann/Info/Info-<flavor>.plist`. Enables `Runner/Info.plist` to remain a
|
|
57
|
+
live, always-consulted base layer instead of a one-time sync-time template
|
|
58
|
+
— the change this whole release exists to support. See
|
|
59
|
+
[plan 038](../../docs/03-planning/features/038-info-plist-build-time-merge.md)
|
|
60
|
+
and the [`Info.plist`
|
|
61
|
+
keys](../../docs/04-userguide/ios/overview.md#infoplist-keys) section of the
|
|
62
|
+
iOS userguide for the full design and migration notes.
|
|
63
|
+
|
|
3
64
|
## 0.2.0
|
|
4
65
|
|
|
5
66
|
### Added
|
|
@@ -155,6 +155,7 @@ module AnnFlavorCocoapods
|
|
|
155
155
|
user_project.native_targets.each do |target|
|
|
156
156
|
if target.symbol_type == :application
|
|
157
157
|
find_or_create_icon_catalog(target, user_project)
|
|
158
|
+
target_has_entitlements = false
|
|
158
159
|
|
|
159
160
|
ios.flavors.each_key do |flavor_key|
|
|
160
161
|
flavor = ios.flavors[flavor_key]
|
|
@@ -174,24 +175,32 @@ module AnnFlavorCocoapods
|
|
|
174
175
|
# until checked against what the xcconfig #include actually
|
|
175
176
|
# applied).
|
|
176
177
|
xcconfig_path = "ann/xcconfig/#{flavor_key}#{bt.capitalize}.xcconfig"
|
|
177
|
-
info_plist_path = "ann/Info/Info-#{flavor_key}.plist"
|
|
178
178
|
icon_name = "#{flavor_key.capitalize}AppIcon"
|
|
179
179
|
|
|
180
180
|
assert_icon_generated!(user_project, flavor_key, icon_name)
|
|
181
181
|
|
|
182
|
-
#
|
|
183
|
-
#
|
|
184
|
-
#
|
|
185
|
-
# entitlements
|
|
186
|
-
#
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
182
|
+
# Extended opt-in check (plan 039): CODE_SIGN_ENTITLEMENTS is
|
|
183
|
+
# wired only when there is something to sign with at all --
|
|
184
|
+
# either this flavor's entitlements: cascade, or a stock
|
|
185
|
+
# Runner.entitlements to fall back to. Mirrors
|
|
186
|
+
# ios_generator.dart's _anyFlavorHasEntitlements OR-condition,
|
|
187
|
+
# but evaluated here instead of at sync time -- the actual
|
|
188
|
+
# merge now happens at this (pod install / build time) layer,
|
|
189
|
+
# not sync time, so this is where "is there anything to sign
|
|
190
|
+
# with" needs to be answered from. The Merge Entitlements
|
|
191
|
+
# phase itself is injected once per target below (like Merge
|
|
192
|
+
# Info.plist), not per flavor/build-type here -- it derives
|
|
193
|
+
# $FLAVOR_NAME from $CONFIGURATION at build time, so one
|
|
194
|
+
# shared phase correctly serves every flavor, whether or not
|
|
195
|
+
# that specific flavor has its own entitlements: cascade.
|
|
196
|
+
flavor_entitlements_file = File.join(user_project.project_dir.to_s, 'ann', 'Entitlements', "#{flavor_key}.entitlements")
|
|
197
|
+
stock_entitlements_file = File.join(user_project.project_dir.to_s, 'Runner', 'Runner.entitlements')
|
|
198
|
+
has_entitlements = File.exist?(flavor_entitlements_file) || File.exist?(stock_entitlements_file)
|
|
199
|
+
entitlements_path = has_entitlements ? '$(DERIVED_FILE_DIR)/Entitlements-merged.entitlements' : nil
|
|
200
|
+
target_has_entitlements ||= has_entitlements
|
|
192
201
|
|
|
193
202
|
configure_build_configuration(
|
|
194
|
-
target, user_project, xcode_config, xcconfig_path,
|
|
203
|
+
target, user_project, xcode_config, xcconfig_path,
|
|
195
204
|
icon_name, entitlements_path
|
|
196
205
|
)
|
|
197
206
|
end
|
|
@@ -202,6 +211,19 @@ module AnnFlavorCocoapods
|
|
|
202
211
|
if print_build_info
|
|
203
212
|
inject_build_info_phase(target)
|
|
204
213
|
end
|
|
214
|
+
|
|
215
|
+
inject_merge_info_plist_phase(target)
|
|
216
|
+
|
|
217
|
+
# Unlike Merge Info.plist (unconditional -- every flavor always
|
|
218
|
+
# has an Info.plist), Merge Entitlements is only injected when at
|
|
219
|
+
# least one flavor actually needs it (its own cascade, or a
|
|
220
|
+
# stock Runner.entitlements) -- entitlements are opt-in overall,
|
|
221
|
+
# and a phase with nothing to sign would just be dead weight.
|
|
222
|
+
if target_has_entitlements
|
|
223
|
+
inject_merge_entitlements_phase(target)
|
|
224
|
+
else
|
|
225
|
+
remove_merge_entitlements_phase(target)
|
|
226
|
+
end
|
|
205
227
|
end
|
|
206
228
|
|
|
207
229
|
# Fixes a real pod-install failure: PBXNativeTarget#resolved_build_setting
|
|
@@ -598,7 +620,7 @@ module AnnFlavorCocoapods
|
|
|
598
620
|
CODE_SIGN_ENTITLEMENTS
|
|
599
621
|
].freeze
|
|
600
622
|
|
|
601
|
-
def self.configure_build_configuration(target, user_project, xcode_config, xcconfig_path,
|
|
623
|
+
def self.configure_build_configuration(target, user_project, xcode_config, xcconfig_path, icon_name, entitlements_path = nil)
|
|
602
624
|
config_list = target.build_configuration_list
|
|
603
625
|
config = config_list[xcode_config]
|
|
604
626
|
|
|
@@ -624,7 +646,12 @@ module AnnFlavorCocoapods
|
|
|
624
646
|
user_project.main_group.new_reference(xcconfig_path)
|
|
625
647
|
config.base_configuration_reference = xcconfig_ref
|
|
626
648
|
|
|
627
|
-
|
|
649
|
+
# Points at the [ann-flavor] Merge Info.plist run-script phase's output
|
|
650
|
+
# (plan 038), not directly at ann/Info/Info-<flavor>.plist -- that file
|
|
651
|
+
# now holds only the flavor's info_plist: cascade delta, not a complete
|
|
652
|
+
# plist; the merge phase composes it with Runner/Info.plist (base) at
|
|
653
|
+
# build time and writes the result here.
|
|
654
|
+
config.build_settings['INFOPLIST_FILE'] = '$(DERIVED_FILE_DIR)/Info-merged.plist'
|
|
628
655
|
config.build_settings['ASSETCATALOG_COMPILER_APPICON_NAME'] = icon_name
|
|
629
656
|
# entitlements: is opt-in (unlike INFOPLIST_FILE/the icon catalog, which
|
|
630
657
|
# every flavor always has) -- only set CODE_SIGN_ENTITLEMENTS when the
|
|
@@ -769,5 +796,229 @@ module AnnFlavorCocoapods
|
|
|
769
796
|
target.build_phases.unshift(phase)
|
|
770
797
|
end
|
|
771
798
|
end
|
|
799
|
+
|
|
800
|
+
# Composes the final Info.plist Xcode actually builds against, from two
|
|
801
|
+
# layers -- Runner/Info.plist (generic/base, developer-owned) and the
|
|
802
|
+
# flavor-specific ann/Info/Info-<flavor>.plist (annspec.yaml's info_plist:
|
|
803
|
+
# cascade, opt-in -- may not exist for a flavor with no cascade) -- with
|
|
804
|
+
# the flavor layer winning on any key collision. Plan 038: since plan 035,
|
|
805
|
+
# ios_generator.dart's _generateInfoPlists used to bake a full copy of
|
|
806
|
+
# Runner/Info.plist into every flavor's generated plist at sync time; that
|
|
807
|
+
# made the generated file impossible to read as "what's actually
|
|
808
|
+
# flavor-specific" and gave nothing else (e.g. a CocoaPods plugin like
|
|
809
|
+
# ann_ads) any way to contribute Info.plist keys, since INFOPLIST_FILE
|
|
810
|
+
# pointed at the fully-resolved flavor file and Runner/Info.plist was
|
|
811
|
+
# never read again. This phase moves that composition to build time
|
|
812
|
+
# instead, so Runner/Info.plist stays a live, always-consulted base layer.
|
|
813
|
+
#
|
|
814
|
+
# Uses PlistBuddy (/usr/libexec/PlistBuddy), not python3/ruby -- PlistBuddy
|
|
815
|
+
# ships as part of Xcode itself, so this phase has no dependency on any
|
|
816
|
+
# scripting runtime beyond what Xcode already requires (OQ-1,
|
|
817
|
+
# docs/03-planning/features/038-info-plist-build-time-merge.md).
|
|
818
|
+
#
|
|
819
|
+
# Runs before_compile, ahead of Xcode's own Info.plist processing --
|
|
820
|
+
# INFOPLIST_FILE (set in configure_build_configuration) points at this
|
|
821
|
+
# phase's output, not at either source file directly.
|
|
822
|
+
def self.inject_merge_info_plist_phase(target)
|
|
823
|
+
script = <<~SHELL
|
|
824
|
+
# Injected by ann-flavor-cocoapods: compose the final Info.plist from
|
|
825
|
+
# two layers -- Runner/Info.plist (generic/base) and the flavor-
|
|
826
|
+
# specific ann/Info/Info-<flavor>.plist (annspec.yaml's info_plist:
|
|
827
|
+
# cascade) -- with the flavor layer winning on any key collision.
|
|
828
|
+
# See docs/03-planning/features/038-info-plist-build-time-merge.md.
|
|
829
|
+
PLISTBUDDY=/usr/libexec/PlistBuddy
|
|
830
|
+
BASE="${SRCROOT}/Runner/Info.plist"
|
|
831
|
+
FLAVOR_NAME="${CONFIGURATION#*-}"
|
|
832
|
+
FLAVOR_PLIST="${SRCROOT}/ann/Info/Info-${FLAVOR_NAME}.plist"
|
|
833
|
+
OUT="${DERIVED_FILE_DIR}/Info-merged.plist"
|
|
834
|
+
|
|
835
|
+
if [ ! -f "$BASE" ]; then
|
|
836
|
+
echo "error: [ann-flavor] Runner/Info.plist not found at $BASE"
|
|
837
|
+
exit 1
|
|
838
|
+
fi
|
|
839
|
+
|
|
840
|
+
# Start from a full copy of the base layer -- every key
|
|
841
|
+
# Runner/Info.plist already has is correct by default; only the
|
|
842
|
+
# flavor delta's keys need explicit merging in below.
|
|
843
|
+
cp "$BASE" "$OUT"
|
|
844
|
+
|
|
845
|
+
if [ ! -f "$FLAVOR_PLIST" ]; then
|
|
846
|
+
echo "warning: [ann-flavor] no flavor Info.plist found for '$FLAVOR_NAME' at $FLAVOR_PLIST -- using Runner/Info.plist unmerged."
|
|
847
|
+
exit 0
|
|
848
|
+
fi
|
|
849
|
+
|
|
850
|
+
# Enumerate the flavor delta's top-level keys. PlistBuddy "Print" with
|
|
851
|
+
# no key path dumps the whole dict; grep the top-level "Key = " lines
|
|
852
|
+
# (four leading spaces = depth 1 in PlistBuddy's indented dump format).
|
|
853
|
+
FLAVOR_KEYS=$("$PLISTBUDDY" -c "Print" "$FLAVOR_PLIST" | grep -E '^ [A-Za-z]' | sed 's/ =.*//' | sed 's/^ *//')
|
|
854
|
+
|
|
855
|
+
for KEY in $FLAVOR_KEYS; do
|
|
856
|
+
# OQ-2: warn (non-fatal) only on a genuine collision -- Runner/Info.plist
|
|
857
|
+
# already had this key, with a different value, before the flavor delta
|
|
858
|
+
# is applied. A net-new key (not previously in Runner/Info.plist) is not
|
|
859
|
+
# a collision and stays silent -- that's the expected, common case.
|
|
860
|
+
# Compared via PlistBuddy's human-readable Print output, which is
|
|
861
|
+
# good enough for equality-detection purposes even though it can't
|
|
862
|
+
# reliably tell types apart (see the VALUE_XML extraction below,
|
|
863
|
+
# which is what actually determines the merged value/type).
|
|
864
|
+
BASE_VALUE=$("$PLISTBUDDY" -c "Print :$KEY" "$OUT" 2>/dev/null)
|
|
865
|
+
BASE_HAD_KEY=$?
|
|
866
|
+
FLAVOR_VALUE=$("$PLISTBUDDY" -c "Print :$KEY" "$FLAVOR_PLIST")
|
|
867
|
+
|
|
868
|
+
if [ "$BASE_HAD_KEY" -eq 0 ] && [ "$BASE_VALUE" != "$FLAVOR_VALUE" ]; then
|
|
869
|
+
echo "[ann-flavor] Info.plist: '$KEY' overridden by flavor value ($FLAVOR_NAME) -- Runner/Info.plist's value ignored for this build."
|
|
870
|
+
fi
|
|
871
|
+
|
|
872
|
+
# Extract the flavor value's own XML fragment (e.g. <string>x</string>,
|
|
873
|
+
# <true/>, <integer>42</integer>, <array>...</array>) via PlistBuddy's
|
|
874
|
+
# -x (XML) output, scoped to just this key, stripping the <plist
|
|
875
|
+
# version="1.0">...</plist> wrapper that -x always adds. This
|
|
876
|
+
# preserves the flavor delta's real plist type -- Print's
|
|
877
|
+
# human-readable output alone can't distinguish an integer 42 from
|
|
878
|
+
# the string "42", or a bool true from the string "true", so a
|
|
879
|
+
# scalar-vs-composite TYPE guess from Print was unreliable and has
|
|
880
|
+
# been replaced with this approach (verified against a real
|
|
881
|
+
# PlistBuddy: bool/int/real/string/array/dict all round-trip
|
|
882
|
+
# correctly this way, plan 038 STEP-02).
|
|
883
|
+
VALUE_XML=$("$PLISTBUDDY" -x -c "Print :$KEY" "$FLAVOR_PLIST" | sed -n '/<plist version/,/<\\/plist>/p' | sed '1d;$d')
|
|
884
|
+
|
|
885
|
+
"$PLISTBUDDY" -c "Delete :$KEY" "$OUT" >/dev/null 2>&1
|
|
886
|
+
FRAGMENT=$(mktemp /tmp/ann-flavor-plist-fragment.XXXXXX)
|
|
887
|
+
cat > "$FRAGMENT" <<XMLEOF
|
|
888
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
889
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
890
|
+
<plist version="1.0">
|
|
891
|
+
<dict>
|
|
892
|
+
<key>$KEY</key>
|
|
893
|
+
$VALUE_XML
|
|
894
|
+
</dict>
|
|
895
|
+
</plist>
|
|
896
|
+
XMLEOF
|
|
897
|
+
"$PLISTBUDDY" -c "Merge \\"$FRAGMENT\\"" "$OUT"
|
|
898
|
+
rm -f "$FRAGMENT"
|
|
899
|
+
done
|
|
900
|
+
SHELL
|
|
901
|
+
|
|
902
|
+
# Find-or-update in place, rather than delete+recreate -- same
|
|
903
|
+
# idempotency rationale as inject_build_info_phase above.
|
|
904
|
+
existing = target.build_phases.find { |p| p.respond_to?(:name) && p.name == '[ann-flavor] Merge Info.plist' }
|
|
905
|
+
phase = existing || target.project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
|
|
906
|
+
phase.name = '[ann-flavor] Merge Info.plist'
|
|
907
|
+
phase.shell_path = '/bin/sh'
|
|
908
|
+
phase.shell_script = script
|
|
909
|
+
phase.show_env_vars_in_log = '0'
|
|
910
|
+
# Declares this phase's output so Xcode's build system understands the
|
|
911
|
+
# dependency (same technique already used for the Firebase-copy phase's
|
|
912
|
+
# output_paths) -- suppresses "input file not found" for INFOPLIST_FILE
|
|
913
|
+
# referencing a path nothing else produces until this phase runs.
|
|
914
|
+
phase.output_paths = ['$(DERIVED_FILE_DIR)/Info-merged.plist']
|
|
915
|
+
|
|
916
|
+
target.build_phases.unshift(phase) unless existing
|
|
917
|
+
end
|
|
918
|
+
|
|
919
|
+
# Composes the final .entitlements file Xcode actually signs with, from
|
|
920
|
+
# two layers -- Runner.entitlements (generic/base, developer-owned, may
|
|
921
|
+
# not exist at all) and the flavor-specific ann/Entitlements/<flavor>
|
|
922
|
+
# .entitlements delta (annspec.yaml's entitlements: cascade, opt-in --
|
|
923
|
+
# may also not exist) -- with the flavor layer winning on any key
|
|
924
|
+
# collision. Plan 039: mirrors inject_merge_info_plist_phase (plan 038)
|
|
925
|
+
# exactly -- same PlistBuddy-based merge (entitlements files and Info.plist
|
|
926
|
+
# are both plain Apple XML property lists; PlistBuddy has no notion of
|
|
927
|
+
# file "kind" beyond that), same find-or-update idempotency, same
|
|
928
|
+
# collision-warning behavior. The one real difference: unlike
|
|
929
|
+
# Runner/Info.plist (every Xcode project has one), most projects have no
|
|
930
|
+
# Runner.entitlements at all -- a missing base file here is a normal,
|
|
931
|
+
# non-fatal case (starts from an empty plist dict), not the fatal error
|
|
932
|
+
# Merge Info.plist treats a missing Runner/Info.plist as.
|
|
933
|
+
def self.inject_merge_entitlements_phase(target)
|
|
934
|
+
script = <<~SHELL
|
|
935
|
+
# Injected by ann-flavor-cocoapods: compose the final .entitlements file
|
|
936
|
+
# from two layers -- Runner.entitlements (generic/base, may not exist)
|
|
937
|
+
# and the flavor-specific ann/Entitlements/<flavor>.entitlements delta
|
|
938
|
+
# (annspec.yaml's entitlements: cascade, may also not exist) -- with the
|
|
939
|
+
# flavor layer winning on any key collision. Mirrors [ann-flavor] Merge
|
|
940
|
+
# Info.plist (plan 038) -- see plan 039 for why entitlements needed the
|
|
941
|
+
# same redesign.
|
|
942
|
+
PLISTBUDDY=/usr/libexec/PlistBuddy
|
|
943
|
+
BASE="${SRCROOT}/Runner/Runner.entitlements"
|
|
944
|
+
FLAVOR_NAME="${CONFIGURATION#*-}"
|
|
945
|
+
FLAVOR_FILE="${SRCROOT}/ann/Entitlements/${FLAVOR_NAME}.entitlements"
|
|
946
|
+
OUT="${DERIVED_FILE_DIR}/Entitlements-merged.entitlements"
|
|
947
|
+
|
|
948
|
+
if [ -f "$BASE" ]; then
|
|
949
|
+
cp "$BASE" "$OUT"
|
|
950
|
+
else
|
|
951
|
+
# No stock Runner.entitlements -- start from an empty plist dict
|
|
952
|
+
# rather than failing; the flavor delta (if any) is still applied
|
|
953
|
+
# below.
|
|
954
|
+
cat > "$OUT" <<PLISTEOF
|
|
955
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
956
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
957
|
+
<plist version="1.0">
|
|
958
|
+
<dict/>
|
|
959
|
+
</plist>
|
|
960
|
+
PLISTEOF
|
|
961
|
+
fi
|
|
962
|
+
|
|
963
|
+
if [ ! -f "$FLAVOR_FILE" ]; then
|
|
964
|
+
echo "[ann-flavor] Entitlements: no flavor delta found for '$FLAVOR_NAME' at $FLAVOR_FILE -- using Runner.entitlements unmerged."
|
|
965
|
+
exit 0
|
|
966
|
+
fi
|
|
967
|
+
|
|
968
|
+
FLAVOR_KEYS=$("$PLISTBUDDY" -c "Print" "$FLAVOR_FILE" | grep -E '^ [A-Za-z]' | sed 's/ =.*//' | sed 's/^ *//')
|
|
969
|
+
|
|
970
|
+
for KEY in $FLAVOR_KEYS; do
|
|
971
|
+
BASE_VALUE=$("$PLISTBUDDY" -c "Print :$KEY" "$OUT" 2>/dev/null)
|
|
972
|
+
BASE_HAD_KEY=$?
|
|
973
|
+
FLAVOR_VALUE=$("$PLISTBUDDY" -c "Print :$KEY" "$FLAVOR_FILE")
|
|
974
|
+
|
|
975
|
+
if [ "$BASE_HAD_KEY" -eq 0 ] && [ "$BASE_VALUE" != "$FLAVOR_VALUE" ]; then
|
|
976
|
+
echo "[ann-flavor] Entitlements: '$KEY' overridden by flavor value ($FLAVOR_NAME) -- Runner.entitlements' value ignored for this build."
|
|
977
|
+
fi
|
|
978
|
+
|
|
979
|
+
VALUE_XML=$("$PLISTBUDDY" -x -c "Print :$KEY" "$FLAVOR_FILE" | sed -n '/<plist version/,/<\\/plist>/p' | sed '1d;$d')
|
|
980
|
+
|
|
981
|
+
"$PLISTBUDDY" -c "Delete :$KEY" "$OUT" >/dev/null 2>&1
|
|
982
|
+
FRAGMENT=$(mktemp /tmp/ann-flavor-entitlements-fragment.XXXXXX)
|
|
983
|
+
cat > "$FRAGMENT" <<XMLEOF
|
|
984
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
985
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
986
|
+
<plist version="1.0">
|
|
987
|
+
<dict>
|
|
988
|
+
<key>$KEY</key>
|
|
989
|
+
$VALUE_XML
|
|
990
|
+
</dict>
|
|
991
|
+
</plist>
|
|
992
|
+
XMLEOF
|
|
993
|
+
"$PLISTBUDDY" -c "Merge \\"$FRAGMENT\\"" "$OUT"
|
|
994
|
+
rm -f "$FRAGMENT"
|
|
995
|
+
done
|
|
996
|
+
SHELL
|
|
997
|
+
|
|
998
|
+
existing = target.build_phases.find { |p| p.respond_to?(:name) && p.name == '[ann-flavor] Merge Entitlements' }
|
|
999
|
+
phase = existing || target.project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
|
|
1000
|
+
phase.name = '[ann-flavor] Merge Entitlements'
|
|
1001
|
+
phase.shell_path = '/bin/sh'
|
|
1002
|
+
phase.shell_script = script
|
|
1003
|
+
phase.show_env_vars_in_log = '0'
|
|
1004
|
+
phase.output_paths = ['$(DERIVED_FILE_DIR)/Entitlements-merged.entitlements']
|
|
1005
|
+
|
|
1006
|
+
target.build_phases.unshift(phase) unless existing
|
|
1007
|
+
end
|
|
1008
|
+
|
|
1009
|
+
# Removes a previously-injected Merge Entitlements phase when no flavor
|
|
1010
|
+
# needs entitlements anymore (annspec.yaml's entitlements: cascade was
|
|
1011
|
+
# removed, and no stock Runner.entitlements exists either) -- entitlements
|
|
1012
|
+
# are opt-in overall, so a stale phase with nothing to sign would be dead
|
|
1013
|
+
# weight left in project.pbxproj. Uses ObjectList#delete (not plain
|
|
1014
|
+
# Array#reject!/select), same rationale as the stale "[ann-flavor] Remove
|
|
1015
|
+
# Firebase plist" cleanup above -- plain array removal only drops the
|
|
1016
|
+
# phase from target.build_phases, leaving the object itself permanently
|
|
1017
|
+
# orphaned in the project's global objects table.
|
|
1018
|
+
def self.remove_merge_entitlements_phase(target)
|
|
1019
|
+
target.build_phases.select do |p|
|
|
1020
|
+
p.respond_to?(:name) && p.name == '[ann-flavor] Merge Entitlements'
|
|
1021
|
+
end.each { |p| target.build_phases.delete(p) }
|
|
1022
|
+
end
|
|
772
1023
|
end
|
|
773
1024
|
end
|