# Swift Build: the build service behind SwiftPM, Xcode and Swift Playground

> swiftlang/swift-build is the llbuild-based build system written in Swift that SwiftPM, Xcode and Swift Playground run on. What the repository hands you is a contributor's workflow for swapping in your own copy, not a build driver you configure and call.

**swiftlang/swift-build** — A high-level build system based on llbuild, used by Xcode, Swift Playground, and the Swift Package Manager

- Repository: https://github.com/swiftlang/swift-build
- Stars: 2,247 · Forks: 236
- Language: Swift
- License: Apache-2.0
- Published: 2026-10-14 · Updated: 2026-10-14 · Language: en
- Canonical page: https://hysenlabs.com/projects/swiftlang-swift-build

## Three Swift clients share one build service

Swift Build occupies the layer between a client's user interface and llbuild, the low-level engine it is built on. The project's description line names Xcode, Swift Playground and the Swift Package Manager as the consumers, and the source language is Swift.

That fixes the audience. Library maintainers who need builds planned correctly, engineers chasing a failed Xcode build, and contributors changing the build system rather than configuring it. There is no standalone entry point anywhere in the repository. Every command in the documentation belongs to another tool, so picking this project up means altering one piece of a toolchain, not installing a build driver you invoke by hand.

## The engine lives inside swift-build or behind a service bundle

The two supported workflows put the same engine in two different places, and the gap between them is what you notice when something goes wrong. With SwiftPM the build runs entirely inside the `swift-build` process, or inside `swift-test` and `swift-run` for the other subcommands, so driver and engine are one program. You can attach a debugger to that process directly:

```bash
swift run --debugger swift-build ...
```

Or attach from an IDE such as VSCode or Xcode. Under the Xcode and xcodebuild workflows the split is real, because the build runs as a separate service bundle. The documented recipe is to open the swift-build package containing your changes in Xcode, choose "Debug > Attach to Process by PID or Name…", type `SWBBuildServiceBundle` as the process name and click Attach. The debugger waits for the process to launch and attaches on its own once you open a workspace.

So a stack trace from a failing SwiftPM build and one from a failing Xcode build come from processes with different names, different lifetimes and different attach procedures. Anyone writing a triage runbook has to cover both.

## Two command plugins launch a copy of your Xcode

The package ships a plugin for each Xcode front end, and both rebuild the picture around your own checkout. One plugin launches a copy of the currently `xcode-select`ed Xcode.app wired to your modified build system service:

```bash
swift package --disable-sandbox launch-xcode
```

Its sibling does the same for xcodebuild, forwarding any arguments written after a double hyphen to xcodebuild unmodified:

```bash
swift package --disable-sandbox run-xcodebuild
```

To exercise SwiftPM against both repositories at once, the instructions use an environment variable rather than a flag:

```bash
SWIFTCI_USE_LOCAL_DEPS=1 swift build --package-path /path/to/swiftpm
```

For macOS engineers, `Utilities` holds `SwiftPM+SwiftBuild.xcworkspace`, which opens the two repositories together in Xcode so a change in one can be edited against the other. Both plugins carry the same caveat: this workflow is generally only supported when using the latest available Xcode version. An engineer pinned to an older Xcode is given no fallback, and none is written down.

## Task construction is planned apart from execution

The test layout makes one architectural point visible: planning a build and running it are separate modules. `SWBTaskConstruction` plans builds, and `SWBTaskConstructionTests` covers that module by planning a build and then inspecting the resulting build graph. That pair is the closest thing to a contract in the repository, because the graph is exactly the hand-off point between planning and execution.

The full suite is one command from the root:

```bash
swift test
```

The `Tests` directory is organized by target, one per component, and much of the suite works on test project model objects that emulate what a higher level client constructs, so behaviour can be checked at each layer without starting a real build. `Project Tests` is the documented guide to writing them. For a contributor this explains the split seen earlier: a SwiftPM failure arrives as a crashed in-process driver, while the graph it was working from stays inspectable through these targets without a client attached.

## A build system that bootstraps itself two ways

The top level of the repository carries a `Package.swift` manifest and a `CMakeLists.txt` with a `cmake` directory beside it, so the tool that replaces the build system can itself be produced by either SwiftPM or CMake. The two routes are not interchangeable. SwiftPM is how the Swift contributors work on it, while the CMake tree covers the builds where SwiftPM is not the entry point.

Around those two sit `.editorconfig`, `.swift-format` and `.swift-version`, which say that formatting and toolchain version are pinned by the repository rather than chosen per developer, plus `.devcontainer` and `.vscode` for editors and a `Plugins` directory holding the command plugins used above. `SwiftBuild.docc` is the only prose about the internals, and it ships inside the package rather than as a documentation site. The package is Apache-2.0, and the README sends readers to https://swift.org/LICENSE.txt for the terms that actually apply, so check that file before assuming the SPDX tag settles the question.

## Nightly snapshots are the only default, newest Xcode the only host

Read the description line and the README side by side and the project's status changes shape. The description says Swift Build is used by Xcode, Swift Playground and the Swift Package Manager. The instructions are narrower. Swift Build is the default SwiftPM build system only in nightly snapshots of Swift's `main` branches, and in Swift 6.2 and 6.3 it stays behind the `--build-system swiftbuild` switch. On the Xcode side the documented support is the two developer plugins above, which launch a copy of the currently `xcode-select`ed Xcode.

Here is the detail a skim misses. Both the plugin workflows and the default-SwiftPM claim sit inside a narrow envelope: nightly toolchains, the latest available Xcode, and a flag in between. Nothing in the repository shows how to turn Swift Build on for a pinned or older toolchain, and nothing describes a configuration that would make Xcode use it permanently. The headline is a statement about where the system ships, while what a reader can actually follow stops at nightly snapshots and one Xcode version.

## Docs arrive as a docc bundle with no rollback path

Technical documentation lives in `SwiftBuild.docc` and is read from a local preview rather than a hosted site:

```bash
docc preview SwiftBuild.docc
```

On macOS the same preview runs through xcrun:

```bash
xcrun docc preview SwiftBuild.docc
```

Beyond that, the repository documents no installation command, no upgrade procedure and no rollback path, and it names no configuration keys for driving a build on its own. That absence follows from the position: the system is consumed by SwiftPM, Xcode and Swift Playground rather than configured by hand, so there is no config file to show you. `SWIFTCI_USE_LOCAL_DEPS=1` is the only environment variable written down, and it exists to test local changes rather than to tune a build. The last push was on 2026-09-28, after the 6.4.0 tag dated 2026-09-15.

## Where llbuild stops and the Swift layer starts

llbuild is the engine Swift Build is built on, and the two relate by layering rather than by replacement. llbuild provides the low-level execution machinery. Swift Build adds the Swift-aware planning layer, the `SWBTaskConstruction` module that produces a build graph, and the client-facing model that SwiftPM, Xcode and Swift Playground each drive in their own way. That split is why a planning change can be tested against graph output without executing anything, and why debugging needs two process names depending on which client started the build.

The limit of the whole project is its audience. If you want a build tool you can point at an arbitrary project tree and configure with flags of your own, this repository cannot help, because nothing here documents a way to drive a build directly. It also does not serve a non-Swift ecosystem: the source is Swift and the clients are Swift tools. The suite, the docc bundle and the CMake tree are all built for contributors to that stack, not for people choosing a build system in general.

## Conclusion

Take swift-build when you intend to change how the Swift toolchain builds, and skip it when you are shopping for a build driver to point at your own project tree. Its real asset is planning: SWBTaskConstruction produces the build graph that all three clients execute, and the test targets check that graph without running a build. What you will not find is a standalone entry point, a config file or a rollback procedure. Verify two things before touching anything: that your SwiftPM accepts `--build-system swiftbuild`, and that your Xcode is the latest available one.

## FAQ

### How do I turn on Swift Build for SwiftPM?

Pass `--build-system swiftbuild` in Swift 6.2 or 6.3. It is already the default SwiftPM build system in nightly snapshots of Swift's `main` branches, and when SwiftPM is built from source Swift Build comes along as a package dependency.

### How do I test a local change to swift-build inside Xcode?

Run `swift package --disable-sandbox launch-xcode` from your checkout. It launches a copy of the currently `xcode-select`ed Xcode.app configured to use your modified copy of the build system service, and the documentation says this workflow is generally only supported on the latest available Xcode version.

### How do I debug the build system when a build fails?

With SwiftPM the build runs entirely inside the `swift-build` process, so `swift run --debugger swift-build ...` or an IDE such as VSCode or Xcode can attach to it. Under the Xcode and xcodebuild workflows you attach to a separate service bundle process named `SWBBuildServiceBundle` instead.

### Does swift-build have its own command line interface or config file?

No standalone entry point is documented. Every command shown belongs to SwiftPM, xcodebuild or docc, and no configuration keys for driving a build directly are written down; the only environment variable named is `SWIFTCI_USE_LOCAL_DEPS=1`, which exists for testing local changes.

### How is swift-build itself built and tested?

The root holds both a `Package.swift` manifest and a `CMakeLists.txt` with a `cmake` directory, so it can be produced through SwiftPM or CMake. The test suite is organised into per-component targets such as `SWBTaskConstructionTests` and runs with `swift test` from the root of the repository.

## Sources

- [Issues](https://github.com/swiftlang/swift-build/issues)
- [License: Apache-2.0](https://github.com/swiftlang/swift-build/blob/main/LICENSE)
- [README](https://github.com/swiftlang/swift-build/blob/main/README.md)
- [Releases](https://github.com/swiftlang/swift-build/releases)
- [swiftlang/swift-build on GitHub](https://github.com/swiftlang/swift-build)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/swiftlang-swift-build
