axiom-build-debugging について
axiom-build-debuggingは、iOS開発者向けのXcodeビルド診断スキルです。コードを変更する前に依存関係の解決を確認し、SPM、CocoaPods、ビルド設定、CI環境の差を調べます。
主な機能
- 01SPMの解決とキャッシュの診断
- 02CocoaPodsの競合とリンクエラーの調査
- 03重複したターゲットメンバーの特定
- 04フレームワーク検索パスの確認
- 05ローカルとCIのビルド環境の比較
活用シーン
- 01パッケージ追加後の「No such module」の解決
- 02出力ファイル重複エラーの原因調査
- 03CocoaPodsの導入後も失敗するビルドの診断
- 04Macと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のインストールには成功するが、フレームワークエラーでビルドに失敗する
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'」と表示される
原因:同じファイルが複数のターゲットまたはビルドフェーズに追加されている
修正方法:
- Xcodeを開きます
- ナビゲーターでファイルを選択します
- File Inspector → Target Membershipを開きます
- 重複するターゲットのチェックを外します
- または、Build Phases → Copy Bundle Resourcesで重複を削除します
問題4:フレームワークの検索パス
症状:「Framework not found」または「Linker command failed」と表示される
ビルド設定を確認する:
# Show all build settings
xcodebuild -showBuildSettings -scheme YourScheme | grep FRAMEWORK_SEARCH_PATHS
Xcodeで修正する:
- Target → Build Settingsを開きます
- 「Framework Search Paths」を検索します
- パスを追加します:
$(PROJECT_DIR)/Frameworks(再帰的) - または、プロジェクトから継承するには
$(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 Store のビルドではアプリが却下されるが、ローカルでは問題なく動作します。
先輩の提案 「ロックファイルを再生成して再提出しよう(7日間の余裕がある)」
対応方法
- ❌ 誤り:すぐに実行し、24時間後に失敗して、残り6日になる
- ✅ 正解:まず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 スキル)
- 依存関係のロックファイルに変更がないか確認する
- 正しいワークスペース/プロジェクトファイルを使用していることを確認する
- 正常なビルドと失敗するビルドの設定を比較する
リリース前
- 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)
理由:競合は避けられません。主に使うパッケージマネージャーを1つ選んでください。
❌ 依存関係の変更後にクリーンアップしない
# ❌ BAD: Just rebuild
xcodebuild build
# ✅ GOOD: Clean first
xcodebuild clean build
❌ ワークスペースではなくプロジェクトを開く
CocoaPods を使用する場合は、常に .xcodeproj ではなく .xcworkspace を開いてください。
コマンドリファレンス
# 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 を参照してください