cocoapods-binary-matchup 0.0.2 → 0.0.3

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.
@@ -0,0 +1,426 @@
1
+ require 'fileutils'
2
+ require 'digest'
3
+
4
+ module Pod
5
+ module PrebuildCache
6
+ class Cache
7
+
8
+ # 获取缓存根目录
9
+ def self.cache_root_dir
10
+ cache_dir = File.expand_path("~/.PodCache")
11
+ FileUtils.mkdir_p(cache_dir) unless Dir.exist?(cache_dir)
12
+ cache_dir
13
+ end
14
+
15
+ # 获取特定pod的缓存目录
16
+ def self.cache_dir_for_pod(pod_name, version)
17
+ File.join(cache_root_dir, pod_name, version)
18
+ end
19
+
20
+ # 获取pod的版本信息,优先使用commit hash
21
+ def self.get_pod_version(sandbox, pod_name)
22
+ begin
23
+ Pod::UI.puts "🔍 Looking for version of: #{pod_name}"
24
+ # 优先级:commit > tag > version > timestamp
25
+
26
+ # 1. 首先尝试从Manifest.lock获取commit信息
27
+ manifest_lock = sandbox.root + 'Manifest.lock'
28
+ if manifest_lock.exist?
29
+ manifest_content = YAML.load_file(manifest_lock)
30
+
31
+ # 优先检查 CHECKOUT OPTIONS 中的commit信息
32
+ checkout_options = manifest_content['CHECKOUT OPTIONS'] || {}
33
+ if checkout_options[pod_name].is_a?(Hash)
34
+ checkout_info = checkout_options[pod_name]
35
+ # 优先使用commit,然后是tag
36
+ if checkout_info[:commit] || checkout_info['commit']
37
+ commit = checkout_info[:commit] || checkout_info['commit']
38
+ Pod::UI.puts "📋 Using commit for #{pod_name}: #{commit[0..7]}..."
39
+ return commit
40
+ elsif checkout_info[:tag] || checkout_info['tag']
41
+ tag = checkout_info[:tag] || checkout_info['tag']
42
+ Pod::UI.puts "📋 Using tag for #{pod_name}: #{tag}"
43
+ return tag
44
+ end
45
+ end
46
+
47
+ # 如果没有commit信息,查找版本信息
48
+ pods = manifest_content['PODS'] || []
49
+ Pod::UI.puts "🔍 Searching in #{pods.length} pod entries from Manifest.lock"
50
+
51
+ pods.each do |pod_entry|
52
+ if pod_entry.is_a?(Hash)
53
+ # Hash 格式:{"PodName (1.0.0)" => [...]}
54
+ pod_entry.each do |key, _|
55
+ key_str = key.to_s
56
+ Pod::UI.puts " 📦 Checking hash key: #{key_str}"
57
+
58
+ # 使用更灵活的匹配逻辑,支持subspec
59
+ match = key_str.match(/^#{Regexp.escape(pod_name)}\s*\(([^)]+)\)/)
60
+ if match
61
+ Pod::UI.puts "📋 Found exact match! Using version for #{pod_name}: #{match[1]}"
62
+ return match[1]
63
+ end
64
+
65
+ # 如果精确匹配失败,尝试检查是否是subspec的情况
66
+ # 例如:pod_name是"GoogleUtilities/AppDelegateSwizzler",但key是"GoogleUtilities/AppDelegateSwizzler (8.1.0)"
67
+ if key_str.include?(pod_name) && key_str.include?('(')
68
+ version_match = key_str.match(/\(([^)]+)\)/)
69
+ if version_match
70
+ Pod::UI.puts "📋 Found partial match! Using version for #{pod_name}: #{version_match[1]}"
71
+ return version_match[1]
72
+ end
73
+ end
74
+ end
75
+ elsif pod_entry.is_a?(String)
76
+ # String 格式:"PodName (1.0.0)"
77
+ Pod::UI.puts " 📦 Checking string: #{pod_entry}"
78
+
79
+ match = pod_entry.match(/^#{Regexp.escape(pod_name)}\s*\(([^)]+)\)/)
80
+ if match
81
+ Pod::UI.puts "📋 Found exact match! Using version for #{pod_name}: #{match[1]}"
82
+ return match[1]
83
+ end
84
+
85
+ # 如果精确匹配失败,尝试部分匹配
86
+ if pod_entry.include?(pod_name) && pod_entry.include?('(')
87
+ version_match = pod_entry.match(/\(([^)]+)\)/)
88
+ if version_match
89
+ Pod::UI.puts "📋 Found partial match! Using version for #{pod_name}: #{version_match[1]}"
90
+ return version_match[1]
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ Pod::UI.puts "⚠️ No version found for #{pod_name} in Manifest.lock"
97
+ end
98
+
99
+
100
+
101
+ # 2. 如果Manifest.lock不存在或没找到,尝试从Podfile.lock获取
102
+ podfile_lock = sandbox.root.parent + 'Podfile.lock'
103
+ if podfile_lock.exist?
104
+ podfile_content = YAML.load_file(podfile_lock)
105
+
106
+ # 同样优先检查checkout信息
107
+ checkout_options = podfile_content['CHECKOUT OPTIONS'] || {}
108
+ if checkout_options[pod_name].is_a?(Hash)
109
+ checkout_info = checkout_options[pod_name]
110
+ if checkout_info[:commit] || checkout_info['commit']
111
+ commit = checkout_info[:commit] || checkout_info['commit']
112
+ Pod::UI.puts "📋 Using commit for #{pod_name}: #{commit[0..7]}..."
113
+ return commit
114
+ elsif checkout_info[:tag] || checkout_info['tag']
115
+ tag = checkout_info[:tag] || checkout_info['tag']
116
+ Pod::UI.puts "📋 Using tag for #{pod_name}: #{tag}"
117
+ return tag
118
+ end
119
+ end
120
+
121
+ # 查找版本信息
122
+ pods = podfile_content['PODS'] || []
123
+ Pod::UI.puts "🔍 Searching in #{pods.length} pod entries from Podfile.lock"
124
+
125
+ pods.each do |pod_entry|
126
+ if pod_entry.is_a?(Hash)
127
+ pod_entry.each do |key, _|
128
+ key_str = key.to_s
129
+ Pod::UI.puts " 📦 Checking hash key: #{key_str}"
130
+
131
+ # 使用更灵活的匹配逻辑,支持subspec
132
+ match = key_str.match(/^#{Regexp.escape(pod_name)}\s*\(([^)]+)\)/)
133
+ if match
134
+ Pod::UI.puts "📋 Found exact match! Using version for #{pod_name}: #{match[1]}"
135
+ return match[1]
136
+ end
137
+
138
+ # 如果精确匹配失败,尝试部分匹配
139
+ if key_str.include?(pod_name) && key_str.include?('(')
140
+ version_match = key_str.match(/\(([^)]+)\)/)
141
+ if version_match
142
+ Pod::UI.puts "📋 Found partial match! Using version for #{pod_name}: #{version_match[1]}"
143
+ return version_match[1]
144
+ end
145
+ end
146
+ end
147
+ elsif pod_entry.is_a?(String)
148
+ # String 格式:"PodName (1.0.0)"
149
+ Pod::UI.puts " 📦 Checking string: #{pod_entry}"
150
+
151
+ match = pod_entry.match(/^#{Regexp.escape(pod_name)}\s*\(([^)]+)\)/)
152
+ if match
153
+ Pod::UI.puts "📋 Found exact match! Using version for #{pod_name}: #{match[1]}"
154
+ return match[1]
155
+ end
156
+
157
+ # 如果精确匹配失败,尝试部分匹配
158
+ if pod_entry.include?(pod_name) && pod_entry.include?('(')
159
+ version_match = pod_entry.match(/\(([^)]+)\)/)
160
+ if version_match
161
+ Pod::UI.puts "📋 Found partial match! Using version for #{pod_name}: #{version_match[1]}"
162
+ return version_match[1]
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ Pod::UI.puts "⚠️ No version found for #{pod_name} in Podfile.lock"
169
+ end
170
+
171
+ # 3. 如果无法从任何lockfile获取,使用时间戳作为版本
172
+ timestamp = Time.now.strftime("%Y%m%d_%H%M%S")
173
+ Pod::UI.puts "⚠️ Warning: Cannot find version/commit for #{pod_name} in lock files, using timestamp: #{timestamp}"
174
+ return timestamp
175
+ rescue => e
176
+ timestamp = Time.now.strftime("%Y%m%d_%H%M%S")
177
+ Pod::UI.puts "⚠️ Warning: Error getting version for #{pod_name}: #{e.message}, using timestamp: #{timestamp}"
178
+ return timestamp
179
+ end
180
+ end
181
+
182
+ # 计算目录内容的哈希值(用于验证缓存完整性)
183
+ def self.calculate_dir_hash(dir_path)
184
+ return nil unless Dir.exist?(dir_path)
185
+
186
+ files = Dir.glob("#{dir_path}/**/*", File::FNM_DOTMATCH).select { |f| File.file?(f) }
187
+ files.sort!
188
+
189
+ hasher = Digest::SHA256.new
190
+ files.each do |file|
191
+ # 添加文件路径和修改时间到哈希计算中
192
+ relative_path = file.sub("#{dir_path}/", "")
193
+ hasher.update(relative_path)
194
+ hasher.update(File.mtime(file).to_s)
195
+ end
196
+
197
+ hasher.hexdigest
198
+ end
199
+
200
+ # 检查缓存是否存在
201
+ def self.cache_exists?(pod_name, version)
202
+ cache_dir = cache_dir_for_pod(pod_name, version)
203
+ Dir.exist?(cache_dir) && !Dir.empty?(cache_dir)
204
+ end
205
+
206
+ # 检查缓存是否存在且有效(用于验证完整性)
207
+ def self.cache_valid?(pod_name, version, source_dir = nil)
208
+ cache_dir = cache_dir_for_pod(pod_name, version)
209
+ return false unless Dir.exist?(cache_dir)
210
+
211
+ # 如果没有提供源目录,只检查缓存是否存在
212
+ return true if source_dir.nil?
213
+
214
+ # 检查缓存的哈希文件
215
+ hash_file = File.join(cache_dir, '.cache_hash')
216
+ return false unless File.exist?(hash_file)
217
+
218
+ begin
219
+ cached_hash = File.read(hash_file).strip
220
+ current_hash = calculate_dir_hash(source_dir)
221
+
222
+ return cached_hash == current_hash
223
+ rescue => e
224
+ Pod::UI.puts "⚠️ Warning: Cannot validate cache for #{pod_name}: #{e.message}"
225
+ return false
226
+ end
227
+ end
228
+
229
+ # 从缓存恢复pod
230
+ def self.restore_from_cache(pod_name, version, target_dir)
231
+ cache_dir = cache_dir_for_pod(pod_name, version)
232
+
233
+ return false unless Dir.exist?(cache_dir)
234
+
235
+ begin
236
+ # 删除目标目录
237
+ FileUtils.rm_rf(target_dir) if Dir.exist?(target_dir)
238
+
239
+ # 从缓存拷贝到目标目录
240
+ FileUtils.cp_r(cache_dir, target_dir, :remove_destination => true)
241
+
242
+ # 删除缓存标记文件
243
+ hash_file = File.join(target_dir, '.cache_hash')
244
+ File.delete(hash_file) if File.exist?(hash_file)
245
+
246
+ Pod::UI.puts "📦 Restored #{pod_name} (#{version}) from cache"
247
+ return true
248
+ rescue => e
249
+ Pod::UI.puts "❌ Failed to restore #{pod_name} from cache: #{e.message}"
250
+ return false
251
+ end
252
+ end
253
+
254
+ # 保存到缓存(如果缓存不存在的话)
255
+ def self.save_to_cache(pod_name, version, source_dir)
256
+ return unless Dir.exist?(source_dir)
257
+
258
+ # 检查缓存是否已经存在,如果存在则不覆盖
259
+ if cache_exists?(pod_name, version)
260
+ Pod::UI.puts "📦 Cache already exists for #{pod_name} (#{version}), skipping save"
261
+ return true
262
+ end
263
+
264
+ cache_dir = cache_dir_for_pod(pod_name, version)
265
+
266
+ begin
267
+ # 创建缓存目录
268
+ FileUtils.mkdir_p(File.dirname(cache_dir))
269
+
270
+ # 删除旧缓存(如果存在)
271
+ FileUtils.rm_rf(cache_dir) if Dir.exist?(cache_dir)
272
+
273
+ # 拷贝到缓存
274
+ FileUtils.cp_r(source_dir, cache_dir, :remove_destination => true)
275
+
276
+ # 保存哈希值
277
+ source_hash = calculate_dir_hash(source_dir)
278
+ hash_file = File.join(cache_dir, '.cache_hash')
279
+ File.write(hash_file, source_hash)
280
+
281
+ Pod::UI.puts "💾 Saved #{pod_name} (#{version}) to cache"
282
+ return true
283
+ rescue => e
284
+ Pod::UI.puts "❌ Failed to save #{pod_name} to cache: #{e.message}"
285
+ return false
286
+ end
287
+ end
288
+
289
+ # 尝试从缓存拷贝到目标目录(如果缓存存在)
290
+ def self.copy_from_cache_if_exists(pod_name, version, target_dir)
291
+ return false unless cache_exists?(pod_name, version)
292
+
293
+ cache_dir = cache_dir_for_pod(pod_name, version)
294
+
295
+ begin
296
+ # 删除目标目录
297
+ FileUtils.rm_rf(target_dir) if Dir.exist?(target_dir)
298
+
299
+ # 从缓存拷贝到目标目录
300
+ FileUtils.cp_r(cache_dir, target_dir, :remove_destination => true)
301
+
302
+ # 删除缓存标记文件
303
+ hash_file = File.join(target_dir, '.cache_hash')
304
+ File.delete(hash_file) if File.exist?(hash_file)
305
+
306
+ Pod::UI.puts "📦 Copied #{pod_name} (#{version}) from cache"
307
+ return true
308
+ rescue => e
309
+ Pod::UI.puts "❌ Failed to copy #{pod_name} from cache: #{e.message}"
310
+ return false
311
+ end
312
+ end
313
+
314
+ # 清理过期缓存(可选功能)
315
+ def self.clean_expired_cache(days = 30)
316
+ return unless Dir.exist?(cache_root_dir)
317
+
318
+ cutoff_time = Time.now - (days * 24 * 60 * 60)
319
+ cleaned_count = 0
320
+
321
+ Dir.glob("#{cache_root_dir}/*/*").each do |cache_dir|
322
+ next unless Dir.exist?(cache_dir)
323
+
324
+ if File.mtime(cache_dir) < cutoff_time
325
+ begin
326
+ FileUtils.rm_rf(cache_dir)
327
+ cleaned_count += 1
328
+ Pod::UI.puts "🗑️ Cleaned expired cache: #{File.basename(File.dirname(cache_dir))}/#{File.basename(cache_dir)}"
329
+ rescue => e
330
+ Pod::UI.puts "❌ Failed to clean cache #{cache_dir}: #{e.message}"
331
+ end
332
+ end
333
+ end
334
+
335
+ Pod::UI.puts "✅ Cleaned #{cleaned_count} expired cache entries" if cleaned_count > 0
336
+ end
337
+
338
+ # 获取缓存统计信息
339
+ def self.cache_stats
340
+ return {} unless Dir.exist?(cache_root_dir)
341
+
342
+ stats = {
343
+ total_pods: 0,
344
+ total_versions: 0,
345
+ total_size: 0
346
+ }
347
+
348
+ Dir.glob("#{cache_root_dir}/*").each do |pod_dir|
349
+ next unless Dir.exist?(pod_dir)
350
+
351
+ stats[:total_pods] += 1
352
+
353
+ Dir.glob("#{pod_dir}/*").each do |version_dir|
354
+ next unless Dir.exist?(version_dir)
355
+
356
+ stats[:total_versions] += 1
357
+
358
+ # 计算目录大小
359
+ size = `du -sk "#{version_dir}" 2>/dev/null`.split.first.to_i * 1024
360
+ stats[:total_size] += size
361
+ end
362
+ end
363
+
364
+ stats
365
+ end
366
+
367
+ # 打印缓存统计信息
368
+ def self.print_cache_stats
369
+ stats = cache_stats
370
+ if stats[:total_pods] > 0
371
+ size_mb = (stats[:total_size] / 1024.0 / 1024.0).round(2)
372
+ Pod::UI.puts "📊 Cache Stats: #{stats[:total_pods]} pods, #{stats[:total_versions]} versions, #{size_mb} MB"
373
+ else
374
+ Pod::UI.puts "📊 Cache is empty"
375
+ end
376
+ end
377
+
378
+ # 从 ~/.PodCache 恢复缓存到 _prebuild 目录
379
+ def self.restore_from_pod_cache(pod_name, prebuild_sandbox)
380
+ begin
381
+ Pod::UI.puts "🔍 Checking cache for #{pod_name} #{prebuild_sandbox}"
382
+
383
+ restored_count = 0
384
+ missing_pods = []
385
+
386
+ # 获取pod版本信息
387
+ pod_version = get_pod_version(prebuild_sandbox, pod_name)
388
+
389
+ # 检查缓存是否存在
390
+ if cache_exists?(pod_name, pod_version)
391
+ # 从缓存复制到_prebuild目录
392
+ cache_dir = cache_dir_for_pod(pod_name, pod_version)
393
+ target_dir = prebuild_sandbox.framework_folder_path_for_pod_name(pod_name)
394
+
395
+ # 确保目标目录存在
396
+ target_dir.parent.mkpath unless target_dir.parent.exist?
397
+
398
+ # 复制缓存到_prebuild
399
+ FileUtils.cp_r(cache_dir, target_dir, :remove_destination => true)
400
+
401
+ # 删除缓存标记文件
402
+ hash_file = target_dir + '.cache_hash'
403
+ hash_file.delete if hash_file.exist?
404
+
405
+ Pod::UI.puts "📦 Restored #{pod_name} (#{pod_version}) from cache"
406
+ restored_count += 1
407
+ else
408
+ missing_pods << pod_name
409
+ end
410
+
411
+ if missing_pods.empty?
412
+ Pod::UI.puts "✅ Successfully restored all #{restored_count} pods from cache"
413
+ return true
414
+ else
415
+ Pod::UI.puts "⚠️ Missing cache for #{missing_pods.count} pods: #{missing_pods.join(', ')}"
416
+ return false
417
+ end
418
+
419
+ rescue => e
420
+ Pod::UI.puts "❌ Error restoring from cache: #{e.message}"
421
+ return false
422
+ end
423
+ end
424
+ end
425
+ end
426
+ end
@@ -0,0 +1,171 @@
1
+ # encoding: UTF-8
2
+ require_relative 'helper/podfile_options'
3
+ require_relative 'tool/tool'
4
+ require_relative 'Integration_cache'
5
+
6
+ module Pod
7
+ class Podfile
8
+ module DSL
9
+
10
+ # Enable prebuiding for all pods
11
+ # it has a lower priority to other binary settings
12
+ def all_binary!
13
+ DSL.prebuild_all = true
14
+ end
15
+
16
+ def simulator_build_disable!
17
+ DSL.simulator_build_enabled = false
18
+ end
19
+
20
+ # Enable bitcode for prebuilt frameworks
21
+ def enable_bitcode_for_prebuilt_frameworks!
22
+ DSL.bitcode_enabled = true
23
+ end
24
+
25
+ # Don't remove source code of prebuilt pods
26
+ # It may speed up the pod install if git didn't
27
+ # include the `Pods` folder
28
+ def keep_source_code_for_prebuilt_frameworks!
29
+ DSL.dont_remove_source_code = true
30
+ end
31
+
32
+ # Add custom xcodebuild option to the prebuilding action
33
+ #
34
+ # You may use this for your special demands. For example: the default archs in dSYMs
35
+ # of prebuilt frameworks is 'arm64 armv7 x86_64', and no 'i386' for 32bit simulator.
36
+ # It may generate a warning when building for a 32bit simulator. You may add following
37
+ # to your podfile
38
+ #
39
+ # ` set_custom_xcodebuild_options_for_prebuilt_frameworks :simulator => "ARCHS=$(ARCHS_STANDARD)" `
40
+ #
41
+ # Another example to disable the generating of dSYM file:
42
+ #
43
+ # ` set_custom_xcodebuild_options_for_prebuilt_frameworks "DEBUG_INFORMATION_FORMAT=dwarf"`
44
+ #
45
+ #
46
+ # @param [String or Hash] options
47
+ #
48
+ # If is a String, it will apply for device and simulator. Use it just like in the commandline.
49
+ # If is a Hash, it should be like this: { :device => "XXXXX", :simulator => "XXXXX" }
50
+ #
51
+ def set_custom_xcodebuild_options_for_prebuilt_frameworks(options)
52
+ if options.kind_of? Hash
53
+ DSL.custom_build_options = [ options[:device] ] unless options[:device].nil?
54
+ DSL.custom_build_options_simulator = [ options[:simulator] ] unless options[:simulator].nil?
55
+ elsif options.kind_of? String
56
+ DSL.custom_build_options = [options]
57
+ DSL.custom_build_options_simulator = [options]
58
+ else
59
+ raise "Wrong type."
60
+ end
61
+ end
62
+
63
+ class_attr_accessor :simulator_build_enabled
64
+ simulator_build_enabled = true
65
+
66
+ private
67
+ class_attr_accessor :prebuild_all
68
+ prebuild_all = false
69
+
70
+ class_attr_accessor :bitcode_enabled
71
+ bitcode_enabled = false
72
+
73
+ class_attr_accessor :dont_remove_source_code
74
+ dont_remove_source_code = false
75
+
76
+ class_attr_accessor :custom_build_options
77
+ class_attr_accessor :custom_build_options_simulator
78
+ self.custom_build_options = []
79
+ self.custom_build_options_simulator = []
80
+ end
81
+ end
82
+ end
83
+
84
+ Pod::HooksManager.register('cocoapods-binary-matchup', :pre_install) do |installer_context|
85
+
86
+ require_relative 'helper/feature_switches'
87
+ if Pod.is_prebuild_stage
88
+ next
89
+ end
90
+
91
+ # [Check Environment]
92
+ # check user_framework is on
93
+ podfile = installer_context.podfile
94
+ podfile.target_definition_list.each do |target_definition|
95
+ next if target_definition.prebuild_framework_names.empty?
96
+ if not target_definition.uses_frameworks?
97
+ STDERR.puts "[!] Cocoapods-binary requires `use_frameworks!`".red
98
+ exit
99
+ end
100
+ end
101
+
102
+
103
+ # -- step 1: prebuild framework ---
104
+ # Execute a sperated pod install, to generate targets for building framework,
105
+ # then compile them to framework files.
106
+ require_relative 'helper/prebuild_sandbox'
107
+ require_relative 'Prebuild'
108
+
109
+ Pod::UI.puts "🚀 Prebuild frameworks"
110
+
111
+ # Fetch original installer (which is running this pre-install hook) options,
112
+ # then pass them to our installer to perform update if needed
113
+ # Looks like this is the most appropriate way to figure out that something should be updated
114
+
115
+ update = nil
116
+ repo_update = nil
117
+
118
+ include ObjectSpace
119
+ ObjectSpace.each_object(Pod::Installer) { |installer|
120
+ update = installer.update
121
+ repo_update = installer.repo_update
122
+ }
123
+
124
+ # control features
125
+ Pod.is_prebuild_stage = true
126
+ Pod::Podfile::DSL.enable_prebuild_patch true # enable sikpping for prebuild targets
127
+ Pod::Installer.force_disable_integration true # don't integrate targets
128
+ Pod::Config.force_disable_write_lockfile true # disbale write lock file for perbuild podfile
129
+ Pod::Installer.disable_install_complete_message true # disable install complete message
130
+
131
+ # make another custom sandbox
132
+ standard_sandbox = installer_context.sandbox
133
+ prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sandbox)
134
+
135
+ # get the podfile for prebuild
136
+ prebuild_podfile = Pod::Podfile.from_ruby(podfile.defined_in_file)
137
+
138
+ # install
139
+ lockfile = installer_context.lockfile
140
+ binary_installer = Pod::Installer.new(prebuild_sandbox, prebuild_podfile, lockfile)
141
+
142
+ # 优化的三级缓存逻辑
143
+ if binary_installer.have_exact_prebuild_cache? && !update
144
+ # 1. 优先:_prebuild 目录已有完整缓存
145
+ Pod::UI.puts "📦 Using exact prebuild cache from _Prebuild"
146
+ binary_installer.install_when_cache_hit!
147
+ else
148
+ # 3. 最后:重新构建
149
+ Pod::UI.puts "🔨 Building frameworks (no cache available)"
150
+ binary_installer.update = update
151
+ binary_installer.repo_update = repo_update
152
+ binary_installer.install!
153
+ end
154
+
155
+
156
+ # reset the environment
157
+ Pod.is_prebuild_stage = false
158
+ Pod::Installer.force_disable_integration false
159
+ Pod::Podfile::DSL.enable_prebuild_patch false
160
+ Pod::Config.force_disable_write_lockfile false
161
+ Pod::Installer.disable_install_complete_message false
162
+
163
+
164
+ # -- step 2: pod install ---
165
+ # install
166
+ Pod::UI.puts "\n"
167
+ Pod::UI.puts "🤖 Pod Install"
168
+ require_relative 'Integration'
169
+ # go on the normal install step ...
170
+ end
171
+