Xcode
coding errors
debugging
software development
programming issues

Cycle inside ; building could produce unreliable results Xcode Error

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The Xcode warning Cycle inside <target>; building could produce unreliable results means your build system has a circular dependency — step A depends on step B, which depends back on step A. Xcode cannot determine the correct build order and warns that the output may be inconsistent. This usually occurs when a "Run Script" build phase uses files it also produces, when targets depend on each other in a loop, or when Copy Files and Compile Sources phases reference each other's outputs.

The Warning

 
1⚠️ Cycle inside MyApp; building could produce unreliable results.
2Cycle details:
3Target 'MyApp' has compile command with input '.../ViewController.swift'
4Target 'MyApp' has copy command from '.../Generated.swift' to '.../DerivedSources/Generated.swift'
5That command depends on the build phase "Run Script - Generate Code"
6That command depends on the compile command for 'ViewController.swift'

Xcode detects that compiling depends on a generated file, which depends on a script, which depends on compiling — a cycle.

Fix 1: Check Build Phase Order

Open your target's Build Phases tab and ensure they are in the correct order:

 
11. Dependencies
22. Run Script (code generation)Must come BEFORE Compile Sources
33. Compile Sources
44. Copy Bundle Resources
55. Run Script (post-build tasks)Must come AFTER everything else

If a "Run Script" phase that generates source files appears after "Compile Sources," Xcode sees a cycle because it needs the generated files to compile but generates them after compiling.

Fix: Drag the script phase to the correct position in Build Phases.

Fix 2: Declare Script Input and Output Files

Xcode's build system uses input/output file lists to determine dependencies. Without them, it cannot know when a script needs to run:

 
1Run Script Phase:
2  Script: ${SRCROOT}/scripts/generate_version.sh
3
4  Input Files:
5    $(SRCROOT)/version.json
6
7  Output Files:
8    $(DERIVED_FILE_DIR)/Version.swift
bash
# scripts/generate_version.sh
VERSION=$(cat "${SCRIPT_INPUT_FILE_0}" | python3 -c "import sys,json; print(json.load(sys.stdin)['version'])")
echo "let appVersion = \"${VERSION}\"" > "${SCRIPT_OUTPUT_FILE_0}"

Declaring input/output files tells Xcode:

  • The script reads version.json (so run it when that file changes)
  • The script produces Version.swift (so other phases can depend on this output)
  • The script does NOT depend on compiled sources

Fix 3: Break Target Dependency Cycles

If target A depends on target B and target B depends on target A:

 
Target: MyApp → depends on → MyFramework
Target: MyFramework → depends on → MyAppCYCLE!

Fix: Extract shared code into a third target:

 
Target: MyApp → depends on → MyFramework, SharedCode
Target: MyFramework → depends on → SharedCode
Target: SharedCode → no dependencies on MyApp or MyFramework

Check dependencies in:

  • Build Phases → Dependencies
  • Build Phases → Link Binary With Libraries
  • General → Frameworks, Libraries, and Embedded Content

Fix 4: SwiftGen / R.swift / Code Generation Tools

Code generation tools often cause this cycle:

 
1Compile Sources needs Generated.swift
2Generated.swift is produced by Run Script (SwiftGen)
3SwiftGen reads storyboards/assets
4Storyboards are in Copy Bundle Resources
5Which happens after Compile SourcesCYCLE

Fix for SwiftGen:

  1. Move the SwiftGen script phase to the top of Build Phases (before Compile Sources)
  2. Add explicit input files (the resources SwiftGen reads)
  3. Add explicit output files

Input Files:

 
$(SRCROOT)/MyApp/Assets.xcassets
$(SRCROOT)/MyApp/Base.lproj/Main.storyboard
$(SRCROOT)/MyApp/en.lproj/Localizable.strings

Output Files:

 
$(DERIVED_FILE_DIR)/Assets+Generated.swift
$(DERIVED_FILE_DIR)/Storyboards+Generated.swift
$(DERIVED_FILE_DIR)/Strings+Generated.swift

Fix 5: CocoaPods and Script Phases

CocoaPods adds script phases like [CP] Check Pods Manifest.lock and [CP] Copy Pods Resources. These can create cycles:

bash
1# Regenerate pods to fix ordering issues
2pod deintegrate
3pod install
4
5# Or manually reorder CocoaPods script phases in Build Phases
6# [CP] Check Pods Manifest.lock → should be first
7# [CP] Embed Pods Frameworks → should be after Link Binary
8# [CP] Copy Pods Resources → should be last

Fix 6: Clean Build and Derived Data

Sometimes the cycle warning is stale after build system changes:

bash
1# Clean the build
2# Xcode menu: Product → Clean Build Folder (Shift+Cmd+K)
3
4# Delete derived data
5rm -rf ~/Library/Developer/Xcode/DerivedData/MyApp-*
6
7# Or delete all derived data
8rm -rf ~/Library/Developer/Xcode/DerivedData
9
10# Restart Xcode
11killall Xcode
12open MyApp.xcworkspace

Fix 7: Xcode Build System Setting

Ensure you are using the new build system (default since Xcode 10):

 
FileWorkspace SettingsBuild SystemNew Build System (Default)

The legacy build system handled dependency cycles differently (often silently). The new build system is stricter and correctly reports cycles.

Reading the Cycle Details

Xcode shows the cycle path in the build log. Read it as a chain:

 
Phase A needs output of Phase B
Phase B needs output of Phase C
Phase C needs output of Phase AThis closes the cycle

The fix is always to break one of the edges in the cycle:

  • Reorder build phases
  • Declare proper input/output files
  • Extract shared code into a separate target
  • Remove an unnecessary dependency

Common Pitfalls

  • Ignoring the warning: The build may succeed despite the warning, but results are unreliable. The generated file might be stale, or the wrong version might be compiled. Fix the cycle even if the build works.
  • Missing output file declarations: A Run Script phase without declared outputs is treated as if it depends on everything and everything depends on it — guaranteed cycle.
  • Based on dependency analysis checkbox: Unchecking this in the Run Script phase makes the script run on every build, which can mask or worsen cycle issues. Always declare inputs/outputs instead.
  • Swift Package Manager targets: SPM plugins that generate source files can also create cycles. Ensure plugin outputs are declared in the package manifest.
  • Xcode caching: After fixing a cycle, you may need to clean the build folder (Shift+Cmd+K) for Xcode to re-analyze dependencies.

Summary

  • The cycle warning means Xcode found a circular dependency in build phases or targets
  • Most common cause: a Run Script phase that generates code but is in the wrong position or lacks input/output file declarations
  • Fix by reordering build phases so code generation runs before compilation
  • Always declare input and output files for Run Script phases
  • Break target dependency cycles by extracting shared code into a separate target
  • Clean derived data after fixing cycles to force Xcode to re-analyze

Course illustration
Course illustration

All Rights Reserved.