Module: Pod::PodGenerate::Patches::UserIntegratorPatch::ParallelIntegration
- Defined in:
- lib/cocoapods-podgenerate/patches/user_integrator_patch.rb
Instance Method Summary collapse
-
#integrate_user_targets ⇒ Object
── Optimization 1: Parallel integrate_user_targets ── 集成用户项目中的所有 Pod target(添加构建阶段、修改配置等)。.
-
#save_projects(projects) ⇒ Object
── Optimization 2: Parallel save_projects ── 保存修改后的用户项目文件。.
-
#warn_about_xcconfig_overrides ⇒ Object
── Optimization 3: Parallel warn_about_xcconfig_overrides ── 检查并警告用户项目中 xcconfig 构建设置的覆盖情况。.
Instance Method Details
#integrate_user_targets ⇒ Object
── Optimization 1: Parallel integrate_user_targets ──集成用户项目中的所有 Pod target(添加构建阶段、修改配置等)。
【竞态条件修复 H2】多个 AggregateTarget 可能属于同一个 Xcodeproj::Project 文件(例如同一个 .xcodeproj 中包含多个 native target)。TargetIntegrator#integrate! 会修改项目(添加 build phases、修改configurations),如果两个线程同时修改同一个 Xcodeproj::Project 对象,就会产生竞态条件,导致 pbxproj 文件损坏。
修复策略:
1. 按 user_project 将所有 target 分组
2. 同一个项目内的 target → 串行集成(避免竞态)
3. 不同项目之间 → 并行集成(利用多核性能)
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/cocoapods-podgenerate/patches/user_integrator_patch.rb', line 47 def integrate_user_targets target_integrators = targets_to_integrate.sort_by(&:name).map do |target| Pod::Installer::UserProjectIntegrator::TargetIntegrator.new(target, :use_input_output_paths => use_input_output_paths?) end return if target_integrators.empty? return target_integrators.each(&:integrate!) if target_integrators.size <= 1 # 按 user_project 分组:同一项目的 target 共享同一个 Xcodeproj::Project 对象 groups = target_integrators.group_by { |ti| ti.send(:target).user_project } if groups.size <= 1 # 所有 target 都属于同一项目 → 串行执行,避免竞态条件 target_integrators.each(&:integrate!) else # 不同项目 → 跨组并行,组内串行(同一项目内只有一个线程在修改) Pod::UI. "- Integrating #{target_integrators.size} targets across #{groups.size} projects in parallel" threads = groups.map do |project, integrators| Thread.new do integrators.each(&:integrate!) end end threads.each(&:join) end end |
#save_projects(projects) ⇒ Object
── Optimization 2: Parallel save_projects ──保存修改后的用户项目文件。
使用并行线程保存多个 Xcodeproj 项目以提高性能。脏项目调用 project.save 写入 pbxproj,非脏项目则 touch pbxproj 以更新文件修改时间(确保增量构建工具能正确检测变更)。FileUtils.touch 操作用 Mutex 保护,因为 touch 不是线程安全的。
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/cocoapods-podgenerate/patches/user_integrator_patch.rb', line 80 def save_projects(projects) projects = projects.uniq if projects.size <= 1 projects.each do |project| if project.dirty? project.save else FileUtils.touch(project.path + 'project.pbxproj') end end return end Pod::UI. "- Saving #{projects.size} user projects in parallel" mutex = Mutex.new threads = projects.map do |project| Thread.new do begin if project.dirty? project.save else mutex.synchronize do FileUtils.touch(project.path + 'project.pbxproj') end end rescue StandardError => e Pod::UI.warn "[cocoapods-podgenerate] Project save error: #{e.}" end end end threads.each(&:join) end |
#warn_about_xcconfig_overrides ⇒ Object
── Optimization 3: Parallel warn_about_xcconfig_overrides ──检查并警告用户项目中 xcconfig 构建设置的覆盖情况。
通过 prepend 覆盖原始方法,在 integrate! 内部被自动调用。使用 Concurrent::FixedThreadPool 线程池并行检查多个 target,池大小由 compute_pool_size 计算(CPU 核心数 - 1,范围 2..16)。如果 NameError(例如 concurrent-ruby 不可用),回退到串行执行。
注意:此方法操作的是 targets_to_integrate(AggregateTarget 数组),不同 target 属于不同项目(或部分属于同一项目),但由于只是读取xcconfig 设置并打印警告,不修改项目,因此不存在竞态条件。
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/cocoapods-podgenerate/patches/user_integrator_patch.rb', line 125 def warn_about_xcconfig_overrides targets = targets_to_integrate return if targets.empty? if targets.size <= 1 warn_single_target(targets.first) return end pool_size = compute_pool_size Pod::UI. "- Checking xcconfig overrides for #{targets.size} targets (pool: #{pool_size})" pool = Concurrent::FixedThreadPool.new(pool_size) targets.each do |aggregate_target| pool.post do warn_single_target(aggregate_target) rescue StandardError => e Pod::UI.warn "[cocoapods-podgenerate] Xcconfig warning error: #{e.}" end end pool.shutdown unless pool.wait_for_termination(Pod::PodGenerate::Parallel::ThreadPool::DEFAULT_TIMEOUT) Pod::UI.warn '[cocoapods-podgenerate] UserIntegratorPatch: timed out waiting for xcconfig override checks' end rescue NameError targets.each { |t| warn_single_target(t) } end |