-
Notifications
You must be signed in to change notification settings - Fork 2.6k
/
copy_xcframework_script.rb
226 lines (194 loc) · 6.95 KB
/
copy_xcframework_script.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
require 'cocoapods/xcode'
module Pod
module Generator
class CopyXCFrameworksScript
# @return [Array<Pod::Xcode::XCFramework>] List of xcframeworks to copy
#
attr_reader :xcframeworks
# @return [Pathname] the root directory of the sandbox
#
attr_reader :sandbox_root
# @return [Platform] the platform of the target for which this script will run
#
attr_reader :platform
# Creates a script for copying XCFramework slcies into an intermediate build directory
#
# @param [Array<Pod::Xcode::XCFramework>] xcframeworks
# the list of xcframeworks to copy
#
# @param [Pathname] sandbox_root
# the root of the Sandbox into which this script will be installed
#
# @param [Platform] platform
# the platform of the target for which this script will be run
#
def initialize(xcframeworks, sandbox_root, platform)
@xcframeworks = xcframeworks
@sandbox_root = sandbox_root
@platform = platform
end
# Saves the resource script to the given pathname.
#
# @param [Pathname] pathname
# The path where the embed frameworks script should be saved.
#
# @return [void]
#
def save_as(pathname)
pathname.open('w') do |file|
file.puts(script)
end
File.chmod(0o755, pathname.to_s)
end
# @return [String] The contents of the embed frameworks script.
#
def generate
script
end
private
# @!group Private Helpers
# @return [String] The contents of the prepare artifacts script.
#
def script
script = <<-SH.strip_heredoc
#{Pod::Generator::ScriptPhaseConstants::DEFAULT_SCRIPT_PHASE_HEADER}
#{Pod::Generator::ScriptPhaseConstants::RSYNC_PROTECT_TMP_FILES}
#{variant_for_slice}
#{archs_for_slice}
copy_dir()
{
local source="$1"
local destination="$2"
# Use filter instead of exclude so missing patterns don't throw errors.
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \\"- CVS/\\" --filter \\"- .svn/\\" --filter \\"- .git/\\" --filter \\"- .hg/\\" \\"${source}*\\" \\"${destination}\\""
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}"/* "${destination}"
}
SELECT_SLICE_RETVAL=""
select_slice() {
local xcframework_name="$(basename $1)"
local paths=("${@:2}")
# Locate the correct slice of the .xcframework for the current architectures
local target_path=""
# Split archs on space so we can find a slice that has all the needed archs
local target_archs=$(echo $ARCHS | tr " " "\\n")
local target_variant=""
if [[ "$PLATFORM_NAME" == *"simulator" ]]; then
target_variant="simulator"
fi
if [[ ! -z ${EFFECTIVE_PLATFORM_NAME+x} && "$EFFECTIVE_PLATFORM_NAME" == *"maccatalyst" ]]; then
target_variant="maccatalyst"
fi
for i in ${!paths[@]}; do
local matched_all_archs="1"
local slice_archs="$(archs_for_slice "${xcframework_name}/${paths[$i]}")"
local slice_variant="$(variant_for_slice "${xcframework_name}/${paths[$i]}")"
for target_arch in $target_archs; do
if ! [[ "${slice_variant}" == "$target_variant" ]]; then
matched_all_archs="0"
break
fi
if ! echo "${slice_archs}" | tr " " '\n' | grep -F -q -x "$target_arch"; then
matched_all_archs="0"
break
fi
done
if [[ "$matched_all_archs" == "1" ]]; then
# Found a matching slice
echo "Selected xcframework slice ${paths[$i]}"
SELECT_SLICE_RETVAL=${paths[$i]}
break
fi
done
}
install_xcframework() {
local basepath="$1"
local name="$2"
local package_type="$3"
local paths=("${@:4}")
# Locate the correct slice of the .xcframework for the current architectures
select_slice "${basepath}" "${paths[@]}"
local target_path="$SELECT_SLICE_RETVAL"
if [[ -z "$target_path" ]]; then
echo "error: [CP] Unable to find matching .xcframework slice in '${paths[@]}' for the current build architectures ($ARCHS)."
exit 1
fi
local source="$basepath/$target_path"
local destination="#{Pod::Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/${name}"
if [ ! -d "$destination" ]; then
mkdir -p "$destination"
fi
copy_dir "$source/" "$destination"
echo "Copied $source to $destination"
}
SH
xcframeworks.each do |xcframework|
slices = xcframework.slices.select { |f| f.platform.symbolic_name == platform.symbolic_name }
next if slices.empty?
args = install_xcframework_args(xcframework, slices)
script << "install_xcframework #{args}\n"
end
script << "\n" unless xcframeworks.empty?
script
end
def shell_escape(value)
"\"#{value}\""
end
def install_xcframework_args(xcframework, slices)
root = xcframework.path
args = [shell_escape("${PODS_ROOT}/#{root.relative_path_from(sandbox_root)}")]
args << shell_escape(xcframework.target_name)
is_framework = xcframework.build_type.framework?
args << shell_escape(is_framework ? 'framework' : 'library')
slices.each do |slice|
args << shell_escape(slice.path.dirname.relative_path_from(root))
end
args.join(' ')
end
def variant_for_slice
script = ''
script << "variant_for_slice()\n"
script << "{\n"
script << " case \"$1\" in\n"
xcframeworks.each do |xcframework|
root = xcframework.path
xcframework.slices.each do |slice|
script << " #{shell_escape(root.basename.join(slice.path.dirname.relative_path_from(root)))})\n"
script << " echo \"#{slice.platform_variant}\"\n"
script << " ;;\n"
end
end
script << " esac\n"
script << '}'
end
def archs_for_slice
script = ''
script << "archs_for_slice()\n"
script << "{\n"
script << " case \"$1\" in\n"
xcframeworks.each do |xcframework|
root = xcframework.path
xcframework.slices.each do |slice|
script << " #{shell_escape(root.basename.join(slice.path.dirname.relative_path_from(root)))})\n"
script << " echo \"#{slice.supported_archs.sort.join(' ')}\"\n"
script << " ;;\n"
end
end
script << " esac\n"
script << '}'
end
class << self
# @param [Pathname] xcframework_path
# the base path of the .xcframework bundle
#
# @return [Array<Pathname>] all found .dSYM paths
#
def dsym_folder(xcframework_path)
basename = File.basename(xcframework_path, '.xcframework')
dsym_basename = basename + '.dSYMs'
path = xcframework_path.dirname + dsym_basename
Pathname.new(path) if File.directory?(path)
end
end
end
end
end