<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>CocoaPods on Last Stand</title><link>https://amatsuzero.github.io/LastStand/tags/cocoapods/</link><description>Recent content in CocoaPods on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sat, 02 May 2026 22:32:27 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/tags/cocoapods/index.xml" rel="self" type="application/rss+xml"/><item><title>CocoaPods 源码导读：从下载到工程集成</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E4%B8%8B%E8%BD%BD%E5%88%B0%E5%B7%A5%E7%A8%8B%E9%9B%86%E6%88%90/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E4%B8%8B%E8%BD%BD%E5%88%B0%E5%B7%A5%E7%A8%8B%E9%9B%86%E6%88%90/</guid><description>&lt;blockquote&gt;
&lt;p&gt;本文是系列第三篇，基于 CocoaPods 1.16.2 源码。上一篇我们停在 &lt;code&gt;Analyzer&lt;/code&gt; 产出 &lt;code&gt;AnalysisResult&lt;/code&gt;，本文继续走完 &lt;code&gt;download_dependencies&lt;/code&gt; → &lt;code&gt;validate_targets&lt;/code&gt; → &lt;code&gt;generate_pods_project&lt;/code&gt; → &lt;code&gt;integrate_user_project&lt;/code&gt; → &lt;code&gt;write_lockfiles&lt;/code&gt; 这五个阶段。&lt;/p&gt;
&lt;p&gt;上一篇：&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E5%91%BD%E4%BB%A4%E5%88%B0%E4%BE%9D%E8%B5%96%E6%B1%82%E8%A7%A3/"&gt;从命令到依赖求解&lt;/a&gt; · 首篇：&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E6%9E%B6%E6%9E%84%E6%80%BB%E8%A7%88/"&gt;架构总览&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一全景从-spec-到可编译的工程"&gt;一、全景：从 spec 到可编译的工程&lt;/h2&gt;
&lt;p&gt;先把本文要走的流程重新放一遍，让你带着地图读代码：&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TB
A[AnalysisResult] --&gt; B[download_dependencies]
B --&gt;|per pod| B1[PodSourceDownloader]
B1 --&gt;|命中| C1[Downloader::Cache]
B1 --&gt;|未命中| C2[cocoapods-downloader&lt;br/&gt;Git/HTTP/SVN/...]
C2 --&gt; C3[rsync → Pods/&amp;lt;name&amp;gt;/]
B --&gt;|per pod| B2[PodSourceInstaller]
B2 --&gt; B3[PodSourcePreparer&lt;br/&gt;prepare_command]
B2 --&gt; B4[PodDirCleaner&lt;br/&gt;按 spec.source_files 裁剪]
B --&gt; D[validate_targets&lt;br/&gt;TargetValidator#validate!]
D --&gt; E[generate_pods_project]
E --&gt; E1[ProjectCacheAnalyzer&lt;br/&gt;增量识别要重生成的 target]
E --&gt; E2[SinglePodsProjectGenerator#generate!]
E2 --&gt; E21[FileReferencesInstaller]
E2 --&gt; E22[PodTargetInstaller]
E2 --&gt; E23[AggregateTargetInstaller]
E2 --&gt; E24[xcconfig / modulemap / umbrella / info.plist / dummy.m]
E --&gt; E3[PodsProjectWriter#write!&lt;br/&gt;写盘前触发 Podfile post_install]
E --&gt; F[integrate_user_project]
F --&gt; F1[create_workspace&lt;br/&gt;写 .xcworkspace]
F --&gt; F2[deintegrate_removed_targets]
F --&gt; F3[TargetIntegrator#integrate!&lt;br/&gt;xcconfig / frameworks / scripts]
F --&gt; G[write_lockfiles]
G --&gt; G1[Podfile.lock]
G --&gt; G2[Pods/Manifest.lock]
G --&gt; H[perform_post_install_actions&lt;br/&gt;plugin post_install hook]
&lt;/pre&gt;
&lt;p&gt;对应的 &lt;code&gt;Installer#install!&lt;/code&gt; 片段：&lt;/p&gt;</description></item><item><title>CocoaPods 源码导读：从命令到依赖求解</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E5%91%BD%E4%BB%A4%E5%88%B0%E4%BE%9D%E8%B5%96%E6%B1%82%E8%A7%A3/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E5%91%BD%E4%BB%A4%E5%88%B0%E4%BE%9D%E8%B5%96%E6%B1%82%E8%A7%A3/</guid><description>&lt;blockquote&gt;
&lt;p&gt;本文是系列第二篇，基于 CocoaPods 1.16.2 源码。我们从 &lt;code&gt;bin/pod&lt;/code&gt; 进场，走完 CLAide 的命令分发、&lt;code&gt;Podfile&lt;/code&gt; 的 DSL 求值、&lt;code&gt;Analyzer&lt;/code&gt; 的七步分析、&lt;code&gt;Resolver + Molinillo&lt;/code&gt; 的回溯求解，最后交付 &lt;code&gt;AggregateTarget&lt;/code&gt;/&lt;code&gt;PodTarget&lt;/code&gt; 给下一篇讲的下载与集成。&lt;/p&gt;
&lt;p&gt;上一篇：&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E6%9E%B6%E6%9E%84%E6%80%BB%E8%A7%88/"&gt;架构总览&lt;/a&gt; · 下一篇：&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E4%B8%8B%E8%BD%BD%E5%88%B0%E5%B7%A5%E7%A8%8B%E9%9B%86%E6%88%90/"&gt;从下载到工程集成&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;运行示例贯穿全文：&lt;code&gt;pod install --repo-update&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一binpod16-行的入口"&gt;一、&lt;code&gt;bin/pod&lt;/code&gt;：16 行的入口&lt;/h2&gt;
&lt;p&gt;CocoaPods 的可执行文件非常薄，核心逻辑全在 &lt;code&gt;require 'cocoapods'&lt;/code&gt; 之后的 &lt;code&gt;Pod::Command.run&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# CocoaPods/bin/pod : 24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; $PROGRAM_NAME &lt;span style="color:#f92672"&gt;==&lt;/span&gt; __FILE__ &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;COCOAPODS_NO_BUNDLER&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;BUNDLE_GEMFILE&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#39;../../Gemfile&amp;#39;&lt;/span&gt;, __FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;bundler/setup&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $LOAD_PATH&lt;span style="color:#f92672"&gt;.&lt;/span&gt;unshift &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#39;../../lib&amp;#39;&lt;/span&gt;, __FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;elsif&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;COCOAPODS_NO_BUNDLER&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;cocoapods&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;STDOUT&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sync &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;CP_STDOUT_SYNC&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;TRUE&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;cocoapods&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; profile_filename &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;COCOAPODS_PROFILE&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 开 ruby-prof 做性能剖析&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; reporter&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#66d9ef"&gt;RubyProf&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;profile { &lt;span style="color:#66d9ef"&gt;Pod&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Command&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;run(&lt;span style="color:#66d9ef"&gt;ARGV&lt;/span&gt;) })&lt;span style="color:#f92672"&gt;.&lt;/span&gt;print(io)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Pod&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Command&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;run(&lt;span style="color:#66d9ef"&gt;ARGV&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里有两个工程化细节值得留意：&lt;/p&gt;</description></item><item><title>CocoaPods 源码导读：架构总览</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E6%9E%B6%E6%9E%84%E6%80%BB%E8%A7%88/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E6%9E%B6%E6%9E%84%E6%80%BB%E8%A7%88/</guid><description>&lt;blockquote&gt;
&lt;p&gt;本系列基于 &lt;strong&gt;CocoaPods 1.16.2&lt;/strong&gt;（2026 年 4 月）源码进行分析。源码仓库由 15 个 Ruby Gem 组成，本文先从整体架构与职责拆分讲起，再以 &lt;code&gt;pod install --repo-update&lt;/code&gt; 为主线绘制全景执行图，串起后续两篇专题的切入点。&lt;/p&gt;
&lt;p&gt;系列目录：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;架构总览&lt;/strong&gt;（本文）&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E5%91%BD%E4%BB%A4%E5%88%B0%E4%BE%9D%E8%B5%96%E6%B1%82%E8%A7%A3/"&gt;从命令到依赖求解&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E4%B8%8B%E8%BD%BD%E5%88%B0%E5%B7%A5%E7%A8%8B%E9%9B%86%E6%88%90/"&gt;从下载到工程集成&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一cocoapods-不是单一仓库"&gt;一、CocoaPods 不是单一仓库&lt;/h2&gt;
&lt;p&gt;很多人以为 CocoaPods 就是一个 Ruby 项目，其实官方仓库 &lt;code&gt;CocoaPods/CocoaPods&lt;/code&gt; 只是入口，真正的能力被拆成 15 个独立 gem，每个 gem 只做一件事。用 &lt;code&gt;gem dependency cocoapods&lt;/code&gt; 会看到这样的依赖拓扑：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph "入口"
A["bin/pod&lt;br/&gt;(CocoaPods gem)"]
end
subgraph "命令行框架"
B["CLAide&lt;br/&gt;Command/Arg/Option DSL"]
end
subgraph "领域模型"
C["Core&lt;br/&gt;Podfile/Podspec/Source/Lockfile"]
end
subgraph "依赖求解"
D["Molinillo&lt;br/&gt;回溯式 SAT 求解器"]
end
subgraph "下载"
E["cocoapods-downloader&lt;br/&gt;Git/HTTP/SVN/Hg/SCP"]
end
subgraph "Xcode 工程读写"
F["Xcodeproj&lt;br/&gt;pbxproj/xcconfig/workspace"]
G["Nanaimo&lt;br/&gt;ASCII plist 解析"]
end
subgraph "插件与子命令"
H["cocoapods-plugins"]
I["cocoapods-trunk&lt;br/&gt;cocoapods-search&lt;br/&gt;cocoapods-try&lt;br/&gt;cocoapods-deintegrate"]
end
subgraph "辅助"
J["cork&lt;br/&gt;彩色输出"]
K["nap&lt;br/&gt;轻量 HTTP 客户端"]
end
A --&gt; B
A --&gt; C
A --&gt; D
A --&gt; E
A --&gt; F
F --&gt; G
A -.加载.-&gt; H
H -.调用.-&gt; I
A --&gt; J
I --&gt; K
&lt;/pre&gt;
&lt;p&gt;各 gem 的一句话职责：&lt;/p&gt;</description></item></channel></rss>