This document describes every optimization check the agent skills perform, why each check matters for build time, and where to learn more. It is the developer-facing reference; implementation details live in the skill-level docs under skills/*/references/.
The xcode-project-analyzer audits project-level and target-level build settings against a curated best-practices checklist. Misconfigured settings are one of the most common causes of unnecessarily slow builds, especially in projects that have been migrated across Xcode versions.
Debug configuration checks:
| Setting | Key | Recommended | Why |
|---|---|---|---|
| Compilation Mode | SWIFT_COMPILATION_MODE |
singlefile |
Recompiles only changed files instead of the entire target |
| Swift Optimization | SWIFT_OPTIMIZATION_LEVEL |
-Onone |
Optimization passes add compile time with no debug benefit |
| C/ObjC Optimization | GCC_OPTIMIZATION_LEVEL |
0 |
Same rationale for C-family sources |
| Active Arch Only | ONLY_ACTIVE_ARCH |
YES |
Building all architectures doubles or triples compile and link time |
| Debug Info Format | DEBUG_INFORMATION_FORMAT |
dwarf |
dwarf-with-dsym generates a separate dSYM bundle, adding overhead |
| Testability | ENABLE_TESTABILITY |
YES |
Required for @testable import; minor overhead is expected |
| Compilation Conditions | SWIFT_ACTIVE_COMPILATION_CONDITIONS |
includes DEBUG |
Guards #if DEBUG code paths |
| Eager Linking | EAGER_LINKING |
YES |
Starts linking before all compilation finishes, reducing wall-clock time |
Release configuration checks:
| Setting | Key | Recommended | Why |
|---|---|---|---|
| Compilation Mode | SWIFT_COMPILATION_MODE |
wholemodule |
Produces optimized runtime code |
| Swift Optimization | SWIFT_OPTIMIZATION_LEVEL |
-O or -Osize |
Optimized binaries for distribution |
| C/ObjC Optimization | GCC_OPTIMIZATION_LEVEL |
s |
Optimizes for size |
| Active Arch Only | ONLY_ACTIVE_ARCH |
NO |
Release must include all supported architectures |
| Debug Info Format | DEBUG_INFORMATION_FORMAT |
dwarf-with-dsym |
Required for crash symbolication |
| Testability | ENABLE_TESTABILITY |
NO |
Removes internal-symbol export overhead |
General (all configurations) checks:
| Setting | Key | Recommended | Why |
|---|---|---|---|
| Compilation Caching | COMPILATION_CACHE_ENABLE_CACHING |
YES |
Caches Swift and C-family compilation results; biggest wins on branch switching and clean builds |
| Integrated Swift Driver | SWIFT_USE_INTEGRATED_DRIVER |
YES |
Eliminates inter-process overhead for compilation scheduling |
| Clang Modules | CLANG_ENABLE_MODULES |
YES |
Caches module maps on disk instead of reprocessing headers |
| Explicit Modules | SWIFT_ENABLE_EXPLICIT_MODULES |
Evaluate per-project | Improves parallelism but may regress due to scanning overhead; benchmark before and after |
References:
- Improving the speed of incremental builds -- Apple Documentation
- SwiftLee: Build performance analysis for speeding up Xcode builds
- Xcode Release Notes: Compilation Caching (feature ID 149700201)
- Bitrise: Xcode Compilation Cache FAQ
CocoaPods is deprecated. When a project uses CocoaPods, do not attempt CocoaPods-specific build optimizations (linkage mode changes, COCOAPODS_PARALLEL_CODE_SIGN, Podfile tweaks). These are unreliable and frequently regress build times.
Recommend migrating to Swift Package Manager as the highest-impact long-term improvement. SPM advantages for build time: compilation caching works out of the box, better build parallelism from the dependency graph, no pod install xcconfig regeneration overhead, and native Xcode integration with full support for modern features like explicit modules.
Focus analysis on first-party targets and build settings the project controls directly. Do not audit Pods.xcodeproj or the Podfile.
The xcode-project-analyzer inspects every Run Script phase in the project for missing metadata and unnecessary execution.
What the agent checks:
- Scripts without declared input and output files run on every build regardless of changes. The agent flags these and recommends adding declarations or
.xcfilelistfiles. - Scripts that always run (
alwaysOutOfDate = 1) are flagged with a recommendation to make them conditional. - Debug/simulator guards: scripts that upload symbols, run release-only tools, or perform network calls should be skipped in Debug or Simulator builds.
- Timestamp-touching tools: linters or formatters that modify file timestamps without changing content silently invalidate build inputs and force replanning of every Swift module.
- Parallelization: scripts with correctly declared dependencies can run in parallel with compilation instead of blocking it.
References:
- Improving the speed of incremental builds -- Apple Documentation (script input/output declarations,
.xcfilelist) - Swift Forums: Slow incremental builds because of "Planning Swift module" -- timestamp invalidation case study
The xcode-compilation-analyzer identifies Swift source files and expressions that take disproportionately long to type-check.
What the agent checks:
- Build Timing Summary categories to find targets where
CompileSwiftSourcesdominates. - Compiler diagnostic flags (
-warn-long-function-bodies,-warn-long-expression-type-checking) to surface specific slow expressions. - Optional deep diagnostics:
-debug-time-compilation(per-file ranking),-debug-time-function-bodies(per-function timing),-stats-output-dir(compiler statistics as JSON). - Patterns that commonly cause slow type-checking:
- Complex chained or nested expressions without intermediate type annotations
- Nested ternaries or overloaded generic chains
- Long method chains (
.map().flatMap().filter().reduce()) without typed intermediates - Closures passed to generic functions without explicit return types
References:
- Improving build efficiency with good coding practices -- Apple Documentation
- SwiftLee: Build performance analysis for speeding up Xcode builds -- compiler diagnostic flags
The xcode-project-analyzer measures and diagnoses the fixed cost of rebuilding when nothing has changed.
What the agent checks:
Even with no source edits, incremental builds incur fixed overhead. The agent measures zero-change build time and investigates these categories from the Build Timing Summary:
| Category | What it does | Why it matters |
|---|---|---|
PhaseScriptExecution |
Script phases with alwaysOutOfDate or missing I/O |
Runs on every build regardless of changes |
CodeSign |
Signs the app and embedded frameworks | Runs unconditionally; scales with signed binary count |
ValidateEmbeddedBinary |
Validates against provisioning profile | Runs unconditionally |
CopySwiftLibs |
Copies Swift standard libraries | Runs even when nothing changed |
RegisterWithLaunchServices |
Registers the built app | Fast but always present |
ProcessInfoPlistFile |
Re-processes Info.plist files | Scales with target count |
ExtractAppIntentsMetadata |
Extracts App Intents metadata from all targets including third-party dependencies | Driven by Xcode, not by per-target project settings; unnecessary overhead if the project does not use App Intents but not cleanly suppressible from the repo (classify as xcode-behavior) |
A zero-change build above 5 seconds on Apple Silicon typically indicates script phase overhead or excessive codesigning.
References:
- Improving the speed of incremental builds -- Apple Documentation
- Swift Forums: Slow incremental builds because of "Planning Swift module" -- zero-change overhead breakdown
The xcode-project-analyzer audits target dependencies and scheme configuration for correctness and parallelism.
What the agent checks:
- Target dependencies are explicit and accurate. Missing dependencies cause build failures; inflated dependencies block parallel work.
- Removed or stale dependencies that no longer reflect real build requirements.
- Scheme builds targets in
Dependency Order(not manual order). - Oversized monolithic targets that serialize compilation when the work could be split across parallel targets.
DEFINES_MODULEis enabled for custom frameworks that should benefit from module maps.- Public headers are self-contained enough to compile as a module.
References:
- Improving the speed of incremental builds -- Apple Documentation (target dependencies, module maps)
The xcode-project-analyzer and spm-build-analysis skills check for configuration drift that causes the same module to be built multiple times with different options.
What the agent checks:
- Targets that import the same SPM package but compile with different Swift compiler options produce separate module variants, inflating
SwiftEmitModuletask counts. - Drift in
SWIFT_OPTIMIZATION_LEVEL,SWIFT_COMPILATION_MODE,OTHER_SWIFT_FLAGS, and target-level overrides. - Project-level vs target-level build setting overrides: settings should be at the project level unless a target has a specific reason to override.
- Preprocessor macros or other build options that differ across sibling targets importing the same modules.
References:
- Building your project with explicit module dependencies -- Apple Documentation
- WWDC24: Demystify explicitly built modules
- Bitrise: Demystifying Explicitly Built Modules for Xcode
The spm-build-analysis skill inspects Swift Package Manager dependencies for graph structure issues, plugin overhead, and dependency hygiene.
What the agent checks:
- Large umbrella packages that trigger widespread rebuilds.
- Dependency layering violations: features depending on features instead of flowing inward (Common/Core → Services → Features/UI).
- Circular dependencies (target-level cycles must be refactored; extract shared contracts into a separate module).
- Build-tool and command plugins that run during incremental builds even when no input changed.
- Branch-pinned packages (
branch:) that force network checks on every fresh resolve; recommends pinning to tags orrevision:hashes. - Package reference verification: confirms packages listed in recommendations actually appear in
project.pbxprojas linked dependencies. - Transitive dependency minimization: flags
@_exported importumbrella modules that create hidden rebuild chains. - Interface/implementation separation opportunities for modules with heavy dependencies.
- Test target isolation: test targets should depend on the module under test, not the entire app target.
References:
- Improving the speed of incremental builds -- Apple Documentation
- Building your project with explicit module dependencies -- Apple Documentation
The spm-build-analysis skill checks for incremental build cascading caused by heavy Swift macro usage.
What the agent checks:
- Projects using macro-heavy libraries (e.g., TCA, swift-syntax-based tools) are susceptible to cascading where a trivial change rebuilds most of the app.
- Macro expansion can invalidate downstream modules even when the expanded output has not changed.
swift-syntaxbuilding universally (all architectures) when no prebuilt binary is available adds significant overhead to clean builds and CI.- Recommends isolating macro-using code into fewer, more stable modules to limit the invalidation blast radius.
References:
- Swift Forums: Slow incremental builds because of "Planning Swift module" -- macro cascading, swift-syntax overhead
The xcode-compilation-analyzer checks for SwiftUI view bodies that are expensive to type-check.
What the agent checks:
- Monolithic
bodyproperties (roughly 50+ lines) that force the type-checker to resolve a single large result-builder expression. @ViewBuilderhelper properties instead of separatestruct Viewtypes -- separate structs reduce the type-checker scope perbody.- Deeply nested
Group/VStack/HStackhierarchies within a single body. - Recommends extracting subviews into dedicated
struct Viewtypes.
References:
- Improving build efficiency with good coding practices -- Apple Documentation
The xcode-project-analyzer checks asset catalog compilation for single-threaded bottlenecks.
What the agent checks:
CompileAssetCatalogis single-threaded per target. Multiple catalogs within the same target compile sequentially in a single process.- If asset catalog compilation appears as a significant timing category, recommends splitting assets into separate resource bundles across separate targets for parallel compilation.
- Asset catalog compilation is not cacheable by the Xcode compilation cache (
CompileAssetCatalogVariantis non-cacheable). - Checks whether asset catalogs rebuild during incremental builds even when no assets changed.
References:
- Swift Forums: Slow incremental builds because of "Planning Swift module" -- asset catalog single-threaded compilation
- Bitrise: Xcode Compilation Cache FAQ -- non-cacheable task types
The xcode-compilation-analyzer checks for access control patterns that inflate compiler work.
What the agent checks:
- Classes not intended for subclassing should be marked
final. This eliminates virtual dispatch overhead and lets the compiler de-virtualize method calls. - Properties and methods not used outside their declaration or file should use
privateorfileprivate. Narrower visibility reduces the compiler's symbol search space. internal(the default) is preferred overpublicunless the symbol genuinely crosses module boundaries.structandenumare preferred overclasswhen reference semantics are not needed. Value types are simpler for the compiler to reason about.- Objective-C bridging surfaces should be kept narrow. Swift members marked
privatedo not need Objective-C visibility.
References:
- Improving build efficiency with good coding practices -- Apple Documentation
The xcode-compilation-analyzer and xcode-project-analyzer investigate categories that disproportionately inflate incremental builds.
What the agent checks:
- Planning Swift module: Can dominate incremental builds (up to 30s per module), sometimes exceeding clean build time. If modules are replanned but no compiles are scheduled, build inputs are being invalidated unexpectedly.
- SwiftEmitModule: Can take 60s+ after a single-line change in large modules. If it exceeds compile time for the same target, the module's public API surface may be unnecessarily wide.
- Task Backtraces (Xcode 16.4+): Enable via Scheme Editor > Build > Build Debugging to see why each task re-ran. The agent recommends enabling this when incremental build overhead is unexplained.
- Multi-platform build multiplication: Adding a secondary platform (e.g., watchOS) can cause shared SPM packages to build multiple times per platform/architecture combination.
References: