mcpField
A
axiom-build-debugging

axiom-build-debugging

github.com/charleswiltgen开发1.2k179 次安装今天更新
代码仓库

关于 axiom-build-debugging

axiom-build-debugging 是面向 iOS 开发者的 Xcode 构建故障排查技能,优先检查依赖解析,并提供 SPM、CocoaPods、构建设置及 CI 差异的诊断方法。

主要功能

  1. 01排查 SPM 解析与缓存问题
  2. 02调查 CocoaPods 冲突和链接错误
  3. 03查找重复的目标成员关系
  4. 04检查框架搜索路径
  5. 05比较本地与 CI 构建环境

适用场景

  1. 01解决添加包后出现的“No such module”
  2. 02追查重复生成输出文件的构建错误
  3. 03排查 CocoaPods 安装成功但构建失败
  4. 04比较 Mac 与 CI 上不同的构建结果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/charleswiltgen/axiom --skill axiom-build-debugging

安装后在 Claude Code 中输入/axiom-build-debugging确认已加载。

详细介绍

构建调试

概述

在归咎于代码之前,先检查依赖项。核心原则:80% 的持续性构建失败都是依赖项解析问题(CocoaPods、SPM、框架冲突),而不是代码错误。

示例提示词

以下是开发者实际会提出的问题,本技能旨在解答这些问题:

1. “我添加了一个 Swift Package,但遇到了 ‘No such module’ 错误。这个包在我的 Xcode 项目中,但无法编译。”

→ 本技能涵盖 SPM 解析工作流、清理包缓存以及诊断框架搜索路径

2. “构建失败,并提示同一个输出文件由 ‘Multiple commands produce’ 生成。我该如何找出哪些文件重复了?”

→ 本技能演示如何识别重复的目标成员资格,并解决构建设置中的文件冲突

3. “CocoaPods 已成功安装依赖项,但构建仍然失败。我该如何调试 CocoaPods 问题?”

→ 本技能涵盖 Podfile.lock 冲突解决、链接错误和版本约束调试

4. “我的构建在 Mac 上正常,但在 CI 服务器上失败。两台机器都安装了最新版 Xcode。有什么不同?”

→ 本技能解释依赖项缓存差异、特定于环境的路径以及可复现构建策略

5. “我遇到了框架版本冲突,但不知道是哪个依赖项导致的。我该如何解决?”

→ 本技能演示如何分析依赖关系图,以及如何为复杂依赖关系树解决版本约束问题


危险信号 — 依赖项/构建问题

如果看到以下任意情况,请怀疑是依赖项问题:

  • 添加包后出现 “No such module”
  • 同一个输出文件出现 “Multiple commands produce”
  • 构建在一台机器上成功,在另一台机器上失败
  • CocoaPods 安装成功,但构建失败
  • SPM 解析耗时过长或超时
  • 错误日志中出现框架版本冲突

快速决策树

Build failing?
├─ "No such module XYZ"?
│  ├─ After adding SPM package?
│  │  └─ Clean build folder + reset package caches
│  ├─ After pod install?
│  │  └─ Check Podfile.lock conflicts
│  └─ Framework not found?
│     └─ Check FRAMEWORK_SEARCH_PATHS
├─ "Multiple commands produce"?
│  └─ Duplicate files in target membership
├─ SPM resolution hangs?
│  └─ Clear package caches + derived data
└─ Version conflicts?
   └─ Use dependency resolution strategies below

常见构建问题

问题 1:未找到 SPM 包

症状:添加 Swift Package 后出现 “No such module PackageName”

❌ 错误做法:

# Rebuilding without cleaning
xcodebuild build

✅ 正确做法:

# Reset package caches first
rm -rf ~/Library/Developer/Xcode/DerivedData
rm -rf ~/Library/Caches/org.swift.swiftpm

# Reset packages in project
xcodebuild -resolvePackageDependencies

# Clean build
xcodebuild clean build -scheme YourScheme
问题 2:CocoaPods 冲突

症状:Pod install 成功,但构建因框架错误而失败

检查 Podfile.lock:

# See what versions were actually installed
cat Podfile.lock | grep -A 2 "PODS:"

# Compare with Podfile requirements
cat Podfile | grep "pod "

解决版本冲突:

# Podfile - be explicit about versions
pod 'Alamofire', '~> 5.8.0'  # Not just 'Alamofire'
pod 'SwiftyJSON', '5.0.1'     # Exact version if needed

清理并重新安装:

# Remove all pods
rm -rf Pods/
rm Podfile.lock

# Reinstall
pod install

# Open workspace (not project!)
open YourApp.xcworkspace
问题 3:Multiple Commands Produce 错误

症状:“Multiple commands produce '/path/to/file'”

原因:同一文件被添加到多个目标或构建阶段

解决方法:

  1. 打开 Xcode
  2. 在导航器中选择文件
  3. 文件检查器 → 目标成员资格
  4. 取消勾选重复的目标
  5. 或者:构建阶段 → 复制 Bundle 资源 → 移除重复项
问题 4:框架搜索路径

症状:“Framework not found” 或 “Linker command failed”

检查构建设置:

# Show all build settings
xcodebuild -showBuildSettings -scheme YourScheme | grep FRAMEWORK_SEARCH_PATHS

在 Xcode 中解决:

  1. 目标 → 构建设置
  2. 搜索 “Framework Search Paths”
  3. 添加路径:$(PROJECT_DIR)/Frameworks(递归)
  4. 或添加 $(inherited),以继承项目设置
问题 5:SPM 版本冲突

症状:包解析因版本冲突而失败

查看依赖关系图:

# In project directory
swift package show-dependencies

# Or see resolved versions
cat Package.resolved

解决冲突:

// Package.swift - be explicit
.package(url: "https://github.com/owner/repo", exact: "1.2.3")  // Exact version
.package(url: "https://github.com/owner/repo", from: "1.2.0")   // Minimum version
.package(url: "https://github.com/owner/repo", .upToNextMajor(from: "1.0.0"))  // SemVer

重置解析:

# Clear package caches
rm -rf .build
rm Package.resolved

# Re-resolve
swift package resolve

依赖项解析策略

策略 1:锁定到特定版本

当稳定性比最新功能更重要时:

CocoaPods:

pod 'Alamofire', '5.8.0'      # Exact version
pod 'SwiftyJSON', '~> 5.0.0'  # Any 5.0.x

SPM:

.package(url: "...", exact: "1.2.3")
策略 2:使用版本范围

当你需要错误修复但不需要破坏性更改时:

CocoaPods:

pod 'Alamofire', '~> 5.8'     # 5.8.x but not 5.9
pod 'SwiftyJSON', '>= 5.0', '< 6.0'  # Range

SPM:

.package(url: "...", from: "1.2.0")              // 1.2.0 and higher
.package(url: "...", .upToNextMajor(from: "1.0.0"))  // 1.x.x but not 2.0.0
策略 3:创建分支并固定版本

当你需要自定义修改时:

# Fork repo on GitHub
# Clone your fork
git clone https://github.com/yourname/package.git

# In Package.swift, use your fork
.package(url: "https://github.com/yourname/package", branch: "custom-fixes")
策略 4:排除传递依赖项

当某个依赖项的依赖项发生冲突时:

SPM(不直接支持,请使用变通方案):

// Instead of this:
.package(url: "https://github.com/problematic/package")

// Fork it and remove the conflicting dependency from its Package.swift

CocoaPods:

# Exclude specific subspecs
pod 'Firebase/Core'  # Not all of Firebase
pod 'Firebase/Analytics'

构建配置问题

Debug 与 Release 的差异

症状:Debug 构建成功,Release 构建失败(或反之)

检查优化设置:

# Compare Debug and Release settings
xcodebuild -showBuildSettings -configuration Debug > debug.txt
xcodebuild -showBuildSettings -configuration Release > release.txt
diff debug.txt release.txt

常见原因:

  • SWIFT_OPTIMIZATION_LEVEL(-Onone 与 -O)
  • ENABLE_TESTABILITY(Debug 中为 YES,Release 中为 NO)
  • DEBUG 预处理器标志
  • 代码签名设置
工作区与项目

使用 CocoaPods 时始终打开工作区:

# ❌ WRONG
open YourApp.xcodeproj

# ✅ CORRECT
open YourApp.xcworkspace

检查你正在构建的对象:

# For workspace
xcodebuild -workspace YourApp.xcworkspace -scheme YourScheme build

# For project only (no CocoaPods)
xcodebuild -project YourApp.xcodeproj -scheme YourScheme build

压力情境:何时应抵制“快速修复”建议

问题

在截止日期的压力下,资深工程师和队友会根据模式匹配给出“快速修复”建议:

  • “重新生成锁文件就行”
  • “增加构建号”
  • “删除 DerivedData,然后重新构建”

这些建议让人觉得稳妥,因为它们来自经验。但如果诊断有误,这种修复只会浪费你本就不充裕的时间。

关键见解 时间压力会加剧权威偏见。人在压力下更容易相信别人的建议。

危险信号——行动前先停下来

如果听到以下任何一句话,执行前先暂停 5 分钟:

  • ❌ “感觉像是……”(模式匹配,而非诊断)
  • ❌ “只要……”(低估了复杂性)
  • ❌ “这通常能修好”(曾经有效 ≠ 总是有效)
  • ❌ “时间很充裕”(对 24 小时周转时间过于乐观)
  • ❌ “这很安全”(重新生成锁文件确实可能引发问题)

压力下的大脑 会因为这些话听起来很有把握而相信它们,却不会追问:“但他们有证据证明这就是根本原因吗?”

“快速修复”前必须先诊断

在时间紧迫时,如果资深同事建议修复方法:

步骤 1:提问(不要争论)
"I understand the pressure. Before we regenerate lock files,
can we spend 5 minutes comparing the broken build to our
working build? I want to know what we're fixing."
步骤 2:要求提供证据
  • “是什么让你觉得这是锁文件问题?”
  • “上次构建成功到这次失败之间,发生了什么变化?”
  • “能看看 App Store 构建与我们的构建各自的实际错误吗?”
步骤 3:记录这次冒险
If we try "pod install":
- Time to execute: 10 minutes
- Time to learn it failed: 24 hours (next submission cycle)
- Remaining time if it fails: 6 days
- Alternative: Spend 1-2 hours diagnosing first

Cost of being wrong with quick fix: High
Cost of spending 1 hour on diagnosis: Low
步骤 4:以专业的方式提出异议
"I want to move fast too. A 1-hour diagnosis now means we
won't waste another 24-hour cycle. Let's document what we're
testing before we submit."
这样做的效果
  • 你并没有质疑对方的专业能力
  • 你是在要求证据(合理的要求)
  • 你表明自己理解当前的压力
  • 你让时间上的考量一目了然
真实案例:App Store 审核阻塞

情境:App 在 App Store 构建中被拒,但本地构建通过。

资深同事说:“重新生成锁文件并重新提交(有 7 天缓冲)”

你的做法
  1. ❌ 错误:立即执行,24 小时后仍然失败,现在只剩 6 天
  2. ✅ 正确:先花 1 小时比较构建结果
比较清单
Local build that works:
- Pod versions in Podfile.lock: [list them]
- Xcode version: [version]
- Derived Data: [timestamp]
- CocoaPods version: [version]

App Store build that fails:
- Pod versions used: [from error message]
- Build system: [App Store's environment]
- Differences: [explicitly document]
比较之后
  • 如果版本一致:锁文件不是问题所在。跳过快速修复。
  • 如果版本不同:现在你就清楚该修复什么了。

节省时间:避免浪费 24 小时反复尝试。

何时可以相信快速修复(少数情况)

只有在以下条件均满足时,快速修复才安全:

  • 你以前遇到过这个完全相同的错误(而非“类似的”)
  • 你知道根本原因(而非“通常这样就行”)
  • 你能在本地复现问题(以便确认修复是否有效)
  • 你有超过 48 小时的缓冲时间(失败的代价较小)
  • 你记录了修复方法,以便之后需要解释时查阅
在生产环境危机中,这些条件通常一个都不满足。

测试清单

添加依赖项时
  • 指定确切版本或版本范围(而非只用最新版本)
  • 检查是否与现有依赖项存在已知冲突
  • 添加后进行干净构建测试
  • 提交锁文件(Podfile.lock 或 Package.resolved)
构建失败时
  • 运行必需的环境检查(xcode-debugging skill)
  • 检查依赖项锁文件是否有更改
  • 确认使用了正确的工作区/项目文件
  • 比较正常与故障构建的设置
发布前
  • 测试 Debug 和 Release 构建
  • 确认所有依赖项的许可证均兼容
  • 检查依赖项对二进制文件大小的影响
  • 在干净的机器或 CI 上测试

常见错误

❌ 不提交锁文件
# ❌ BAD: .gitignore includes lockfiles
Podfile.lock
Package.resolved

原因:团队成员使用的版本不同,构建结果也会不同

❌ 使用“Latest”版本
# ❌ BAD: No version specified
pod 'Alamofire'

原因:依赖项更新时会出现破坏性变更

❌ 混用包管理器
Project uses both:
- CocoaPods (Podfile)
- Carthage (Cartfile)
- SPM (Package.swift)

原因:冲突不可避免,应选定一个主要的包管理器

❌ 更改依赖项后未清理
# ❌ BAD: Just rebuild
xcodebuild build

# ✅ GOOD: Clean first
xcodebuild clean build
❌ 打开项目而非工作区

使用 CocoaPods 时,始终打开 .xcworkspace,而非 .xcodeproj

命令参考

# CocoaPods
pod install                    # Install dependencies
pod update                     # Update to latest versions
pod update PodName             # Update specific pod
pod outdated                   # Check for updates
pod deintegrate                # Remove CocoaPods from project

# Swift Package Manager
swift package resolve          # Resolve dependencies
swift package update           # Update dependencies
swift package show-dependencies # Show dependency tree
swift package reset            # Reset package cache
xcodebuild -resolvePackageDependencies  # Xcode's SPM resolve

# Carthage
carthage update                # Update dependencies
carthage bootstrap             # Download pre-built frameworks
carthage build --platform iOS  # Build for specific platform

# Xcode Build
xcodebuild clean               # Clean build folder
xcodebuild -list               # List schemes and targets
xcodebuild -showBuildSettings  # Show all build settings

实际影响

之前(通过反复试错处理依赖项):

  • 依赖项问题:花费 2-4 小时调试
  • 未能始终运行干净构建
  • 版本冲突让团队措手不及
  • 依赖项不匹配导致 CI 失败

之后(系统化管理依赖项):

  • 依赖项问题:花费 15-30 分钟(检查锁定文件 → 解决问题)
  • 更改依赖项后必须进行干净构建
  • 明确的版本约束可避免意外
  • CI 与本地构建一致(提交锁定文件)

关键要点:尽早锁定依赖项版本。灵活性带来的问题往往多于它解决的问题。

资源

文档:swift.org/package-manager、/xcode/build-system

GitHub:Carthage/Carthage

技能:axiom-xcode-debugging


历史记录: 查看 git log 了解变更

评论

支持 Markdown