cocoapods-dongjia 1.1.2 → 1.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa6197291c8d0327124cdfe9a152f5a4cddc91a15fb42571ca10c175f96fa730
4
- data.tar.gz: 4e68535d83b1c174b1e01314cf00f4fecd45c0131de4fbb4b37e64ffb4504c10
3
+ metadata.gz: abe6387bbccd1ac19c893b9c384025c976cf5a8975668725670aac190b750abb
4
+ data.tar.gz: 125582ad4f0aa628467990eb2b43e32007f43043044a4a57a17331a1893bd734
5
5
  SHA512:
6
- metadata.gz: 6d3a68721994c607cace3a8bca9bd89832887ef55646f5d9950c71c23099881f7299449cfd37940201a703116819d9173f18f99aaffa4a5dc0272ff7256ef598
7
- data.tar.gz: dc481b20dc7a3505f0a089ef465a513e4e026086df1a89fe7d97563c30accab74cd6492897a8debf79645aae1ffa0ac1241bd4356584cd7b6a5567e115cda484
6
+ metadata.gz: ce36c1a22df3189675dec1775e998fbfdf2a6e413c730db99ea6abfdf90bbf8cb6af04df6d00a90b9b8ce1e7c0c65ee5e4bf1274c2290880b87a03f4b0e44fe6
7
+ data.tar.gz: d9a8b6d5b4496424efb19e4499edacaabf232cdf3069f7ec10cc554de5b2771fe2d63c2596e1e21a5055e3f3197ff3fa7227b9d54b0c31a594e43e852759f93f
@@ -1,5 +1,6 @@
1
1
  require 'cocoapods-dongjia/command/reinstall'
2
2
  require 'cocoapods-dongjia/command/install'
3
+ require 'cocoapods-dongjia/command/release'
3
4
  require 'cocoapods-dongjia/command/demo'
4
5
  require 'cocoapods-dongjia/command/strip'
5
6
  require 'cocoapods-dongjia/command/open'
@@ -1,11 +1,8 @@
1
1
  require 'cocoapods'
2
2
 
3
3
  module Pod
4
-
5
4
  class Command
6
-
7
5
  class Install < Command
8
-
9
6
  alias_method :run_retryable, :run
10
7
  def run
11
8
  begin
@@ -18,9 +15,6 @@ module Pod
18
15
  end
19
16
  end
20
17
  end
21
-
22
18
  end
23
-
24
19
  end
25
-
26
20
  end
@@ -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
- 'Umeng',
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
- puts "无效资源文件:"
172
- images.each do |img|
173
- path = Pathname.new(img.fullpath).relative_path_from(Dir.pwd).to_s
174
- puts " #{path}"
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
@@ -1,7 +1,7 @@
1
1
  module CocoapodsDongjia
2
- VERSION = "1.1.2"
2
+ VERSION = "1.1.7"
3
3
  UPDATE_DESC = <<-EOS
4
- - 修复路由抓取错误
5
- - 修复 pod strip
4
+ - 修复源码和二进制切换后的集成依赖问题
5
+ - 修复一些导致 crash 的问题
6
6
  EOS
7
7
  end
@@ -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 'dongjia_scheme_manager'
6
+ require_relative 'dongjia_binarization'
8
7
 
9
- require_relative 'helper/podfile_local_importer'
8
+ require_relative 'helper/podfile'
10
9
  require_relative 'helper/podfile_options'
11
- require_relative 'helper/podfile_warnings'
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