cocoapods-meitu-bin 1.0.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.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.md +56 -0
  4. data/lib/cocoapods-meitu-bin/command/bin/archive.rb +206 -0
  5. data/lib/cocoapods-meitu-bin/command/bin/auto.rb +212 -0
  6. data/lib/cocoapods-meitu-bin/command/bin/build_all.rb +345 -0
  7. data/lib/cocoapods-meitu-bin/command/bin/header_files_specifications.rb +262 -0
  8. data/lib/cocoapods-meitu-bin/command/bin/init.rb +72 -0
  9. data/lib/cocoapods-meitu-bin/command/bin/install.rb +44 -0
  10. data/lib/cocoapods-meitu-bin/command/bin/lib/lint.rb +67 -0
  11. data/lib/cocoapods-meitu-bin/command/bin/lock/dependency.rb +89 -0
  12. data/lib/cocoapods-meitu-bin/command/bin/lock/spec_repo.rb +105 -0
  13. data/lib/cocoapods-meitu-bin/command/bin/lock/version.rb +68 -0
  14. data/lib/cocoapods-meitu-bin/command/bin/lock.rb +36 -0
  15. data/lib/cocoapods-meitu-bin/command/bin/output_source.rb +146 -0
  16. data/lib/cocoapods-meitu-bin/command/bin/repo/push.rb +88 -0
  17. data/lib/cocoapods-meitu-bin/command/bin/repo/update.rb +42 -0
  18. data/lib/cocoapods-meitu-bin/command/bin/repo.rb +14 -0
  19. data/lib/cocoapods-meitu-bin/command/bin/source/add.rb +148 -0
  20. data/lib/cocoapods-meitu-bin/command/bin/source/delete.rb +59 -0
  21. data/lib/cocoapods-meitu-bin/command/bin/source/list.rb +46 -0
  22. data/lib/cocoapods-meitu-bin/command/bin/source.rb +30 -0
  23. data/lib/cocoapods-meitu-bin/command/bin/spec/create.rb +73 -0
  24. data/lib/cocoapods-meitu-bin/command/bin/spec/lint.rb +109 -0
  25. data/lib/cocoapods-meitu-bin/command/bin/spec.rb +13 -0
  26. data/lib/cocoapods-meitu-bin/command/bin/update.rb +154 -0
  27. data/lib/cocoapods-meitu-bin/command/bin/upload.rb +175 -0
  28. data/lib/cocoapods-meitu-bin/command/bin.rb +69 -0
  29. data/lib/cocoapods-meitu-bin/command.rb +1 -0
  30. data/lib/cocoapods-meitu-bin/config/config.rb +149 -0
  31. data/lib/cocoapods-meitu-bin/config/config_asker.rb +57 -0
  32. data/lib/cocoapods-meitu-bin/config/config_builder.rb +216 -0
  33. data/lib/cocoapods-meitu-bin/gem_version.rb +9 -0
  34. data/lib/cocoapods-meitu-bin/helpers/Info.plist +0 -0
  35. data/lib/cocoapods-meitu-bin/helpers/buildAll/bin_helper.rb +97 -0
  36. data/lib/cocoapods-meitu-bin/helpers/buildAll/builder.rb +434 -0
  37. data/lib/cocoapods-meitu-bin/helpers/buildAll/podspec_util.rb +140 -0
  38. data/lib/cocoapods-meitu-bin/helpers/buildAll/zip_file_helper.rb +87 -0
  39. data/lib/cocoapods-meitu-bin/helpers/build_helper.rb +167 -0
  40. data/lib/cocoapods-meitu-bin/helpers/build_utils.rb +64 -0
  41. data/lib/cocoapods-meitu-bin/helpers/framework.rb +86 -0
  42. data/lib/cocoapods-meitu-bin/helpers/framework_builder.rb +551 -0
  43. data/lib/cocoapods-meitu-bin/helpers/library.rb +54 -0
  44. data/lib/cocoapods-meitu-bin/helpers/library_builder.rb +90 -0
  45. data/lib/cocoapods-meitu-bin/helpers/pod_size_helper.rb +54 -0
  46. data/lib/cocoapods-meitu-bin/helpers/sources_helper.rb +35 -0
  47. data/lib/cocoapods-meitu-bin/helpers/spec_creator.rb +170 -0
  48. data/lib/cocoapods-meitu-bin/helpers/spec_files_helper.rb +80 -0
  49. data/lib/cocoapods-meitu-bin/helpers/spec_source_creator.rb +304 -0
  50. data/lib/cocoapods-meitu-bin/helpers/upload_helper.rb +104 -0
  51. data/lib/cocoapods-meitu-bin/helpers.rb +5 -0
  52. data/lib/cocoapods-meitu-bin/native/acknowledgements.rb +27 -0
  53. data/lib/cocoapods-meitu-bin/native/analyzer.rb +109 -0
  54. data/lib/cocoapods-meitu-bin/native/file_accessor.rb +28 -0
  55. data/lib/cocoapods-meitu-bin/native/gen.rb +79 -0
  56. data/lib/cocoapods-meitu-bin/native/installation_options.rb +28 -0
  57. data/lib/cocoapods-meitu-bin/native/installer.rb +259 -0
  58. data/lib/cocoapods-meitu-bin/native/linter.rb +26 -0
  59. data/lib/cocoapods-meitu-bin/native/lockfile.rb +85 -0
  60. data/lib/cocoapods-meitu-bin/native/path_source.rb +33 -0
  61. data/lib/cocoapods-meitu-bin/native/pod_source_installer.rb +19 -0
  62. data/lib/cocoapods-meitu-bin/native/pod_target_installer.rb +87 -0
  63. data/lib/cocoapods-meitu-bin/native/podfile.rb +99 -0
  64. data/lib/cocoapods-meitu-bin/native/podfile_env.rb +38 -0
  65. data/lib/cocoapods-meitu-bin/native/podfile_generator.rb +201 -0
  66. data/lib/cocoapods-meitu-bin/native/podspec_finder.rb +25 -0
  67. data/lib/cocoapods-meitu-bin/native/resolver.rb +299 -0
  68. data/lib/cocoapods-meitu-bin/native/sandbox_analyzer.rb +34 -0
  69. data/lib/cocoapods-meitu-bin/native/source.rb +35 -0
  70. data/lib/cocoapods-meitu-bin/native/sources_manager.rb +21 -0
  71. data/lib/cocoapods-meitu-bin/native/specification.rb +31 -0
  72. data/lib/cocoapods-meitu-bin/native/target_validator.rb +41 -0
  73. data/lib/cocoapods-meitu-bin/native/validator.rb +40 -0
  74. data/lib/cocoapods-meitu-bin/native.rb +26 -0
  75. data/lib/cocoapods-meitu-bin/source_provider_hook.rb +68 -0
  76. data/lib/cocoapods-meitu-bin.rb +2 -0
  77. data/lib/cocoapods_plugin.rb +11 -0
  78. data/spec/command/bin_spec.rb +12 -0
  79. data/spec/spec_helper.rb +50 -0
  80. metadata +201 -0
@@ -0,0 +1,97 @@
1
+ require 'digest'
2
+
3
+ module CBin
4
+ module BuildAll
5
+ class BinHelper
6
+ include Pod
7
+
8
+ def initialize
9
+ super
10
+ @specs_str_md5_hash = Hash.new
11
+ end
12
+
13
+ # 二进制版本号(x.y.z.bin[md5前6位])
14
+ def version(pod_name, original_version, specifications, configuration = 'Debug')
15
+ # 有缓存从缓存中取,没有则新建
16
+ if @specs_str_md5_hash[pod_name].nil?
17
+ specs = specifications.map(&:name).select { |spec|
18
+ spec.include?(pod_name) && !spec.include?('/Binary')
19
+ }.sort!
20
+ specs << dependencies_str(pod_name, specifications)
21
+ specs << xcode_version
22
+ specs << (configuration.nil? ? 'Debug' : configuration)
23
+ specs_str = specs.join('')
24
+ if ENV['p_bin_v'] == '1'
25
+ UI.puts "`#{pod_name}`:#{specs_str}".red
26
+ end
27
+ specs_str_md5 = Digest::MD5.hexdigest(specs_str)[0,6]
28
+ @specs_str_md5_hash[pod_name] = specs_str_md5
29
+ else
30
+ specs_str_md5 = @specs_str_md5_hash[pod_name]
31
+ end
32
+ "#{original_version}.bin#{specs_str_md5}"
33
+ end
34
+
35
+ def xcode_version
36
+ @xcode_version ||= begin
37
+ `xcodebuild -version`.split(' ').join('')
38
+ end
39
+ end
40
+
41
+ def self.xcode_version
42
+ xcode_version = `xcodebuild -version`.split(' ').join('')
43
+ xcode_version
44
+ end
45
+
46
+ # 将当前 Pod 库的依赖库拼接成字符串(格式:pod1_name(pod1_version),pod2_name(pod2_version),...)
47
+ def dependencies_str(pod_name, specifications)
48
+ deps = []
49
+ specifications.map do |spec|
50
+ if spec.root.name == pod_name
51
+ deps.concat(spec.dependencies)
52
+ end
53
+ end
54
+ if deps.empty?
55
+ UI.puts "`#{pod_name}`无依赖库".red if ENV['p_bin_d'] == '1'
56
+ return ''
57
+ end
58
+ result = []
59
+ deps.uniq.map do |dep|
60
+ if dep.root_name == pod_name
61
+ next
62
+ end
63
+ version = dep_version(dep, specifications)
64
+ result << "#{dep.name}(#{version})"
65
+ end
66
+ if ENV['p_bin_d'] == '1'
67
+ if result.empty?
68
+ UI.puts "`#{pod_name}`无依赖库".red
69
+ else
70
+ UI.puts "`#{pod_name}`依赖的库如下:".yellow
71
+ result.map { |pod| puts "- #{pod}" }
72
+ end
73
+ end
74
+ result.join(',')
75
+ end
76
+
77
+ # 获取依赖库版本号
78
+ def dep_version(dep, specifications)
79
+ version = ''
80
+ specifications.map do |spec|
81
+ if spec.root.name == dep.root_name
82
+ version = spec.root.version.to_s
83
+ # 如果是二进制版本,去掉二进制版本号后缀
84
+ version_arr = version.split('.')
85
+ if version_arr.last.include?('bin')
86
+ version_arr.delete_at(version_arr.size - 1)
87
+ version = version_arr.join('.')
88
+ end
89
+ break
90
+ end
91
+ end
92
+ version
93
+ end
94
+
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,434 @@
1
+
2
+ module CBin
3
+ module BuildAll
4
+ class Builder
5
+ include Pod
6
+
7
+ def initialize(pod_target, checkout_sources, skip_simulator = false, configuration = 'Debug')
8
+ @pod_target = pod_target
9
+ @checkout_sources = checkout_sources
10
+ @skip_simulator = skip_simulator
11
+ @configuration = configuration
12
+ @file_accessors = pod_target.file_accessors unless pod_target.nil?
13
+ @base_dir = "#{Pathname.pwd}/build_pods"
14
+ end
15
+
16
+ # 构建
17
+ def build
18
+ UI.info "编译`#{@pod_target}`".yellow
19
+ dir = result_product_dir
20
+ FileUtils.rm_rf(dir) if File.exist?(dir)
21
+ # 编译模拟器
22
+ unless @skip_simulator
23
+ result = build_pod_target
24
+ return false unless result
25
+ end
26
+ # 编译真机
27
+ build_pod_target(false)
28
+ end
29
+
30
+ # 创建binary
31
+ def create_binary
32
+ UI.info "创建`#{@pod_target.framework_name}`".yellow
33
+ # 如果是framework需要先copy
34
+ if build_as_framework?
35
+ copy_framework
36
+ else
37
+ create_framework_dir
38
+ copy_headers
39
+ copy_headers(false )
40
+ generate_umbrella_header
41
+ generate_module_map
42
+ compile_resources
43
+ if @pod_target.uses_swift?
44
+ copy_iphoneos_swiftmodules
45
+ copy_simulator_swiftmodules unless @skip_simulator
46
+ end
47
+ if @skip_simulator
48
+ device_lib = "#{product_dir}/#{iphoneos}/#{@pod_target}/#{@pod_target.static_library_name}"
49
+ output = "#{result_product_dir}/#{@pod_target.product_module_name}"
50
+ `cp -f #{device_lib} #{output}`
51
+ end
52
+ end
53
+ # 合并真机模拟器
54
+ merge_device_sim unless @skip_simulator
55
+ # 拷贝资源文件
56
+ copy_resources
57
+ # 拷贝 vendored_frameworks 和 vendored_libraries
58
+ copy_vendored_frameworks
59
+ copy_vendored_libraries
60
+ end
61
+
62
+ # 是否以framework形式构建
63
+ def build_as_framework?
64
+ path = "#{product_dir}/#{iphoneos}/#{@pod_target}/#{@pod_target.framework_name}"
65
+ File.exist?(path)
66
+ end
67
+
68
+ # xxx.framework/Modules
69
+ def modules_dir
70
+ "#{result_product_dir}/Modules"
71
+ end
72
+
73
+ # xxx.framework/Headers
74
+ def headers_dir
75
+ "#{result_product_dir}/Headers"
76
+ end
77
+
78
+ # xxx.framework/PrivateHeaders
79
+ def private_headers_dir
80
+ "#{result_product_dir}/PrivateHeaders"
81
+ end
82
+
83
+ # xxx.framework/resources
84
+ def resources_dir
85
+ "#{result_product_dir}/resources"
86
+ end
87
+
88
+ # xxx.framework
89
+ def result_product_dir
90
+ "#{product_dir}/#{@pod_target.framework_name}"
91
+ end
92
+
93
+ # xxx.framework 所在目录
94
+ def product_dir
95
+ @product_dir = "#{@base_dir}/#{@pod_target}/Products"
96
+ @product_dir
97
+ end
98
+
99
+ # 构建临时产物目录
100
+ def temp_dir
101
+ "#{@base_dir}/#{@pod_target}/Temp"
102
+ end
103
+
104
+ def iphoneos
105
+ "#{@configuration}-iphoneos"
106
+ end
107
+
108
+ def iphonesimulator
109
+ "#{@configuration}-iphonesimulator"
110
+ end
111
+
112
+ # 需要排除的资源文件后缀
113
+ def reject_resource_ext
114
+ %w[.xcdatamodeld .xcdatamodel .xcmappingmodel .xib .storyboard]
115
+ end
116
+
117
+ private
118
+
119
+ # 加载当前 target 的 build_settings
120
+ def load_target_build_settings(project, target)
121
+ @build_settings ||= begin
122
+ command = <<-BUILDSETTINGS
123
+ xcodebuild \
124
+ -target #{target} \
125
+ -project #{project} \
126
+ -showBuildSettings \
127
+ -configuration #{@configuration}
128
+ BUILDSETTINGS
129
+ output = `#{command}`
130
+ # 删除临时文件夹 build,防止出现 clean failed
131
+ FileUtils.rm_rf("#{Pod::Config.instance.installation_root}/build")
132
+ output
133
+ end
134
+ end
135
+
136
+ # 加载具体某个 build_setting
137
+ def load_single_build_setting(project, target, key)
138
+ build_settings = load_target_build_settings(project, target)
139
+ flags = `echo '#{build_settings}' | grep #{key}`
140
+ if flags.size > 0
141
+ flags = flags.split("#{key} =")
142
+ if flags.size == 2
143
+ flags = flags.last
144
+ end
145
+ end
146
+ flags.strip
147
+ end
148
+
149
+ # 构建单个pod
150
+ def build_pod_target(simulator = true)
151
+ sdk = simulator ? 'iphonesimulator' : 'iphoneos'
152
+ archs = simulator ? 'x86_64' : 'arm64'
153
+ product_dir = product_dir()
154
+ temp_dir = temp_dir()
155
+ pod_project_path = Dir.pwd + "/Pods/#{@pod_target}.xcodeproj"
156
+ if File.exist?(pod_project_path)
157
+ project = "./Pods/#{@pod_target}.xcodeproj"
158
+ else
159
+ project = "./Pods/Pods.xcodeproj"
160
+ end
161
+
162
+ other_c_flags = load_single_build_setting(project, @pod_target, 'OTHER_CFLAGS')
163
+ other_c_flags += " -fdebug-prefix-map=#{Pod::Config.instance.sandbox_root}=."
164
+ other_swift_flags = load_single_build_setting(project, @pod_target, 'OTHER_SWIFT_FLAGS')
165
+ other_swift_flags += " -debug-prefix-map #{Pod::Config.instance.sandbox_root}=."
166
+
167
+ command = <<-BUILD
168
+ xcodebuild GCC_PREPROCESSOR_DEFINITIONS='$(inherited)' \
169
+ GCC_WARN_INHIBIT_ALL_WARNINGS=YES \
170
+ CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES=YES \
171
+ -sdk #{sdk} \
172
+ ARCHS=#{archs} \
173
+ CONFIGURATION_TEMP_DIR=#{temp_dir} \
174
+ BUILD_ROOT=#{product_dir} \
175
+ BUILD_DIR=#{product_dir} \
176
+ OTHER_CFLAGS="#{other_c_flags}" \
177
+ OTHER_SWIFT_FLAGS="#{other_swift_flags}" \
178
+ clean build \
179
+ -configuration #{@configuration} \
180
+ -target #{@pod_target} \
181
+ -project #{project}
182
+ BUILD
183
+ UI.info "#{command}"
184
+ output = `#{command}`
185
+ if $CHILD_STATUS.exitstatus != 0
186
+ UI.info "`#{@pod_target}(#{sdk})`编译失败!".red
187
+ error_log_file = "#{temp_dir}/#{@pod_target}_error.log"
188
+ File.open(error_log_file, "w+") do |f|
189
+ f.write(output)
190
+ end
191
+ return false
192
+ end
193
+ return true
194
+ end
195
+
196
+ # 合并真机模拟器
197
+ def merge_device_sim
198
+ if build_as_framework?
199
+ device_lib_dir = "#{product_dir}/#{iphoneos}/#{@pod_target}/#{@pod_target.framework_name}/#{@pod_target.product_module_name}"
200
+ sim_lib_dir = "#{product_dir}/#{iphonesimulator}/#{@pod_target}/#{@pod_target.framework_name}/#{@pod_target.product_module_name}"
201
+ else
202
+ device_lib_dir = "#{product_dir}/#{iphoneos}/#{@pod_target}/#{@pod_target.static_library_name}"
203
+ sim_lib_dir = "#{product_dir}/#{iphonesimulator}/#{@pod_target}/#{@pod_target.static_library_name}"
204
+ end
205
+ output = "#{result_product_dir}/#{@pod_target.product_module_name}"
206
+ libs = [device_lib_dir, sim_lib_dir]
207
+ FileUtils.mkdir(result_product_dir) unless File.exist?(result_product_dir)
208
+ `lipo -create -output #{output} #{libs.join(' ')}` unless libs.empty?
209
+ end
210
+
211
+ # 创建 xxx.framework 文件夹
212
+ def create_framework_dir
213
+ fwk_path = "#{product_dir}/#{@pod_target.product_module_name}.framework"
214
+ FileUtils.rm_rf(fwk_path) if File.exist?(fwk_path)
215
+ FileUtils.mkdir(fwk_path)
216
+ end
217
+
218
+ # -------------------------- 编译需要编译的资源 --------------------------------
219
+
220
+ # 需要编译的资源
221
+ def need_compile_resources
222
+ return [] if @file_accessors.nil?
223
+ resources = @file_accessors.flat_map(&:resources)
224
+ return [] if resources.nil? || resources.size == 0
225
+ resources.compact.select { |res| reject_resource_ext.include?(res.extname) }.map(&:to_s)
226
+ end
227
+
228
+ # 编译需要编译的资源
229
+ def compile_resources
230
+ resources = need_compile_resources
231
+ resources.map { |res| compile_resource(res) }
232
+ end
233
+
234
+ # 编译单个资源
235
+ def compile_resource(resource)
236
+ return unless File.exist?(resource)
237
+ case File.extname(resource)
238
+ when '.storyboard', '.xib'
239
+ compile_storyboard_xib(resource)
240
+ when '.xcdatamodeld', '.xcdatamodel'
241
+ compile_xcdatamodel(resource)
242
+ when '.xcmappingmodel'
243
+ compile_xcmappingmodel(resource)
244
+ end
245
+ end
246
+
247
+ # 编译storyboard、xib
248
+ def compile_storyboard_xib(resource)
249
+ file_ext = File.extname(resource)
250
+ file_name = File.basename(resource, file_ext)
251
+ command = <<-COMMAND
252
+ ibtool \
253
+ --reference-external-strings-file \
254
+ --errors --warnings \
255
+ --notices \
256
+ --output-format human-readable-text \
257
+ --compile #{result_product_dir}/#{file_name}.#{file_ext == '.storyboard' ? 'storyboardc' : 'nib'} #{resource} \
258
+ --target-device ipad --target-device iphone
259
+ COMMAND
260
+ `#{command}`
261
+ end
262
+
263
+ # 编译xcdatamodel、xcdatamodeld
264
+ def compile_xcdatamodel(resource)
265
+ file_ext = File.extname(resource)
266
+ file_name = File.basename(resource, file_ext)
267
+ `xcrun momc #{resource} #{result_product_dir}/#{file_name}.#{file_ext == 'xcdatamodeld' ? 'momd' : 'mom'}`
268
+ end
269
+
270
+ # 编译xcmappingmodel
271
+ def compile_xcmappingmodel(resource)
272
+ file_ext = File.extname(resource)
273
+ file_name = File.basename(resource, file_ext)
274
+ `xcrun mapc #{resource} #{result_product_dir}/#{file_name}.cdm`
275
+ end
276
+
277
+ # -------------------------- 拷贝头文件、资源等 --------------------------------
278
+
279
+ # 拷贝头文件
280
+ def copy_headers(public = true)
281
+ if public
282
+ headers = @file_accessors.map(&:public_headers).flatten.compact.uniq
283
+ header_dir = headers_dir
284
+ if @pod_target.uses_swift?
285
+ umbrella_header = "#{product_dir}/#{iphoneos}/#{@pod_target}/#{@pod_target}-umbrella.h"
286
+ swift_header = "#{product_dir}/#{iphoneos}/#{@pod_target}/Swift Compatibility Header/#{@pod_target.product_module_name}-Swift.h"
287
+ headers.concat([umbrella_header, swift_header])
288
+ end
289
+ else
290
+ headers = @file_accessors.map(&:private_headers).flatten.compact.uniq
291
+ header_dir = private_headers_dir
292
+ end
293
+ return if headers.empty?
294
+ FileUtils.mkdir(header_dir) unless File.exist?(header_dir)
295
+ headers.map do |header|
296
+ header_path = header
297
+ if header.is_a?(String)
298
+ header_path = header.gsub(/ /, '\ ') if header.include?(' ')
299
+ elsif header.is_a?(Pathname)
300
+ header_path = header.to_s.gsub(/ /, '\ ') if header.to_s.include?(' ')
301
+ end
302
+ `cp -f #{header_path} #{header_dir}`
303
+ end
304
+ end
305
+
306
+ # 获取podspec中的resource_bundles
307
+ def resource_bundles
308
+ return [] if @file_accessors.nil?
309
+ resource_bundles = @file_accessors.flat_map(&:resource_bundles)
310
+ return [] if resource_bundles.nil? || resource_bundles.size == 0
311
+ resource_bundles.compact.flat_map(&:keys).map { |key| "#{product_dir}/#{iphoneos}/#{@pod_target}/#{key}.bundle" }
312
+ end
313
+
314
+ # 获取podspec中resource/resources
315
+ def other_resources
316
+ return [] if @file_accessors.nil?
317
+ resources = @file_accessors.flat_map(&:resources)
318
+ return [] if resources.nil? || resources.size == 0
319
+ resources.compact.reject { |res| reject_resource_ext.include?(res.extname) }.map(&:to_s)
320
+ end
321
+
322
+ # 拷贝资源文件
323
+ def copy_resources
324
+ resources = resource_bundles + other_resources
325
+ return if resources.empty?
326
+ resources_dir = "#{result_product_dir}/resources"
327
+ FileUtils.mkdir(resources_dir) unless File.exist?(resources_dir)
328
+ resources.uniq.map do |resource|
329
+ `rsync -av #{resource} #{resources_dir}`
330
+ end
331
+ end
332
+
333
+ # 拷贝 vendored_libraries
334
+ def copy_vendored_libraries
335
+ libs = @pod_target.file_accessors.map(&:vendored_libraries).flatten.compact.uniq
336
+ return if libs.empty?
337
+ libs_dir = "#{result_product_dir}/libs"
338
+ FileUtils.mkdir(libs_dir) unless File.exist?(libs_dir)
339
+ libs.map do |lib|
340
+ `rsync -av #{lib} #{libs_dir}`
341
+ end
342
+ end
343
+
344
+ # 拷贝 vendored_frameworks
345
+ def copy_vendored_frameworks
346
+ fwks = @pod_target.file_accessors.map(&:vendored_frameworks).flatten.compact.uniq
347
+ return if fwks.empty?
348
+ fwks_dir = "#{result_product_dir}/fwks"
349
+ FileUtils.mkdir(fwks_dir) unless File.exist?(fwks_dir)
350
+ fwks.map do |fwk|
351
+ `rsync -av #{fwk} #{fwks_dir}`
352
+ end
353
+ end
354
+
355
+ # 拷贝 framework
356
+ def copy_framework
357
+ source_path = "#{product_dir}/#{iphoneos}/#{@pod_target}/#{@pod_target.framework_name}"
358
+ if File.exist?(source_path)
359
+ `rsync -av #{source_path} #{product_dir}`
360
+ end
361
+ # 如果包含Swift代码且需要编译模拟器,则copy模拟器swiftmodules
362
+ if @pod_target.uses_swift?
363
+ copy_simulator_swiftmodules unless @skip_simulator
364
+ end
365
+ end
366
+
367
+ # 拷贝真机swiftmodules(只用于static library)
368
+ def copy_iphoneos_swiftmodules
369
+ FileUtils.mkdir(modules_dir) unless File.exist?(modules_dir)
370
+ `cp -rf #{product_dir}/#{iphoneos}/#{@pod_target}/#{@pod_target.product_module_name}.swiftmodule #{modules_dir}`
371
+ end
372
+
373
+ # 拷贝模拟器swiftmodules
374
+ def copy_simulator_swiftmodules
375
+ target_swift_module = "#{modules_dir}/#{@pod_target.product_module_name}.swiftmodule"
376
+ if build_as_framework?
377
+ src_swift_module = "#{product_dir}/#{iphonesimulator}/#{@pod_target}/#{@pod_target.framework_name}/Modules/#{@pod_target.product_module_name}.swiftmodule"
378
+ else
379
+ src_swift_module = "#{product_dir}/#{iphonesimulator}/#{@pod_target}/#{@pod_target.product_module_name}.swiftmodule"
380
+ end
381
+ if File.exist?(target_swift_module)
382
+ `cp -af #{src_swift_module}/* #{target_swift_module}`
383
+ `cp -af #{src_swift_module}/Project/* #{target_swift_module}/Project`
384
+ end
385
+ end
386
+
387
+ # -------------------------- clang module --------------------------------
388
+
389
+ # 生成 module map
390
+ def generate_module_map
391
+ module_map = "#{modules_dir}/module.modulemap"
392
+ FileUtils.mkdir(modules_dir) unless File.exist?(modules_dir)
393
+ FileUtils.rm_f(module_map) if File.exist?(module_map)
394
+ File.open(module_map, "w+") do |f|
395
+ content = <<-MODULEMAP
396
+ framework module #{@pod_target.product_module_name} {
397
+ umbrella header "#{@pod_target}-umbrella.h"
398
+
399
+ export *
400
+ module * { export * }
401
+ }
402
+ MODULEMAP
403
+ # 有Swift代码
404
+ if @pod_target.uses_swift?
405
+ content += <<-SWIFT
406
+
407
+ module #{@pod_target.product_module_name}.Swift {
408
+ header "#{@pod_target.product_module_name}-Swift.h"
409
+ requires objc
410
+ }
411
+ SWIFT
412
+ end
413
+ f.write(content)
414
+ end
415
+ end
416
+
417
+ # 生成 umbrella header
418
+ def generate_umbrella_header
419
+ umbrella_header_path = "#{headers_dir}/#{@pod_target}-umbrella.h"
420
+ return if File.exist?(umbrella_header_path)
421
+
422
+ umbrella_header = Pod::Generator::UmbrellaHeader.new(@pod_target)
423
+ # 需要导入的头文件
424
+ umbrella_header.imports = @file_accessors.flat_map(&:public_headers).compact.uniq.map { |header| header.basename }
425
+ FileUtils.mkdir(headers_dir) unless File.exist?(headers_dir)
426
+ result = umbrella_header.generate
427
+ File.open(umbrella_header_path, "w+") do |f|
428
+ f.write(result)
429
+ end
430
+ end
431
+
432
+ end
433
+ end
434
+ end
@@ -0,0 +1,140 @@
1
+
2
+ module CBin
3
+ module BuildAll
4
+ class PodspecUtil
5
+ include Pod
6
+
7
+ def initialize(pod_target, version, build_as_framework = false, configuration = 'Debug')
8
+ @pod_target = pod_target
9
+ @version = version
10
+ @build_as_framework = build_as_framework
11
+ @configuration = configuration
12
+ end
13
+
14
+ # 创建二进制podspec
15
+ def create_binary_podspec
16
+ UI.info "创建二进制podspec:`#{@pod_target}`".yellow
17
+ spec = @pod_target.root_spec.to_hash
18
+ root_dir = @pod_target.framework_name
19
+ # 处理版本号
20
+ spec['version'] = version
21
+ # 处理source
22
+ spec['source'] = source
23
+ # 处理头文件
24
+ spec['source_files'] = "#{root_dir}/Headers/*.h"
25
+ spec['public_header_files'] = "#{root_dir}/Headers/*.h"
26
+ spec['private_header_files'] = "#{root_dir}/PrivateHeaders/*.h"
27
+ # 处理vendored_libraries和vendored_frameworks
28
+ spec['vendored_libraries'] = "#{root_dir}/libs/*.a"
29
+ spec['vendored_frameworks'] = %W[#{root_dir} #{root_dir}/fwks/*.framework]
30
+ # 处理资源
31
+ resources = %W[#{root_dir}/*.{#{special_resource_exts.join(',')}} #{root_dir}/resources/*]
32
+ spec['resources'] = resources
33
+ # 删除无用的字段
34
+ delete_unused(spec)
35
+ # 处理subspecs
36
+ handle_subspecs(spec)
37
+ # 生成二进制podspec
38
+ bin_spec = Pod::Specification.from_hash(spec)
39
+ bin_spec.description = <<-EOF
40
+ 「converted automatically by plugin cocoapods-meitu-bin @美图 - zys」
41
+ #{bin_spec.description}
42
+ EOF
43
+ bin_spec
44
+ # puts bin_spec.to_json
45
+ end
46
+
47
+ # podspec写入文件
48
+ def write_binary_podspec(spec)
49
+ UI.info "写入podspec:`#{@pod_target}`".yellow
50
+ podspec_dir = "#{Pathname.pwd}/build_pods/#{@pod_target}/Products/podspec"
51
+ FileUtils.mkdir(podspec_dir) unless File.exist?(podspec_dir)
52
+ file = "#{podspec_dir}/#{@pod_target.pod_name}.podspec.json"
53
+ FileUtils.rm_rf(file) if File.exist?(file)
54
+
55
+ File.open(file, "w+") do |f|
56
+ f.write(spec.to_pretty_json)
57
+ end
58
+ file
59
+ end
60
+
61
+ # 上传二进制podspec
62
+ def push_binary_podspec(binary_podsepc_json)
63
+ UI.info "推送podspec:`#{@pod_target}`".yellow
64
+ return unless File.exist?(binary_podsepc_json)
65
+ repo_name = Pod::Config.instance.sources_manager.binary_source.name
66
+ # repo_name = 'example-private-spec-bin'
67
+ argvs = %W[#{repo_name} #{binary_podsepc_json} --skip-import-validation --use-libraries --allow-warnings --verbose]
68
+
69
+ begin
70
+ push = Pod::Command::Repo::Push.new(CLAide::ARGV.new(argvs))
71
+ push.validate!
72
+ push.run
73
+ return true
74
+ rescue Pod::StandardError => e
75
+ UI.info "推送podspec:`#{@pod_target}`失败,#{e.to_s}".red
76
+ return false
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ # 删除无用的字段
83
+ def delete_unused(spec)
84
+ spec.delete('project_header_files')
85
+ spec.delete('resource_bundles')
86
+ spec.delete('exclude_files')
87
+ spec.delete('preserve_paths')
88
+ spec.delete('prepare_command')
89
+ end
90
+
91
+ # 处理subspecs
92
+ def handle_subspecs(spec)
93
+ spec['subspecs'].map do |subspec|
94
+ # 处理单个subspec
95
+ handle_single_subspec(subspec, spec)
96
+ # 递归处理subspec
97
+ recursive_handle_subspecs(subspec['subspecs'], spec)
98
+ end if spec && spec['subspecs']
99
+ end
100
+
101
+ # 递归处理subspecs
102
+ def recursive_handle_subspecs(subspecs, spec)
103
+ subspecs.map do |s|
104
+ # 处理单个subspec
105
+ handle_single_subspec(s, spec)
106
+ # 递归处理
107
+ recursive_handle_subspecs(s['subspecs'], spec)
108
+ end if subspecs
109
+ end
110
+
111
+ # 处理单个subspec
112
+ def handle_single_subspec(subspec, spec)
113
+ subspec['source_files'] = spec['source_files']
114
+ subspec['public_header_files'] = spec['public_header_files']
115
+ subspec['private_header_files'] = spec['private_header_files']
116
+ subspec['vendored_frameworks'] = spec['vendored_frameworks']
117
+ subspec['vendored_libraries'] = spec['vendored_libraries']
118
+ subspec['resources'] = spec['resources']
119
+ # 删除无用字段
120
+ delete_unused(subspec)
121
+ end
122
+
123
+ def source
124
+ # url = "http://localhost:8080/frameworks/#{BinHelper.xcode_version}/#{@pod_target.root_spec.module_name}/#{version}/zip"
125
+ url = "#{CBin.config.binary_download_url_str}/#{BinHelper.xcode_version}/#{@configuration}/#{@pod_target.root_spec.module_name}/#{version}/#{@pod_target.framework_name}_#{version}.zip"
126
+ { http: url, type: CBin.config.download_file_type }
127
+ end
128
+
129
+ def version
130
+ @version || @pod_target.root_spec.version
131
+ end
132
+
133
+ # 特殊的资源后缀
134
+ def special_resource_exts
135
+ %w[momd mom cdm nib storyboardc]
136
+ end
137
+
138
+ end
139
+ end
140
+ end