cocoapods-binary-matchup 0.0.29 → 0.0.30

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.
@@ -1,337 +0,0 @@
1
- require 'fourflusher'
2
- require 'xcpretty'
3
-
4
- CONFIGURATION = "Debug"
5
- PLATFORMS = { 'iphonesimulator' => 'iOS',
6
- 'appletvsimulator' => 'tvOS',
7
- 'watchsimulator' => 'watchOS' }
8
-
9
- # Build specific target to framework file
10
- # @param [PodTarget] target
11
- # a specific pod target
12
- #
13
- def build_for_iosish_platform(sandbox,
14
- build_dir,
15
- output_path,
16
- target,
17
- device,
18
- simulator,
19
- bitcode_enabled,
20
- custom_build_options = [], # Array<String>
21
- custom_build_options_simulator = [] # Array<String>
22
- )
23
-
24
- target_label = target.label # name with platform if it's used in multiple platforms
25
- Pod::UI.puts "Prebuilding #{target_label}..."
26
-
27
- other_options = []
28
- # bitcode enabled
29
- other_options += ['BITCODE_GENERATION_MODE=bitcode'] if bitcode_enabled
30
-
31
- is_succeed, _ = xcodebuild(sandbox, target_label, device, target, other_options + custom_build_options)
32
- exit 1 unless is_succeed
33
- if Pod::Podfile::DSL.simulator_build_enabled
34
- # make less arch to iphone simulator for faster build
35
- custom_build_options_simulator += ['ARCHS=x86_64', 'ONLY_ACTIVE_ARCH=NO'] if simulator == 'iphonesimulator'
36
- is_succeed, _ = xcodebuild(sandbox, target_label, simulator, target, other_options + custom_build_options_simulator)
37
- exit 1 unless is_succeed
38
- end
39
-
40
- # paths
41
- target_name = target.name # equals target.label, like "AFNeworking-iOS" when AFNetworking is used in multiple platforms.
42
- module_name = target.product_module_name
43
- device_framework_path = "#{build_dir}/#{CONFIGURATION}-#{device}/#{target_name}/#{module_name}.framework"
44
- device_binary = device_framework_path + "/#{module_name}"
45
-
46
- tmp_lipoed_binary_path = "#{build_dir}/#{target_name}"
47
- lipo_log = `lipo -create -output #{tmp_lipoed_binary_path} #{device_binary}`
48
-
49
- if Pod::Podfile::DSL.simulator_build_enabled
50
- simulator_framework_path = "#{build_dir}/#{CONFIGURATION}-#{simulator}/#{target_name}/#{module_name}.framework"
51
- simulator_binary = simulator_framework_path + "/#{module_name}"
52
- return unless File.file?(device_binary) && File.file?(simulator_binary)
53
- else
54
- return unless File.file?(device_binary)
55
- end
56
-
57
- puts lipo_log unless File.exist?(tmp_lipoed_binary_path)
58
- FileUtils.mv tmp_lipoed_binary_path, device_binary, :force => true
59
-
60
- # collect the swiftmodule file for various archs.
61
- device_swiftmodule_path = device_framework_path + "/Modules/#{module_name}.swiftmodule"
62
- if File.exist?(device_swiftmodule_path) && Pod::Podfile::DSL.simulator_build_enabled
63
- simulator_framework_path = "#{build_dir}/#{CONFIGURATION}-#{simulator}/#{target_name}/#{module_name}.framework"
64
- simulator_swiftmodule_path = simulator_framework_path + "/Modules/#{module_name}.swiftmodule"
65
- FileUtils.cp_r simulator_swiftmodule_path + "/.", device_swiftmodule_path
66
- end
67
-
68
- # combine the generated swift headers
69
- # (In xcode 10.2, the generated swift headers vary for each archs)
70
- # https://github.com/leavez/cocoapods-binary/issues/58
71
- if Pod::Podfile::DSL.simulator_build_enabled
72
- device_generated_swift_header_path = device_framework_path + "/Headers/#{module_name}-Swift.h"
73
- device_header = File.read(device_generated_swift_header_path)
74
- simulator_generated_swift_header_path = simulator_framework_path + "/Headers/#{module_name}-Swift.h"
75
- if File.exist? simulator_generated_swift_header_path
76
-
77
- simulator_header = File.read(simulator_generated_swift_header_path)
78
- # https://github.com/Carthage/Carthage/issues/2718#issuecomment-473870461
79
- combined_header_content = %Q{
80
- #if TARGET_OS_SIMULATOR // merged by cocoapods-binary
81
-
82
- #{simulator_header}
83
-
84
- #else // merged by cocoapods-binary
85
-
86
- #{device_header}
87
-
88
- #endif // merged by cocoapods-binary
89
- }
90
- File.write(device_generated_swift_header_path, combined_header_content.strip)
91
- end
92
- else
93
- device_generated_swift_header_path = device_framework_path + "/Headers/#{module_name}-Swift.h"
94
- if File.exist?(device_generated_swift_header_path)
95
- device_header = File.read(device_generated_swift_header_path)
96
- combined_header_content = %Q{
97
- #if TARGET_OS_SIMULATOR // merged by cocoapods-binary
98
-
99
- #else // merged by cocoapods-binary
100
-
101
- #{device_header}
102
-
103
- #endif // merged by cocoapods-binary
104
- }
105
- File.write(device_generated_swift_header_path, combined_header_content.strip)
106
- end
107
- end
108
-
109
- # handle the dSYM files
110
- # device_dsym = "#{device_framework_path}.dSYM"
111
- # if File.exist? device_dsym
112
- # # lipo the simulator dsym
113
- # simulator_dsym = "#{simulator_framework_path}.dSYM"
114
- # if File.exist? simulator_dsym
115
- # tmp_lipoed_binary_path = "#{output_path}/#{module_name}.draft"
116
- # lipo_log = `lipo -create -output #{tmp_lipoed_binary_path} #{device_dsym}/Contents/Resources/DWARF/#{module_name} #{simulator_dsym}/Contents/Resources/DWARF/#{module_name}`
117
- # puts lipo_log unless File.exist?(tmp_lipoed_binary_path)
118
- # FileUtils.mv tmp_lipoed_binary_path, "#{device_framework_path}.dSYM/Contents/Resources/DWARF/#{module_name}", :force => true
119
- # end
120
- # # move
121
- # FileUtils.mv device_dsym, output_path, :force => true
122
- # end
123
-
124
- # output
125
- output_path.mkpath unless output_path.exist?
126
-
127
- if target.static_framework?
128
- # 🔑 添加资源处理 - 修复静态库资源丢失问题
129
- copy_resources_to_framework(sandbox, target, device_framework_path)
130
- end
131
-
132
- FileUtils.mv device_framework_path, output_path, :force => true
133
-
134
- end
135
-
136
- # 新增函数:拷贝资源文件到 framework
137
- def copy_resources_to_framework(sandbox, target, framework_path)
138
- Pod::UI.puts "📋 Processing resources for #{target.name}..."
139
-
140
- pod_dir = Pathname.new(sandbox.pod_dir(target.pod_name))
141
- framework_dir = Pathname.new(framework_path)
142
-
143
- # 直接递归扫描 pod 目录下的所有资源文件,拷贝到 framework 根目录
144
- scan_and_copy_resources_flat(pod_dir, framework_dir)
145
-
146
- Pod::UI.puts "✅ Resource processing completed for #{target.name}"
147
- end
148
-
149
- # 递归扫描资源文件并平铺拷贝到目标目录
150
- def scan_and_copy_resources_flat(source_dir, target_dir)
151
- # 确保参数是Pathname类型
152
- source_dir = Pathname.new(source_dir) unless source_dir.is_a?(Pathname)
153
- target_dir = Pathname.new(target_dir) unless target_dir.is_a?(Pathname)
154
-
155
- Pod::UI.puts "📁 Recursively scanning directory: #{source_dir}"
156
-
157
- # 资源文件扩展名
158
- resource_extensions = [
159
- '.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', # 图片
160
- '.storyboard', '.xib', '.storyboardc', '.nib', # 界面文件
161
- '.ttf', '.otf', '.woff', '.woff2', # 字体
162
- '.mp3', '.wav', '.m4a', '.mp4', '.mov', '.avi', # 媒体
163
- '.json', '.plist', '.strings', '.xcassets', # 配置文件
164
- '.bin', # 二进制资源
165
- 'metallib' # metal or opengl文件
166
- ]
167
-
168
- # 特殊处理的目录类型(这些需要完整保留)
169
- special_directory_extensions = ['.bundle', '.xcassets', '.lproj']
170
-
171
- # 递归查找并拷贝资源文件,传递原始根目录用于路径计算
172
- find_and_copy_resources_recursively(source_dir, target_dir, source_dir, resource_extensions, special_directory_extensions)
173
- end
174
-
175
- # 仅 .bin:Apps/Cocome/Resources/m/m.bin -> m/m.bin
176
- def bin_relative_path_for_copy(child, source_root_dir)
177
- rel_parts = child.relative_path_from(source_root_dir).each_filename.to_a
178
- if (idx = rel_parts.index('Resources')) && idx < rel_parts.length - 1
179
- return Pathname.new(rel_parts[(idx + 1)..-1].join('/'))
180
- end
181
- if rel_parts.length >= 2
182
- return Pathname.new(rel_parts[-2..-1].join('/'))
183
- end
184
- Pathname.new(child.basename)
185
- end
186
-
187
- # 递归查找资源文件并拷贝
188
- def find_and_copy_resources_recursively(current_dir, target_dir, source_root_dir, resource_extensions, special_extensions)
189
- # 确保所有参数都是Pathname类型
190
- current_dir = Pathname.new(current_dir) unless current_dir.is_a?(Pathname)
191
- target_dir = Pathname.new(target_dir) unless target_dir.is_a?(Pathname)
192
- source_root_dir = Pathname.new(source_root_dir) unless source_root_dir.is_a?(Pathname)
193
-
194
- return unless current_dir.exist? && current_dir.directory?
195
-
196
- current_dir.children.each do |child|
197
- # 跳过隐藏文件和系统目录
198
- next if child.basename.to_s.start_with?('.')
199
- next if ['.git', '.svn', 'node_modules', '.DS_Store'].include?(child.basename.to_s)
200
-
201
- if child.directory?
202
- # 检查是否是特殊资源目录(需要完整保留的)
203
- if special_extensions.include?(child.extname)
204
- Pod::UI.puts " 📦 Copying special directory: #{child.basename}"
205
- target_path = target_dir + child.basename
206
- FileUtils.cp_r(child.to_s, target_path.to_s, :remove_destination => true)
207
- else
208
- # 递归处理普通目录
209
- find_and_copy_resources_recursively(child, target_dir, source_root_dir, resource_extensions, special_extensions)
210
- end
211
- else
212
- # 检查是否是资源文件
213
- if resource_extensions.include?(child.extname.downcase)
214
- # .bin:仅扩展路径保留(m/m.bin),其它资源仍平铺,逻辑不变
215
- if child.extname.downcase == '.bin'
216
- relative_path = bin_relative_path_for_copy(child, source_root_dir)
217
- target_path = target_dir + relative_path
218
- Pod::UI.puts " 📄 Copying bin resource: #{relative_path}"
219
- target_path.dirname.mkpath unless target_path.dirname.exist?
220
- FileUtils.cp(child.to_s, target_path.to_s)
221
- else
222
- Pod::UI.puts " 📄 Copying resource file: #{child.basename}"
223
- target_path = target_dir + child.basename
224
-
225
- # 处理文件名冲突(如果有重名文件,添加路径前缀)
226
- if target_path.exist?
227
- # 计算相对于根目录的路径作为前缀
228
- relative_dir = child.dirname.relative_path_from(source_root_dir)
229
- safe_name = "#{relative_dir.to_s.gsub('/', '_')}_#{child.basename}"
230
- target_path = target_dir + safe_name
231
- Pod::UI.puts " ⚠️ File name conflict, renamed to: #{safe_name}"
232
- end
233
-
234
- FileUtils.cp(child.to_s, target_path.to_s)
235
- end
236
- end
237
- end
238
- end
239
- end
240
-
241
- def xcodebuild(sandbox, target, sdk='macosx', deployment_target=nil, other_options=[])
242
- args = %W(-project #{sandbox.project_path.realdirpath} -scheme #{target} -configuration #{CONFIGURATION} -sdk #{sdk} )
243
- platform = PLATFORMS[sdk]
244
- args += Fourflusher::SimControl.new.destination(:oldest, platform, deployment_target) unless platform.nil?
245
- args += other_options
246
- Pod::UI.puts "📦 start compile project #{target} (#{args}) "
247
- log = `xcodebuild #{args.join(" ")} 2>&1`
248
- exit_code = $?.exitstatus # Process::Status
249
- is_succeed = (exit_code == 0)
250
-
251
- if !is_succeed
252
- Pod::UI.puts "❌ Build failed for target #{target} (exit code: #{exit_code})".red
253
- begin
254
- if log.include?('** BUILD FAILED **')
255
- # use xcpretty to print build log
256
- # 64 represent command invalid. http://www.manpagez.com/man/3/sysexits/
257
- printer = XCPretty::Printer.new({:formatter => XCPretty::Simple, :colorize => 'auto'})
258
- log.each_line do |line|
259
- printer.pretty_print(line)
260
- end
261
- else
262
- raise "shouldn't be handle by xcpretty"
263
- end
264
- rescue
265
- puts log.red
266
- end
267
- Pod::UI.puts "💥 Compilation terminated due to build failure. Please check the error messages above.".red
268
- exit 1
269
- end
270
- [is_succeed, log]
271
- end
272
-
273
- module Pod
274
- class Prebuild
275
-
276
- # Build the frameworks with sandbox and targets
277
- #
278
- # @param [String] sandbox_root_path
279
- # The sandbox root path where the targets project place
280
- #
281
- # [PodTarget] target
282
- # The pod targets to build
283
- #
284
- # [Pathname] output_path
285
- # output path for generated frameworks
286
- #
287
- def self.build(sandbox_root_path, target, output_path, bitcode_enabled = false, custom_build_options=[], custom_build_options_simulator=[])
288
-
289
- return if target.nil?
290
-
291
- sandbox_root = Pathname(sandbox_root_path)
292
- sandbox = Pod::Sandbox.new(sandbox_root)
293
- build_dir = self.build_dir(sandbox_root)
294
-
295
- # -- build the framework
296
- case target.platform.name
297
- when :ios then build_for_iosish_platform(sandbox, build_dir, output_path, target, 'iphoneos', 'iphonesimulator', bitcode_enabled, custom_build_options, custom_build_options_simulator)
298
- when :osx then xcodebuild(sandbox, target.label, 'macosx', nil, custom_build_options)
299
- # when :tvos then build_for_iosish_platform(sandbox, build_dir, target, 'appletvos', 'appletvsimulator')
300
- when :watchos then build_for_iosish_platform(sandbox, build_dir, output_path, target, 'watchos', 'watchsimulator', true, custom_build_options, custom_build_options_simulator)
301
- else raise "Unsupported platform for '#{target.name}': '#{target.platform.name}'" end
302
-
303
- raise Pod::Informative, 'The build directory was not found in the expected location.' unless build_dir.directory?
304
-
305
- # # --- copy the vendored libraries and framework
306
- # frameworks = build_dir.children.select{ |path| File.extname(path) == ".framework" }
307
- # Pod::UI.puts "Built #{frameworks.count} #{'frameworks'.pluralize(frameworks.count)}"
308
-
309
- # pod_target = target
310
- # consumer = pod_target.root_spec.consumer(pod_target.platform.name)
311
- # file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(pod_target.pod_name), consumer)
312
- # frameworks += file_accessor.vendored_libraries
313
- # frameworks += file_accessor.vendored_frameworks
314
-
315
- # frameworks.uniq!
316
-
317
- # frameworks.each do |framework|
318
- # FileUtils.mkdir_p destination
319
- # FileUtils.cp_r framework, destination, :remove_destination => true
320
- # end
321
- # build_dir.rmtree if build_dir.directory?
322
- end
323
-
324
- def self.remove_build_dir(sandbox_root)
325
- path = build_dir(sandbox_root)
326
- path.rmtree if path.exist?
327
- end
328
-
329
- private
330
-
331
- def self.build_dir(sandbox_root)
332
- # don't know why xcode chose this folder
333
- sandbox_root.parent + 'build'
334
- end
335
-
336
- end
337
- end
@@ -1,12 +0,0 @@
1
- # attr_accessor for class variable.
2
- # usage:
3
- #
4
- # ```
5
- # class Pod
6
- # class_attr_accessor :is_prebuild_stage
7
- # end
8
- # ```
9
- #
10
- def class_attr_accessor(symbol)
11
- self.class.send(:attr_accessor, symbol)
12
- end
@@ -1 +0,0 @@
1
- require 'cocoapods-binary-matchup/gem_version'
@@ -1,2 +0,0 @@
1
- require 'cocoapods-binary-matchup/Main'
2
-
data/spec/plugin_spec.rb DELETED
@@ -1,43 +0,0 @@
1
- require File.expand_path('../spec_helper', __FILE__)
2
-
3
- describe "CocoaPods Binary Matchup Plugin" do
4
- it "should load the plugin" do
5
- Pod::Prebuild.keyword.should == :binary
6
- end
7
-
8
- it "should load successfully" do
9
- # 简单验证插件加载成功
10
- defined?(Pod::Prebuild).should.not.be.nil
11
- end
12
-
13
- it "should have basic constants defined" do
14
- # 验证基本常量存在
15
- Pod.constants.should.include?(:Prebuild)
16
- end
17
-
18
- it "should define DSL instance methods" do
19
- # 验证实例方法存在(这些是在Podfile中使用的方法)
20
- # instance_methods是反射方法,用于获取所有的实例方法,注意false代表不获取父类
21
- dsl_methods = Pod::Podfile::DSL.instance_methods(false)
22
- dsl_methods.should.include?(:all_binary!)
23
- dsl_methods.should.include?(:enable_bitcode_for_prebuilt_frameworks!)
24
- dsl_methods.should.include?(:keep_source_code_for_prebuilt_frameworks!)
25
- dsl_methods.should.include?(:simulator_build_disable!)
26
- dsl_methods.should.include?(:set_custom_xcodebuild_options_for_prebuilt_frameworks)
27
- end
28
-
29
- it "should have correct default values for public attributes" do
30
- # 验证公开的默认配置值
31
- Pod::Podfile::DSL.simulator_build_enabled.should == true
32
- end
33
-
34
-
35
- it "should allow toggling simulator build" do
36
- # 验证可以切换模拟器构建设置
37
- original_value = Pod::Podfile::DSL.simulator_build_enabled
38
- Pod::Podfile::DSL.simulator_build_enabled = false
39
- Pod::Podfile::DSL.simulator_build_enabled.should == false
40
- # 恢复原值
41
- Pod::Podfile::DSL.simulator_build_enabled = original_value
42
- end
43
- end
data/spec/spec_helper.rb DELETED
@@ -1,50 +0,0 @@
1
- require 'pathname'
2
- ROOT = Pathname.new(File.expand_path('../../', __FILE__))
3
- $:.unshift((ROOT + 'lib').to_s)
4
- $:.unshift((ROOT + 'spec').to_s)
5
-
6
- require 'bundler/setup'
7
- require 'bacon'
8
- require 'mocha-on-bacon'
9
- require 'pretty_bacon'
10
- require 'pathname'
11
- require 'cocoapods'
12
-
13
- # Mocha::Configuration.prevent(:stubbing_non_existent_method) # 兼容性问题,暂时注释
14
-
15
- require 'cocoapods_plugin'
16
-
17
- #-----------------------------------------------------------------------------#
18
-
19
- module Pod
20
-
21
- # Disable the wrapping so the output is deterministic in the tests.
22
- #
23
- UI.disable_wrap = true
24
-
25
- # Redirects the messages to an internal store.
26
- #
27
- module UI
28
- @output = ''
29
- @warnings = ''
30
-
31
- class << self
32
- attr_accessor :output
33
- attr_accessor :warnings
34
-
35
- def puts(message = '')
36
- @output << "#{message}\n"
37
- end
38
-
39
- def warn(message = '', actions = [])
40
- @warnings << "#{message}\n"
41
- end
42
-
43
- def print(message)
44
- @output << message
45
- end
46
- end
47
- end
48
- end
49
-
50
- #-----------------------------------------------------------------------------#