iOS Development
xcodebuild
Code Signing
Apple Xcode
App Development

Building iOS applications using xcodebuild without codesign

Master System Design with Codemia

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

Introduction

Building an iOS project without code signing is useful in local CI, simulator-only workflows, and validation jobs where you only need compilation artifacts. The important constraint is that unsigned builds are mainly for the simulator or for intermediate build steps. If you need to install on a physical device or ship an App Store archive, signing is still required.

When Unsigned Builds Make Sense

Code signing proves the identity of the app and its entitlements. That matters for devices and distribution, but it is unnecessary for many build-only tasks such as:

  • verifying the project compiles in CI
  • running unit tests on the simulator
  • generating derived data for static analysis
  • testing whether an Xcode project is configured correctly

In those cases, disabling signing avoids provisioning-profile noise and keeps the command line simpler.

The Core xcodebuild Command

For a simulator build, this pattern is the usual baseline:

bash
1xcodebuild \
2  -project MyApp.xcodeproj \
3  -scheme MyApp \
4  -configuration Debug \
5  -sdk iphonesimulator \
6  CODE_SIGNING_ALLOWED=NO \
7  CODE_SIGNING_REQUIRED=NO \
8  CODE_SIGN_IDENTITY=""

These build settings tell Xcode not to perform signing during the build.

The most important flag for unsigned work is the simulator SDK. Building for iphonesimulator avoids many device-signing requirements entirely.

Workspace Example

If the app uses CocoaPods or another workspace-based setup, switch from -project to -workspace:

bash
1xcodebuild \
2  -workspace MyApp.xcworkspace \
3  -scheme MyApp \
4  -configuration Debug \
5  -sdk iphonesimulator \
6  -destination 'platform=iOS Simulator,name=iPhone 15' \
7  CODE_SIGNING_ALLOWED=NO \
8  CODE_SIGNING_REQUIRED=NO \
9  CODE_SIGN_IDENTITY=""

Adding -destination is useful for test runs because it makes the simulator target explicit.

Running Tests Without Signing

Unsigned simulator builds work well with tests too:

bash
1xcodebuild test \
2  -project MyApp.xcodeproj \
3  -scheme MyApp \
4  -sdk iphonesimulator \
5  -destination 'platform=iOS Simulator,name=iPhone 15' \
6  CODE_SIGNING_ALLOWED=NO \
7  CODE_SIGNING_REQUIRED=NO \
8  CODE_SIGN_IDENTITY=""

This is a common CI setup because unit tests and many UI tests do not need a signed device build.

What Happens with Device Builds

This is where many teams get tripped up. You can suppress parts of signing behavior from the command line, but if the target platform is a real iPhone or a device archive, unsigned output is usually not useful.

For example, building an installable app for a device still involves entitlements, provisioning, and code-signing rules. Even if the build command completes, the result may not be deployable.

So the safe rule is:

  • no signing needed for simulator-focused compile or test workflows
  • signing still needed for device installation and distribution

That distinction saves a lot of time.

Check Target Build Settings Too

Command-line overrides help, but project settings can still interfere. If a target hardcodes signing-related values or a CI script injects them elsewhere, you may still see signing failures.

A useful inspection command is:

bash
1xcodebuild \
2  -project MyApp.xcodeproj \
3  -scheme MyApp \
4  -showBuildSettings

That output helps you confirm whether the intended values are really being applied.

If a target includes signing entitlements or special capabilities, the project may need additional cleanup even for simulator-only builds.

Derived Data and Repeatability

In CI, it is often helpful to isolate build products and derived data:

bash
1xcodebuild \
2  -project MyApp.xcodeproj \
3  -scheme MyApp \
4  -sdk iphonesimulator \
5  -derivedDataPath ./DerivedData \
6  CODE_SIGNING_ALLOWED=NO \
7  CODE_SIGNING_REQUIRED=NO \
8  CODE_SIGN_IDENTITY=""

This keeps artifacts predictable and makes debugging easier when a build agent behaves differently from your local machine.

Why CODE_SIGNING_ALLOWED=NO Is Usually the Key Flag

Older command examples often use CODE_SIGNING_REQUIRED=NO or blank CODE_SIGN_IDENTITY alone. Those can help, but CODE_SIGNING_ALLOWED=NO is usually the clearest signal that signing should be skipped entirely for the build.

Using all three is common because it makes the intent explicit and works across a wider range of project setups.

Common Pitfalls

The most common mistake is trying to produce a device-installable app without signing. Unsigned simulator builds are fine. Unsigned device distribution is not.

Another issue is forgetting to target iphonesimulator. If the SDK or destination points at device-related output, signing requirements return quickly.

Teams also sometimes assume the command-line overrides always win. In practice, target settings, schemes, or CI environment variables can still complicate the build.

Finally, inspect the build settings when the command seems correct but the build still demands a provisioning profile.

Summary

  • Unsigned xcodebuild workflows are best for simulator builds, tests, and CI verification jobs.
  • Use CODE_SIGNING_ALLOWED=NO, CODE_SIGNING_REQUIRED=NO, and an empty CODE_SIGN_IDENTITY to disable signing during the build.
  • Prefer the iphonesimulator SDK for no-signing scenarios.
  • Do not expect unsigned builds to replace proper device signing and distribution.
  • Use -showBuildSettings and isolated derived data paths when debugging CI signing issues.

Course illustration
Course illustration

All Rights Reserved.