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.
- 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,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
|