cocoapods-dongjia 1.1.2 → 1.1.7
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 +4 -4
- data/lib/cocoapods-dongjia/command.rb +1 -0
- data/lib/cocoapods-dongjia/command/install.rb +0 -6
- data/lib/cocoapods-dongjia/command/open.rb +0 -6
- data/lib/cocoapods-dongjia/command/reinstall.rb +8 -1
- data/lib/cocoapods-dongjia/command/release.rb +40 -0
- data/lib/cocoapods-dongjia/command/strip.rb +9 -8
- data/lib/cocoapods-dongjia/gem_version.rb +3 -3
- data/lib/cocoapods_plugin.rb +18 -16
- data/lib/dongjia_binarization.rb +642 -0
- data/lib/dongjia_pods_iterator.rb +50 -22
- data/lib/dongjia_router.rb +2 -0
- data/lib/helper/Core/podfile/dsl.rb +16 -0
- data/lib/helper/{podfile_warnings.rb → installer.rb} +17 -3
- data/lib/helper/podfile.rb +60 -0
- metadata +41 -12
- data/lib/dongjia_branch_inspector.rb +0 -43
- data/lib/dongjia_scheme_manager.rb +0 -58
- data/lib/helper/podfile_local_importer.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: abe6387bbccd1ac19c893b9c384025c976cf5a8975668725670aac190b750abb
|
4
|
+
data.tar.gz: 125582ad4f0aa628467990eb2b43e32007f43043044a4a57a17331a1893bd734
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce36c1a22df3189675dec1775e998fbfdf2a6e413c730db99ea6abfdf90bbf8cb6af04df6d00a90b9b8ce1e7c0c65ee5e4bf1274c2290880b87a03f4b0e44fe6
|
7
|
+
data.tar.gz: d9a8b6d5b4496424efb19e4499edacaabf232cdf3069f7ec10cc554de5b2771fe2d63c2596e1e21a5055e3f3197ff3fa7227b9d54b0c31a594e43e852759f93f
|
@@ -1,11 +1,8 @@
|
|
1
1
|
require 'cocoapods'
|
2
2
|
|
3
3
|
module Pod
|
4
|
-
|
5
4
|
class Command
|
6
|
-
|
7
5
|
class Open < Command
|
8
|
-
|
9
6
|
self.summary = '快速打开项目的 .xcworkspace'
|
10
7
|
|
11
8
|
self.description = <<-DESC
|
@@ -24,9 +21,6 @@ module Pod
|
|
24
21
|
def run
|
25
22
|
`open #{@workspace_path}`
|
26
23
|
end
|
27
|
-
|
28
24
|
end
|
29
|
-
|
30
25
|
end
|
31
|
-
|
32
26
|
end
|
@@ -18,7 +18,14 @@ module Pod
|
|
18
18
|
CLAide::Argument.new('XCODE_PROJECT', false),
|
19
19
|
]
|
20
20
|
|
21
|
+
def self.options
|
22
|
+
[
|
23
|
+
["--save", "将重新生成的 project.pbxproj 文件保存下来"]
|
24
|
+
]
|
25
|
+
end
|
26
|
+
|
21
27
|
def initialize(argv)
|
28
|
+
@save = argv.flag?("save")
|
22
29
|
path = argv.shift_argument
|
23
30
|
@project_path = Pathname.new(path) if path
|
24
31
|
super
|
@@ -45,7 +52,7 @@ module Pod
|
|
45
52
|
|
46
53
|
deintegrator = Deintegrator.new
|
47
54
|
deintegrator.deintegrate_project(@project)
|
48
|
-
@project.save
|
55
|
+
@project.save if @save
|
49
56
|
|
50
57
|
verify_podfile_exists!
|
51
58
|
installer = installer_for_config
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'cocoapods'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
|
5
|
+
class Podfile
|
6
|
+
@@is_release_mode = false
|
7
|
+
def self.set_is_release_mode(mode)
|
8
|
+
@@is_release_mode = mode
|
9
|
+
end
|
10
|
+
def self.is_release_mode?
|
11
|
+
@@is_release_mode
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Command
|
16
|
+
|
17
|
+
class Release < Command
|
18
|
+
|
19
|
+
self.summary = '以 release 模式集成 pods'
|
20
|
+
|
21
|
+
self.description = <<-DESC
|
22
|
+
|
23
|
+
以 release 模式集成 Pods
|
24
|
+
|
25
|
+
可以在 Podfile 中通过 @@debug_only_pods = [pod_name] 的方式指定 debug 模式下的 Pod
|
26
|
+
|
27
|
+
当执行 pod release 时,会自动剔除 @@debug_only_pods 内所定义的 Pod
|
28
|
+
|
29
|
+
DESC
|
30
|
+
|
31
|
+
def run
|
32
|
+
Pod::Podfile::set_is_release_mode(true)
|
33
|
+
installer_for_config.install!
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -111,7 +111,7 @@ module Pod
|
|
111
111
|
'AlipaySDK.bundle',
|
112
112
|
'AppIcon.appiconset',
|
113
113
|
'KPCameraImages.xcassets',
|
114
|
-
'
|
114
|
+
'UMSocialSDKResources.bundle',
|
115
115
|
'LaunchResource'
|
116
116
|
]
|
117
117
|
except_files = [
|
@@ -168,15 +168,16 @@ module Pod
|
|
168
168
|
|
169
169
|
def run
|
170
170
|
images = analyze(get_source_files, get_images)
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
puts "
|
171
|
+
if images.empty?
|
172
|
+
puts "未找到无效资源"
|
173
|
+
else
|
174
|
+
puts "无效资源文件:"
|
175
|
+
images.each do |img|
|
176
|
+
path = Pathname.new(img.fullpath).relative_path_from(Dir.pwd).to_s
|
177
|
+
puts " #{path}"
|
178
|
+
end
|
175
179
|
end
|
176
180
|
end
|
177
|
-
|
178
181
|
end
|
179
|
-
|
180
182
|
end
|
181
|
-
|
182
183
|
end
|
data/lib/cocoapods_plugin.rb
CHANGED
@@ -1,19 +1,31 @@
|
|
1
1
|
require 'cocoapods-dongjia/command'
|
2
2
|
require_relative 'dongjia_source'
|
3
|
-
require_relative 'dongjia_branch_inspector'
|
4
3
|
require_relative 'dongjia_enterprise_inspector'
|
5
4
|
require_relative 'dongjia_pods_iterator'
|
6
5
|
require_relative 'dongjia_router'
|
7
|
-
require_relative '
|
6
|
+
require_relative 'dongjia_binarization'
|
8
7
|
|
9
|
-
require_relative 'helper/
|
8
|
+
require_relative 'helper/podfile'
|
10
9
|
require_relative 'helper/podfile_options'
|
11
|
-
require_relative 'helper/
|
10
|
+
require_relative 'helper/installer'
|
11
|
+
require_relative 'helper/Core/podfile/dsl'
|
12
12
|
|
13
13
|
module Dongjia
|
14
14
|
|
15
15
|
Pod::HooksManager.register('cocoapods-dongjia', :pre_install) do |ctx, params|
|
16
16
|
|
17
|
+
private_config_path = ctx.podfile.defined_in_file.dirname.join("PrivateConfig.yml")
|
18
|
+
if private_config_path.exist?
|
19
|
+
private_config = YAML.load(File.read(private_config_path))
|
20
|
+
if private_config.is_a?(Hash)
|
21
|
+
binary = private_config["binary"]
|
22
|
+
if binary.is_a?(Hash)
|
23
|
+
Binarization.load_private_config(ctx, binary)
|
24
|
+
Binarization.remove_dirty_pod_projects()
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
17
29
|
podfile = ctx.podfile
|
18
30
|
|
19
31
|
# 禁用集成完后的反馈
|
@@ -24,7 +36,6 @@ module Dongjia
|
|
24
36
|
|
25
37
|
# 关闭静态框架依赖传递的校验
|
26
38
|
Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
|
27
|
-
|
28
39
|
end
|
29
40
|
|
30
41
|
Pod::HooksManager.register('cocoapods-dongjia', :post_install) do |ctx, params|
|
@@ -32,17 +43,8 @@ module Dongjia
|
|
32
43
|
# 关闭警告 / 检查 LTO
|
33
44
|
PodsIterator.iterate(params, ctx.sandbox_root)
|
34
45
|
|
35
|
-
# 处理 appspec 配置
|
36
|
-
SchemeManager.setup(ctx, params)
|
37
|
-
|
38
|
-
# 企业版文件引用校验
|
39
|
-
files = EnterpriseInspector.inspect()
|
40
|
-
Pod::UI.warn "文件未加入企业版:#{files}" if files.count > 0
|
41
|
-
|
42
46
|
# 抓取所有路由汇总至
|
43
|
-
router = Router.new
|
44
|
-
router.scrape_routers(ctx.sandbox_root, params[:scrap_routers])
|
45
|
-
|
47
|
+
# router = Router.new
|
48
|
+
# router.scrape_routers(ctx.sandbox_root, params[:scrap_routers])
|
46
49
|
end
|
47
|
-
|
48
50
|
end
|
@@ -0,0 +1,642 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'archive/zip'
|
4
|
+
require 'net/http'
|
5
|
+
require 'json'
|
6
|
+
require 'yaml'
|
7
|
+
require 'down'
|
8
|
+
require 'pry'
|
9
|
+
require 'uri'
|
10
|
+
|
11
|
+
module Dongjia
|
12
|
+
class Binarization
|
13
|
+
|
14
|
+
@@ctx = nil
|
15
|
+
@@pod_cfg = {}
|
16
|
+
@@enabled = false
|
17
|
+
@@submodules = {}
|
18
|
+
@@server_host = ""
|
19
|
+
|
20
|
+
@@target_name = "dongjia" # 项目的 target 名
|
21
|
+
@@pods_proj = nil # Pods.xcodeproj
|
22
|
+
@@pods_target = nil # Pods.xcodeproj 中的 target 对象
|
23
|
+
|
24
|
+
class << self
|
25
|
+
# 加载配置
|
26
|
+
def load_private_config(ctx, binary)
|
27
|
+
@@ctx = ctx
|
28
|
+
|
29
|
+
submodule_info = load_submodules_info
|
30
|
+
@@submodules = submodule_info.to_h { |s|
|
31
|
+
[
|
32
|
+
s[:name],
|
33
|
+
{ sha: s[:sha], binary: s[:binary], }
|
34
|
+
]
|
35
|
+
}
|
36
|
+
|
37
|
+
@@enabled ||= binary["enabled"]
|
38
|
+
@@server_host = binary["server_host"]
|
39
|
+
@@target_name = (binary["target_name"] || "").strip
|
40
|
+
ignores = binary["ignores"] || []
|
41
|
+
|
42
|
+
if @@enabled
|
43
|
+
@@submodules = query_components_existing(submodule_info).to_h { |s|
|
44
|
+
[
|
45
|
+
s["name"],
|
46
|
+
{ sha: s["sha"], binary: s["binary"], }
|
47
|
+
]
|
48
|
+
}.each { |k, v|
|
49
|
+
ignored = ignores.include?(k)
|
50
|
+
v[:binary] &&= !ignored && @@enabled
|
51
|
+
v[:ignored] = ignored
|
52
|
+
}
|
53
|
+
end
|
54
|
+
rescue => e
|
55
|
+
puts "Binarization error: #{e}"
|
56
|
+
end
|
57
|
+
|
58
|
+
# 移除脏工程
|
59
|
+
def remove_dirty_pod_projects
|
60
|
+
if @@enabled
|
61
|
+
@@submodules
|
62
|
+
.filter { |k,v| !v[:binary] }
|
63
|
+
.map { |k,v| k }
|
64
|
+
.each { |name|
|
65
|
+
path = File.join(@@ctx.sandbox_root, "#{name}.xcodeproj")
|
66
|
+
next unless File.exist?(path)
|
67
|
+
proj = Xcodeproj::Project.open(path)
|
68
|
+
if proj.targets.map(&:name).include?("#{name}-Binary")
|
69
|
+
FileUtils.rm_rf(path)
|
70
|
+
end
|
71
|
+
}
|
72
|
+
else
|
73
|
+
# 不启用,清除所有包含 -Binary 的工程
|
74
|
+
removing_paths = []
|
75
|
+
Dir.foreach(@@ctx.sandbox_root) { |filename|
|
76
|
+
next if File.extname(filename) != '.xcodeproj'
|
77
|
+
pod_name = filename.delete_suffix('.xcodeproj')
|
78
|
+
next if pod_name == "Pods"
|
79
|
+
process_pod_xcconfig(pod_name)
|
80
|
+
path = File.join(@@ctx.sandbox_root, filename)
|
81
|
+
proj = Xcodeproj::Project.open(path)
|
82
|
+
included_binary_target = proj.targets.map(&:name).any? { |target_name|
|
83
|
+
target_name.end_with?("-Binary")
|
84
|
+
}
|
85
|
+
removing_paths << path if included_binary_target
|
86
|
+
}
|
87
|
+
removing_paths.each { |path| FileUtils.rm_rf(path) }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# 开始处理二进制
|
92
|
+
def process(installer)
|
93
|
+
return if @@ctx == nil || @@ctx.sandbox_root == nil
|
94
|
+
|
95
|
+
path = File.join(@@ctx.sandbox_root, "Pods.xcodeproj")
|
96
|
+
@@pods_proj = Xcodeproj::Project.open(path) if File.exist?(path)
|
97
|
+
@@pods_target = (@@target_name.empty?) ? @@pods_proj.targets.first : @@pods_proj.target_by_name("Pods-#{@@target_name}")
|
98
|
+
if @@pods_target.nil?
|
99
|
+
Pod::UI.warn("[Binarization] 未完成二进制转换,target_name 配置错误")
|
100
|
+
return
|
101
|
+
end
|
102
|
+
|
103
|
+
setup_pod_cfg(installer)
|
104
|
+
|
105
|
+
download_frameworks
|
106
|
+
|
107
|
+
each_pod_proj do |name, cfg|
|
108
|
+
process_pods_project_dependencies(name)
|
109
|
+
|
110
|
+
# 处理 Binary Group
|
111
|
+
process_binary_group(name)
|
112
|
+
|
113
|
+
# 处理 XXX-xcframeworks.sh 脚本
|
114
|
+
process_xcframeworks_shell(name)
|
115
|
+
|
116
|
+
process_pod_xcconfig(name)
|
117
|
+
end
|
118
|
+
|
119
|
+
# 更新依赖关系
|
120
|
+
each_pod_proj do |name, cfg|
|
121
|
+
target = cfg[:target]
|
122
|
+
next if target.nil?
|
123
|
+
delete_list = []
|
124
|
+
add_list = []
|
125
|
+
target.dependencies.each { |dep|
|
126
|
+
dep_pod_name = real_name(dep.name)
|
127
|
+
dep_cfg = @@pod_cfg[dep_pod_name]
|
128
|
+
next if dep_cfg.nil?
|
129
|
+
if dep_cfg[:target].name != dep.name
|
130
|
+
add_list << dep_cfg[:target]
|
131
|
+
delete_list << dep
|
132
|
+
end
|
133
|
+
}
|
134
|
+
target.dependencies.delete_if { |dep| delete_list.include?(dep) }
|
135
|
+
add_list.each { |t| target.add_dependency(t) }
|
136
|
+
cfg[:save] ||= !delete_list.empty? || !add_list.empty?
|
137
|
+
end
|
138
|
+
|
139
|
+
# 保存
|
140
|
+
save_projects
|
141
|
+
|
142
|
+
process_aggregate_target_xcconfig(installer.aggregate_targets.first.name)
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
# 加载配置
|
148
|
+
def setup_pod_cfg(installer)
|
149
|
+
installer.analysis_result.podfile_dependency_cache.podfile_dependencies.each { |dep|
|
150
|
+
name = dep.name.split('/').first
|
151
|
+
cfg = @@submodules[name] || {}
|
152
|
+
cfg[:binary] = false unless cfg[:binary]
|
153
|
+
cfg[:save] = false unless cfg[:save]
|
154
|
+
cfg[:project] = Xcodeproj::Project.open(File.join(@@ctx.sandbox_root, "#{name}.xcodeproj"))
|
155
|
+
@@pod_cfg[name] = cfg
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
# 获取实际的 pod 名,如果有 -Binary 后缀,则去除后缀
|
160
|
+
def real_name(name)
|
161
|
+
name = name.delete_suffix("-Binary") if name.end_with?("-Binary")
|
162
|
+
return name
|
163
|
+
end
|
164
|
+
|
165
|
+
def save_projects
|
166
|
+
if Pod::Config.instance.verbose == true
|
167
|
+
pods_should_save = @@pod_cfg.filter { |k, v| v[:save] }.keys
|
168
|
+
Pod::UI.notice "Saving Pods project" unless pods_should_save.empty?
|
169
|
+
pods_should_save.each { |name|
|
170
|
+
puts " #{name}"
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
should_save = false
|
175
|
+
each_pod_proj do |name, cfg|
|
176
|
+
cfg[:project].save if cfg[:save]
|
177
|
+
should_save ||= cfg[:save]
|
178
|
+
end
|
179
|
+
@@pods_proj.save if !@@pods_proj.nil? && should_save
|
180
|
+
end
|
181
|
+
|
182
|
+
# 遍历 Pods 目录下的 xcodeproj
|
183
|
+
def each_pod_proj
|
184
|
+
Dir.foreach(@@ctx.sandbox_root) do |filename|
|
185
|
+
next if File.extname(filename) != '.xcodeproj'
|
186
|
+
|
187
|
+
name = File.basename(filename, '.xcodeproj')
|
188
|
+
next if name == 'Pods'
|
189
|
+
|
190
|
+
cfg = @@pod_cfg[name]
|
191
|
+
next if cfg.nil?
|
192
|
+
|
193
|
+
yield(name, cfg) if block_given?
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# 向服务器查询哪些 Pod 需要打包
|
198
|
+
def query_components_existing(components)
|
199
|
+
return components unless @@enabled
|
200
|
+
result = components
|
201
|
+
begin
|
202
|
+
uri = URI.parse(URI::join(@@server_host, 'api/binary/checkup').to_s)
|
203
|
+
headers = {
|
204
|
+
'Content-Type': 'application/json'
|
205
|
+
}
|
206
|
+
req = Net::HTTP::Post.new(uri, headers)
|
207
|
+
req.body = {components: components}.to_json
|
208
|
+
resp = Net::HTTP.start(uri.host, uri.port) do |http|
|
209
|
+
http.request(req)
|
210
|
+
end
|
211
|
+
result = JSON.parse(resp.body).dig('res', 'components')
|
212
|
+
rescue => e
|
213
|
+
puts "Binarization error: #{e}"
|
214
|
+
end
|
215
|
+
return result
|
216
|
+
end
|
217
|
+
|
218
|
+
# 加载子模块信息
|
219
|
+
def load_submodules_info
|
220
|
+
return [] unless File.exist?("./componentsOnRemote")
|
221
|
+
|
222
|
+
# 获取子模块的哈希值
|
223
|
+
def git_sha_value(component_name)
|
224
|
+
git_dir = ".git/modules/componentsOnRemote/#{component_name}"
|
225
|
+
git_sha = File.read(File.join(git_dir, "HEAD")).strip
|
226
|
+
if git_sha.start_with?("ref: ")
|
227
|
+
head_file = git_sha[5, git_sha.length]
|
228
|
+
head_path = File.join(git_dir, head_file)
|
229
|
+
if File.exist?(head_path)
|
230
|
+
git_sha = File.read(head_path).strip
|
231
|
+
else
|
232
|
+
git_sha = nil
|
233
|
+
end
|
234
|
+
end
|
235
|
+
git_sha
|
236
|
+
end
|
237
|
+
|
238
|
+
Dir.foreach("./componentsOnRemote").to_a
|
239
|
+
.delete_if { |x| x.start_with?('.') }
|
240
|
+
.delete_if { |x|
|
241
|
+
# 如果子模块初始化错误,会导致目录下没有内容,需要排除掉
|
242
|
+
Dir.foreach("./componentsOnRemote/#{x}").to_a.all? { |f| f.start_with?(".") }
|
243
|
+
}
|
244
|
+
.map { |comp|
|
245
|
+
{
|
246
|
+
name: comp,
|
247
|
+
sha: git_sha_value(comp),
|
248
|
+
binary: false,
|
249
|
+
}
|
250
|
+
}
|
251
|
+
end
|
252
|
+
|
253
|
+
# 处理 Pods.xcodeproj 的依赖
|
254
|
+
def process_pods_project_dependencies(name)
|
255
|
+
cfg = @@pod_cfg[name]
|
256
|
+
proj = cfg[:project]
|
257
|
+
changed = false
|
258
|
+
|
259
|
+
latest_target = nil
|
260
|
+
removing_target_name = nil
|
261
|
+
|
262
|
+
if cfg[:binary] == true
|
263
|
+
# 使用 Binary 版本的 target,如果不存在则创建一个
|
264
|
+
binary_target = proj.target_by_name("#{name}-Binary")
|
265
|
+
if binary_target == nil
|
266
|
+
binary_target = add_binary_target(proj, name)
|
267
|
+
changed = true
|
268
|
+
end
|
269
|
+
|
270
|
+
latest_target = binary_target
|
271
|
+
removing_target_name = name
|
272
|
+
else
|
273
|
+
# 使用源码版本的 target
|
274
|
+
source_target = proj.target_by_name(name)
|
275
|
+
source_target.build_configurations.each { |cfg|
|
276
|
+
if cfg.build_settings["BUILD_LIBRARY_FOR_DISTRIBUTION"] != "YES"
|
277
|
+
cfg.build_settings["BUILD_LIBRARY_FOR_DISTRIBUTION"] = "YES"
|
278
|
+
changed = true
|
279
|
+
end
|
280
|
+
}
|
281
|
+
|
282
|
+
latest_target = source_target
|
283
|
+
removing_target_name = "#{name}-Binary"
|
284
|
+
end
|
285
|
+
|
286
|
+
cfg[:target] = latest_target
|
287
|
+
|
288
|
+
# 更新依赖
|
289
|
+
changed = update_pods_target_dependency(removing_target_name, latest_target) || changed
|
290
|
+
changed = proj.targets.map(&:name).include?(removing_target_name) || changed
|
291
|
+
proj.targets.delete_if { |t| t.name == removing_target_name }
|
292
|
+
|
293
|
+
cfg[:save] = changed
|
294
|
+
end
|
295
|
+
|
296
|
+
# 处理组件 pod 的 xcconfig
|
297
|
+
def process_pod_xcconfig(name)
|
298
|
+
# 根据 pod 是源码还是二进制包,切换路径为 PODS_CONFIGURATION_BUILD_DIR 或 PODS_XCFRAMEWORKS_BUILD_DIR
|
299
|
+
["debug", "release"].each { |cfg_name|
|
300
|
+
cfg_path = Pathname(File.join(@@ctx.sandbox_root, "Target Support Files", name, "#{name}.#{cfg_name}.xcconfig"))
|
301
|
+
next if not File.exist?(cfg_path)
|
302
|
+
cfg = Xcodeproj::Config.new(cfg_path)
|
303
|
+
fsp_str = cfg.attributes["FRAMEWORK_SEARCH_PATHS"] || "$(inherited)"
|
304
|
+
fsp = fsp_str.split(" ")
|
305
|
+
|
306
|
+
# 源码的 prefix
|
307
|
+
source_prefix = "\"${PODS_CONFIGURATION_BUILD_DIR}/"
|
308
|
+
# 二进制包的 prefix
|
309
|
+
binary_prefix = "\"${PODS_XCFRAMEWORKS_BUILD_DIR}/"
|
310
|
+
|
311
|
+
fsp.map! { |path|
|
312
|
+
if path.start_with?(source_prefix)
|
313
|
+
pod_name = path[source_prefix.length, path.length].delete_suffix("\"")
|
314
|
+
sm = @@submodules[pod_name]
|
315
|
+
if !sm.nil? && sm[:binary]
|
316
|
+
path = path.gsub("PODS_CONFIGURATION_BUILD_DIR", "PODS_XCFRAMEWORKS_BUILD_DIR")
|
317
|
+
end
|
318
|
+
elsif path.start_with?(binary_prefix)
|
319
|
+
pod_name = path[binary_prefix.length, path.length].delete_suffix("\"")
|
320
|
+
sm = @@submodules[pod_name]
|
321
|
+
if !sm.nil? && !sm[:binary]
|
322
|
+
path = path.gsub("PODS_XCFRAMEWORKS_BUILD_DIR", "PODS_CONFIGURATION_BUILD_DIR")
|
323
|
+
end
|
324
|
+
end
|
325
|
+
path
|
326
|
+
}
|
327
|
+
cfg.attributes["FRAMEWORK_SEARCH_PATHS"] = fsp.flatten.uniq.join(" ")
|
328
|
+
cfg.save_as(cfg_path)
|
329
|
+
}
|
330
|
+
end
|
331
|
+
|
332
|
+
# 处理集成对象的 xcconfig(项目的 xcconfig)
|
333
|
+
def process_aggregate_target_xcconfig(aggregate_target_name)
|
334
|
+
# 处理 Pods/Target Support Files/Pods-项目名/Pods-项目名.debug(release).xcconfig
|
335
|
+
# 所有被二进制化的 pod,增加 "${PODS_XCFRAMEWORKS_BUILD_DIR}/#{pod_name}"
|
336
|
+
["debug", "release"].each { |cfg_name|
|
337
|
+
cfg_path = Pathname(File.join(@@ctx.sandbox_root, "Target Support Files", aggregate_target_name, "#{aggregate_target_name}.#{cfg_name}.xcconfig"))
|
338
|
+
next if not File.exist?(cfg_path)
|
339
|
+
cfg = Xcodeproj::Config.new(cfg_path)
|
340
|
+
fsp = cfg.attributes["FRAMEWORK_SEARCH_PATHS"].split(" ") || ["$(inherited)"]
|
341
|
+
@@submodules.each { |k, v|
|
342
|
+
path = "\"${PODS_XCFRAMEWORKS_BUILD_DIR}/#{k}\""
|
343
|
+
if v[:binary] == true
|
344
|
+
fsp << path if not fsp.include?(path)
|
345
|
+
else
|
346
|
+
fsp.delete_if { |x| x == path }
|
347
|
+
end
|
348
|
+
}
|
349
|
+
cfg.attributes["FRAMEWORK_SEARCH_PATHS"] = fsp.flatten.uniq.join(" ")
|
350
|
+
cfg.save_as(cfg_path)
|
351
|
+
}
|
352
|
+
end
|
353
|
+
|
354
|
+
def add_binary_target(proj, name)
|
355
|
+
source_target = proj.target_by_name(name)
|
356
|
+
bin_target = proj.new_aggregate_target("#{name}-Binary", [], :ios, '10.0')
|
357
|
+
|
358
|
+
# 处理 xcconfig 引用
|
359
|
+
cfg_list0 = source_target.build_configuration_list
|
360
|
+
cfg_list1 = bin_target.build_configuration_list
|
361
|
+
cfg_list1["Debug"].base_configuration_reference ||= cfg_list0["Debug"].base_configuration_reference
|
362
|
+
cfg_list1["Release"].base_configuration_reference ||= cfg_list0["Release"].base_configuration_reference
|
363
|
+
|
364
|
+
# 处理 Build Phases
|
365
|
+
phase = bin_target.new_shell_script_build_phase("[CP] Copy XCFrameworks")
|
366
|
+
phase.shell_script = "\"${PODS_ROOT}/Target Support Files/#{name}/#{name}-xcframeworks.sh\""
|
367
|
+
|
368
|
+
# 添加依赖
|
369
|
+
bin_target.dependencies.replace(source_target.dependencies)
|
370
|
+
|
371
|
+
return bin_target
|
372
|
+
end
|
373
|
+
|
374
|
+
# 更新 Pods.xcodeproj 中 target 的依赖关系
|
375
|
+
def update_pods_target_dependency(removing_target_name, new_target)
|
376
|
+
dep_names = @@pods_target.dependencies.map(&:name)
|
377
|
+
changed = false
|
378
|
+
|
379
|
+
index = dep_names.index(removing_target_name)
|
380
|
+
if index
|
381
|
+
@@pods_target.dependencies.delete_at(index)
|
382
|
+
changed = true
|
383
|
+
end
|
384
|
+
|
385
|
+
index = dep_names.index(new_target.name)
|
386
|
+
unless index
|
387
|
+
@@pods_target.add_dependency(new_target)
|
388
|
+
changed = true
|
389
|
+
end
|
390
|
+
|
391
|
+
return changed
|
392
|
+
end
|
393
|
+
|
394
|
+
# 下载 framework 到 Pods/_Frameworks 目录下
|
395
|
+
def download_frameworks
|
396
|
+
return unless @@enabled
|
397
|
+
framework_root = File.join(@@ctx.sandbox_root, "_Frameworks")
|
398
|
+
cache_root = File.join(framework_root, "Caches")
|
399
|
+
FileUtils.mkdir_p(cache_root) unless File.exist?(cache_root)
|
400
|
+
|
401
|
+
@@submodules.each { |k, v|
|
402
|
+
if !v[:binary] || !v[:sha]
|
403
|
+
puts "#{k} 未发现二进制版本" if @@enabled && !v[:ignored]
|
404
|
+
next
|
405
|
+
end
|
406
|
+
|
407
|
+
module_cache_dir = File.join(cache_root, k)
|
408
|
+
FileUtils.mkdir_p(module_cache_dir) unless File.exist?(module_cache_dir)
|
409
|
+
|
410
|
+
filename = "#{v[:sha]}.zip"
|
411
|
+
binary_dir = File.join(module_cache_dir, v[:sha])
|
412
|
+
if not File.exist?(binary_dir)
|
413
|
+
# 目录不存在,下载 zip 包并解压
|
414
|
+
binary_zip_path = File.join(module_cache_dir, filename)
|
415
|
+
puts "Downloading #{k} (#{v[:sha]})"
|
416
|
+
url = URI::join(@@server_host, "binary/#{k}/#{filename}")
|
417
|
+
Down.download(url, destination: binary_zip_path)
|
418
|
+
Archive::Zip.extract(binary_zip_path, binary_dir)
|
419
|
+
FileUtils.rm_f(binary_zip_path)
|
420
|
+
end
|
421
|
+
target = File.expand_path(File.join(binary_dir, "#{k}.xcframework"))
|
422
|
+
FileUtils.ln_s(target, framework_root, force: true)
|
423
|
+
}
|
424
|
+
end
|
425
|
+
|
426
|
+
def process_binary_group(name)
|
427
|
+
cfg = @@pod_cfg[name]
|
428
|
+
proj = cfg[:project]
|
429
|
+
binary_group = proj.groups.find { |g| g.name == "Binary" }
|
430
|
+
if cfg[:binary] == true
|
431
|
+
if binary_group == nil
|
432
|
+
binary_group = proj.new_group("Binary")
|
433
|
+
binary_group.new_reference("_Frameworks/#{name}.xcframework")
|
434
|
+
proj.sort
|
435
|
+
end
|
436
|
+
else
|
437
|
+
if binary_group != nil
|
438
|
+
binary_group.remove_from_project
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
def process_xcframeworks_shell(name)
|
444
|
+
cfg = @@pod_cfg[name]
|
445
|
+
return if cfg[:binary] != true
|
446
|
+
script_path = File.join(@@ctx.sandbox_root, "Target Support Files", name, "#{name}-xcframeworks.sh")
|
447
|
+
File.open(script_path, 'w') do |f|
|
448
|
+
f.write(xcframeworks_shell(name))
|
449
|
+
end
|
450
|
+
FileUtils.chmod('a+x', script_path)
|
451
|
+
end
|
452
|
+
|
453
|
+
# 获取当前 Wi-Fi 的 SSID
|
454
|
+
def get_wifi_ssid
|
455
|
+
lines = `/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I`.split("\n").map { |line| line.strip }
|
456
|
+
target = lines.find { |x| x.start_with?("SSID: ") }
|
457
|
+
target.nil? ? "" : target.delete_prefix("SSID: ")
|
458
|
+
end
|
459
|
+
end
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
module Dongjia
|
464
|
+
class Binarization
|
465
|
+
def self.xcframeworks_shell(pod_name)
|
466
|
+
<<-DESC
|
467
|
+
#!/bin/sh
|
468
|
+
set -e
|
469
|
+
set -u
|
470
|
+
set -o pipefail
|
471
|
+
|
472
|
+
function on_error {
|
473
|
+
echo "$(realpath -mq "${0}"):$1: error: Unexpected failure"
|
474
|
+
}
|
475
|
+
trap 'on_error $LINENO' ERR
|
476
|
+
|
477
|
+
|
478
|
+
# This protects against multiple targets copying the same framework dependency at the same time. The solution
|
479
|
+
# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
|
480
|
+
RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
|
481
|
+
|
482
|
+
|
483
|
+
copy_dir()
|
484
|
+
{
|
485
|
+
local source="$1"
|
486
|
+
local destination="$2"
|
487
|
+
|
488
|
+
# Use filter instead of exclude so missing patterns don't throw errors.
|
489
|
+
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \\"- CVS/\\" --filter \\"- .svn/\\" --filter \\"- .git/\\" --filter \\"- .hg/\\" \\"${source}\\" \\"${destination}\\""
|
490
|
+
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}" "${destination}"
|
491
|
+
}
|
492
|
+
|
493
|
+
SELECT_SLICE_RETVAL=""
|
494
|
+
|
495
|
+
select_slice() {
|
496
|
+
local paths=("$@")
|
497
|
+
# Locate the correct slice of the .xcframework for the current architectures
|
498
|
+
local target_path=""
|
499
|
+
|
500
|
+
# Split archs on space so we can find a slice that has all the needed archs
|
501
|
+
local target_archs=$(echo $ARCHS | tr " " "\\n")
|
502
|
+
|
503
|
+
local target_variant=""
|
504
|
+
if [[ "$PLATFORM_NAME" == *"simulator" ]]; then
|
505
|
+
target_variant="simulator"
|
506
|
+
fi
|
507
|
+
if [[ ! -z ${EFFECTIVE_PLATFORM_NAME+x} && "$EFFECTIVE_PLATFORM_NAME" == *"maccatalyst" ]]; then
|
508
|
+
target_variant="maccatalyst"
|
509
|
+
fi
|
510
|
+
for i in ${!paths[@]}; do
|
511
|
+
local matched_all_archs="1"
|
512
|
+
for target_arch in $target_archs
|
513
|
+
do
|
514
|
+
if ! [[ "${paths[$i]}" == *"$target_variant"* ]]; then
|
515
|
+
matched_all_archs="0"
|
516
|
+
break
|
517
|
+
fi
|
518
|
+
|
519
|
+
# Verifies that the path contains the variant string (simulator or maccatalyst) if the variant is set.
|
520
|
+
if [[ -z "$target_variant" && ("${paths[$i]}" == *"simulator"* || "${paths[$i]}" == *"maccatalyst"*) ]]; then
|
521
|
+
matched_all_archs="0"
|
522
|
+
break
|
523
|
+
fi
|
524
|
+
|
525
|
+
# This regex matches all possible variants of the arch in the folder name:
|
526
|
+
# Let's say the folder name is: ios-armv7_armv7s_arm64_arm64e/CoconutLib.framework
|
527
|
+
# We match the following: -armv7_, _armv7s_, _arm64_ and _arm64e/.
|
528
|
+
# If we have a specific variant: ios-i386_x86_64-simulator/CoconutLib.framework
|
529
|
+
# We match the following: -i386_ and _x86_64-
|
530
|
+
# When the .xcframework wraps a static library, the folder name does not include
|
531
|
+
# any .framework. In that case, the folder name can be: ios-arm64_armv7
|
532
|
+
# We also match _armv7$ to handle that case.
|
533
|
+
local target_arch_regex="[_\\-]${target_arch}([\\/_\\-]|$)"
|
534
|
+
if ! [[ "${paths[$i]}" =~ $target_arch_regex ]]; then
|
535
|
+
matched_all_archs="0"
|
536
|
+
break
|
537
|
+
fi
|
538
|
+
done
|
539
|
+
|
540
|
+
if [[ "$matched_all_archs" == "1" ]]; then
|
541
|
+
# Found a matching slice
|
542
|
+
echo "Selected xcframework slice ${paths[$i]}"
|
543
|
+
SELECT_SLICE_RETVAL=${paths[$i]}
|
544
|
+
break
|
545
|
+
fi
|
546
|
+
done
|
547
|
+
}
|
548
|
+
|
549
|
+
install_library() {
|
550
|
+
local source="$1"
|
551
|
+
local name="$2"
|
552
|
+
local destination="${PODS_XCFRAMEWORKS_BUILD_DIR}/${name}"
|
553
|
+
|
554
|
+
# Libraries can contain headers, module maps, and a binary, so we'll copy everything in the folder over
|
555
|
+
|
556
|
+
local source="$binary"
|
557
|
+
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \\"- CVS/\\" --filter \\"- .svn/\\" --filter \\"- .git/\\" --filter \\"- .hg/\\" \\"${source}/*\\" \\"${destination}\\""
|
558
|
+
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}/*" "${destination}"
|
559
|
+
}
|
560
|
+
|
561
|
+
# Copies a framework to derived data for use in later build phases
|
562
|
+
install_framework()
|
563
|
+
{
|
564
|
+
local source="$1"
|
565
|
+
local name="$2"
|
566
|
+
local destination="${PODS_XCFRAMEWORKS_BUILD_DIR}/${name}"
|
567
|
+
|
568
|
+
if [ ! -d "$destination" ]; then
|
569
|
+
mkdir -p "$destination"
|
570
|
+
fi
|
571
|
+
|
572
|
+
copy_dir "$source" "$destination"
|
573
|
+
echo "Copied $source to $destination"
|
574
|
+
}
|
575
|
+
|
576
|
+
install_xcframework_library() {
|
577
|
+
local basepath="$1"
|
578
|
+
local name="$2"
|
579
|
+
local paths=("$@")
|
580
|
+
|
581
|
+
# Locate the correct slice of the .xcframework for the current architectures
|
582
|
+
select_slice "${paths[@]}"
|
583
|
+
local target_path="$SELECT_SLICE_RETVAL"
|
584
|
+
if [[ -z "$target_path" ]]; then
|
585
|
+
echo "warning: [CP] Unable to find matching .xcframework slice in '${paths[@]}' for the current build architectures ($ARCHS)."
|
586
|
+
return
|
587
|
+
fi
|
588
|
+
|
589
|
+
install_framework "$basepath/$target_path" "$name"
|
590
|
+
}
|
591
|
+
|
592
|
+
install_xcframework() {
|
593
|
+
local basepath="$1"
|
594
|
+
local name="$2"
|
595
|
+
local package_type="$3"
|
596
|
+
local paths=("$@")
|
597
|
+
|
598
|
+
# Locate the correct slice of the .xcframework for the current architectures
|
599
|
+
select_slice "${paths[@]}"
|
600
|
+
local target_path="$SELECT_SLICE_RETVAL"
|
601
|
+
if [[ -z "$target_path" ]]; then
|
602
|
+
echo "warning: [CP] Unable to find matching .xcframework slice in '${paths[@]}' for the current build architectures ($ARCHS)."
|
603
|
+
return
|
604
|
+
fi
|
605
|
+
local source="$basepath/$target_path"
|
606
|
+
|
607
|
+
local destination="${PODS_XCFRAMEWORKS_BUILD_DIR}/${name}"
|
608
|
+
|
609
|
+
if [ ! -d "$destination" ]; then
|
610
|
+
mkdir -p "$destination"
|
611
|
+
fi
|
612
|
+
|
613
|
+
copy_dir "$source/" "$destination"
|
614
|
+
|
615
|
+
echo "Copied $source to $destination"
|
616
|
+
}
|
617
|
+
|
618
|
+
install_xcframework "${PODS_ROOT}/_Frameworks/#{pod_name}.xcframework" "#{pod_name}" "framework" "ios-arm64_armv7" "ios-x86_64-simulator"
|
619
|
+
DESC
|
620
|
+
end
|
621
|
+
end
|
622
|
+
end
|
623
|
+
|
624
|
+
module Xcodeproj
|
625
|
+
class Project
|
626
|
+
def target_by_name(name)
|
627
|
+
targets.find { |t| t.name == name }
|
628
|
+
end
|
629
|
+
|
630
|
+
def group_by_name(name)
|
631
|
+
groups.find { |g| g.name == name }
|
632
|
+
end
|
633
|
+
|
634
|
+
module Object
|
635
|
+
class PBXGroup
|
636
|
+
def group_by_name(name)
|
637
|
+
groups.find { |g| g.name == name }
|
638
|
+
end
|
639
|
+
end
|
640
|
+
end
|
641
|
+
end
|
642
|
+
end
|