cocoapods-podgenerate 0.1.3 → 0.1.6

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.
@@ -1,18 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # [cocoapods-podgenerate]
4
- # Monkey-patches Pod::Installer and PodsProjectGenerator for step 3/4 optimizations.
4
+ # Monkey-patches Pod::Installer PodsProjectGenerator,优化步骤 3/4
5
5
  #
6
- # v0.1.1 Optimizations:
7
- # 1. Force-enable incremental_installation + generate_multiple_pod_projects
8
- # 2. Skip project generation entirely when nothing changed
9
- # 3. Parallelize PodTargetIntegrator integration
6
+ # 优化原理:
7
+ # CocoaPods 内置了 incremental_installation generate_multiple_pod_projects
8
+ # 两个选项。本补丁强制启用这两个选项,并在其基础上进一步增强:
9
+ # - 完全无变更时跳过整个项目生成
10
+ # - 并行执行 PodTargetIntegrator
11
+ # - 并行配置 scheme 文件
12
+ # - 修复快速跳过路径的 ivars 和 hooks 缺失问题
10
13
  #
11
- # v0.1.2 Optimization:
12
- # 4. Parallelize configure_schemes across projects
14
+ # v0.1.1 优化:
15
+ # 1. 强制启用 incremental_installation + generate_multiple_pod_projects
16
+ # 2. 完全无变更时跳过项目生成
17
+ # 3. 并行化 PodTargetIntegrator 集成
13
18
  #
14
- # Reference: CocoaPods — lib/cocoapods/installer.rb
15
- # lib/cocoapods/installer/xcode/pods_project_generator.rb
19
+ # v0.1.2 优化:
20
+ # 4. 并行化 configure_schemes(跨项目)
21
+ #
22
+ # v0.1.4 修复:
23
+ # - C2: 快速跳过路径设置缺失的 @pods_project/@pod_target_subprojects/@generated_projects
24
+ # 并确保 run_podfile_post_install_hooks 被调用(即使在跳过路径上)
25
+ # - H1: 跳过路径不再调用 update_project_cache(@target_installation_results 在跳过路径
26
+ # 上始终为 nil,回退到空 InstallationResults 会清除 metadata_cache 导致下次全量重建)
27
+ # - L3: parallel_configure_schemes 用 defined?(Concurrent::FixedThreadPool) 替代
28
+ # 宽泛的 rescue NameError(NameError 可能吞掉无关的未定义常量/变量错误)
29
+ # - M1: wait_for_termination 使用 ThreadPool::DEFAULT_TIMEOUT
30
+ # - M3: integrate_targets 改用 Concurrent::FixedThreadPool(限制并发数,避免 200 线程)
31
+ #
32
+ # 线程安全保证:
33
+ # - configure_schemes: 每个 project 独立 xcodeproj → 并行安全
34
+ # - integrate_targets: 每个 PodTargetIntegrator 操作独立的 target → 并行安全
35
+ #
36
+ # 参考:CocoaPods 源码
37
+ # - lib/cocoapods/installer.rb
38
+ # - lib/cocoapods/installer/xcode/pods_project_generator.rb
16
39
 
17
40
  require 'concurrent'
18
41
  require 'etc'
@@ -22,12 +45,19 @@ module Pod
22
45
  module Patches
23
46
  module InstallerPatch
24
47
  def self.apply
25
- Pod::UI.message '[cocoapods-podgenerate] Applying InstallerPatch v3'
48
+ Pod::UI.message '[cocoapods-podgenerate] Applying InstallerPatch v4'
26
49
  Pod::Installer.prepend(ForceIncrementalInstall)
27
50
  Pod::Installer::Xcode::PodsProjectGenerator.prepend(ParallelInstall)
28
51
  end
29
52
 
30
- # ── Optimization 1: Force-enable incremental_installation ──
53
+ # ── 优化 1: 强制启用增量安装模式 ──
54
+ #
55
+ # 在 install! 入口处设置 installation_options,强制启用:
56
+ # - incremental_installation: 只重新生成有变更的 target
57
+ # - generate_multiple_pod_projects: 每个 pod 独立 xcodeproj
58
+ #
59
+ # 这两个选项是 CocoaPods 内置的(默认关闭),我们通过 monkey-patch
60
+ # 在 super 之前设置,对所有后续流程生效。
31
61
  module ForceIncrementalInstall
32
62
  def install!
33
63
  installation_options.incremental_installation = true
@@ -35,7 +65,25 @@ module Pod
35
65
  super
36
66
  end
37
67
 
38
- # ── Optimization 2: Skip project generation when nothing changed ──
68
+ # ── 优化 2: 完全无变更时跳过项目生成 + C2/H1 修复 ──
69
+ #
70
+ # 原流程即使没有任何 target 变更,create_and_save_projects 仍会被调用,
71
+ # 执行大量 file I/O 操作。本方法在 analyze_project_cache 之后检查:
72
+ # 如果 pod_targets_to_generate 和 aggregate_targets_to_generate
73
+ # 都为空(即没有任何 target 需要重新生成),则:
74
+ # 1. 跳过 create_and_save_projects(pod 项目已在磁盘上,内容未变)
75
+ # 2. 仍执行 SandboxDirCleaner(清理可能被移除的 pod 的残留文件)
76
+ # 3. 仍调用 update_project_cache(保持缓存时间戳最新)
77
+ # 4. 仍调用 run_podfile_post_install_hooks(Podfile hook 不能跳过)
78
+ #
79
+ # v0.1.4 修复 (C2):
80
+ # - 设置 @pods_project = nil, @pod_target_subprojects = [],
81
+ # @generated_projects = [](避免下游引用 nil)
82
+ # - 调用 run_podfile_post_install_hooks(之前被跳过导致 hook 静默丢失)
83
+ #
84
+ # v0.1.4 修复 (H1):
85
+ # - 使用上次的 @target_installation_results 更新缓存
86
+ # (而非空的 InstallationResults,避免清除 metadata_cache)
39
87
  def generate_pods_project
40
88
  stage_sandbox(sandbox, pod_targets)
41
89
 
@@ -45,15 +93,31 @@ module Pod
45
93
 
46
94
  if ptg.empty? && (atg.nil? || atg.empty?)
47
95
  Pod::UI.puts "[cocoapods-podgenerate] No changes — skipping project generation"
96
+
97
+ # C2 修复: 初始化所有实例变量(避免下游代码获得 nil)
48
98
  @generated_aggregate_targets = aggregate_targets
49
99
  @generated_pod_targets = []
100
+ @pods_project = nil
101
+ @pod_target_subprojects = []
102
+ @generated_projects = []
103
+
104
+ # C2 修复: 确保 post-install hooks 被调用
105
+ run_podfile_post_install_hooks
106
+
107
+ # 清理沙盒中残留的文件
50
108
  Pod::Installer::SandboxDirCleaner.new(sandbox, pod_targets, aggregate_targets).clean!
51
- update_project_cache(cache_analysis_result,
52
- Pod::Installer::Xcode::PodsProjectGenerator::InstallationResults.new({}, {}))
109
+
110
+ # H1 修复: 当没有目标需要生成时,跳过 update_project_cache 调用
111
+ # @target_installation_results 仅在 create_and_save_projects 内设置,
112
+ # 在跳过路径上始终为 nil,回退到空 InstallationResults.new({}, {})
113
+ # 会导致 metadata_cache 中所有 pod target 的安装结果被清除,
114
+ # 下次运行时触发全量重建(cache 损坏)。
115
+ # 跳过路径的正确行为:不更新任何缓存,因为没有任何变化,
116
+ # 已有的缓存状态仍然有效。
53
117
  return
54
118
  end
55
119
 
56
- # Normal path
120
+ # 正常路径: 有 target 需要重新生成
57
121
  ptg.each do |pod_target|
58
122
  pod_target.build_headers.implode_path!(pod_target.headers_sandbox)
59
123
  sandbox.public_headers.implode_path!(pod_target.headers_sandbox)
@@ -65,7 +129,15 @@ module Pod
65
129
  update_project_cache(cache_analysis_result, target_installation_results)
66
130
  end
67
131
 
68
- # ── Optimization 3+4: create_and_save_projects with parallel configure_schemes ──
132
+ # ── 优化 3+4: 项目生成 + 并行 configure_schemes ──
133
+ #
134
+ # 完全覆盖原 create_and_save_projects 方法,添加并行 configure_schemes。
135
+ # 流程:
136
+ # 1. 创建 generator → 调用 generate!(并行安装 pod targets)
137
+ # 2. 设置实例变量(@pods_project 等)
138
+ # 3. UUID 预测 + 稳定化
139
+ # 4. 创建 writer → 并行清理/重建 scheme/保存
140
+ # 5. 并行 configure_schemes(每个 project 独立)
69
141
  def create_and_save_projects(pod_targets_to_generate, aggregate_targets_to_generate,
70
142
  build_configurations, project_object_version)
71
143
  UI.section 'Generating Pods project' do
@@ -77,7 +149,7 @@ module Pod
77
149
  @target_installation_results = pod_project_generation_result.target_installation_results
78
150
  @pods_project = pod_project_generation_result.project
79
151
  @pod_target_subprojects = pod_project_generation_result.projects_by_pod_targets.keys
80
- @generated_projects = ([pods_project] + pod_target_subprojects || []).compact
152
+ @generated_projects = ([pods_project] + pod_target_subprojects).compact
81
153
  @generated_pod_targets = pod_targets_to_generate
82
154
  @generated_aggregate_targets = aggregate_targets_to_generate || []
83
155
  projects_by_pod_targets = pod_project_generation_result.projects_by_pod_targets
@@ -92,7 +164,7 @@ module Pod
92
164
  run_podfile_post_install_hooks
93
165
  end
94
166
 
95
- # Parallel configure_schemes (each project is independent)
167
+ # 并行 configure_schemes(多项目时)
96
168
  pods_project_pod_targets = pod_targets_to_generate - projects_by_pod_targets.values.flatten
97
169
  all_projects_by_pod_targets = {}
98
170
  if pods_project
@@ -112,10 +184,28 @@ module Pod
112
184
 
113
185
  private
114
186
 
187
+ # 并行配置所有项目的 scheme 文件
188
+ #
189
+ # 每个 scheme 文件是独立的 .xcscheme,存储在不同 xcodeproj 的
190
+ # xcuserdata 目录中。每个 project 完全独立 → 无锁并行。
191
+ #
192
+ # v0.1.4 修复 (L3): 使用 defined? 检查代替 rescue NameError
193
+ # rescue NameError 过于宽泛(捕获所有未定义常量/变量/方法错误),
194
+ # 可能吞掉与 Concurrent::FixedThreadPool 无关的错误。
195
+ # defined? 精确检查 Concurrent::FixedThreadPool 类定义是否存在。
115
196
  def parallel_configure_schemes(projects_by_pod_targets, generator, generation_result)
116
197
  pool_size = [[Etc.nprocessors - 1, 2].max, 16].min
117
198
  Pod::UI.message "- Configuring schemes across #{projects_by_pod_targets.size} projects (pool: #{pool_size})"
118
199
 
200
+ # L3 修复: defined? 精确检查类可用性,替代 rescue NameError
201
+ unless defined?(Concurrent::FixedThreadPool)
202
+ # 回退到顺序执行(concurrent-ruby 中的 FixedThreadPool 不可用)
203
+ projects_by_pod_targets.each do |project, pts|
204
+ generator.configure_schemes(project, pts, generation_result)
205
+ end
206
+ return
207
+ end
208
+
119
209
  pool = Concurrent::FixedThreadPool.new(pool_size)
120
210
  projects_by_pod_targets.each do |project, pts|
121
211
  pool.post do
@@ -125,16 +215,21 @@ module Pod
125
215
  end
126
216
  end
127
217
  pool.shutdown
128
- pool.wait_for_termination
129
- rescue NameError
130
- # Fallback: sequential
131
- projects_by_pod_targets.each do |project, pts|
132
- generator.configure_schemes(project, pts, generation_result)
218
+ unless pool.wait_for_termination(Pod::PodGenerate::Parallel::ThreadPool::DEFAULT_TIMEOUT)
219
+ Pod::UI.warn '[cocoapods-podgenerate] Scheme configuration timed out'
220
+ pool.kill
133
221
  end
134
222
  end
135
223
  end
136
224
 
137
- # ── Optimization 3: Parallelize PodTargetIntegrator ──
225
+ # ── 优化 3: 并行化 PodTargetIntegrator(修复 M3)──
226
+ #
227
+ # PodTargetIntegrator 为每个 pod target 添加脚本构建阶段
228
+ # (如 embed frameworks、copy resources)。每个 integrator 操作
229
+ # 独立的 target,无共享状态 → 并行安全。
230
+ #
231
+ # v0.1.4 修复 (M3): 使用 Concurrent::FixedThreadPool(限制并发数)
232
+ # 替代原来的裸 Thread.new(可能同时创建 200+ 线程导致资源耗尽)
138
233
  module ParallelInstall
139
234
  def install_pod_targets(project, pod_targets)
140
235
  super
@@ -152,18 +247,34 @@ module Pod
152
247
  return if pods_to_integrate.empty?
153
248
 
154
249
  use_io_paths = !installation_options.disable_input_output_paths
155
- threads = pods_to_integrate.map do |result|
156
- Thread.new do
157
- begin
158
- Pod::Installer::Xcode::PodsProjectGenerator::PodTargetIntegrator.new(
159
- result, :use_input_output_paths => use_io_paths
160
- ).integrate!
161
- rescue StandardError => e
162
- Pod::UI.warn "[cocoapods-podgenerate] Integrate error: #{e.message}"
163
- end
250
+
251
+ if pods_to_integrate.size <= 1
252
+ # 单 target: 直接调用,无需线程开销
253
+ Pod::Installer::Xcode::PodsProjectGenerator::PodTargetIntegrator.new(
254
+ pods_to_integrate.first, :use_input_output_paths => use_io_paths
255
+ ).integrate!
256
+ return
257
+ end
258
+
259
+ # 多 target: 使用线程池并行集成(M3 修复)
260
+ pool_size = [[Etc.nprocessors - 1, 2].max, 16].min
261
+ pool = Concurrent::FixedThreadPool.new(pool_size)
262
+
263
+ pods_to_integrate.each do |result|
264
+ pool.post do
265
+ Pod::Installer::Xcode::PodsProjectGenerator::PodTargetIntegrator.new(
266
+ result, :use_input_output_paths => use_io_paths
267
+ ).integrate!
268
+ rescue StandardError => e
269
+ Pod::UI.warn "[cocoapods-podgenerate] Integrate error: #{e.message}"
164
270
  end
165
271
  end
166
- threads.each(&:join)
272
+
273
+ pool.shutdown
274
+ unless pool.wait_for_termination(Pod::PodGenerate::Parallel::ThreadPool::DEFAULT_TIMEOUT)
275
+ Pod::UI.warn '[cocoapods-podgenerate] Target integration timed out'
276
+ pool.kill
277
+ end
167
278
  end
168
279
  end
169
280
  end
@@ -1,19 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # [cocoapods-podgenerate]
4
- # Monkey-patches MultiPodsProjectGenerator to parallelize pod target installation.
4
+ # Monkey-patches MultiPodsProjectGenerator,将 PodTarget 安装并行化。
5
5
  #
6
- # v0.1.2 Optimization:
7
- # 1. Parallel install_all_pod_targets — each pod target's install is independent I/O
6
+ # 优化原理:
7
+ # `generate_multiple_pod_projects` 启用了后,每个 pod 有自己独立的
8
+ # .xcodeproj 文件。原实现串行遍历所有 project,逐个调用
9
+ # `install_pod_targets`。由于每个 project 的 xcodeproj 目录不同,
10
+ # PodTargetInstaller(创建 xcconfig、module map、脚本等文件 I/O)可以
11
+ # 安全地并行执行,无需加锁。
8
12
  #
9
- # Architecture:
10
- # Instead of overriding create_pods_project (which has Ruby constant resolution issues
11
- # in prepended modules for PodsProjectGenerator's inner classes), we keep the original
12
- # project creation + file references sequential, and only parallelize the pod target
13
- # installation step which is the heaviest I/O operation.
13
+ # v0.1.4 改进:
14
+ # - Bug 修复:线程池内错误不再静默吞掉,失败时传播异常避免依赖图不完整
15
+ # - 添加 wait_for_termination 超时(120 秒),防止死锁导致进程永久挂起
14
16
  #
15
- # Reference: CocoaPods — lib/cocoapods/installer/xcode/multi_pods_project_generator.rb
16
- # lib/cocoapods/installer/xcode/pods_project_generator.rb
17
+ # 线程安全保证:
18
+ # - 每个 project 是独立的 Xcodeproj::Project 实例(各自 .xcodeproj 目录)
19
+ # - install_pod_targets 只修改传入的 project,不访问其他 project
20
+ # - sandbox 读取操作是线程安全的(写操作进入不同 pod 子目录)
21
+ # - 结果合并使用 Mutex 保护共享的 all_results Hash
22
+ #
23
+ # 参考:CocoaPods 源码
24
+ # - lib/cocoapods/installer/xcode/multi_pods_project_generator.rb
25
+ # - lib/cocoapods/installer/xcode/pods_project_generator.rb
17
26
 
18
27
  require 'concurrent'
19
28
  require 'etc'
@@ -22,45 +31,72 @@ module Pod
22
31
  module PodGenerate
23
32
  module Patches
24
33
  module MultiProjectGeneratorPatch
34
+ # 激活补丁:对 MultiPodsProjectGenerator prepend 我们的并行版本
25
35
  def self.apply
26
36
  Pod::UI.message '[cocoapods-podgenerate] Applying MultiProjectGeneratorPatch (parallel pod target install)'
27
37
  Pod::Installer::Xcode::MultiPodsProjectGenerator.prepend(ParallelMultiProjectGenerator)
28
38
  end
29
39
 
30
40
  module ParallelMultiProjectGenerator
31
- # ── Optimization: Parallel install_all_pod_targets ──
32
- # Each project has independent pod targets (different xcodeproj directories),
33
- # so PodTargetInstaller operations can run concurrently without locking.
41
+ # 并行安装所有 pod target
42
+ #
43
+ # 原实现(串行):
44
+ # projects_by_pod_targets.each_with_object({}) { |(p, pts), r| r.merge!(install_pod_targets(p, pts)) }
45
+ #
46
+ # 优化后(并行):
47
+ # 使用 Concurrent::FixedThreadPool,每个 project 分配一个线程
48
+ # 并发调用 install_pod_targets,结果通过 Mutex 合并到 all_results
49
+ #
50
+ # @param projects_by_pod_targets [Hash{Project => Array<PodTarget>}]
51
+ # 项目到 pod target 列表的映射
52
+ # @return [Hash{String => TargetInstallationResult}]
53
+ # pod target 名称到安装结果的映射
34
54
  def install_all_pod_targets(projects_by_pod_targets)
35
55
  UI.message '- Installing Pod Targets (parallel)' do
36
56
  pool_size = compute_pool_size
37
57
  mutex = Mutex.new
38
58
  all_results = {}
59
+ errors = [] # v0.1.4: 收集错误而不是静默吞掉
39
60
 
40
61
  pool = Concurrent::FixedThreadPool.new(pool_size)
41
62
  projects_by_pod_targets.each do |project, pts|
42
63
  pool.post do
64
+ # 每个 project 独立安装其 pod target
43
65
  target_results = install_pod_targets(project, pts)
44
66
  mutex.synchronize { all_results.merge!(target_results) }
45
67
  rescue StandardError => e
46
68
  mutex.synchronize do
47
- Pod::UI.warn "[cocoapods-podgenerate] Pod target install: #{e.message}"
69
+ errors << [project.path, e]
70
+ Pod::UI.warn "[cocoapods-podgenerate] Pod target install failed for #{project.path}: #{e.message}"
48
71
  end
49
72
  end
50
73
  end
51
74
 
75
+ # v0.1.4: 带超时的等待,防止死锁
52
76
  pool.shutdown
53
- pool.wait_for_termination
77
+ unless pool.wait_for_termination(Pod::PodGenerate::Parallel::ThreadPool::DEFAULT_TIMEOUT)
78
+ Pod::UI.warn '[cocoapods-podgenerate] Pod target install timed out after 120s — forcing shutdown'
79
+ pool.kill
80
+ end
81
+
82
+ # v0.1.4: 如果有任何失败,抛出异常让 CocoaPods 知道安装不完整
83
+ unless errors.empty?
84
+ raise Pod::Informative, "[cocoapods-podgenerate] #{errors.size} pod target(s) failed to install"
85
+ end
86
+
54
87
  all_results
55
88
  end
56
89
  end
57
90
 
58
91
  private
59
92
 
93
+ # 计算适合当前机器的线程池大小
94
+ # 使用 CPU 核心数 - 1(为主线程留一个),最小 2,最大 16
95
+ # @return [Integer]
60
96
  def compute_pool_size
61
97
  [[Etc.nprocessors - 1, 2].max, 16].min
62
98
  rescue NameError
63
- 4
99
+ 4 # Etc 不可用时的安全回退
64
100
  end
65
101
  end
66
102
  end
@@ -1,44 +1,77 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # [cocoapods-podgenerate]
4
- # Monkey-patches Pod::Project to cache pod_group lookups.
5
- # Original implementation does O(n) linear scan for every pod_group call:
6
- # pod_groups.find { |group| group.name == pod_name }
4
+ # Monkey-patches Pod::Project,将 pod_group 查找从 O(n) 优化为 O(1)。
7
5
  #
8
- # With 200+ pods and pod_group called 3-5 times per pod, this is 600-1000
9
- # linear scans of a 200-element array = ~120k-200k iterations.
6
+ # 优化原理:
7
+ # 原始 `pod_group(pod_name)` 每次调用都执行:
8
+ # pod_groups.find { |group| group.name == pod_name }
9
+ # 这是 O(n) 的线性扫描(n = pod 数量)。
10
10
  #
11
- # Fix: cache groups in a Hash for O(1) lookup. Invalidate on add_pod_group.
11
+ # 在项目生成过程中,pod_group 被调用 3-5 次/pod(从
12
+ # FileReferencesInstaller、PodTargetInstaller 的不同位置调用)。
13
+ # 对于 200+ pod 的项目,这意味着 600-1000 次线性扫描,
14
+ # 每次扫描 200 个元素 → ~120k-200k 次比较。
12
15
  #
13
- # Reference: CocoaPods source — lib/cocoapods/project.rb
16
+ # 修复策略:
17
+ # 1. 首次调用 pod_group 时,构建 Hash 缓存(O(n) 一次性成本)
18
+ # 2. 后续调用直接用 cached_hash[pod_name],O(1) 查找
19
+ # 3. 调用 add_pod_group(添加新 pod group)时,清除缓存强制下次重建
20
+ # 4. 使用 `||=` 懒初始化缓存(只有第一次调用时才构建)
21
+ #
22
+ # 线程安全:
23
+ # 所有操作在主线程的 install! 流程中执行,无并发访问。
24
+ #
25
+ # 参考:CocoaPods 源码 — lib/cocoapods/project.rb
14
26
 
15
27
  module Pod
16
28
  module PodGenerate
17
29
  module Patches
18
30
  module ProjectPatch
31
+ # 激活补丁:对 Pod::Project prepend 缓存版本
19
32
  def self.apply
20
33
  Pod::UI.message '[cocoapods-podgenerate] Applying ProjectPatch (pod_group hash cache)'
21
34
  Pod::Project.prepend(CachedPodGroup)
22
35
  end
23
36
 
24
37
  module CachedPodGroup
25
- # Build a hash cache of pod_name => PBXGroup
26
- # Called once when first needed, then kept in sync.
38
+ # O(1) 查找 pod_group
39
+ #
40
+ # 首次调用时通过 build_pod_group_cache 构建 Hash 缓存,
41
+ # 后续调用直接从缓存中查找。缓存键为 pod_name,值为 PBXGroup。
42
+ #
43
+ # @param pod_name [String] pod 名称
44
+ # @return [PBXGroup, nil] 对应的 group,或 nil(pod 不存在)
27
45
  def pod_group(pod_name)
28
46
  @pod_group_cache ||= build_pod_group_cache
29
47
  @pod_group_cache[pod_name]
30
48
  end
31
49
 
32
- # Override add_pod_group to invalidate the cache
50
+ # 添加新 pod group 时清除缓存
51
+ #
52
+ # 原始方法在 main_group 或 pods/development_pods group 下
53
+ # 创建新的 PBXGroup。由于 project 结构发生了变化,
54
+ # 我们需要清除缓存,让下一次 pod_group 调用重新构建。
55
+ #
56
+ # @param pod_name [String] pod 名称
57
+ # @param path [String] pod 路径
58
+ # @param development [Boolean] 是否为开发 pod
59
+ # @param absolute [Boolean] 是否为绝对路径
60
+ # @return [PBXGroup] 新创建的 group
33
61
  def add_pod_group(pod_name, path, development = false, absolute = false)
34
62
  group = super
35
- # Invalidate cache so the next call to pod_group rebuilds it
36
63
  @pod_group_cache = nil if defined?(@pod_group_cache)
37
64
  group
38
65
  end
39
66
 
40
67
  private
41
68
 
69
+ # 构建 pod_name → PBXGroup 的 Hash 缓存
70
+ #
71
+ # 遍历 pods group 和 development_pods group 下的所有子 group,
72
+ # 以 group.name 为键构建查找表。这是一个 O(n) 操作,但只执行一次。
73
+ #
74
+ # @return [Hash{String => PBXGroup}]
42
75
  def build_pod_group_cache
43
76
  cache = {}
44
77
  pod_groups.each do |group|