cocoapods-bb-xcframework 0.2.6.6 → 0.2.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b0b8247f09ae9e9a153bdbf204ea123bec0ad7ac63d40673f51fe6c282d02c23
4
- data.tar.gz: 6473f2b2995b8474794979db49c6497bf21f3ec31af77cbd47619f294aca8d38
3
+ metadata.gz: d978114db2ee372ac4e3d21ff2aa2e0142703f8f2b7513a7cb7f66446e7a38f3
4
+ data.tar.gz: 5ce56a269c08760bd8d2e4c7a1103da23518ef46e311cb6894d3b8c2c4c040a4
5
5
  SHA512:
6
- metadata.gz: b6ca50c209203d62016f6672f348e7d4937b9620fde16a1f1ae7cf3415a2adc161e8c18931ec4a29bed22d6460e2c79097225b690c259ae352f966b30c3a7067
7
- data.tar.gz: 3e711237af20aea6305694e093664fff7cd66e2cb719326c507d3469008ea4bdd92624f47c5e6dbed2ba3255587be05f53cb292f74f99db622b47bf18a4ed1d2
6
+ metadata.gz: c6395271306ac0f9019d4649d87606e49336c67e5b082f2c0ad212b523ce2eed44c5f719b8d825aff4ae2fe210195cdc70747ff733f697ec69159007ec9b38fb
7
+ data.tar.gz: 296d7bd8e51898bcff76e6b11abaf92f6597db1f0f12ed1af9b19ae20f879de23c594d486407cebdd7c806ad830d9f237b964f7a5607cd73170f8851040d0190
@@ -36,7 +36,8 @@ module Pod
36
36
  ['--enable-bitcode', 'package enable bitcode'],
37
37
  ['--no-symbols', 'package not use symbols'], # 符号表
38
38
  ['--no-support-maccatalyst', 'package support generate MacCatalyst'], # 是否支持MacCatalyst方式支持iOS应用在mac平台运行库生成
39
- ['--no-support-dynamic', 'package support Mach-O dynamically linked shared library'] # 是否支持动态库生成
39
+ ['--no-support-dynamic', 'package support Mach-O dynamically linked shared library'], # 是否支持动态库生成
40
+ ['--no-archive-export', 'xcodebuild archive export'] # 是否支持本地导出,导出dylib动态库
40
41
  ].concat super
41
42
  end
42
43
 
@@ -54,6 +55,7 @@ module Pod
54
55
  @symbols = argv.flag?('symbols',true)
55
56
  @support_maccatalyst = argv.flag?('support-maccatalyst',true)
56
57
  @support_dynamic = argv.flag?('support-dynamic',false)
58
+ @archive_export = argv.flag?('archive-export',true)
57
59
  config.static_library_enable = @use_static_library
58
60
  super
59
61
  end
@@ -64,9 +66,16 @@ module Pod
64
66
  end
65
67
 
66
68
  def run
67
- UI.puts "argvs @name:#{@name} @source:#{@source} @spec_sources:#{@spec_sources}"
68
- frameworker = Frameworker.new(@name, @source, @spec_sources, @subspecs, @configuration, @force, @use_modular_headers, @enable_bitcode, @symbols, @support_maccatalyst, @support_dynamic)
69
- frameworker.run
69
+ UI.puts "argvs @name:#{@name} @source:#{@source} @spec_sources:#{@spec_sources} @subspecs:#{@subspecs} @archive_export:#{@archive_export}"
70
+ if @archive_export
71
+ puts "local builder xcframework"
72
+ frameworker = LocalBuilder.new(@name, @source, @spec_sources, @subspecs, @configuration, @force, @use_modular_headers, @enable_bitcode, @symbols, @support_maccatalyst, @support_dynamic, Dir.pwd)
73
+ frameworker.build
74
+ else
75
+ puts "remote builder xcframework"
76
+ frameworker = Frameworker.new(@name, @source, @spec_sources, @subspecs, @configuration, @force, @use_modular_headers, @enable_bitcode, @symbols, @support_maccatalyst, @support_dynamic)
77
+ frameworker.run
78
+ end
70
79
  end
71
80
  end
72
81
  end
@@ -1,3 +1,3 @@
1
1
  module CocoapodsXCFramework
2
- VERSION = "0.2.6.6"
2
+ VERSION = "0.2.7.0"
3
3
  end
@@ -0,0 +1,323 @@
1
+ module Pod
2
+ class LocalBuilder
3
+ include PodUtil
4
+ include DirUtil
5
+ include Config::Mixin
6
+ def initialize(name, source, spec_sources, subspecs, configuration, force, use_modular_headers=true, enable_bitcode=false, symbols=true, support_maccatalyst=true, support_dynamic=false, source_dir=Dir.pwd)
7
+ @name = name
8
+ @source = source
9
+ @spec_sources = spec_sources
10
+ @subspecs = subspecs
11
+ @configuration = configuration
12
+ @force = force
13
+ @use_modular_headers = use_modular_headers
14
+ @enable_bitcode = enable_bitcode
15
+ @symbols = symbols
16
+ @support_maccatalyst = support_maccatalyst
17
+ @support_dynamic = support_dynamic
18
+ @spec = spec_with_path @name
19
+ @source_dir = source_dir
20
+ @outputs = Hash.new
21
+ end
22
+
23
+ def run
24
+ end
25
+
26
+ def build
27
+ spec = spec_with_path @name
28
+ UI.puts "正在生成Local XCFramework #{spec.name}(#{spec.version}) with configuration #{@configuration} isSymbols:#{@symbols}".yellow
29
+ @is_spec_from_path = true if spec
30
+ spec ||= spec_with_name @name
31
+ target_dir, work_dir = create_working_directory_by_spec spec, @force
32
+ build_dir = "#{work_dir}/build"
33
+ archive_path = "#{build_dir}/archives"
34
+ defines = ""
35
+ if @configuration == 'Debug'
36
+ defines << 'GCC_GENERATE_DEBUGGING_SYMBOLS=YES ONLY_ACTIVE_ARCH=NO'
37
+ else
38
+ if @symbols
39
+ defines << "GCC_GENERATE_DEBUGGING_SYMBOLS=YES" # Release模式需要符号表应于问题排查(二进制切源码操作) by hm 21/10/13
40
+ else
41
+ defines << "GCC_GENERATE_DEBUGGING_SYMBOLS=NO" # 去除符号表
42
+ end
43
+ end
44
+ FileUtils.rm_rf(build_dir)
45
+
46
+ build_all_device(defines, build_dir, archive_path)
47
+ makeXCFramework(archive_path, build_dir)
48
+ exportdSYMs(archive_path, build_dir)
49
+ outputs(target_dir)
50
+ end
51
+
52
+ def xcode_xbuild(destination, archs, platform, defines, build_dir, archive_path)
53
+ # xcodebuild archive requires -scheme when -archivePath is specified
54
+ spec = spec_with_path @name
55
+ spec ||= spec_with_name @name
56
+
57
+ scheme_name = @spec&.name
58
+ configuration = @configuration
59
+ skip_install = 'NO'
60
+ plat_name = platform.to_s.gsub(/\s+/, '_')
61
+ archivePath = "#{archive_path}/#{scheme_name}-#{plat_name}.xcarchive"
62
+ UI.puts "archivePath:#{archivePath}"
63
+ if scheme_name.nil?
64
+ UI.puts("❌ archive 构建缺少 scheme,请在调用 xcode_xbuild 时显式传入 scheme").red
65
+ Process.exit 1
66
+ end
67
+ command = "xcodebuild archive " \
68
+ "-scheme '#{scheme_name}' " \
69
+ "-archivePath '#{archivePath}' " \
70
+ "-destination '#{destination}' " \
71
+ "-configuration #{configuration} " \
72
+ "ARCHS='#{archs}' " \
73
+ "SKIP_INSTALL=#{skip_install}" \
74
+ "#{defines} " \
75
+ "SWIFT_OPTIMIZATION_LEVEL=-Onone DEBUG_INFORMATION_FORMAT=dwarf-with-dsym " \
76
+ "BUILD_LIBRARY_FOR_DISTRIBUTION=YES clean build" \
77
+
78
+ # --- enhanced logging & reliable failure surfacing ---
79
+ log_dir = File.join(archivePath, 'logs')
80
+ FileUtils.mkdir_p(log_dir)
81
+ log_raw = File.join(log_dir, "xcodebuild-#{scheme_name}-#{plat_name}-#{configuration}.raw.log")
82
+
83
+ # Allow disabling xcpretty via env
84
+ use_pretty = ENV['XBUILDER_NOPRETTY'] != '1'
85
+ wrapped = if use_pretty
86
+ "set -o pipefail; #{command} | tee '#{log_raw}' | xcpretty"
87
+ else
88
+ # no pretty: just tee to log and console
89
+ "set -o pipefail; #{command} | tee '#{log_raw}'"
90
+ end
91
+ UI.puts "XBuilder command: #{command}"
92
+ success = system('bash', '-lc', wrapped)
93
+ unless success
94
+ UI.puts "\n** xcodebuild failed — showing last 200 lines of raw log: #{log_raw}".red
95
+ if File.exist?(log_raw)
96
+ tail = `tail -n 200 '#{log_raw}'`
97
+ UI.puts tail
98
+ end
99
+ Pod::ErrorUtil.error_report(command, []) if defined?(Pod::ErrorUtil)
100
+ Process.exit $?.exitstatus.nonzero? || 1
101
+ end
102
+ end
103
+
104
+ def build_all_device(defines, build_dir, archive_path)
105
+ # build general first because simulator will exchange SDKROOT to simulat sdk
106
+ build_general_device defines, build_dir, archive_path
107
+ build_simulator_device defines, build_dir, archive_path
108
+ build_MacCatalyst_device defines, build_dir, archive_path if @support_maccatalyst
109
+ end
110
+
111
+ def build_general_device defines, build_dir, archive_path
112
+ UI.puts("--- Building framework #{@spec} with general device")
113
+ destination = 'generic/platform=iOS'
114
+ archs = 'arm64'
115
+ xcode_xbuild(destination, archs, "iOS", defines, build_dir, archive_path)
116
+ end
117
+
118
+ def build_simulator_device defines, build_dir, archive_path
119
+ UI.puts("--- Building framework #{@spec} with simulator device")
120
+ destination = 'generic/platform=iOS Simulator'
121
+ archs = 'x86_64 arm64'
122
+ xcode_xbuild(destination, archs, "Simulator", defines, build_dir, archive_path)
123
+ end
124
+
125
+ def build_MacCatalyst_device defines, build_dir, archive_path
126
+ UI.puts("--- Building framework #{@spec} with MacCatalyst device")
127
+ destination = 'generic/platform=macOS,variant=Mac Catalyst,name=Any Mac'
128
+ archs = 'x86_64 arm64'
129
+ xcode_xbuild(destination, archs, "MacCatalyst", defines, build_dir, archive_path)
130
+ end
131
+
132
+ def makeXCFramework(archive_path, output_dir)
133
+ spec = spec_with_path @name
134
+ spec ||= spec_with_name @name
135
+ framework_name = spec.name
136
+
137
+ # scan xcarchive directories
138
+ archives = Dir.glob(File.join(archive_path, '*.xcarchive'))
139
+ if archives.empty?
140
+ UI.puts("❌ 未在 #{archive_path} 下找到 xcarchive 产物,无法生成 xcframework").red
141
+ Process.exit 1
142
+ end
143
+
144
+ framework_args = []
145
+
146
+ archives.each do |archive|
147
+ framework_path = File.join(
148
+ archive,
149
+ 'Products',
150
+ 'Library',
151
+ 'Frameworks',
152
+ "#{framework_name}.framework"
153
+ )
154
+ if File.exist?(framework_path)
155
+ framework_args << "-framework '#{framework_path}'"
156
+ UI.puts "� Found framework: #{framework_path}".green
157
+ else
158
+ UI.puts "⚠️ 未在 #{archive} 中找到 #{framework_name}.framework,已跳过".yellow
159
+ end
160
+ end
161
+
162
+ if framework_args.empty?
163
+ UI.puts("❌ 未找到任何可用 Framework,xcframework 生成失败").red
164
+ Process.exit 1
165
+ end
166
+
167
+ xcframework_path = File.join(output_dir, "#{framework_name}.xcframework")
168
+ FileUtils.rm_rf(xcframework_path)
169
+ @outputs[:xcframework] = xcframework_path
170
+
171
+ command = [
172
+ 'xcodebuild -create-xcframework',
173
+ framework_args.join(' '),
174
+ "-output '#{xcframework_path}'"
175
+ ].join(' ')
176
+
177
+ UI.puts "� Creating XCFramework:"
178
+ UI.puts command.cyan
179
+
180
+ success = system(command)
181
+ unless success
182
+ UI.puts("❌ xcodebuild -create-xcframework 执行失败").red
183
+ Process.exit $?.exitstatus.nonzero? || 1
184
+ end
185
+
186
+ UI.puts "✅ XCFramework 生成成功:"
187
+ UI.puts xcframework_path.green
188
+ end
189
+
190
+ # 导出符号表
191
+ def exportdSYMs(archive_path, build_dir)
192
+ spec = spec_with_path @name
193
+ spec ||= spec_with_name @name
194
+ framework_name = spec.name
195
+
196
+ dsym_output_dir = File.join(build_dir, 'dSYMs')
197
+ FileUtils.mkdir_p(dsym_output_dir)
198
+
199
+ archives = Dir.glob(File.join(archive_path, '*.xcarchive'))
200
+ if archives.empty?
201
+ UI.puts("⚠️ 未在 #{archive_path} 下找到 xcarchive,跳过 dSYM 导出").yellow
202
+ return
203
+ end
204
+
205
+ exported = false
206
+
207
+ archives.each do |archive|
208
+ dsym_path = File.join(
209
+ archive,
210
+ 'dSYMs',
211
+ "#{framework_name}.framework.dSYM"
212
+ )
213
+
214
+ if File.exist?(dsym_path)
215
+ archive_name = File.basename(archive, '.xcarchive')
216
+ target_path = File.join(dsym_output_dir, "#{archive_name}.framework.dSYM")
217
+ FileUtils.rm_rf(target_path)
218
+ FileUtils.cp_r(dsym_path, target_path)
219
+ UI.puts "� Exported dSYM: #{target_path}".green
220
+ exported = true
221
+ else
222
+ UI.puts "⚠️ 未在 #{archive} 中找到 dSYM,已跳过".yellow
223
+ end
224
+ end
225
+
226
+ unless exported
227
+ UI.puts("⚠️ 未导出任何 dSYM,请确认 DEBUG_INFORMATION_FORMAT=dwarf-with-dsym").yellow
228
+ else
229
+ UI.puts "✅ dSYM 导出完成,目录:#{dsym_output_dir}".green
230
+ end
231
+ end
232
+
233
+ def outputs target_dir
234
+ puts "outputs:#{target_dir}"
235
+ if not File.exist? target_dir
236
+ Pathname.new(target_dir).mkdir
237
+ end
238
+ outputs_xcframework target_dir
239
+ outputs_bundle target_dir
240
+ new_spec_hash = generic_new_podspec_hash @spec
241
+ new_spec_hash[:vendored_frameworks] = "#{@spec.name}.xcframework"
242
+ xcframework_path = "#{target_dir}/#{@spec.name}.xcframework"
243
+ # new_spec_hash = fix_header_file new_spec_hash, xcframework_path
244
+ # new_spec_hash = fix_bundle_file(@spec, new_spec_hash, @source_dir, xcframework_path)
245
+ # find_bundles(target_dir).each do |plat, value|
246
+ # if new_spec_hash[plat]
247
+ # new_spec_hash[plat]["resource_bundles"] = value
248
+ # else
249
+ # new_spec_hash[plat] = {
250
+ # "resource_bundles" => value
251
+ # }
252
+ # end
253
+ # end
254
+ require 'json'
255
+ spec_json = JSON.pretty_generate(new_spec_hash) << "\n"
256
+ File.open("#{target_dir}/#{@spec.name}.podspec.json",'wb+') do |f|
257
+ f.write(spec_json)
258
+ end
259
+ # fix xcframework-is-not-a-member-type-of-error https://v3.bbcloud.babybus.com/team/184/wiki/13820
260
+ # UI.puts "fix xcframework-is-not-a-member-type-of-error:#{target_dir}"
261
+ # fix_xcframework_error(target_dir, @spec.name)
262
+
263
+ UI.puts "result export at :#{target_dir} 生成成功".green
264
+ target_dir
265
+ end
266
+
267
+ # 解决项目是Swift和Objc混合开发,有一个Swift类名和ModuleName相同,当打包成xcframework引入到项目时, 会报错… is not a member type of …
268
+ def fix_xcframework_error target_dir, name
269
+ # 全量替换代价:Swift module identity 被抹掉,--- 调试时能看不清来自哪个组件
270
+ # command = "find #{target_dir} -name '*.swiftinterface' -exec sed -i -e 's/#{name}\\.//g' {} \\; && find #{target_dir} -name '*.swiftinterface-e' | xargs rm -rf"
271
+ # UI.puts "fix swift error command :#{command}"
272
+
273
+ # 安全版修复: by hm 26/1/30
274
+ # 仅修复 Swift 类名 == ModuleName 时产生的 `ModuleName.ModuleName` 冲突,
275
+ # 避免全量移除 ModuleName. 造成 Swift module identity 丢失。
276
+ UI.puts "fix xcframework-is-not-a-member-type-of-error (safe mode): #{target_dir}"
277
+ # 只替换 `ModuleName.ModuleName` -> `ModuleName`
278
+ pattern = "s/#{name}\\.#{name}/#{name}/g"
279
+ # command = <<~CMD
280
+ # find #{target_dir} -name '*.swiftinterface' \
281
+ # -exec sed -i -e '#{pattern}' {} \; \
282
+ # && find #{target_dir} -name '*.swiftinterface-e' | xargs rm -rf
283
+ # CMD
284
+ command = "find #{target_dir} -name '*.swiftinterface' -exec sed -i -e 's/#{name}\\.#{name}/#{name}//g' {} \\; && find #{target_dir} -name '*.swiftinterface-e' | xargs rm -rf"
285
+ UI.puts "fix swift error command (safe): #{command}"
286
+ output = `#{command}`.lines.to_a
287
+ if $?.exitstatus != 0
288
+ Pod::ErrorUtil.error_report command, output
289
+ Process.exit -1
290
+ end
291
+ end
292
+
293
+ def find_bundles target_dir
294
+ bundle_root = "#{target_dir}/bundle/"
295
+ pattern = "#{bundle_root}*"
296
+ result = {}
297
+ Pathname.glob(pattern).each do |bundle|
298
+ bundle_relative_path = bundle.to_s.gsub(bundle_root, "")
299
+ plat = bundle_relative_path
300
+ result[plat] = {
301
+ "#{@spec.name}" => "bundle/" + bundle_relative_path + "/*"
302
+ }
303
+ end
304
+ result
305
+ end
306
+
307
+ def outputs_xcframework target_dir
308
+ command = "cp -rp #{@outputs[:xcframework]} #{target_dir} 2>&1"
309
+ output = `#{command}`.lines.to_a
310
+ if $?.exitstatus != 0
311
+ Pod::ErrorUtil.error_report command,output
312
+ Process.exit -1
313
+ end
314
+ end
315
+
316
+ def outputs_bundle target_dir
317
+ if @outputs[:bundle]
318
+ FileUtils.cp_r(Dir[@outputs[:bundle]],target_dir)
319
+ end
320
+ end
321
+
322
+ end
323
+ end
@@ -201,20 +201,35 @@ module Pod
201
201
  f.write(spec_json)
202
202
  end
203
203
  # fix xcframework-is-not-a-member-type-of-error https://v3.bbcloud.babybus.com/team/184/wiki/13820
204
- UI.puts "fix xcframework-is-not-a-member-type-of-error:#{target_dir}"
205
- fix_xcframework_error(target_dir, @spec.name)
204
+ # UI.puts "fix xcframework-is-not-a-member-type-of-error:#{target_dir}"
205
+ # fix_xcframework_error(target_dir, @spec.name)
206
206
 
207
207
  UI.puts "result export at :#{target_dir} 生成成功".green
208
208
  target_dir
209
209
  end
210
210
 
211
+ # 解决项目是Swift和Objc混合开发,有一个Swift类名和ModuleName相同,当打包成xcframework引入到项目时, 会报错… is not a member type of …
211
212
  def fix_xcframework_error target_dir, name
212
- command = "find #{target_dir} -name '*.swiftinterface' -exec sed -i -e 's/#{name}\\.//g' {} \\; && find #{target_dir} -name '*.swiftinterface-e' | xargs rm -rf"
213
- UI.puts "fix swift error command :#{command}"
214
-
213
+ # 全量替换代价:Swift module identity 被抹掉,--- 调试时能看不清来自哪个组件
214
+ # command = "find #{target_dir} -name '*.swiftinterface' -exec sed -i -e 's/#{name}\\.//g' {} \\; && find #{target_dir} -name '*.swiftinterface-e' | xargs rm -rf"
215
+ # UI.puts "fix swift error command :#{command}"
216
+
217
+ # 安全版修复: by hm 26/1/30
218
+ # 仅修复 Swift 类名 == ModuleName 时产生的 `ModuleName.ModuleName` 冲突,
219
+ # 避免全量移除 ModuleName. 造成 Swift module identity 丢失。
220
+ UI.puts "fix xcframework-is-not-a-member-type-of-error (safe mode): #{target_dir}"
221
+ # 只替换 `ModuleName.ModuleName` -> `ModuleName`
222
+ pattern = "s/#{name}\\.#{name}/#{name}/g"
223
+ # command = <<~CMD
224
+ # find #{target_dir} -name '*.swiftinterface' \
225
+ # -exec sed -i -e '#{pattern}' {} \; \
226
+ # && find #{target_dir} -name '*.swiftinterface-e' | xargs rm -rf
227
+ # CMD
228
+ command = "find #{target_dir} -name '*.swiftinterface' -exec sed -i -e 's/#{name}\\.#{name}/#{name}//g' {} \\; && find #{target_dir} -name '*.swiftinterface-e' | xargs rm -rf"
229
+ UI.puts "fix swift error command (safe): #{command}"
215
230
  output = `#{command}`.lines.to_a
216
231
  if $?.exitstatus != 0
217
- Pod::ErrorUtil.error_report command,output
232
+ Pod::ErrorUtil.error_report command, output
218
233
  Process.exit -1
219
234
  end
220
235
  end
@@ -3,6 +3,7 @@ require 'cocoapods-xcframework/gem_version.rb'
3
3
  require 'cocoapods-xcframework/config'
4
4
  require 'cocoapods-xcframework/util'
5
5
  require 'cocoapods-xcframework/xbuilder'
6
+ require 'cocoapods-xcframework/local_build'
6
7
  require 'cocoapods-xcframework/frameworker'
7
8
  require 'cocoapods-xcframework/muti_frameworker'
8
9
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods-bb-xcframework
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6.6
4
+ version: 0.2.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - humin
@@ -73,6 +73,7 @@ files:
73
73
  - lib/cocoapods-xcframework/config.rb
74
74
  - lib/cocoapods-xcframework/frameworker.rb
75
75
  - lib/cocoapods-xcframework/gem_version.rb
76
+ - lib/cocoapods-xcframework/local_build.rb
76
77
  - lib/cocoapods-xcframework/muti_frameworker.rb
77
78
  - lib/cocoapods-xcframework/util.rb
78
79
  - lib/cocoapods-xcframework/util/cmd.rb