<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>Shawn</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://blog.vv0x.com/</id>
  <link href="https://blog.vv0x.com/" rel="alternate"/>
  <link href="https://blog.vv0x.com/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, Shawn</rights>
  <subtitle>Welcome</subtitle>
  <title>Shawn's Blog</title>
  <updated>2026-03-19T07:20:31.951Z</updated>
  <entry>
    <author>
      <name>Shawn</name>
    </author>
    <category term="Swift" scheme="https://blog.vv0x.com/tags/Swift/"/>
    <category term="iOS" scheme="https://blog.vv0x.com/tags/iOS/"/>
    <category term="SPM" scheme="https://blog.vv0x.com/tags/SPM/"/>
    <content>
      <![CDATA[<p>Swift Package Manager（SPM）是 Swift 官方的构建与依赖管理工具。本文面向 <strong>iOS&#x2F;Swift 开发者入门与进阶</strong>，把「创建包 &#x2F; Xcode 集成 &#x2F; 添加依赖 &#x2F; 资源打包 &#x2F; 命令行工具 &#x2F; 常见坑」串成一条可直接照做的路径。</p><span id="more"></span><h2 id="TL-DR（最常用命令）"><a href="#TL-DR（最常用命令）" class="headerlink" title="TL;DR（最常用命令）"></a>TL;DR（最常用命令）</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建可执行包（命令行工具）</span></span><br><span class="line"><span class="built_in">mkdir</span> hello &amp;&amp; <span class="built_in">cd</span> hello</span><br><span class="line">swift package init --<span class="built_in">type</span> executable</span><br><span class="line"></span><br><span class="line"><span class="comment"># 构建/运行/测试</span></span><br><span class="line">swift build</span><br><span class="line">swift run</span><br><span class="line">swift <span class="built_in">test</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查当前包信息（排错时很有用）</span></span><br><span class="line">swift package describe</span><br><span class="line">swift package dump-package</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重新解析依赖（必要时）</span></span><br><span class="line">swift package resolve</span><br></pre></td></tr></table></figure><h2 id="1-新建一个可执行-Package（命令行工具）"><a href="#1-新建一个可执行-Package（命令行工具）" class="headerlink" title="1. 新建一个可执行 Package（命令行工具）"></a>1. 新建一个可执行 Package（命令行工具）</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> hello &amp;&amp; <span class="built_in">cd</span> hello</span><br><span class="line">swift package init --<span class="built_in">type</span> executable</span><br></pre></td></tr></table></figure><p>初始化后，默认结构通常是：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">hello/</span><br><span class="line">  Package.swift</span><br><span class="line">  Sources/</span><br><span class="line">    hello/</span><br><span class="line">      main.swift</span><br><span class="line">  Tests/</span><br><span class="line">    helloTests/</span><br></pre></td></tr></table></figure><p>你可以直接运行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">swift run</span><br></pre></td></tr></table></figure><h2 id="2-先搞清楚：Target、Product、Dependency-是什么"><a href="#2-先搞清楚：Target、Product、Dependency-是什么" class="headerlink" title="2. 先搞清楚：Target、Product、Dependency 是什么"></a>2. 先搞清楚：Target、Product、Dependency 是什么</h2><ul><li><strong>Dependency</strong>：你依赖的“外部包”（例如 Alamofire 的 Git 仓库）</li><li><strong>Target</strong>：你自己包里的“模块”（源码组织单位，能被其他 target 依赖）</li><li><strong>Product</strong>：对外暴露出来可被别人使用的产物（library &#x2F; executable），通常由 target 组合而来</li></ul><p>常见误区是把“外部依赖包名”当作可以直接写进 <code>dependencies: [...]</code> 的名字。更稳妥的方式是 <strong>依赖它的 product</strong>：</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.product(name: <span class="string">&quot;Alamofire&quot;</span>, package: <span class="string">&quot;Alamofire&quot;</span>)</span><br></pre></td></tr></table></figure><h2 id="3-用-Xcode-打开与运行（推荐方式）"><a href="#3-用-Xcode-打开与运行（推荐方式）" class="headerlink" title="3. 用 Xcode 打开与运行（推荐方式）"></a>3. 用 Xcode 打开与运行（推荐方式）</h2><p>现在一般不需要生成 <code>.xcodeproj</code>：<strong>直接用 Xcode 打开 <code>Package.swift</code></strong> 即可 Run &#x2F; Debug（或在目录里执行 <code>xed .</code>）。</p><blockquote><p>旧命令 <code>swift package generate-xcodeproj</code> 已经逐渐退出主流工作流；建议直接用 Xcode 打开 package。</p></blockquote><h2 id="4-在-Xcode-工程里添加-SPM-依赖（两条路）"><a href="#4-在-Xcode-工程里添加-SPM-依赖（两条路）" class="headerlink" title="4. 在 Xcode 工程里添加 SPM 依赖（两条路）"></a>4. 在 Xcode 工程里添加 SPM 依赖（两条路）</h2><h3 id="4-1-通过-Xcode-UI-添加（最常见）"><a href="#4-1-通过-Xcode-UI-添加（最常见）" class="headerlink" title="4.1 通过 Xcode UI 添加（最常见）"></a>4.1 通过 Xcode UI 添加（最常见）</h3><p>两种入口等价（也支持本地 package，选择时点 Add Local）：</p><ul><li>Xcode → File → Add Packages…</li><li>Project Settings → Project → <code>Package Dependencies</code> → “+”</li></ul><h3 id="4-2-把依赖写回-Package-swift（更可控）"><a href="#4-2-把依赖写回-Package-swift（更可控）" class="headerlink" title="4.2 把依赖写回 Package.swift（更可控）"></a>4.2 把依赖写回 <code>Package.swift</code>（更可控）</h3><p>当你的工程本身也是一个 package（或你在维护一个库）时，把依赖写进 <code>Package.swift</code> 更容易 review 与回滚。</p><h2 id="5-Package-swift：一个“可复制粘贴就能跑”的示例"><a href="#5-Package-swift：一个“可复制粘贴就能跑”的示例" class="headerlink" title="5. Package.swift：一个“可复制粘贴就能跑”的示例"></a>5. <code>Package.swift</code>：一个“可复制粘贴就能跑”的示例</h2><p>下面示例匹配默认目录结构（<code>Sources/&lt;TargetName&gt;/...</code>），并演示：</p><ul><li>一个可执行 target：<code>Hello</code></li><li>一个内部模块：<code>Core</code></li><li>一个外部依赖：<code>Alamofire</code>（用 <code>.product(...)</code> 引入）</li></ul><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// swift-tools-version: 5.8</span></span><br><span class="line"><span class="keyword">import</span> PackageDescription</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">package</span> <span class="operator">=</span> <span class="type">Package</span>(</span><br><span class="line">    name: <span class="string">&quot;Hello&quot;</span>,</span><br><span class="line">    platforms: [</span><br><span class="line">        .macOS(.v13)</span><br><span class="line">    ],</span><br><span class="line">    dependencies: [</span><br><span class="line">        .package(url: <span class="string">&quot;https://github.com/Alamofire/Alamofire.git&quot;</span>, .upToNextMajor(from: <span class="string">&quot;5.6.4&quot;</span>))</span><br><span class="line">    ],</span><br><span class="line">    targets: [</span><br><span class="line">        .executableTarget(</span><br><span class="line">            name: <span class="string">&quot;Hello&quot;</span>,</span><br><span class="line">            dependencies: [</span><br><span class="line">                <span class="string">&quot;Core&quot;</span>,</span><br><span class="line">                .product(name: <span class="string">&quot;Alamofire&quot;</span>, package: <span class="string">&quot;Alamofire&quot;</span>)</span><br><span class="line">            ]</span><br><span class="line">        ),</span><br><span class="line">        .target(</span><br><span class="line">            name: <span class="string">&quot;Core&quot;</span></span><br><span class="line">        ),</span><br><span class="line">        .testTarget(</span><br><span class="line">            name: <span class="string">&quot;CoreTests&quot;</span>,</span><br><span class="line">            dependencies: [<span class="string">&quot;Core&quot;</span>]</span><br><span class="line">        )</span><br><span class="line">    ]</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>对应的建议目录结构：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Sources/</span><br><span class="line">  Hello/</span><br><span class="line">    main.swift</span><br><span class="line">  Core/</span><br><span class="line">    Core.swift</span><br><span class="line">Tests/</span><br><span class="line">  CoreTests/</span><br></pre></td></tr></table></figure><p>如果你要做的是 <strong>iOS App&#x2F;Framework 的依赖包</strong>，通常会把 <code>.executableTarget</code> 换成 <code>.target</code> &#x2F; <code>.library</code>，并把 <code>platforms</code> 改成 <code>.iOS(.vXX)</code>（或同时支持 iOS&#x2F;macOS）。</p><h2 id="6-给-Swift-Package-添加资源（Resources）与-Bundle-module"><a href="#6-给-Swift-Package-添加资源（Resources）与-Bundle-module" class="headerlink" title="6. 给 Swift Package 添加资源（Resources）与 Bundle.module"></a>6. 给 Swift Package 添加资源（Resources）与 <code>Bundle.module</code></h2><p>SwiftPM 支持把资源打进 bundle（图片、json 等）。典型做法是把资源放进某个目录（例如 <code>Sources/Core/Resources</code>），然后在 target 配置 <code>resources</code>：</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">.target(</span><br><span class="line">    name: <span class="string">&quot;Core&quot;</span>,</span><br><span class="line">    resources: [</span><br><span class="line">        .process(<span class="string">&quot;Resources&quot;</span>)</span><br><span class="line">    ]</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>读取资源时用 <code>Bundle.module</code>（只在 package 内可用）：</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Foundation</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> url <span class="operator">=</span> <span class="type">Bundle</span>.module.url(forResource: <span class="string">&quot;config&quot;</span>, withExtension: <span class="string">&quot;json&quot;</span>)</span><br></pre></td></tr></table></figure><p>参考：<code>https://useyourloaf.com/blog/add-resources-to-swift-packages/</code></p><h2 id="7-常见问题与排错（按优先级）"><a href="#7-常见问题与排错（按优先级）" class="headerlink" title="7. 常见问题与排错（按优先级）"></a>7. 常见问题与排错（按优先级）</h2><h3 id="7-1-Xcode-命令行拉依赖很慢或失败（代理-网络）"><a href="#7-1-Xcode-命令行拉依赖很慢或失败（代理-网络）" class="headerlink" title="7.1 Xcode&#x2F;命令行拉依赖很慢或失败（代理&#x2F;网络）"></a>7.1 Xcode&#x2F;命令行拉依赖很慢或失败（代理&#x2F;网络）</h3><p>某些网络环境下 Xcode 拉取 GitHub 依赖不稳定，可以先用命令行把依赖 resolve 掉：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 按你本机代理端口调整（常见还有 http_proxy / all_proxy）</span></span><br><span class="line"><span class="built_in">export</span> https_proxy=http://127.0.0.1:1234</span><br><span class="line"></span><br><span class="line">xcodebuild -resolvePackageDependencies</span><br></pre></td></tr></table></figure><p>如果 SPM 依赖是“挂在某个 xcode project”上，可以指定 project + scheme：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xcodebuild -resolvePackageDependencies -project Kickstarter.xcodeproj -scheme Kickstarter-iOS</span><br></pre></td></tr></table></figure><p>如果你的目的是让 <strong><code>xcodebuild -resolvePackageDependencies</code> 走代理</strong>，更可靠的方式通常是给“这一次命令”设置代理环境变量（避免污染全局 git 配置）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># HTTP 代理（按你本机代理端口调整）</span></span><br><span class="line">http_proxy=http://127.0.0.1:7890 \</span><br><span class="line">https_proxy=http://127.0.0.1:7890 \</span><br><span class="line">xcodebuild -resolvePackageDependencies</span><br><span class="line"></span><br><span class="line"><span class="comment"># SOCKS5 代理（如你的代理软件提供的是 socks5）</span></span><br><span class="line">ALL_PROXY=socks5://127.0.0.1:7890 \</span><br><span class="line">xcodebuild -resolvePackageDependencies</span><br></pre></td></tr></table></figure><p>另外在部分环境下，<code>-scmProvider system</code> 会更稳定（强制使用系统的 SCM provider）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xcodebuild -resolvePackageDependencies -scmProvider system</span><br></pre></td></tr></table></figure><h3 id="7-2-xcodebuild-找不到-Xcode（CommandLineTools-被选中）"><a href="#7-2-xcodebuild-找不到-Xcode（CommandLineTools-被选中）" class="headerlink" title="7.2 xcodebuild 找不到 Xcode（CommandLineTools 被选中）"></a>7.2 <code>xcodebuild</code> 找不到 Xcode（CommandLineTools 被选中）</h3><p>报错类似：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xcode-select: error: tool &#x27;xcodebuild&#x27; requires Xcode, but active developer directory &#x27;/Library/Developer/CommandLineTools&#x27; is a command line tools instance</span><br></pre></td></tr></table></figure><p>执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> xcode-select -s /Applications/Xcode.app/Contents/Developer</span><br></pre></td></tr></table></figure><h3 id="7-3-Package-resolved-schema-version-不兼容"><a href="#7-3-Package-resolved-schema-version-不兼容" class="headerlink" title="7.3 Package.resolved schema&#x2F;version 不兼容"></a>7.3 <code>Package.resolved</code> schema&#x2F;version 不兼容</h3><p>当 Xcode 与 SwiftPM 的 <code>Package.resolved</code> 格式不兼容时，最简单的处理通常是 <strong>删除并重新解析</strong>。</p><p>常见位置：</p><ul><li><strong>在 package 仓库里</strong>：<code>.swiftpm/Package.resolved</code>（或项目根目录的 <code>Package.resolved</code>，取决于工具链&#x2F;项目类型）</li><li><strong>在 Xcode 工程&#x2F;工作区里</strong>：<code>Project.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved</code></li></ul><p>删除后再执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">swift package resolve</span><br><span class="line"><span class="comment"># 或</span></span><br><span class="line">xcodebuild -resolvePackageDependencies</span><br></pre></td></tr></table></figure><h3 id="7-4-Realm-产品名冲突（multiple-products-named-‘Realm’-‘RealmSwift’）"><a href="#7-4-Realm-产品名冲突（multiple-products-named-‘Realm’-‘RealmSwift’）" class="headerlink" title="7.4 Realm 产品名冲突（multiple products named ‘Realm’ &#x2F; ‘RealmSwift’）"></a>7.4 Realm 产品名冲突（multiple products named ‘Realm’ &#x2F; ‘RealmSwift’）</h3><p>报错类似：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">multiple products named &#x27;Realm&#x27; in: &#x27;realm-cocoa&#x27;, &#x27;realm-swift&#x27;</span><br><span class="line">multiple products named &#x27;RealmSwift&#x27; in: &#x27;realm-cocoa&#x27;, &#x27;realm-swift&#x27;</span><br></pre></td></tr></table></figure><p>常见原因是 Realm 仓库地址调整导致的重复依赖。把旧 URL 改为新仓库即可：</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 旧：</span></span><br><span class="line">.package(name: <span class="string">&quot;Realm&quot;</span>, url: <span class="string">&quot;https://github.com/realm/realm-cocoa&quot;</span>, from: <span class="string">&quot;10.5.0&quot;</span>)</span><br><span class="line"><span class="comment">// 新：</span></span><br><span class="line">.package(name: <span class="string">&quot;Realm&quot;</span>, url: <span class="string">&quot;https://github.com/realm/realm-swift&quot;</span>, from: <span class="string">&quot;10.5.0&quot;</span>)</span><br></pre></td></tr></table></figure><img src="/images/2023/spm/realm-url.png" alt="Realm repo rename" width="90%"><h2 id="8-“更新依赖”与清缓存（谨慎使用）"><a href="#8-“更新依赖”与清缓存（谨慎使用）" class="headerlink" title="8. “更新依赖”与清缓存（谨慎使用）"></a>8. “更新依赖”与清缓存（谨慎使用）</h2><p>命令行没有一个“万能的一键更新所有依赖”的命令；通常是“更新版本约束 + 重新 resolve”。当你遇到缓存&#x2F;checkout 异常，才考虑清缓存。</p><p>建议先从轻到重：</p><ul><li>在 Xcode 里 Reset Package Caches（通常在 <code>File → Packages → Reset Package Caches</code>）</li><li>删除 <code>Package.resolved</code> 并重新 resolve</li><li>最后再清理 DerivedData 与 SwiftPM 缓存（会比较重）</li></ul><p>一个“重置到能重新拉依赖”的命令集：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">rm</span> -rf ~/Library/Developer/Xcode/DerivedData/ \</span><br><span class="line">  ~/Library/Caches/org.swift.swiftpm/ \</span><br><span class="line">  ~/Library/org.swift.swiftpm/</span><br><span class="line"></span><br><span class="line"><span class="built_in">rm</span> -rf ProjectName.xcodeproj/project.xcworkspace/xcshareddata/swiftpm</span><br><span class="line"></span><br><span class="line">xcodebuild -resolvePackageDependencies</span><br></pre></td></tr></table></figure><h2 id="9-命令行工具-Keep-Alive（避免异步任务没跑完就退出）"><a href="#9-命令行工具-Keep-Alive（避免异步任务没跑完就退出）" class="headerlink" title="9. 命令行工具 Keep Alive（避免异步任务没跑完就退出）"></a>9. 命令行工具 Keep Alive（避免异步任务没跑完就退出）</h2><p>命令行程序跑到 <code>main.swift</code> 末尾就会退出，异步任务可能还没完成。常见做法是在末尾 keep alive：</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">RunLoop</span>.main.run() <span class="comment">// 或 dispatchMain()</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 在异步完成时调用 exit(EXIT_SUCCESS) 结束程序</span></span><br></pre></td></tr></table></figure><h2 id="10-常用路径速查（理解“依赖到底存哪儿了”）"><a href="#10-常用路径速查（理解“依赖到底存哪儿了”）" class="headerlink" title="10. 常用路径速查（理解“依赖到底存哪儿了”）"></a>10. 常用路径速查（理解“依赖到底存哪儿了”）</h2><ul><li>SwiftPM 缓存（git repo 存储）：<code>~/Library/Caches/org.swift.swiftpm/</code></li><li>Xcode DerivedData 下依赖 checkout：<code>~/Library/Developer/Xcode/DerivedData/ProjectName-xxxx/SourcePackages</code></li></ul><h2 id="参考链接（延伸阅读）"><a href="#参考链接（延伸阅读）" class="headerlink" title="参考链接（延伸阅读）"></a>参考链接（延伸阅读）</h2><ul><li>Package Collections：<code>https://swift.org/blog/package-collections/</code></li><li>Apple 文档：<code>https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app</code></li><li>Guide：<ul><li><code>https://www.raywenderlich.com/1993018-an-introduction-to-swift-package-manager</code></li><li><code>https://www.swiftbysundell.com/articles/building-a-command-line-tool-using-the-swift-package-manager/</code></li><li><code>https://www.fivestars.blog/articles/ultimate-guide-swift-executables/</code></li><li><code>https://stackoverflow.com/questions/31944011/how-to-prevent-a-command-line-tool-from-exiting-before-asynchronous-operation-co</code></li><li><code>https://forums.swift.org/t/xcode-environment-variables/45249</code></li><li><code>https://appcoda.com.tw/swift-package-manager/</code></li></ul></li></ul>]]>
    </content>
    <id>https://blog.vv0x.com/2023/04/15/SwiftPackageManager-GetStarted/</id>
    <link href="https://blog.vv0x.com/2023/04/15/SwiftPackageManager-GetStarted/"/>
    <published>2023-04-15T12:58:51.000Z</published>
    <summary>
      <![CDATA[<p>Swift Package Manager（SPM）是 Swift 官方的构建与依赖管理工具。本文面向 <strong>iOS&#x2F;Swift 开发者入门与进阶</strong>，把「创建包 &#x2F; Xcode 集成 &#x2F; 添加依赖 &#x2F; 资源打包 &#x2F; 命令行工具 &#x2F; 常见坑」串成一条可直接照做的路径。</p>]]>
    </summary>
    <title>Swift Package Manager 快速入门</title>
    <updated>2026-03-19T07:20:31.951Z</updated>
  </entry>
  <entry>
    <author>
      <name>Shawn</name>
    </author>
    <category term="OC" scheme="https://blog.vv0x.com/tags/OC/"/>
    <category term="读书笔记" scheme="https://blog.vv0x.com/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
    <content>
      <![CDATA[<p>《Objective-C 高级编程》读书笔记</p><span id="more"></span><p>##前言<br>命令行编译objc文件</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">clang -fobjc-arc test.m -o test # 编译简单的oc文件，启用arc</span><br><span class="line">clang -fobjc-arc -S test.m # 将test.m转成汇编 test.s</span><br><span class="line">clang -fobjc-arc -framework Foundation test.m -o test  # 编译 链接Foundation.framework</span><br><span class="line">clang -rewrite-objc test.m  # 将 oc源码转换成cpp源码</span><br><span class="line"></span><br><span class="line">clang -fobjc-arc -arch arm64 test.m # 将test.m转成arm64汇编test.s</span><br><span class="line"># 编译iPhone arm64版本</span><br><span class="line">clang -fobjc-arc -framework Foundation  test.m -o test -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.2.sdk</span><br></pre></td></tr></table></figure><h2 id="Block-本质"><a href="#Block-本质" class="headerlink" title="Block 本质"></a>Block 本质</h2><p>block可以类比函数指针，但是OC利用结构体的辅助来实现，该结构体开头为isa指针，所以可以用Object的方式管理。</p><p>以一个最简单的block.m文件为例</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">test</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">void</span> (^blk)(<span class="type">void</span>) = ^&#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;hello block\n&quot;</span>);</span><br><span class="line">    &#125;;</span><br><span class="line">    </span><br><span class="line">    blk();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>使用 <code>clang -rewrite-objc block.m</code> 将其转换为cpp，再查看block.cpp文件末尾内容</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> __<span class="title">test_block_impl_0</span> &#123;</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> __<span class="title">block_impl</span> <span class="title">impl</span>;</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> __<span class="title">test_block_desc_0</span>* <span class="title">Desc</span>;</span></span><br><span class="line">  __test_block_impl_0(<span class="type">void</span> *fp, <span class="keyword">struct</span> __test_block_desc_0 *desc, <span class="type">int</span> flags=<span class="number">0</span>) &#123;</span><br><span class="line">    impl.isa = &amp;_NSConcreteStackBlock;</span><br><span class="line">    impl.Flags = flags;</span><br><span class="line">    impl.FuncPtr = fp;</span><br><span class="line">    Desc = desc;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// block方法内容</span></span><br><span class="line"><span class="type">static</span> <span class="type">void</span> __test_block_func_0(<span class="keyword">struct</span> __test_block_impl_0 *__cself) &#123;</span><br><span class="line"></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;hello block\n&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="type">static</span> <span class="class"><span class="keyword">struct</span> __<span class="title">test_block_desc_0</span> &#123;</span></span><br><span class="line">  <span class="type">size_t</span> reserved;</span><br><span class="line">  <span class="type">size_t</span> Block_size;</span><br><span class="line">&#125; __test_block_desc_0_DATA = &#123; <span class="number">0</span>, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> __test_block_impl_0)&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// test()函数</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">test</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">void</span> (*blk)(<span class="type">void</span>) = ((<span class="type">void</span> (*)()) &amp;__test_block_impl_0((<span class="type">void</span> *)__test_block_func_0, &amp;__test_block_desc_0_DATA));</span><br><span class="line"></span><br><span class="line">    ((<span class="type">void</span> (*)(__block_impl *)) ((__block_impl *)blk)-&gt;FuncPtr)((__block_impl *)blk);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 可以在前面找到 __block_impl的定义</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> __<span class="title">block_impl</span> &#123;</span></span><br><span class="line">  <span class="type">void</span> *isa;</span><br><span class="line">  <span class="type">int</span> Flags;</span><br><span class="line">  <span class="type">int</span> Reserved;</span><br><span class="line">  <span class="type">void</span> *FuncPtr;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>分析该文件：首先blk被声明为了函数指针，指向的是强制转换的 <code>__test_block_impl_0 </code> 引用。<br><code>__test_block_impl_0 </code> 的第一个成员为 <code>__block_impl </code>，而<code>__block_impl </code>的第一个成员又是 isa，所以最终整个<code>__test_block_impl_0 </code>其实是一个OC对象，可以直接NSLog输出<code>NSLog(@&quot;blk = %@&quot;, blk); </code>处理，打印结果<code>blk = &lt;__NSGlobalBlock__: 0x100004150&gt;</code>。</p>]]>
    </content>
    <id>https://blog.vv0x.com/2020/12/26/OC%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%20-%20Block%20%E7%AC%94%E8%AE%B0/</id>
    <link href="https://blog.vv0x.com/2020/12/26/OC%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%20-%20Block%20%E7%AC%94%E8%AE%B0/"/>
    <published>2020-12-26T06:06:54.000Z</published>
    <summary>
      <![CDATA[<p>《Objective-C 高级编程》读书笔记</p>]]>
    </summary>
    <title>OC高级编程 - Block 笔记</title>
    <updated>2026-03-17T06:45:30.314Z</updated>
  </entry>
  <entry>
    <author>
      <name>Shawn</name>
    </author>
    <category term="读书笔记" scheme="https://blog.vv0x.com/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
    <content>
      <![CDATA[<p>程序员的自我修养-读书笔记</p><span id="more"></span><ul><li><p>可执行文件生成流程：<br><br>  预处理(.i) -&gt;编译(.s) -&gt;汇编(.o) -&gt;链接(a.out)</p></li><li><p>分步骤生成可执行文件：(以hello.c为例</p></li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">gcc -E hello.c -o hello.i    预处理</span><br><span class="line">gcc -S hello.i  -o hello.s   编译</span><br><span class="line">gcc -c hello.s -o hello.o   汇编，也可使用as命令 as hello.s -o hello.o</span><br><span class="line">ld -static /usr/lib/crt1.o /usr/lib/crti.o ... -L/lib hello.o  链接</span><br></pre></td></tr></table></figure><ul><li><p>链接过程主要包括：地址和空间分配，符号决议，重定位</p></li><li><p>目标文件: <br><br>源代码编译后生成目标文件(.o) 格式跟可执行文件类似，Windows下为 PE，Linux下为ELF，macOS下为Mach-O<br>动态库.dll &#x2F; .so、静态库 .a &#x2F; 、可执行文件 a.out &#x2F; .ext、目标文件.o &#x2F; .obj 都有相似的格式。<br>目标文件组织格式为：header + sections</p></li><li><p>查看文件目标文件格式使用file命令</p></li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ file hello.o    # linux-arm</span><br><span class="line">hello.o: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), not stripped</span><br><span class="line"></span><br><span class="line">$ file hello.o    # macOS-x64</span><br><span class="line">hello.o: Mach-O 64-bit object x86_64</span><br></pre></td></tr></table></figure><h3 id="查看目标文件-header-内容"><a href="#查看目标文件-header-内容" class="headerlink" title="查看目标文件 header 内容"></a>查看目标文件 header 内容</h3><details><summary>header 输出 </summary><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br></pre></td><td class="code"><pre><span class="line">$ objdump -x hello.o    # linux-arm</span><br><span class="line">hello.o:     file format elf32-littlearm</span><br><span class="line">hello.o</span><br><span class="line">architecture: arm, flags 0x00000011:</span><br><span class="line">HAS_RELOC, HAS_SYMS</span><br><span class="line">start address 0x00000000</span><br><span class="line">private flags = 5000000: [Version5 EABI]</span><br><span class="line"></span><br><span class="line">Sections:</span><br><span class="line">Idx Name          Size      VMA       LMA       File off  Algn</span><br><span class="line">  0 .text         00000064  00000000  00000000  00000034  2**2</span><br><span class="line">                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE</span><br><span class="line">  1 .data         00000008  00000000  00000000  00000098  2**2</span><br><span class="line">                  CONTENTS, ALLOC, LOAD, DATA</span><br><span class="line">  2 .bss          00000000  00000000  00000000  000000a0  2**0</span><br><span class="line">                  ALLOC</span><br><span class="line">  3 .rodata       00000004  00000000  00000000  000000a0  2**2</span><br><span class="line">                  CONTENTS, ALLOC, LOAD, READONLY, DATA</span><br><span class="line">  4 .comment      00000024  00000000  00000000  000000a4  2**0</span><br><span class="line">                  CONTENTS, READONLY</span><br><span class="line">  5 .note.GNU-stack 00000000  00000000  00000000  000000c8  2**0</span><br><span class="line">                  CONTENTS, READONLY</span><br><span class="line">  6 .ARM.attributes 0000002f  00000000  00000000  000000c8  2**0</span><br><span class="line">                  CONTENTS, READONLY</span><br><span class="line">SYMBOL TABLE:</span><br><span class="line">00000000 l    df *ABS*    00000000 hello.c</span><br><span class="line">00000000 l    d  .text    00000000 .text</span><br><span class="line">00000000 l    d  .data    00000000 .data</span><br><span class="line">00000000 l    d  .bss    00000000 .bss</span><br><span class="line">00000000 l    d  .rodata    00000000 .rodata</span><br><span class="line">00000004 l     O .data    00000004 static_int.5961</span><br><span class="line">00000000 l    d  .note.GNU-stack    00000000 .note.GNU-stack</span><br><span class="line">00000000 l    d  .comment    00000000 .comment</span><br><span class="line">00000000 l    d  .ARM.attributes    00000000 .ARM.attributes</span><br><span class="line">00000000 g     O .data    00000004 global_int</span><br><span class="line">00000000 g     F .text    0000002c foo</span><br><span class="line">00000000         *UND*    00000000 printf</span><br><span class="line">0000002c g     F .text    00000038 main</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">RELOCATION RECORDS FOR [.text]:</span><br><span class="line">OFFSET   TYPE              VALUE </span><br><span class="line">00000018 R_ARM_CALL        printf</span><br><span class="line">00000028 R_ARM_ABS32       .rodata</span><br><span class="line">00000050 R_ARM_CALL        foo</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">$ objdump -x -macho hello.o    # macOS-x64 </span><br><span class="line">hello.o:</span><br><span class="line">Relocation information (__TEXT,__text) 3 entries</span><br><span class="line">address  pcrel length extern type    scattered symbolnum/value</span><br><span class="line">0000004f True  long   True   BRANCH  False     _foo</span><br><span class="line">00000018 True  long   True   BRANCH  False     _printf</span><br><span class="line">00000011 True  long   False  SIGNED  False     3 (__TEXT,__cstring)</span><br><span class="line">Relocation information (__LD,__compact_unwind) 2 entries</span><br><span class="line">address  pcrel length extern type    scattered symbolnum/value</span><br><span class="line">00000020 False quad   False  UNSIGND False     1 (__TEXT,__text)</span><br><span class="line">00000000 False quad   False  UNSIGND False     1 (__TEXT,__text)</span><br><span class="line">Sections:</span><br><span class="line">Idx Name             Size     VMA              Type</span><br><span class="line">  0 __text           0000005c 0000000000000000 TEXT</span><br><span class="line">  1 __data           00000008 000000000000005c DATA</span><br><span class="line">  2 __cstring        00000004 0000000000000064 DATA</span><br><span class="line">  3 __compact_unwind 00000040 0000000000000068 DATA</span><br><span class="line">  4 __eh_frame       00000068 00000000000000a8 DATA</span><br><span class="line"></span><br><span class="line">SYMBOL TABLE:</span><br><span class="line">0000000000000060 l     O __DATA,__data _main.static_int</span><br><span class="line">0000000000000000 g     F __TEXT,__text _foo</span><br><span class="line">000000000000005c g     O __DATA,__data _global_int</span><br><span class="line">0000000000000030 g     F __TEXT,__text _main</span><br><span class="line">0000000000000000         *UND* _printf</span><br><span class="line">Mach header</span><br><span class="line">      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags</span><br><span class="line">MH_MAGIC_64  X86_64        ALL  0x00      OBJECT     4        600 SUBSECTIONS_VIA_SYMBOLS</span><br><span class="line">Load command 0</span><br><span class="line">      cmd LC_SEGMENT_64</span><br><span class="line">  cmdsize 472</span><br><span class="line">  segname </span><br><span class="line">   vmaddr 0x0000000000000000</span><br><span class="line">   vmsize 0x0000000000000110</span><br><span class="line">  fileoff 632</span><br><span class="line"> filesize 272</span><br><span class="line">  maxprot rwx</span><br><span class="line"> initprot rwx</span><br><span class="line">   nsects 5</span><br><span class="line">    flags (none)</span><br><span class="line">Section</span><br><span class="line">  sectname __text</span><br><span class="line">   segname __TEXT</span><br><span class="line">      addr 0x0000000000000000</span><br><span class="line">      size 0x000000000000005c</span><br><span class="line">    offset 632</span><br><span class="line">     align 2^4 (16)</span><br><span class="line">    reloff 904</span><br><span class="line">    nreloc 3</span><br><span class="line">      type S_REGULAR</span><br><span class="line">attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS</span><br><span class="line"> reserved1 0</span><br><span class="line"> reserved2 0</span><br><span class="line">Section</span><br><span class="line">  sectname __data</span><br><span class="line">   segname __DATA</span><br><span class="line">      addr 0x000000000000005c</span><br><span class="line">      size 0x0000000000000008</span><br><span class="line">    offset 724</span><br><span class="line">     align 2^2 (4)</span><br><span class="line">    reloff 0</span><br><span class="line">    nreloc 0</span><br><span class="line">      type S_REGULAR</span><br><span class="line">attributes (none)</span><br><span class="line"> reserved1 0</span><br><span class="line"> reserved2 0</span><br><span class="line">Section</span><br><span class="line">  sectname __cstring</span><br><span class="line">   segname __TEXT</span><br><span class="line">      addr 0x0000000000000064</span><br><span class="line">      size 0x0000000000000004</span><br><span class="line">    offset 732</span><br><span class="line">     align 2^0 (1)</span><br><span class="line">    reloff 0</span><br><span class="line">    nreloc 0</span><br><span class="line">      type S_CSTRING_LITERALS</span><br><span class="line">attributes (none)</span><br><span class="line"> reserved1 0</span><br><span class="line"> reserved2 0</span><br><span class="line">Section</span><br><span class="line">  sectname __compact_unwind</span><br><span class="line">   segname __LD</span><br><span class="line">      addr 0x0000000000000068</span><br><span class="line">      size 0x0000000000000040</span><br><span class="line">    offset 736</span><br><span class="line">     align 2^3 (8)</span><br><span class="line">    reloff 928</span><br><span class="line">    nreloc 2</span><br><span class="line">      type S_REGULAR</span><br><span class="line">attributes DEBUG</span><br><span class="line"> reserved1 0</span><br><span class="line"> reserved2 0</span><br><span class="line">Section</span><br><span class="line">  sectname __eh_frame</span><br><span class="line">   segname __TEXT</span><br><span class="line">      addr 0x00000000000000a8</span><br><span class="line">      size 0x0000000000000068</span><br><span class="line">    offset 800</span><br><span class="line">     align 2^3 (8)</span><br><span class="line">    reloff 0</span><br><span class="line">    nreloc 0</span><br><span class="line">      type S_COALESCED</span><br><span class="line">attributes NO_TOC STRIP_STATIC_SYMS LIVE_SUPPORT</span><br><span class="line"> reserved1 0</span><br><span class="line"> reserved2 0</span><br><span class="line">Load command 1</span><br><span class="line">       cmd LC_BUILD_VERSION</span><br><span class="line">   cmdsize 24</span><br><span class="line">  platform macos</span><br><span class="line">       sdk 10.15.6</span><br><span class="line">     minos 10.15</span><br><span class="line">    ntools 0</span><br><span class="line">Load command 2</span><br><span class="line">     cmd LC_SYMTAB</span><br><span class="line"> cmdsize 24</span><br><span class="line">  symoff 944</span><br><span class="line">   nsyms 5</span><br><span class="line">  stroff 1024</span><br><span class="line"> strsize 52</span><br><span class="line">Load command 3</span><br><span class="line">            cmd LC_DYSYMTAB</span><br><span class="line">        cmdsize 80</span><br><span class="line">      ilocalsym 0</span><br><span class="line">      nlocalsym 1</span><br><span class="line">     iextdefsym 1</span><br><span class="line">     nextdefsym 3</span><br><span class="line">      iundefsym 4</span><br><span class="line">      nundefsym 1</span><br><span class="line">         tocoff 0</span><br><span class="line">           ntoc 0</span><br><span class="line">      modtaboff 0</span><br><span class="line">        nmodtab 0</span><br><span class="line">   extrefsymoff 0</span><br><span class="line">    nextrefsyms 0</span><br><span class="line"> indirectsymoff 0</span><br><span class="line">  nindirectsyms 0</span><br><span class="line">      extreloff 0</span><br><span class="line">        nextrel 0</span><br><span class="line">      locreloff 0</span><br><span class="line">        nlocrel 0</span><br></pre></td></tr></table></figure></details><h3 id="查看目标文件size"><a href="#查看目标文件size" class="headerlink" title="查看目标文件size"></a>查看目标文件size</h3><details><summary>size 结果 </summary><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$ size hello.o    # linux-arm</span><br><span class="line">   text      data        bss        dec        hex    filename</span><br><span class="line">    104          8          0        112        70    hello.o</span><br><span class="line"></span><br><span class="line">$ size hello.o    # macOS-x64</span><br><span class="line">__TEXT    __DATA    __OBJC    others    dec    hex</span><br><span class="line">200    8    0    64    272    110</span><br></pre></td></tr></table></figure></details><h3 id="查看目标文件结构"><a href="#查看目标文件结构" class="headerlink" title="查看目标文件结构"></a>查看目标文件结构</h3><p>不同的平台，目标文件结构不同，生成的section也有差异，但是最基本的代码段.text、数据段.data、只读段.rodata &#x2F; __cstring 都是通用的， bss段为未初始化全局或静态变量，默认都为0，不占据目标文件空间</p><details><summary>objdump -h 结果 </summary><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">$ objdump -h hello.o   # linux-arm</span><br><span class="line">hello.o:     file format elf32-littlearm</span><br><span class="line">Sections:</span><br><span class="line">Idx Name          Size      VMA       LMA       File off  Algn</span><br><span class="line">  0 .text         00000064  00000000  00000000  00000034  2**2</span><br><span class="line">                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE</span><br><span class="line">  1 .data         00000008  00000000  00000000  00000098  2**2</span><br><span class="line">                  CONTENTS, ALLOC, LOAD, DATA</span><br><span class="line">  2 .bss          00000000  00000000  00000000  000000a0  2**0</span><br><span class="line">                  ALLOC</span><br><span class="line">  3 .rodata       00000004  00000000  00000000  000000a0  2**2</span><br><span class="line">                  CONTENTS, ALLOC, LOAD, READONLY, DATA</span><br><span class="line">  4 .comment      00000024  00000000  00000000  000000a4  2**0</span><br><span class="line">                  CONTENTS, READONLY</span><br><span class="line">  5 .note.GNU-stack 00000000  00000000  00000000  000000c8  2**0</span><br><span class="line">                  CONTENTS, READONLY</span><br><span class="line">  6 .ARM.attributes 0000002f  00000000  00000000  000000c8  2**0</span><br><span class="line">                  CONTENTS, READONLY</span><br><span class="line"></span><br><span class="line">$ objdump -h hello.o     # macOS-x64</span><br><span class="line">hello.o:    file format Mach-O 64-bit x86-64</span><br><span class="line">Sections:</span><br><span class="line">Idx Name             Size     VMA              Type</span><br><span class="line">  0 __text           0000005c 0000000000000000 TEXT</span><br><span class="line">  1 __data           00000008 000000000000005c DATA</span><br><span class="line">  2 __cstring        00000004 0000000000000064 DATA</span><br><span class="line">  3 __compact_unwind 00000040 0000000000000068 DATA</span><br><span class="line">  4 __eh_frame       00000068 00000000000000a8 DATA</span><br></pre></td></tr></table></figure></details><h3 id="查看目标文件内容，并反编译汇编代码"><a href="#查看目标文件内容，并反编译汇编代码" class="headerlink" title="查看目标文件内容，并反编译汇编代码"></a>查看目标文件内容，并反编译汇编代码</h3><details><summary>objdump -s -d 结果 </summary><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br></pre></td><td class="code"><pre><span class="line">$ objdump -s -d hello.o   # linux-arm</span><br><span class="line">hello.o:     file format elf32-littlearm</span><br><span class="line"></span><br><span class="line">Contents of section .text:</span><br><span class="line"> 0000 00482de9 04b08de2 08d04de2 08000be5  .H-.......M.....</span><br><span class="line"> 0010 08101be5 0c009fe5 feffffeb 0000a0e1  ................</span><br><span class="line"> 0020 04d04be2 0088bde8 00000000 00482de9  ..K..........H-.</span><br><span class="line"> 0030 04b08de2 08d04de2 0130a0e3 08300be5  ......M..0...0..</span><br><span class="line"> 0040 08201be5 0c301be5 033082e0 0300a0e1  . ...0...0......</span><br><span class="line"> 0050 feffffeb 0c301be5 0300a0e1 04d04be2  .....0........K.</span><br><span class="line"> 0060 0088bde8                             ....            </span><br><span class="line">Contents of section .data:</span><br><span class="line"> 0000 a5000000 5a000000                    ....Z...        </span><br><span class="line">Contents of section .rodata:</span><br><span class="line"> 0000 256c640a 00                          %ld..           </span><br><span class="line">Contents of section .comment:</span><br><span class="line"> 0000 00474343 3a202852 61737062 69616e20  .GCC: (Raspbian </span><br><span class="line"> 0010 382e332e 302d362b 72706931 2920382e  8.3.0-6+rpi1) 8.</span><br><span class="line"> 0020 332e3000                             3.0.            </span><br><span class="line">Contents of section .ARM.attributes:</span><br><span class="line"> 0000 412e0000 00616561 62690001 24000000  A....aeabi..$...</span><br><span class="line"> 0010 05360006 06080109 010a0212 04140115  .6..............</span><br><span class="line"> 0020 01170318 0119011a 021c011e 062201    .............&quot;. </span><br><span class="line"></span><br><span class="line">Disassembly of section .text:</span><br><span class="line"></span><br><span class="line">00000000 &lt;foo&gt;:</span><br><span class="line">   0:    e92d4800     push    &#123;fp, lr&#125;</span><br><span class="line">   4:    e28db004     add    fp, sp, #4</span><br><span class="line">   8:    e24dd008     sub    sp, sp, #8</span><br><span class="line">   c:    e50b0008     str    r0, [fp, #-8]</span><br><span class="line">  10:    e51b1008     ldr    r1, [fp, #-8]</span><br><span class="line">  14:    e59f000c     ldr    r0, [pc, #12]    ; 28 &lt;foo+0x28&gt;</span><br><span class="line">  18:    ebfffffe     bl    0 &lt;printf&gt;</span><br><span class="line">  1c:    e1a00000     nop            ; (mov r0, r0)</span><br><span class="line">  20:    e24bd004     sub    sp, fp, #4</span><br><span class="line">  24:    e8bd8800     pop    &#123;fp, pc&#125;</span><br><span class="line">  28:    00000000     .word    0x00000000</span><br><span class="line"></span><br><span class="line">0000002c &lt;main&gt;:</span><br><span class="line">  2c:    e92d4800     push    &#123;fp, lr&#125;</span><br><span class="line">  30:    e28db004     add    fp, sp, #4</span><br><span class="line">  34:    e24dd008     sub    sp, sp, #8</span><br><span class="line">  38:    e3a03001     mov    r3, #1</span><br><span class="line">  3c:    e50b3008     str    r3, [fp, #-8]</span><br><span class="line">  40:    e51b2008     ldr    r2, [fp, #-8]</span><br><span class="line">  44:    e51b300c     ldr    r3, [fp, #-12]</span><br><span class="line">  48:    e0823003     add    r3, r2, r3</span><br><span class="line">  4c:    e1a00003     mov    r0, r3</span><br><span class="line">  50:    ebfffffe     bl    0 &lt;foo&gt;</span><br><span class="line">  54:    e51b300c     ldr    r3, [fp, #-12]</span><br><span class="line">  58:    e1a00003     mov    r0, r3</span><br><span class="line">  5c:    e24bd004     sub    sp, fp, #4</span><br><span class="line">  60:    e8bd8800     pop    &#123;fp, pc&#125;</span><br><span class="line"></span><br><span class="line">$ objdump -s -d hello.o    # macOS-x64</span><br><span class="line">hello.o:    file format Mach-O 64-bit x86-64</span><br><span class="line"></span><br><span class="line">Contents of section __text:</span><br><span class="line"> 0000 554889e5 4883ec10 897dfc8b 75fc488d  UH..H....&#125;..u.H.</span><br><span class="line"> 0010 3d4f0000 00b000e8 00000000 4883c410  =O..........H...</span><br><span class="line"> 0020 5dc3662e 0f1f8400 00000000 0f1f4000  ].f...........@.</span><br><span class="line"> 0030 554889e5 4883ec10 c745fc00 000000c7  UH..H....E......</span><br><span class="line"> 0040 45f80100 00008b45 f80345f4 89c7e800  E......E..E.....</span><br><span class="line"> 0050 0000008b 45f44883 c4105dc3           ....E.H...].</span><br><span class="line">Contents of section __data:</span><br><span class="line"> 005c a5000000 5a000000                    ....Z...</span><br><span class="line">Contents of section __cstring:</span><br><span class="line"> 0064 25640a00                             %d..</span><br><span class="line">Contents of section __compact_unwind:</span><br><span class="line"> 0068 00000000 00000000 22000000 00000001  ........&quot;.......</span><br><span class="line"> 0078 00000000 00000000 00000000 00000000  ................</span><br><span class="line"> 0088 30000000 00000000 2c000000 00000001  0.......,.......</span><br><span class="line"> 0098 00000000 00000000 00000000 00000000  ................</span><br><span class="line">Contents of section __eh_frame:</span><br><span class="line"> 00a8 14000000 00000000 017a5200 01781001  .........zR..x..</span><br><span class="line"> 00b8 100c0708 90010000 24000000 1c000000  ........$.......</span><br><span class="line"> 00c8 38ffffff ffffffff 22000000 00000000  8.......&quot;.......</span><br><span class="line"> 00d8 00410e10 8602430d 06000000 00000000  .A....C.........</span><br><span class="line"> 00e8 24000000 44000000 40ffffff ffffffff  $...D...@.......</span><br><span class="line"> 00f8 2c000000 00000000 00410e10 8602430d  ,........A....C.</span><br><span class="line"> 0108 06000000 00000000                    ........</span><br><span class="line"></span><br><span class="line">Disassembly of section __TEXT,__text:</span><br><span class="line"></span><br><span class="line">0000000000000000 _foo:</span><br><span class="line">       0: 55                               pushq    %rbp</span><br><span class="line">       1: 48 89 e5                         movq    %rsp, %rbp</span><br><span class="line">       4: 48 83 ec 10                      subq    $16, %rsp</span><br><span class="line">       8: 89 7d fc                         movl    %edi, -4(%rbp)</span><br><span class="line">       b: 8b 75 fc                         movl    -4(%rbp), %esi</span><br><span class="line">       e: 48 8d 3d 4f 00 00 00             leaq    79(%rip), %rdi</span><br><span class="line">      15: b0 00                            movb    $0, %al</span><br><span class="line">      17: e8 00 00 00 00                   callq    0 &lt;_foo+0x1c&gt;</span><br><span class="line">      1c: 48 83 c4 10                      addq    $16, %rsp</span><br><span class="line">      20: 5d                               popq    %rbp</span><br><span class="line">      21: c3                               retq</span><br><span class="line">      22: 66 2e 0f 1f 84 00 00 00 00 00    nopw    %cs:(%rax,%rax)</span><br><span class="line">      2c: 0f 1f 40 00                      nopl    (%rax)</span><br><span class="line"></span><br><span class="line">0000000000000030 _main:</span><br><span class="line">      30: 55                               pushq    %rbp</span><br><span class="line">      31: 48 89 e5                         movq    %rsp, %rbp</span><br><span class="line">      34: 48 83 ec 10                      subq    $16, %rsp</span><br><span class="line">      38: c7 45 fc 00 00 00 00             movl    $0, -4(%rbp)</span><br><span class="line">      3f: c7 45 f8 01 00 00 00             movl    $1, -8(%rbp)</span><br><span class="line">      46: 8b 45 f8                         movl    -8(%rbp), %eax</span><br><span class="line">      49: 03 45 f4                         addl    -12(%rbp), %eax</span><br><span class="line">      4c: 89 c7                            movl    %eax, %edi</span><br><span class="line">      4e: e8 00 00 00 00                   callq    0 &lt;_main+0x23&gt;</span><br><span class="line">      53: 8b 45 f4                         movl    -12(%rbp), %eax</span><br><span class="line">      56: 48 83 c4 10                      addq    $16, %rsp</span><br><span class="line">      5a: 5d                               popq    %rbp</span><br><span class="line">      5b: c3                               retq</span><br></pre></td></tr></table></figure></details><h3 id="hello-c源码"><a href="#hello-c源码" class="headerlink" title="hello.c源码"></a>hello.c源码</h3><details><summary> hello.c </summary><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> global_int = <span class="number">0xa5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">foo</span><span class="params">(<span class="type">int</span> i)</span></span><br><span class="line">&#123;</span><br><span class="line">     <span class="built_in">printf</span>(<span class="string">&quot;%d\n&quot;</span>, i);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">(<span class="type">void</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">     <span class="type">static</span> <span class="type">int</span> static_int = <span class="number">0x5a</span>;</span><br><span class="line"></span><br><span class="line">     <span class="type">int</span> b = <span class="number">1</span>;</span><br><span class="line">     <span class="type">int</span> c;</span><br><span class="line"></span><br><span class="line">     foo(b + c);</span><br><span class="line"></span><br><span class="line">     <span class="keyword">return</span> c;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></details>]]>
    </content>
    <id>https://blog.vv0x.com/2020/12/26/%E7%A8%8B%E5%BA%8F%E5%91%98%E7%9A%84%E8%87%AA%E6%88%91%E4%BF%AE%E5%85%BB-%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-%E7%9B%AE%E6%A0%87%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F/</id>
    <link href="https://blog.vv0x.com/2020/12/26/%E7%A8%8B%E5%BA%8F%E5%91%98%E7%9A%84%E8%87%AA%E6%88%91%E4%BF%AE%E5%85%BB-%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-%E7%9B%AE%E6%A0%87%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F/"/>
    <published>2020-12-26T02:41:45.000Z</published>
    <summary>
      <![CDATA[<p>程序员的自我修养-读书笔记</p>]]>
    </summary>
    <title>程序员的自我修养-读书笔记-目标文件格式</title>
    <updated>2026-03-17T06:43:04.547Z</updated>
  </entry>
  <entry>
    <author>
      <name>Shawn</name>
    </author>
    <category term="iOS" scheme="https://blog.vv0x.com/tags/iOS/"/>
    <content>
      <![CDATA[<p>广告推送无处不在，关联性也很高，时长让人有一种被盯着的感觉。。</p><span id="more"></span><p><img src="/images/202006/idfa-uuid.png"></p><p>建议设置： iPhone设置 -&gt;隐私-&gt;广告：<br><img src="/images/202006/iPhone-Settings-privacy-ad.png"></p><ol><li>首先杀掉所有app的后台，然后还原广告标识符，打开几个app，再还原广告标识符，再打开几个其它app，如此循环知道所以的app都打开一遍。这么做的目的是为了防止某些app缓存idfa标识，并且某些广告联盟app可能会共享idfa。</li><li>然后将”限制广告跟踪”选项打开，这样app拿到的idfa 就是全0啦<br><img src="/images/202006/idfa-open-restrict.png"></li></ol><p>另外提一句，开启”限制广告追踪”之后再关闭，拿到的idfa也是会变化的</p>]]>
    </content>
    <id>https://blog.vv0x.com/2020/06/04/iPhone-AD-Restrict/</id>
    <link href="https://blog.vv0x.com/2020/06/04/iPhone-AD-Restrict/"/>
    <published>2020-06-04T03:35:15.000Z</published>
    <summary>
      <![CDATA[<p>广告推送无处不在，关联性也很高，时长让人有一种被盯着的感觉。。</p>]]>
    </summary>
    <title>iPhone限制IDFA广告标识</title>
    <updated>2026-03-17T06:46:05.343Z</updated>
  </entry>
  <entry>
    <author>
      <name>Shawn</name>
    </author>
    <category term="iOS" scheme="https://blog.vv0x.com/tags/iOS/"/>
    <category term="Xcode" scheme="https://blog.vv0x.com/tags/Xcode/"/>
    <category term="Developer" scheme="https://blog.vv0x.com/tags/Developer/"/>
    <category term="Project" scheme="https://blog.vv0x.com/tags/Project/"/>
    <content>
      <![CDATA[<p>项目经过长期维护后，基本会产生大量的无用代码和资源。近期对公司长达7年的项目进行了一次清理，简单记录一下。</p><span id="more"></span><p>这会造成很多问题： </p><ul><li>首先最明显的影响是项目打包之后会无端增加ipa体积</li><li>同时也会影响build和archive速度，代码编译和资源打包都是极耗费时间的操作</li><li>另外过多的无用代码和资源，会导致项目配置文件非常庞大，达到几MB甚至几十MB，尤其一个项目多个target的情况。项目文件过大的后果就是：对项目配置进行更改的时候，经常会菊花转半天，比如点击一下”Build Phases”。。。<br><img src="/images/202006/xcode_project_size.png" alt="project size"></li></ul><h3 id="项目清理"><a href="#项目清理" class="headerlink" title="项目清理"></a>项目清理</h3><p>项目清理注意包括以下这些内容：</p><ol><li>清理重复资源：由于Xcode最开始并没有使用.xcassets 来管理资源，在引入xcassets方式管理之后，有部分资源仍以传统的方式存在于project中，这里使用的方法是借助文件查重工具<a href="https://apps.apple.com/cn/app/duplicate-file-finder-remover/id1032755628?l=en&mt=12">Duplicate File Finder Remover</a>进行排查，然后按需清理即可</li><li>清理无效类：借助工具<a href="https://github.com/dblock/fui">fui</a></li><li>无效资源文件清理：借助工具<a href="https://github.com/tinymind/LSUnusedResources">LSUnusedResources</a>，注意如果是非xcassets资源，不可以直接在工具里删除，而应该去Xcode中删除，另外使用特殊格式引用的资源，也会被当成无效资源列出，要特别处理。</li></ol><h3 id="project-pbxproj文件瘦身"><a href="#project-pbxproj文件瘦身" class="headerlink" title="project.pbxproj文件瘦身"></a>project.pbxproj文件瘦身</h3><ul><li>更改相对引用为文件夹引用</li><li>清理无效资源和无效代码</li><li>使用CocoaPods&#x2F;Carthage&#x2F;SwiftPackageManager工具来管理第三方库</li><li>模块化功能代码，引用其动态&#x2F;静态库，同时该方法也能缩短编译时间，提高项目可维护性和灵活性</li></ul><h3 id="项目维护建议"><a href="#项目维护建议" class="headerlink" title="项目维护建议"></a>项目维护建议</h3><ul><li>功能改版完成之后，清理该功能对应的过期资源，同时清理老代码。</li><li></li></ul>]]>
    </content>
    <id>https://blog.vv0x.com/2020/06/03/iOS-dev-rules_project/</id>
    <link href="https://blog.vv0x.com/2020/06/03/iOS-dev-rules_project/"/>
    <published>2020-06-03T15:42:33.000Z</published>
    <summary>
      <![CDATA[<p>项目经过长期维护后，基本会产生大量的无用代码和资源。近期对公司长达7年的项目进行了一次清理，简单记录一下。</p>]]>
    </summary>
    <title>iOS开发-Xcode项目可持续维护</title>
    <updated>2024-02-14T01:27:37.651Z</updated>
  </entry>
  <entry>
    <author>
      <name>Shawn</name>
    </author>
    <category term="iOS" scheme="https://blog.vv0x.com/tags/iOS/"/>
    <category term="Xcode Server" scheme="https://blog.vv0x.com/tags/Xcode-Server/"/>
    <category term="CI/CD" scheme="https://blog.vv0x.com/tags/CI-CD/"/>
    <content>
      <![CDATA[<p>Xcode Server配置，新手向</p><span id="more"></span><h2 id="背景："><a href="#背景：" class="headerlink" title="背景："></a>背景：</h2><p>iOS手机安装测试包比较麻烦，不像其它平台，丢个安装包就完事了，如果需要进行多设备测试，QA送一堆手机给你，iOSer内心一定是崩溃的。</p><h2 id="Server配置"><a href="#Server配置" class="headerlink" title="Server配置"></a>Server配置</h2><h2 id="⚠️注意事项："><a href="#⚠️注意事项：" class="headerlink" title="⚠️注意事项："></a>⚠️注意事项：</h2><ul><li>配置之前先设置好server端hostname，如果你的hostname是类似于“某某的MacPro”，hostname是大串拼音，输入地址的时候会有点崩溃，而且如果你XCS设置好之后再来重设hostname，又会导致Xcode生成的本地证书跟域名不匹配的问题。</li><li>Target的Product Name使用英文！ 切记不要用中文，否则即使你安装了Profile，允许了证书，但最终还是没法Install, iOS12之前的设备提示”无法连接到server.local”，iOS13则点击没有任何反应，具体原因未知，猜测可能是最终的ipa为 “某某.ipa” 带中文造成的。</li></ul>]]>
    </content>
    <id>https://blog.vv0x.com/2020/01/01/Xcode-Server%E9%83%A8%E7%BD%B2%E5%8F%8A%E4%BD%BF%E7%94%A8/</id>
    <link href="https://blog.vv0x.com/2020/01/01/Xcode-Server%E9%83%A8%E7%BD%B2%E5%8F%8A%E4%BD%BF%E7%94%A8/"/>
    <published>2020-01-01T06:22:59.000Z</published>
    <summary>
      <![CDATA[<p>Xcode Server配置，新手向</p>]]>
    </summary>
    <title>Xcode Server部署及使用</title>
    <updated>2026-03-17T06:43:31.310Z</updated>
  </entry>
</feed>
