Get the FREE Ultimate OpenClaw Setup Guide →

ax-build

npx machina-cli add skill Kasempiternal/axiom-v2/ax-build --openclaw
Files (1)
SKILL.md
17.0 KB

Build & Fix

Quick Patterns

Environment-First Diagnostics (Run BEFORE Debugging Code)

80% of mysterious Xcode issues are environment problems, not code bugs.

# 1. Check for zombie processes
ps aux | grep -E "xcodebuild|Simulator" | grep -v grep

# 2. Check Derived Data size (>10GB = stale)
du -sh ~/Library/Developer/Xcode/DerivedData

# 3. Check simulator states
xcrun simctl list devices | grep -E "Booted|Booting|Shutting Down"

Interpretation:

  • 0 processes + small Derived Data + no stuck sims = environment clean, investigate code
  • 10+ processes OR >10GB OR stuck simulators = environment problem, clean first
  • Stale code executing OR intermittent failures = clean Derived Data regardless of size

Clean Everything (Stale Builds / "No such module")

xcodebuild clean -scheme YourScheme
rm -rf ~/Library/Developer/Xcode/DerivedData/*
rm -rf .build/ build/
xcodebuild build -scheme YourScheme \
  -destination 'platform=iOS Simulator,name=iPhone 16'

SPM Package Not Found

rm -rf ~/Library/Developer/Xcode/DerivedData
rm -rf ~/Library/Caches/org.swift.swiftpm
xcodebuild -resolvePackageDependencies
xcodebuild clean build -scheme YourScheme

CocoaPods Clean Reinstall

rm -rf Pods/
rm Podfile.lock
pod install
open YourApp.xcworkspace   # Always workspace, never .xcodeproj

Simulator Recovery

xcrun simctl shutdown all
xcrun simctl list devices
# If still stuck:
xcrun simctl erase <device-uuid>
# Nuclear option:
killall -9 Simulator

Kill Zombie Processes

killall -9 xcodebuild
ps aux | grep xcodebuild | grep -v grep

Isolate Failing Test

xcodebuild test -scheme YourScheme \
  -destination 'platform=iOS Simulator,name=iPhone 16' \
  -only-testing:YourTests/SpecificTestClass

Crash Log Analysis

# Recent crashes
ls -lt ~/Library/Logs/DiagnosticReports/*.crash | head -5

# Symbolicate address
atos -o YourApp.app.dSYM/Contents/Resources/DWARF/YourApp \
  -arch arm64 0x<address>

Build Performance Quick Wins

# Measure baseline
time xcodebuild build -scheme YourScheme

# Find slowest files to compile
xcodebuild -workspace YourApp.xcworkspace \
  -scheme YourScheme clean build \
  OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" 2>&1 | \
  grep ".[0-9]ms" | sort -nr | head -20

Optimal build settings (Debug):

SettingDebug ValueWhy
SWIFT_COMPILATION_MODEsinglefile (Incremental)Only recompiles changed files
ONLY_ACTIVE_ARCHYESBuild for current device only
DEBUG_INFORMATION_FORMATdwarfSkip dSYM generation

Decision Tree

Build Failing?

Build failing?
├─ BUILD FAILED with no details?
│  └─ Clean Derived Data -> rebuild
├─ Build intermittent (sometimes succeeds/fails)?
│  └─ Clean Derived Data -> rebuild
├─ Build succeeds but old code executes?
│  └─ Delete Derived Data -> rebuild (2-5 min fix)
├─ "Unable to boot simulator"?
│  └─ xcrun simctl shutdown all -> erase simulator
├─ "No such module PackageName"?
│  ├─ 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
├─ Tests hang indefinitely?
│  └─ Check simctl list -> reboot simulator
├─ Tests crash?
│  └─ Check ~/Library/Logs/DiagnosticReports/*.crash
├─ Debug vs Release differences?
│  └─ Compare build settings between configurations
├─ Works locally, fails on CI?
│  └─ Dependency caching differences, environment-specific paths
└─ Code logic bug?
   └─ Use ax-lldb for runtime debugging

Build Slow?

Build slow?
├─ Compilation slowest phase (>50% of build)?
│  ├─ YES -> Enable -warn-long-function-bodies 100
│  │         Add explicit types to slow functions
│  └─ NO -> Is linking slow?
│      ├─ YES -> Check link dependencies
│      └─ NO -> Are scripts slow?
│          ├─ YES -> Make scripts conditional (skip in Debug)
│          └─ NO -> Check parallelization
├─ Incremental builds recompile everything?
│  └─ Set Debug compilation mode to singlefile (Incremental)
├─ Building for multiple architectures in Debug?
│  └─ Set ONLY_ACTIVE_ARCH = YES for Debug
└─ Build Timeline shows serial targets?
   └─ Enable Parallelize Build in scheme settings

TestFlight Crash?

Beta tester reports crash?
├─ Open Xcode Organizer (Window -> Organizer -> Crashes)
├─ Is crash symbolicated?
│  ├─ YES (function names visible) -> Read crash report
│  └─ NO (hex addresses) -> Symbolication workflow
├─ App killed but no crash report?
│  ├─ Check Jetsam reports (memory pressure)
│  ├─ Check for watchdog termination (0x8badf00d)
│  └─ Check Terminations Organizer
└─ Review TestFlight feedback?
   └─ Organizer -> Feedback tab, or ASC -> TestFlight -> Feedback

Anti-Patterns

Debugging code before checking environment -- Always run environment checks first. Environment cleanup takes 2-5 minutes; debugging environment issues in code wastes 30-120 minutes.

Rebuilding without cleaning after dependency changes -- Always xcodebuild clean build after adding/updating packages.

Not committing lockfiles -- Both Podfile.lock and Package.resolved must be committed. Team members get different versions otherwise.

Using "latest" version for dependencies -- Always specify explicit versions or ranges. Breaking changes surprise you when dependencies update.

Mixing package managers -- Using CocoaPods + Carthage + SPM in one project guarantees conflicts. Pick one primary manager.

Opening .xcodeproj instead of .xcworkspace -- When using CocoaPods, always open the workspace.

Optimizing without measuring -- Always measure baseline, apply ONE optimization, measure after. Placebo improvements waste time.

Optimizing Release builds for compile speed -- Release builds ship to users. Optimize Debug for speed, keep Release optimized for runtime.

Ignoring simulator states -- "Booting" can hang 10+ minutes. Shutdown/reboot immediately.

Running full test suite when one test fails -- Use -only-testing to isolate the failing test first.

Skimming rejection messages -- Read the FULL rejection text. Copy every guideline number cited.

Resubmitting without changes hoping for a different reviewer -- Reviewers see rejection history. Unchanged resubmissions get the same result.


Deep Patterns

Dependency Resolution Strategies

Lock to specific versions (stability over latest features):

# CocoaPods
pod 'Alamofire', '5.8.0'       # Exact
pod 'SwiftyJSON', '~> 5.0.0'   # Any 5.0.x
// SPM
.package(url: "...", exact: "1.2.3")

Version ranges (bug fixes, no breaking changes):

pod 'Alamofire', '~> 5.8'      # 5.8.x but not 5.9
.package(url: "...", from: "1.2.0")
.package(url: "...", .upToNextMajor(from: "1.0.0"))

Fork and pin (custom modifications):

.package(url: "https://github.com/yourname/package", branch: "custom-fixes")

SPM Version Conflict Resolution

# See dependency graph
swift package show-dependencies

# See resolved versions
cat Package.resolved

# Reset resolution
rm -rf .build
rm Package.resolved
swift package resolve

Debug vs Release Build Differences

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

Common culprits: SWIFT_OPTIMIZATION_LEVEL (-Onone vs -O), ENABLE_TESTABILITY, DEBUG preprocessor flag, code signing settings.

Build Phase Script Optimization

# Skip heavy scripts in Debug
#!/bin/bash
if [ "${CONFIGURATION}" = "Release" ]; then
    firebase crashlytics upload-symbols
fi

Enable script sandboxing for parallelization:

Build Settings -> User Script Sandboxing -> YES
Build Settings -> FUSE_BUILD_SCRIPT_PHASES -> YES

Only enable FUSE_BUILD_SCRIPT_PHASES if ALL scripts have correct inputs/outputs declared.

Type Checking Performance

// Add to Debug build settings -> Other Swift Flags
-warn-long-function-bodies 100
-warn-long-expression-type-checking 100
// SLOW - Complex type inference (247ms)
func calculateTotal(items: [Item]) -> Double {
    return items.filter { $0.isActive }.map { $0.price * $0.quantity }.reduce(0, +)
}

// FAST - Explicit types (12ms)
func calculateTotal(items: [Item]) -> Double {
    let activeItems: [Item] = items.filter { $0.isActive }
    let prices: [Double] = activeItems.map { $0.price * $0.quantity }
    let total: Double = prices.reduce(0, +)
    return total
}

Compilation Caching (Xcode 26+)

Build Settings -> COMPILATION_CACHE_ENABLE_CACHING -> YES
  • Caches compilation results based on input file content and compiler flags
  • Works across clean builds
  • 20-40% faster clean builds after initial cache population
  • Limitations: SPM dependencies not yet cacheable; storyboard/XIB/link tasks not cacheable

Explicitly Built Modules (Xcode 16+)

Splits module compilation into three phases: scan, build modules, compile. Enabled by default for Swift in Xcode 26.

Reduce module variants (unify settings at project/workspace level):

grep "GCC_PREPROCESSOR_DEFINITIONS" project.pbxproj
# Move target-specific macros to project level where possible

Symbolication Workflow

# Find matching dSYM by UUID from crash report
mdfind "com_apple_xcode_dsym_uuids == YOUR-UUID-HERE"

# Check Archives
ls ~/Library/Developer/Xcode/Archives/

# Symbolicate a specific address
xcrun atos -arch arm64 \
  -o MyApp.app.dSYM/Contents/Resources/DWARF/MyApp \
  -l 0x100000000 \
  0x0000000100abc123
Symbolication FailureCauseFix
System frames OK, app frames hexMissing dSYM for your appFind dSYM in Archives, or re-archive with symbols
Nothing symbolicatedUUID mismatchVerify UUIDs match; rebuild exact same commit
"No such file" from atosdSYM not in Spotlight indexmdimport /path/to/MyApp.dSYM
Can't find dSYM anywhereArchived without symbolsSet DEBUG_INFORMATION_FORMAT = dwarf-with-dsym

Common Crash Patterns

Exception TypeMeaningCommon CausesFix
EXC_BAD_ACCESS (SIGSEGV)Invalid memory accessForce-unwrap nil, deallocated object, array out of boundsguard let / if let, [weak self], bounds check
EXC_CRASH (SIGABRT)Deliberate terminationfatalError(), uncaught ObjC exception, Swift runtime errorRead "Application Specific Information" for message
0x8badf00dWatchdog timeoutSync network on main thread, sync file I/O, deadlockMove work to background thread/Task
Jetsam (no crash report)Memory pressure killImage caching without limits, large data in memoryautoreleasepool, stream large files, release on background

Watchdog time limits: App launch ~20s, background task ~10s, going to background ~5s.

Common Exception Codes

CodeMeaning
KERN_INVALID_ADDRESSNull pointer / bad memory access
KERN_PROTECTION_FAILUREMemory protection violation
0x8badf00dWatchdog timeout (main thread blocked)
0xdead10ccDeadlock detected
0xc00010ffThermal event (device too hot)

Pressure Scenario: "Quick Fix" Under Deadline

When someone senior suggests a quick fix under time pressure:

  1. Ask: "Can we spend 5 minutes comparing the broken build to our working build?"
  2. Demand evidence: "What changed between our last successful build and this failure?"
  3. Document the gamble: Quick fix takes 10 min to execute but 24 hours to learn it failed. Diagnosis takes 1-2 hours but gives certainty.
  4. Push back professionally: "A 1-hour diagnosis now means we won't waste another 24-hour cycle."

Quick fixes are safe ONLY when you've seen this EXACT error before, you know the root cause, you can reproduce locally, and you have >48 hours buffer.

Pressure Scenario: Crash Rate Spiked After TestFlight Build

  1. Open Organizer -> Crashes -> Filter to the new build
  2. Group crashes by exception type (find the dominant signature)
  3. Identify the #1 crash by frequency
  4. Symbolicate and read the crash report fully
  5. Understand the cause before writing any fix
  6. Reproduce locally if possible
  7. Fix the verified cause, not a guess

15 minutes of proper triage prevents hours of misdirected debugging.

Enable Better Diagnostics with MetricKit

import MetricKit

class MetricsManager: NSObject, MXMetricManagerSubscriber {
    static let shared = MetricsManager()

    func startListening() {
        MXMetricManager.shared.add(self)
    }

    func didReceive(_ payloads: [MXDiagnosticPayload]) {
        for payload in payloads {
            if let crashDiagnostics = payload.crashDiagnostics {
                for crash in crashDiagnostics {
                    print("Crash: \(crash.callStackTree)")
                }
            }
            if let hangDiagnostics = payload.hangDiagnostics {
                for hang in hangDiagnostics {
                    print("Hang duration: \(hang.hangDuration)")
                }
            }
        }
    }
}

Diagnostics

Build Performance Audit Checklist

Measurement

  • Measured baseline (clean + incremental)
  • Verified improvement in Build Timeline
  • Documented baseline vs optimized comparison

Compilation Settings

  • Debug uses incremental compilation (singlefile)
  • Build Active Architecture = YES (Debug only)
  • Debug uses DWARF (not dSYM)
  • Type checking warnings enabled
  • Fixed slow type-checking functions (>100ms)

Parallelization

  • Parallelize Build enabled in scheme
  • No unnecessary target dependencies
  • Build phase scripts conditional (skip in Debug when possible)
  • Script sandboxing enabled if using parallel scripts

Xcode 26+

  • Compilation caching enabled (COMPILATION_CACHE_ENABLE_CACHING)
  • Checked module variants (Modules Report in build log)
  • Unified build settings at project level to reduce module variants
  • Explicitly Built Modules enabled (default for Swift in Xcode 26)

Dependency Checklist

When adding dependencies:

  • Specified exact versions or ranges (not just latest)
  • Checked for known conflicts with existing deps
  • Tested clean build after adding
  • Committed lockfile (Podfile.lock or Package.resolved)

When builds fail:

  • Ran environment checks first
  • Checked dependency lockfiles for changes
  • Verified using correct workspace/project file
  • Compared working vs broken build settings

Before shipping:

  • Tested both Debug and Release builds
  • Verified all dependencies have compatible licenses
  • Checked binary size impact
  • Tested on clean machine or CI

Common Error Quick Reference

ErrorFix
BUILD FAILED (no details)Delete Derived Data
Unable to boot simulatorxcrun simctl erase <uuid>
No such moduleClean + delete Derived Data + resolve packages
Tests hangCheck simctl list, reboot simulator
Stale code executingDelete Derived Data
Multiple commands produceRemove duplicate target membership
Framework not foundCheck FRAMEWORK_SEARCH_PATHS
Pod install OK but build failsCheck Podfile.lock conflicts, open .xcworkspace
SPM resolution timeoutClear package caches + derived data
Build works locally, fails CICheck dependency caching, committed lockfiles

Xcode Organizer Triage Questions

  1. How long has this been an issue? -- Check the inspector graph. Legend shows which versions are affected.
  2. Production or TestFlight only? -- Use Release filter in toolbar.
  3. What was the user doing? -- Open Feedback Inspector for tester comments, network state, battery level, disk space.

Terminations Without Crash Reports

When users report "app just closed" but no crash exists:

Termination CategoryMeaning
Launch timeoutApp took too long to launch
Memory limitHit system memory ceiling
CPU limit (background)Too much CPU while backgrounded
Background task timeoutBackground task exceeded time limit

Check: Organizer -> Terminations sidebar. Compare termination rates against previous versions.


Related

For build settings reference, xcodebuild flags, SPM configuration, and xcconfig syntax, load ax-build-ref.

Source

git clone https://github.com/Kasempiternal/axiom-v2/blob/main/axiom-plugin/skills/ax-build/SKILL.mdView on GitHub

Overview

ax-build helps diagnose and triage build failures, dependency conflicts, test crashes, simulator issues, and environment problems in Xcode projects. It provides quick patterns, cleanup steps, crash log analysis, and a decision tree to speed up remediation.

How This Skill Works

It presents quick patterns to diagnose environment issues first (Derived Data, processes, simulator state). It then applies targeted cleanups (DerivedData, build folders, package caches, Pods) and uses a decision tree to map failure modes to remediation steps and build performance tips.

When to Use It

  • Build failures with little or no error detail (often environment or cache issues)
  • Dependency problems like No such module or SPM/Pod conflicts
  • Tests hang, crash, or produce diagnostic crash logs
  • Simulator issues or inconsistencies across devices
  • Local vs CI builds differ or you need to optimize build performance

Quick Start

  1. Step 1: Run Environment-First Diagnostics (ps aux for xcodebuild/Simulator, check DerivedData size, list simulator states)
  2. Step 2: Clean artifacts and rebuild (xcodebuild clean -scheme YourScheme; rm -rf DerivedData; rm -rf .build/ build/; xcodebuild build -scheme YourScheme -destination platform=iOS Simulator,name=iPhone 16)
  3. Step 3: If still failing, isolate tests or analyze crash logs and consult the decision tree

Best Practices

  • Run Environment-First Diagnostics before diving into code
  • Clean Derived Data and stale caches regularly during triage
  • Use workspace (.xcworkspace) for CocoaPods projects
  • Isolate failing tests to quickly identify the source
  • Leverage crash logs and symbolication to pinpoint issues

Example Use Cases

  • Clean Derived Data, reset Derived Data, and rebuild after flaky builds
  • Resolve Swift Package dependencies with xcodebuild -resolvePackageDependencies
  • Pod install after removing Pods and Podfile.lock, using the workspace
  • Symbolicate recent crash logs from DiagnosticsReports to identify faulting symbol
  • Measure baseline build time and identify slow files with -Xfrontend -debug-time-function-bodies

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers