cocoapods-meitu-bin 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +56 -0
- data/lib/cocoapods-meitu-bin/command/bin/archive.rb +206 -0
- data/lib/cocoapods-meitu-bin/command/bin/auto.rb +212 -0
- data/lib/cocoapods-meitu-bin/command/bin/build_all.rb +345 -0
- data/lib/cocoapods-meitu-bin/command/bin/header_files_specifications.rb +262 -0
- data/lib/cocoapods-meitu-bin/command/bin/init.rb +72 -0
- data/lib/cocoapods-meitu-bin/command/bin/install.rb +44 -0
- data/lib/cocoapods-meitu-bin/command/bin/lib/lint.rb +67 -0
- data/lib/cocoapods-meitu-bin/command/bin/lock/dependency.rb +89 -0
- data/lib/cocoapods-meitu-bin/command/bin/lock/spec_repo.rb +105 -0
- data/lib/cocoapods-meitu-bin/command/bin/lock/version.rb +68 -0
- data/lib/cocoapods-meitu-bin/command/bin/lock.rb +36 -0
- data/lib/cocoapods-meitu-bin/command/bin/output_source.rb +146 -0
- data/lib/cocoapods-meitu-bin/command/bin/repo/push.rb +88 -0
- data/lib/cocoapods-meitu-bin/command/bin/repo/update.rb +42 -0
- data/lib/cocoapods-meitu-bin/command/bin/repo.rb +14 -0
- data/lib/cocoapods-meitu-bin/command/bin/source/add.rb +148 -0
- data/lib/cocoapods-meitu-bin/command/bin/source/delete.rb +59 -0
- data/lib/cocoapods-meitu-bin/command/bin/source/list.rb +46 -0
- data/lib/cocoapods-meitu-bin/command/bin/source.rb +30 -0
- data/lib/cocoapods-meitu-bin/command/bin/spec/create.rb +73 -0
- data/lib/cocoapods-meitu-bin/command/bin/spec/lint.rb +109 -0
- data/lib/cocoapods-meitu-bin/command/bin/spec.rb +13 -0
- data/lib/cocoapods-meitu-bin/command/bin/update.rb +154 -0
- data/lib/cocoapods-meitu-bin/command/bin/upload.rb +175 -0
- data/lib/cocoapods-meitu-bin/command/bin.rb +69 -0
- data/lib/cocoapods-meitu-bin/command.rb +1 -0
- data/lib/cocoapods-meitu-bin/config/config.rb +149 -0
- data/lib/cocoapods-meitu-bin/config/config_asker.rb +57 -0
- data/lib/cocoapods-meitu-bin/config/config_builder.rb +216 -0
- data/lib/cocoapods-meitu-bin/gem_version.rb +9 -0
- data/lib/cocoapods-meitu-bin/helpers/Info.plist +0 -0
- data/lib/cocoapods-meitu-bin/helpers/buildAll/bin_helper.rb +97 -0
- data/lib/cocoapods-meitu-bin/helpers/buildAll/builder.rb +434 -0
- data/lib/cocoapods-meitu-bin/helpers/buildAll/podspec_util.rb +140 -0
- data/lib/cocoapods-meitu-bin/helpers/buildAll/zip_file_helper.rb +87 -0
- data/lib/cocoapods-meitu-bin/helpers/build_helper.rb +167 -0
- data/lib/cocoapods-meitu-bin/helpers/build_utils.rb +64 -0
- data/lib/cocoapods-meitu-bin/helpers/framework.rb +86 -0
- data/lib/cocoapods-meitu-bin/helpers/framework_builder.rb +551 -0
- data/lib/cocoapods-meitu-bin/helpers/library.rb +54 -0
- data/lib/cocoapods-meitu-bin/helpers/library_builder.rb +90 -0
- data/lib/cocoapods-meitu-bin/helpers/pod_size_helper.rb +54 -0
- data/lib/cocoapods-meitu-bin/helpers/sources_helper.rb +35 -0
- data/lib/cocoapods-meitu-bin/helpers/spec_creator.rb +170 -0
- data/lib/cocoapods-meitu-bin/helpers/spec_files_helper.rb +80 -0
- data/lib/cocoapods-meitu-bin/helpers/spec_source_creator.rb +304 -0
- data/lib/cocoapods-meitu-bin/helpers/upload_helper.rb +104 -0
- data/lib/cocoapods-meitu-bin/helpers.rb +5 -0
- data/lib/cocoapods-meitu-bin/native/acknowledgements.rb +27 -0
- data/lib/cocoapods-meitu-bin/native/analyzer.rb +109 -0
- data/lib/cocoapods-meitu-bin/native/file_accessor.rb +28 -0
- data/lib/cocoapods-meitu-bin/native/gen.rb +79 -0
- data/lib/cocoapods-meitu-bin/native/installation_options.rb +28 -0
- data/lib/cocoapods-meitu-bin/native/installer.rb +259 -0
- data/lib/cocoapods-meitu-bin/native/linter.rb +26 -0
- data/lib/cocoapods-meitu-bin/native/lockfile.rb +85 -0
- data/lib/cocoapods-meitu-bin/native/path_source.rb +33 -0
- data/lib/cocoapods-meitu-bin/native/pod_source_installer.rb +19 -0
- data/lib/cocoapods-meitu-bin/native/pod_target_installer.rb +87 -0
- data/lib/cocoapods-meitu-bin/native/podfile.rb +99 -0
- data/lib/cocoapods-meitu-bin/native/podfile_env.rb +38 -0
- data/lib/cocoapods-meitu-bin/native/podfile_generator.rb +201 -0
- data/lib/cocoapods-meitu-bin/native/podspec_finder.rb +25 -0
- data/lib/cocoapods-meitu-bin/native/resolver.rb +299 -0
- data/lib/cocoapods-meitu-bin/native/sandbox_analyzer.rb +34 -0
- data/lib/cocoapods-meitu-bin/native/source.rb +35 -0
- data/lib/cocoapods-meitu-bin/native/sources_manager.rb +21 -0
- data/lib/cocoapods-meitu-bin/native/specification.rb +31 -0
- data/lib/cocoapods-meitu-bin/native/target_validator.rb +41 -0
- data/lib/cocoapods-meitu-bin/native/validator.rb +40 -0
- data/lib/cocoapods-meitu-bin/native.rb +26 -0
- data/lib/cocoapods-meitu-bin/source_provider_hook.rb +68 -0
- data/lib/cocoapods-meitu-bin.rb +2 -0
- data/lib/cocoapods_plugin.rb +11 -0
- data/spec/command/bin_spec.rb +12 -0
- data/spec/spec_helper.rb +50 -0
- metadata +201 -0
@@ -0,0 +1,345 @@
|
|
1
|
+
require 'cocoapods-meitu-bin/helpers/buildAll/builder'
|
2
|
+
require 'cocoapods-meitu-bin/helpers/buildAll/podspec_util'
|
3
|
+
require 'cocoapods-meitu-bin/helpers/buildAll/zip_file_helper'
|
4
|
+
require 'cocoapods-meitu-bin/helpers/buildAll/bin_helper'
|
5
|
+
require 'cocoapods-meitu-bin/config/config'
|
6
|
+
require 'yaml'
|
7
|
+
require 'digest'
|
8
|
+
|
9
|
+
module Pod
|
10
|
+
class Command
|
11
|
+
class Bin < Command
|
12
|
+
class BuildAll < Bin
|
13
|
+
include CBin::BuildAll
|
14
|
+
|
15
|
+
CDN = 'https://cdn.cocoapods.org/'.freeze
|
16
|
+
MASTER_HTTP = 'https://github.com/CocoaPods/Specs.git'.freeze
|
17
|
+
MASTER_SSH = 'git@github.com:CocoaPods/Specs.git'.freeze
|
18
|
+
|
19
|
+
self.summary = '根据壳工程打包所有依赖组件为静态库(static framework)'
|
20
|
+
self.description = <<-DESC
|
21
|
+
#{summary},参数 PODS 可选,如果添加 PODS 则只制作 PODS 包含的库,多个库中间用逗号分隔
|
22
|
+
DESC
|
23
|
+
|
24
|
+
self.arguments = [
|
25
|
+
CLAide::Argument.new('PODS', false)
|
26
|
+
]
|
27
|
+
|
28
|
+
def self.options
|
29
|
+
[
|
30
|
+
%w[--clean 全部二进制包制作完成后删除编译临时目录],
|
31
|
+
%w[--clean-single 每制作完一个二进制包就删除该编译临时目录],
|
32
|
+
%w[--repo-update 更新Podfile中指定的repo仓库],
|
33
|
+
%w[--full-build 是否全量打包],
|
34
|
+
%w[--skip-simulator 跳过模拟器编译],
|
35
|
+
%w[--configuration=configName 在构建每个目标时使用configName指定构建配置,如:'Debug'、'Release'等]
|
36
|
+
].concat(super).uniq
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize(argv)
|
40
|
+
@pods = argv.shift_argument
|
41
|
+
@clean = argv.flag?('clean', false)
|
42
|
+
@clean_single = argv.flag?('clean-single', false)
|
43
|
+
@repo_update = argv.flag?('repo-update', false)
|
44
|
+
@full_build = argv.flag?('full-build', false)
|
45
|
+
@skip_simulator = argv.flag?('skip-simulator', false)
|
46
|
+
@configuration = argv.option('configuration', 'Debug')
|
47
|
+
@base_dir = "#{Pathname.pwd}/build_pods"
|
48
|
+
@version_helper = BinHelper.new
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
def run
|
53
|
+
CBin.config.config_file_exist?
|
54
|
+
# 打印提示
|
55
|
+
print_tip
|
56
|
+
# 开始时间
|
57
|
+
@start_time = Time.now.to_i
|
58
|
+
# 读取配置文件
|
59
|
+
read_config
|
60
|
+
# 如果有传入要制作的pod库名
|
61
|
+
if @pods
|
62
|
+
@write_list = @pods.split(',').map(&:strip)
|
63
|
+
end
|
64
|
+
# 更新repo仓库
|
65
|
+
repo_update
|
66
|
+
# 执行pre_build命令
|
67
|
+
pre_build
|
68
|
+
# 分析依赖
|
69
|
+
@analyze_result = analyse
|
70
|
+
# 删除编译产物
|
71
|
+
clean_build_pods
|
72
|
+
# 编译所有pod_targets
|
73
|
+
results = build_pod_targets
|
74
|
+
# 执行post_build命令
|
75
|
+
post_build(results)
|
76
|
+
# 删除编译产物
|
77
|
+
clean_build_pods if @clean
|
78
|
+
# 计算耗时
|
79
|
+
show_cost_time
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def print_tip
|
85
|
+
UI.info '——————————————————————————————————'.blue
|
86
|
+
UI.info "|#{' '.center(32)}|".blue
|
87
|
+
UI.info "|#{"Configuration:`#{@configuration}`".center(32)}|".blue
|
88
|
+
UI.info "|#{' '.center(32)}|".blue
|
89
|
+
UI.info '——————————————————————————————————'.blue
|
90
|
+
end
|
91
|
+
|
92
|
+
# 打印耗时
|
93
|
+
def show_cost_time
|
94
|
+
return if @start_time.nil?
|
95
|
+
UI.info "总耗时:#{Time.now.to_i - @start_time}s".green
|
96
|
+
end
|
97
|
+
|
98
|
+
# 读取配置文件
|
99
|
+
def read_config
|
100
|
+
UI.title 'Read config from file `BinConfig.yaml`'.green do
|
101
|
+
config_file = File.join(Pod::Config.instance.project_root, 'BinConfig.yaml')
|
102
|
+
return unless File.exist?(config_file)
|
103
|
+
config = YAML.safe_load(File.open(config_file))
|
104
|
+
return if config.nil?
|
105
|
+
build_config = config['build_config']
|
106
|
+
return if build_config.nil?
|
107
|
+
@pre_build = build_config['pre_build']
|
108
|
+
@post_build = build_config['post_build']
|
109
|
+
@black_list = build_config['black_list']
|
110
|
+
@write_list = build_config['write_list']
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# 更新repo仓库
|
115
|
+
def repo_update
|
116
|
+
if @repo_update
|
117
|
+
UI.title 'Repo update'.green do
|
118
|
+
return if podfile.nil?
|
119
|
+
sources_manager = Pod::Config.instance.sources_manager
|
120
|
+
podfile.sources.uniq.map do |src|
|
121
|
+
UI.message "Update repo: #{src}"
|
122
|
+
source = sources_manager.source_with_name_or_url(src)
|
123
|
+
source.update(false)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# 执行pre build
|
130
|
+
def pre_build
|
131
|
+
if @pre_build
|
132
|
+
UI.title 'Execute the command of pre build'.green do
|
133
|
+
system(@pre_build)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# 执行post build
|
139
|
+
def post_build(_results)
|
140
|
+
if @post_build
|
141
|
+
UI.title 'Execute the command of post build'.green do
|
142
|
+
system(@post_build)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# 获取 podfile
|
148
|
+
def podfile
|
149
|
+
@podfile ||= begin
|
150
|
+
podfile_path = File.join(Pathname.pwd, 'Podfile')
|
151
|
+
raise Informative, 'Podfile不存在' unless File.exist?(podfile_path)
|
152
|
+
sources_manager = Pod::Config.instance.sources_manager
|
153
|
+
podfile = Podfile.from_file(Pathname.new(podfile_path))
|
154
|
+
podfile_hash = podfile.to_hash
|
155
|
+
podfile_hash['sources'] = (podfile_hash['sources'] || []).concat(sources_manager.code_source_list.map(&:url))
|
156
|
+
podfile_hash['sources'] << sources_manager.binary_source.url
|
157
|
+
podfile_hash['sources'].uniq!
|
158
|
+
Podfile.from_hash(podfile_hash)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# 获取 podfile.lock
|
163
|
+
def lockfile
|
164
|
+
@lockfile ||= begin
|
165
|
+
lock_path = File.join(Pathname.pwd, 'Podfile.lock')
|
166
|
+
raise Informative, 'Podfile.lock不存在,请执行pod install' unless File.exist?(lock_path)
|
167
|
+
Lockfile.from_file(Pathname.new(lock_path))
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# 获取 sandbox
|
172
|
+
def sandbox
|
173
|
+
@sandbox ||= begin
|
174
|
+
sandbox_path = File.join(Pathname.pwd, 'Pods')
|
175
|
+
raise Informative, 'Pods文件夹不存在,请执行pod install' unless File.exist?(sandbox_path)
|
176
|
+
Pod::Sandbox.new(sandbox_path)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# 根据podfile和podfile.lock分析依赖
|
181
|
+
def analyse
|
182
|
+
UI.title 'Analyze dependencies'.green do
|
183
|
+
analyzer = Pod::Installer::Analyzer.new(
|
184
|
+
sandbox,
|
185
|
+
podfile,
|
186
|
+
lockfile
|
187
|
+
)
|
188
|
+
analyzer.analyze(true)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# 删除单个Pod的编译中间产物
|
193
|
+
def clean_single_build_pod(pod_target)
|
194
|
+
UI.title "Clean build pod: `#{pod_target}`".green do
|
195
|
+
build_pod_path = File.join(Dir.pwd, 'build_pods', "#{pod_target}")
|
196
|
+
FileUtils.rm_rf(build_pod_path) if File.exist?(build_pod_path)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# 删除编译产物
|
201
|
+
def clean_build_pods
|
202
|
+
UI.title 'Clean build pods'.green do
|
203
|
+
build_path = Dir.pwd + '/build'
|
204
|
+
FileUtils.rm_rf(build_path) if File.exist?(build_path)
|
205
|
+
build_pods_path = Dir.pwd + '/build_pods'
|
206
|
+
FileUtils.rm_rf(build_pods_path) if File.exist?(build_pods_path)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# 构建所有pod_targets
|
211
|
+
def build_pod_targets
|
212
|
+
UI.title "Build all pod targets(#{@full_build ? '全量打包' : '非全量打包'})".green do
|
213
|
+
pod_targets = @analyze_result.pod_targets.uniq
|
214
|
+
success_pods = []
|
215
|
+
fail_pods = []
|
216
|
+
local_pods = []
|
217
|
+
external_pods = []
|
218
|
+
binary_pods = []
|
219
|
+
created_pods = []
|
220
|
+
pod_targets.map do |pod_target|
|
221
|
+
begin
|
222
|
+
version = @version_helper.version(pod_target.pod_name, pod_target.root_spec.version.to_s, @analyze_result.specifications, @configuration)
|
223
|
+
# 黑名单(不分全量和非全量)
|
224
|
+
next if skip_build?(pod_target)
|
225
|
+
# 白名单(有白名单,只看白名单,不分全量和非全量)
|
226
|
+
next if !@write_list.nil? && !@write_list.empty? && !@write_list.include?(pod_target.pod_name)
|
227
|
+
# 本地库
|
228
|
+
if @sandbox.local?(pod_target.pod_name)
|
229
|
+
local_pods << pod_target.pod_name
|
230
|
+
show_skip_tip("#{pod_target.pod_name} 是本地库")
|
231
|
+
next
|
232
|
+
end
|
233
|
+
# 外部源(如 git)
|
234
|
+
if @sandbox.checkout_sources[pod_target.pod_name]
|
235
|
+
external_pods << pod_target.pod_name
|
236
|
+
show_skip_tip("#{pod_target.pod_name} 以external方式引入")
|
237
|
+
next
|
238
|
+
end
|
239
|
+
# 无源码
|
240
|
+
if !@sandbox.local?(pod_target.pod_name) && !pod_target.should_build?
|
241
|
+
binary_pods << pod_target.pod_name
|
242
|
+
show_skip_tip("#{pod_target.pod_name} 无需编译")
|
243
|
+
next
|
244
|
+
end
|
245
|
+
# 非全量编译、不在白名单中且已经有相应的二进制版本
|
246
|
+
if has_created_binary?(pod_target.pod_name, version)
|
247
|
+
created_pods << pod_target.pod_name
|
248
|
+
show_skip_tip("#{pod_target.pod_name}(#{version}) 已经有二进制版本了")
|
249
|
+
next
|
250
|
+
end
|
251
|
+
# 构建产物
|
252
|
+
builder = Builder.new(pod_target, @sandbox.checkout_sources, @skip_simulator, @configuration)
|
253
|
+
result = builder.build
|
254
|
+
fail_pods << pod_target.pod_name unless result
|
255
|
+
next unless result
|
256
|
+
builder.create_binary
|
257
|
+
# 压缩并上传zip
|
258
|
+
zip_helper = ZipFileHelper.new(pod_target, version, builder.product_dir, builder.build_as_framework?, @configuration)
|
259
|
+
result = zip_helper.zip_lib
|
260
|
+
fail_pods << pod_target.pod_name unless result
|
261
|
+
next unless result
|
262
|
+
result = zip_helper.upload_zip_lib
|
263
|
+
fail_pods << pod_target.pod_name unless result
|
264
|
+
next unless result
|
265
|
+
# 生成二进制podspec并上传
|
266
|
+
podspec_creator = PodspecUtil.new(pod_target, version, builder.build_as_framework?, @configuration)
|
267
|
+
bin_spec = podspec_creator.create_binary_podspec
|
268
|
+
bin_spec_file = podspec_creator.write_binary_podspec(bin_spec)
|
269
|
+
result = podspec_creator.push_binary_podspec(bin_spec_file)
|
270
|
+
fail_pods << pod_target.pod_name unless result
|
271
|
+
success_pods << pod_target.pod_name if result
|
272
|
+
rescue Pod::StandardError => e
|
273
|
+
UI.info "`#{pod_target}`编译失败,原因:#{e}".red
|
274
|
+
fail_pods << pod_target.pod_name
|
275
|
+
next
|
276
|
+
ensure
|
277
|
+
clean_single_build_pod(pod_target) if @clean_single
|
278
|
+
end
|
279
|
+
end
|
280
|
+
results = {
|
281
|
+
'Total' => pod_targets,
|
282
|
+
'Success' => success_pods,
|
283
|
+
'Fail' => fail_pods,
|
284
|
+
'Local' => local_pods,
|
285
|
+
'External' => external_pods,
|
286
|
+
'No Source File' => binary_pods,
|
287
|
+
'Created Binary' => created_pods,
|
288
|
+
'Black List' => @black_list || [],
|
289
|
+
'Write List' => @write_list || []
|
290
|
+
}
|
291
|
+
show_results(results)
|
292
|
+
results
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def show_skip_tip(title)
|
297
|
+
UI.info title.yellow
|
298
|
+
end
|
299
|
+
|
300
|
+
# 是否跳过编译
|
301
|
+
def skip_build?(pod_target)
|
302
|
+
!@black_list.nil? && !@black_list.empty? && @black_list.include?(pod_target.pod_name)
|
303
|
+
end
|
304
|
+
|
305
|
+
# 展示结果
|
306
|
+
def show_results(results)
|
307
|
+
UI.title '打包结果:'.green do
|
308
|
+
UI.info '——————————————————————————————————'.green
|
309
|
+
UI.info "|#{'Type'.center(20)}|#{'Count'.center(11)}|".green
|
310
|
+
UI.info '——————————————————————————————————'.green
|
311
|
+
results.each do |key, value|
|
312
|
+
UI.info "|#{key.center(20)}|#{value.size.to_s.center(11)}|".green
|
313
|
+
end
|
314
|
+
UI.info '——————————————————————————————————'.green
|
315
|
+
|
316
|
+
# 打印出失败的 target
|
317
|
+
unless results['Fail'].empty?
|
318
|
+
UI.info "\n打包失败的库:#{results['Fail']}".red
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
# 是否已经有二进制版本了
|
324
|
+
def has_created_binary?(pod_name, version)
|
325
|
+
# name 或 version 为nil
|
326
|
+
return false if pod_name.nil? || version.nil?
|
327
|
+
# 是否全量打包
|
328
|
+
return false if @full_build
|
329
|
+
# 是否在白名单中
|
330
|
+
return false if !@write_list.nil? && !@write_list.empty? && @write_list.include?(pod_name)
|
331
|
+
sources_manager = Config.instance.sources_manager
|
332
|
+
binary_source = sources_manager.binary_source
|
333
|
+
result = false
|
334
|
+
begin
|
335
|
+
specification = binary_source.specification(pod_name, version)
|
336
|
+
result = true unless specification.nil?
|
337
|
+
rescue Pod::StandardError => e
|
338
|
+
result = false
|
339
|
+
end
|
340
|
+
result
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
@@ -0,0 +1,262 @@
|
|
1
|
+
require 'cocoapods-meitu-bin/helpers/buildAll/builder'
|
2
|
+
require 'cocoapods-meitu-bin/helpers/buildAll/podspec_util'
|
3
|
+
require 'cocoapods-meitu-bin/helpers/buildAll/zip_file_helper'
|
4
|
+
require 'cocoapods-meitu-bin/helpers/buildAll/bin_helper'
|
5
|
+
require 'cocoapods-meitu-bin/config/config'
|
6
|
+
require 'xcodeproj'
|
7
|
+
require 'yaml'
|
8
|
+
require 'digest'
|
9
|
+
|
10
|
+
module Pod
|
11
|
+
class Command
|
12
|
+
class Bin < Command
|
13
|
+
class HeaderFilesSpecifications < Bin
|
14
|
+
self.summary = '规范组件在壳工程使用方式,非<>引入头文件会提示修改,同时会检查壳工程不在参与编译的文件并提示删除'
|
15
|
+
self.description = <<-DESC
|
16
|
+
#{summary}
|
17
|
+
DESC
|
18
|
+
|
19
|
+
def self.options
|
20
|
+
[
|
21
|
+
%w[--xcodeproj-path xcodeproj路径,默认会查找podfile同级目录下的xcodeproj_path],
|
22
|
+
%w[--classes-path 壳工程默认的代码文件路径,默认会查找podfile同级目录下的Classes目录],
|
23
|
+
%w[--error-del 提示不规范的组件头文件引入,并删除壳工程不参与编译的文件],
|
24
|
+
%w[--ignore-header header白名单设置,也可以在BinConfig.yml里配置,比如壳工程中的协议.h,或者纯.h文件,多个文件用;分割,例如CanvasProtocol.h;PainterProtocol.h]
|
25
|
+
].concat(super).uniq
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(argv)
|
29
|
+
@xcodeproj_path = argv.option('xcodeproj_path', "")
|
30
|
+
@classes_path = argv.option('classes_path', "")
|
31
|
+
@error_del = argv.flag?('error-del', false)
|
32
|
+
@ignore_header = argv.option('ignore-header', '')
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
def run
|
37
|
+
# 开始时间
|
38
|
+
@start_time = Time.now.to_i
|
39
|
+
# 读取配置文件
|
40
|
+
read_config
|
41
|
+
#xcodeproj_path为空字符串,默认获取当前目录下的xxx.xcodeproj
|
42
|
+
# 获取xcodeproj_path
|
43
|
+
if @xcodeproj_path.empty?
|
44
|
+
files = `ls`
|
45
|
+
file_list = files.split("\n")
|
46
|
+
xcodeproj = file_list.find_all { |n| n.include? ".xcodeproj" }[0]
|
47
|
+
scheme = xcodeproj.split(".")[0]
|
48
|
+
@xcodeproj_path = File.join(Pod::Config.instance.project_root, xcodeproj)
|
49
|
+
end
|
50
|
+
|
51
|
+
if !@xcodeproj_path.include? ".xcodeproj"
|
52
|
+
UI.info ".xcodeproj 路径不存在".red
|
53
|
+
return
|
54
|
+
end
|
55
|
+
# 获取xcodeproj 中的 Compile Sources 实际参与编译的文件
|
56
|
+
project = Xcodeproj::Project.open(@xcodeproj_path)
|
57
|
+
target = project.targets.select { |a_target| a_target.name.eql?(scheme) }[0]
|
58
|
+
files = target.source_build_phase.files
|
59
|
+
#获取 Compile Sources 中的所有文件名称
|
60
|
+
names = Array.new
|
61
|
+
files.each do |reference|
|
62
|
+
if reference.respond_to? 'file_ref' and reference.file_ref.respond_to? 'path'
|
63
|
+
names << reference.file_ref.path
|
64
|
+
else
|
65
|
+
puts reference
|
66
|
+
end
|
67
|
+
end
|
68
|
+
# puts names
|
69
|
+
#过滤出 .m 和 .mm 文件名
|
70
|
+
find_names = names.find_all { |n| (n.respond_to? 'include?' and (n.include? ".m" or n.include? ".mm")) }
|
71
|
+
find_swift_names = names.find_all { |n| (n.respond_to? 'include?' and n.include? ".swift") }
|
72
|
+
if @classes_path.empty?
|
73
|
+
@classes_path = File.join(Pod::Config.instance.project_root, "Classes")
|
74
|
+
end
|
75
|
+
|
76
|
+
if File.exist?(@classes_path)
|
77
|
+
files_h = `find #{@classes_path} -name "*.h"`
|
78
|
+
files_m = `find #{@classes_path} -name "*.m"`
|
79
|
+
files_swift = `find #{@classes_path} -name "*.swift"`
|
80
|
+
file_h_list = files_h.split("\n")
|
81
|
+
file_m_list = files_m.split("\n")
|
82
|
+
file_s_list = files_swift.split("\n")
|
83
|
+
del_h_path_list = Array.new
|
84
|
+
save_h_path_list = Array.new
|
85
|
+
del_m_path_list = Array.new
|
86
|
+
save_m_path_list = Array.new
|
87
|
+
del_s_path_list = Array.new
|
88
|
+
#获取在Compile Sources 的.h 和 本地路径下不在Compile Sources 的.h(需要删除的)
|
89
|
+
file_h_list.each do |file_h_path|
|
90
|
+
is_save = false
|
91
|
+
find_names.each { |name|
|
92
|
+
name_to = ''
|
93
|
+
if name.include? '.mm'
|
94
|
+
name_to = name.sub(".mm", ".h")
|
95
|
+
elsif name.include? '.m'
|
96
|
+
name_to = name.sub(".m", ".h")
|
97
|
+
else
|
98
|
+
puts "error:------#{name}"
|
99
|
+
end
|
100
|
+
|
101
|
+
if file_h_path.include? name_to
|
102
|
+
is_save = true
|
103
|
+
break
|
104
|
+
end
|
105
|
+
}
|
106
|
+
if is_save
|
107
|
+
save_h_path_list << file_h_path
|
108
|
+
else
|
109
|
+
del_h_path_list << file_h_path
|
110
|
+
end
|
111
|
+
end
|
112
|
+
#获取在Compile Sources 的.m .mm 和 本地路径下不在Compile Sources 的.m .mm(需要删除的)
|
113
|
+
file_m_list.each do |file_m_path|
|
114
|
+
is_save = false
|
115
|
+
find_names.each { |name|
|
116
|
+
if file_m_path.include? name
|
117
|
+
is_save = true
|
118
|
+
break
|
119
|
+
end
|
120
|
+
}
|
121
|
+
if is_save
|
122
|
+
save_m_path_list << file_m_path
|
123
|
+
else
|
124
|
+
del_m_path_list << file_m_path
|
125
|
+
end
|
126
|
+
end
|
127
|
+
#获取在Compile Sources 的.swift 和 本地路径下不在Compile Sources 的.swift(需要删除的)
|
128
|
+
file_s_list.each do |file_s_path|
|
129
|
+
is_save = false
|
130
|
+
find_swift_names.each { |name|
|
131
|
+
if file_s_path.include? name
|
132
|
+
is_save = true
|
133
|
+
break
|
134
|
+
end
|
135
|
+
}
|
136
|
+
if !is_save
|
137
|
+
del_s_path_list << file_s_path
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# puts "del_h_path_list"
|
142
|
+
# puts del_h_path_list
|
143
|
+
# puts "save_h_path_list"
|
144
|
+
# puts save_h_path_list
|
145
|
+
# puts "del_m_path_list"
|
146
|
+
UI.title "提示: 壳工程不参与编译的文件,由于之前下层组件,删除引用并未删除代码文件或者其他分支又合入的不在使用或者已经下沉到组件的代码文件".green
|
147
|
+
del_m_path_list.each { |name| UI.info "- #{name}".red }
|
148
|
+
del_s_path_list.each { |name| UI.info "- #{name}".red }
|
149
|
+
# puts "save_m_path_list"
|
150
|
+
# puts save_m_path_list
|
151
|
+
if @error_del
|
152
|
+
del_m_path_list.each { |path|
|
153
|
+
h_path = path.gsub(".m", ".h")
|
154
|
+
if File.exist?(h_path)
|
155
|
+
`rm -rf #{h_path}`
|
156
|
+
end
|
157
|
+
`rm -rf #{path}`
|
158
|
+
}
|
159
|
+
|
160
|
+
del_s_path_list.each { |path|
|
161
|
+
`rm -rf #{path}`
|
162
|
+
}
|
163
|
+
end
|
164
|
+
|
165
|
+
header_path = save_h_path_list.join(sep = "#",)
|
166
|
+
all_header_list = Array.new
|
167
|
+
all_header_annotation_list = Array.new
|
168
|
+
save_h_path_list.each { |h_path|
|
169
|
+
list = `cat #{h_path} | grep '#import "' | awk -F ' ' '{print $2}'`
|
170
|
+
list_annotation = `cat #{h_path} | grep '//#import' | awk -F ' ' '{print $2}'`
|
171
|
+
#注释的头文件
|
172
|
+
list_annotation.split("\n").each { |name|
|
173
|
+
if !name.include? "-Swift.h\"" and name.include? ".h\""
|
174
|
+
all_header_annotation_list << name.gsub("\"", "")
|
175
|
+
end
|
176
|
+
}
|
177
|
+
list.split("\n").each { |name|
|
178
|
+
if !name.include? "-Swift.h\"" and name.include? ".h\""
|
179
|
+
all_header_list << name.gsub("\"", "")
|
180
|
+
end
|
181
|
+
}
|
182
|
+
}
|
183
|
+
save_m_path_list.each { |m_path|
|
184
|
+
list = `cat #{m_path} | grep '#import "' | awk -F ' ' '{print $2}'`
|
185
|
+
list_annotation = `cat #{m_path} | grep '//#import' | awk -F ' ' '{print $2}'`
|
186
|
+
list_annotation.split("\n").each { |name|
|
187
|
+
if !name.include? "-Swift.h\"" and name.include? ".h\""
|
188
|
+
all_header_annotation_list << name.gsub("\"", "")
|
189
|
+
end
|
190
|
+
}
|
191
|
+
list.split("\n").each { |name|
|
192
|
+
if !name.include? "-Swift.h\"" and name.include? ".h\""
|
193
|
+
all_header_list << name.gsub("\"", "")
|
194
|
+
end
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
modified_header_file_list = Array.new
|
199
|
+
all_header_annotation_list_to = all_header_annotation_list.uniq
|
200
|
+
all_header_list_to = all_header_list.uniq
|
201
|
+
|
202
|
+
all_header_del_list = Array.new
|
203
|
+
|
204
|
+
all_header_list_to.each { |name|
|
205
|
+
is_unsave = true
|
206
|
+
all_header_annotation_list_to.each { |name_to|
|
207
|
+
if name == name_to
|
208
|
+
is_unsave = false
|
209
|
+
break
|
210
|
+
end
|
211
|
+
}
|
212
|
+
if is_unsave
|
213
|
+
all_header_del_list << name
|
214
|
+
end
|
215
|
+
}
|
216
|
+
|
217
|
+
UI.title "提示: 使用方式需要调整为<>方式的头文件,请在壳工程代码搜索并修改".green
|
218
|
+
if !@ignore_header.empty?
|
219
|
+
@ignore_header.split(";").each { |name|
|
220
|
+
@ignore_header_list << name
|
221
|
+
}
|
222
|
+
end
|
223
|
+
@ignore_header_list.uniq
|
224
|
+
all_header_del_list.each { |name|
|
225
|
+
if !header_path.include? name and !@ignore_header_list.include? name
|
226
|
+
modified_header_file_list << name
|
227
|
+
UI.info "- #{name} 头文件不能在壳工程使用 #import \"#{name}\" 需要修改成#import <xxx/#{name}.h>".red
|
228
|
+
end
|
229
|
+
}
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
# 计算耗时
|
234
|
+
show_cost_time
|
235
|
+
end
|
236
|
+
|
237
|
+
private
|
238
|
+
|
239
|
+
# 读取配置文件
|
240
|
+
def read_config
|
241
|
+
UI.title 'Read config from file `BinConfig.yaml`'.green do
|
242
|
+
config_file = File.join(Pod::Config.instance.project_root, 'BinConfig.yaml')
|
243
|
+
return unless File.exist?(config_file)
|
244
|
+
config = YAML.safe_load(File.open(config_file))
|
245
|
+
return if config.nil?
|
246
|
+
build_config = config['build_config']
|
247
|
+
return if build_config.nil?
|
248
|
+
@ignore_header_list = build_config['ignore_header_list']
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# 打印耗时
|
253
|
+
def show_cost_time
|
254
|
+
return if @start_time.nil?
|
255
|
+
UI.info "总耗时:#{Time.now.to_i - @start_time}s".green
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'cocoapods-meitu-bin/config/config_asker'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Command
|
5
|
+
class Bin < Command
|
6
|
+
class Init < Bin
|
7
|
+
self.summary = '配置插件'
|
8
|
+
self.description = <<-DESC
|
9
|
+
创建yml配置文件,保存插件需要的配置信息,如二进制podspec仓库、二进制下载地址等
|
10
|
+
DESC
|
11
|
+
|
12
|
+
def self.options
|
13
|
+
[
|
14
|
+
%w[--bin-url=URL 配置文件地址,直接从此地址下载配置文件]
|
15
|
+
].concat(super)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(argv)
|
19
|
+
@bin_url = argv.option('bin-url')
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
raise Informative, "当前目录下没有`Podfile`文件" unless File.exist?(File.join(Dir.pwd, "Podfile"))
|
25
|
+
raise Informative, "当前目录下已经存在配置文件" if File.exist?(CBin.config.config_file)
|
26
|
+
if @bin_url.nil?
|
27
|
+
config_with_asker
|
28
|
+
else
|
29
|
+
config_with_url(@bin_url)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# 从远端下载配置文件
|
36
|
+
def config_with_url(url)
|
37
|
+
require 'open-uri'
|
38
|
+
|
39
|
+
UI.puts "开始下载配置文件..."
|
40
|
+
file = open(url)
|
41
|
+
contents = YAML.safe_load(file.read)
|
42
|
+
|
43
|
+
UI.puts "开始同步配置文件..."
|
44
|
+
CBin.config.sync_config(contents.to_hash)
|
45
|
+
UI.puts "设置完成.".green
|
46
|
+
rescue Errno::ENOENT => e
|
47
|
+
raise Informative, "配置文件路径 #{url} 无效,请确认后重试."
|
48
|
+
end
|
49
|
+
|
50
|
+
# 询问用户相关的配置
|
51
|
+
def config_with_asker
|
52
|
+
asker = CBin::Config::Asker.new
|
53
|
+
asker.welcome_message
|
54
|
+
|
55
|
+
config = {}
|
56
|
+
template_hash = CBin.config.template_hash
|
57
|
+
template_hash.each do |k, v|
|
58
|
+
default = begin
|
59
|
+
CBin.config.send(k)
|
60
|
+
rescue StandardError
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
config[k] = asker.ask_with_answer(v[:description], default, v[:selection])
|
64
|
+
end
|
65
|
+
|
66
|
+
CBin.config.sync_config(config)
|
67
|
+
asker.done_message
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|