cocoapods-meitu-bin 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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