# swift-driver: the Swift compiler driver rewritten in Swift, one executable at a time

> swift-driver is the reimplementation of the program you invoke as swift or swiftc, and it is what Swift Package Manager and Swift Build call on your behalf. Building it locally and putting it in front of your toolchain takes a symlink, and on Windows a manually linked Swift runtime.

**swiftlang/swift-driver** — Swift compiler driver reimplementation in Swift

- Repository: https://github.com/swiftlang/swift-driver
- Stars: 847 · Forks: 242
- Language: Swift
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/swiftlang-swift-driver

## The program that sits between your build and the compiler

Swift's compiler driver is the program that coordinates the compilation of Swift source code into executables, libraries, object files, Swift modules and interfaces. It is the thing you invoke from the command line as swift or swiftc, and it is just as often invoked on your behalf by a build system, with the Swift Package Manager and Swift Build both named in the README as the callers.

That placement is the reason the driver matters even if you never type the command yourself. It parses the arguments, works out what the user asked for, and turns that into a plan of compiler and linker invocations. A change in how it plans those invocations changes what every Swift build in the world does, which is why the project treats it as infrastructure rather than as a tool.

The swift-driver project is the primary implementation of that driver. The README says it has replaced the legacy driver that lived in lib/Driver in the main Swift repository, and the stated reasons are a code base that is easier to maintain and extend, a library-based architecture that allows better integration with build tools, the reuse of existing Swift build technologies such as SwiftPM and llbuild, and a platform for experimenting with more efficient build models, including compile servers and unifying build graphs across different driver invocations.

That last pillar is the most interesting one for an adopter, because unifying build graphs across driver invocations is the kind of change that alters build times rather than build results.

## Building it with SwiftPM, and the Windows linker problem

The preferred build is the Swift package manager, and on most platforms it is a single command:

```
$ swift build
```

Windows is the exception, and the reason is specific rather than incidental. The README explains that Swift Package Manager does not differentiate between C/C++ and Swift targets, and uses the Swift driver as the linker driver, so on Windows the Swift runtime has to be linked into all targets manually:

```cmd
swift build -Xlinker "%SDKROOT%\usr\lib\swift\windows\x86_64\swiftCore.lib"
```

This is the kind of detail that only shows up in a README written by people who hit the problem. It also tells you something about the architecture: because the driver is itself the linker driver in that configuration, the toolchain and the driver cannot be cleanly separated on Windows, and the runtime has to be supplied by hand for every target.

The result of the build is a swift-driver binary, and from there the README explains how to use it in place of the driver that already ships with your toolchain. You create symbolic links from swift and swiftc to swift-driver:

```
ln -s /path/to/built/swift-driver $SOME_PATH/swift
ln -s /path/to/built/swift-driver $SOME_PATH/swiftc
```

The two names matter, because the driver has to answer to both of them to be a drop-in replacement.

## Pointing SwiftPM and Xcode at your own driver build

Once the symlinks exist, the way to use them is through two environment variables. SWIFT_EXEC is set to refer to the swiftc symlink, and SWIFT_DRIVER_SWIFT_FRONTEND_EXEC is set to refer to the original swift-frontend:

```
SWIFT_EXEC=$SOME_PATH/swiftc SWIFT_DRIVER_SWIFT_FRONTEND_EXEC=$TOOLCHAIN_PATH/bin/swift-frontend swift build
```

The split is worth understanding. The driver is the piece you have replaced, and the frontend is the piece of the toolchain that actually compiles Swift code, so it stays pointed at the installed toolchain. The names in the variables are also a hint about how the driver locates its neighbours, since the driver has to find swift-frontend somewhere and the environment is one of the ways it does it.

The same trick works inside Xcode. The README says you can use the Swift driver within Xcode by adding a custom build setting, usually at the project level, named SWIFT_EXEC that refers to the swiftc symlink.

There is a related detail in the Xcode testing section, which explains that running the driver with a custom toolchain requires setting the TOOLCHAINS environment variable, and that this tells xcrun which toolchain to use, on darwin where xcrun is used to find tools. The variable takes the toolchain name rather than a path, for example Swift Development Snapshot. The README also notes that xcrun lookup is lower priority than the SWIFT_EXEC_*_EXEC family of environment variables, the tools directory, and any tools in the same directory as the driver.

That priority list is the practical answer to the question of which mechanism wins when several are in play.

## The CMake route needs llbuild and two other dependencies first

CMake is offered for environments where the Swift package manager is not yet available, and the README is explicit that several dependencies have to be built first, all with CMake.

The list is swift-corelibs-foundation on non-Apple platforms, llbuild, and swift-argument-parser. llbuild needs its own configuration, with the Swift bindings enabled and, on an Intel machine, the architecture set:

```
cmake -B <llbuild-build-dir> -G Ninja <llbuild-source-dir> -DLLBUILD_SUPPORT_BINDINGS="Swift" -DCMAKE_OSX_ARCHITECTURES=x86_64
```

Then the driver itself, pointing at the CMake module directories of the three dependencies:

```
cmake -B <swift-driver-build-dir> -G Ninja <swift-driver-source-dir> -DTSC_DIR=<swift-tools-support-core-build-dir>/cmake/modules -DLLBuild_DIR=<llbuild-build-dir>/cmake/modules -DArgumentParser_DIR=<swift-argument-parser-build-dir>
cmake --build <swift-driver-build-dir>
```

The TSC_DIR variable points at swift-tools-support-core, which is not in the dependency list above, so the CMake path reaches into a fourth project that the SwiftPM path picks up transitively.

The repository layout reflects this dual build system. Alongside Sources/, Tests/, TestInputs/ and Utilities/ there is a cmake/ directory and a CMakeLists.txt at the root, plus Package.swift and Package.resolved for the SwiftPM path, so both build systems are maintained in the same tree rather than one being generated from the other.

## Testing runs against trunk, and there is a Linux container recipe

The test suite runs with the standard command:

```
$ swift test --parallel
```

The README then explains something about the CI arrangement that changes how you develop against the driver. The swift-driver continuous integration runs against the most recent trunk development snapshot published at swift.org. The advice for a patch with complex interactions with the underlying Swift compiler frontend is to check that the swift-driver tests also pass against the current tip-of-trunk Swift, which is done by creating an empty pull request against the main Swift repository and asking for cross-repository testing:

```
Using:
apple/swift-driver#208
@swift-ci smoke test
```

That is a two-repository workflow, and it is a direct consequence of the driver and the frontend being separate pieces that are released together but developed in separate trees.

For debugging on macOS without a Linux machine nearby, the README gives a container recipe. Pull the newest Swift image, then run it with your checkout mounted and the capabilities a debugger needs:

```
$ docker run -v /path/to/swift-driver:/home/swift-driver \
  --cap-add=SYS_PTRACE --security-opt seccomp=unconfined \
  --security-opt apparmor=unconfined -it swift:latest bash
```

Inside, the dependencies are installed with apt-get for libsqlite3-dev and libncurses-dev, and the tests are then run from the mounted directory.

The driver documentation itself is in the main Swift repository, with Driver.md for a conceptual overview and DriverInternals.md and DriverParseableOutput.md for the internals.

## Apache-2.0, releases tied to Swift versions, and who this is for

The licence is Apache-2.0, with the LICENSE.txt file at the root of the repository, and a .licenseignore file alongside it. Read those files for the terms, and this is not legal advice.

Release activity tracks the compiler closely. The tagged releases include swift-6.4.0-RELEASE on 2026-09-15, swift-6.3.1-RELEASE on 2026-04-24 and swift-6.3-RELEASE on 2026-04-14, and the last push to the repository was on 2026-10-19 with the repository not archived. The naming convention is the point: this is a component of the toolchain, so its versions are the toolchain's versions, and a driver build is not something you pick a version of independently.

That leads to the clearest statement of who this is for. The README describes the compiler driver as constantly evolving and improving, with numerous places for anyone with an interest to contribute. This is a project for people who work on the Swift toolchain, and secondarily for people who want to understand what their build system is doing.

For everyone else, the shipped driver in their toolchain is the one to use. The value of reading this repository is in the design, in the documentation, and in the fact that the driver is now Swift code rather than C++, which matters for anyone extending it or debugging it.

## Where swift-driver is the wrong tool

The first wrong fit is a team that just wants to build Swift. The toolchain you installed already contains a driver, and the releases in this repository are published with the toolchain. Rebuilding it to compile your own code is work with no return, unless your goal is to change the driver itself.

The second is a Windows environment that cannot link the Swift runtime by hand. The Windows build path needs the runtime linked into every target because SwiftPM does not separate C/C++ and Swift targets there, and if your build environment does not allow that manual step, the CMake route exists but needs llbuild, swift-corelibs-foundation, swift-argument-parser and swift-tools-support-core built first. That is a heavy prerequisite list for a driver you could simply use.

The third is the risk that comes with the swap itself. Pointing SWIFT_EXEC at your own build means the thing deciding how your code compiles is a binary you built, and the interaction points are the ones the README flags: the driver has to find the right frontend, xcrun lookup is lower priority than the environment variables and the tools directory, and a driver installed inside a toolchain takes priority as well. An environment with several of these in play at once is exactly where a subtly wrong toolchain gets picked up.

The fourth is the documentation split. The conceptual overview of the driver and its internals live in the main Swift repository rather than here, so understanding how the piece actually works means reading across two projects. That is a reasonable arrangement for a toolchain component, and a mild tax for anyone evaluating it on its own.

## Conclusion

swift-driver fits contributors to the Swift toolchain who want a code base in Swift rather than C++, and anyone curious about how swift build turns into compiler invocations. It does not fit a team that merely wants to compile Swift, since the toolchain already ships a driver, and it does not fit a Windows setup that cannot link the Swift runtime manually. Before adopting it locally, build it with swift build and then point SWIFT_EXEC at the resulting swiftc symlink, and expect the CMake path to need three dependencies built first.

## FAQ

### What is swift-driver?

It is the primary implementation of the Swift compiler driver, the program that coordinates compiling Swift source into executables, libraries, object files, modules and interfaces, and that you invoke as swift or swiftc. It has replaced the legacy driver and is written in Swift.

### How do I build swift-driver locally?

The preferred way is the Swift package manager, with swift build on most platforms. On Windows you also need to link the Swift runtime manually with swift build -Xlinker pointing at swiftCore.lib, because SwiftPM does not separate C/C++ and Swift targets there.

### How do I use a locally built driver instead of the toolchain one?

Create symbolic links from swift and swiftc to your built swift-driver, then set SWIFT_EXEC to the swiftc link and SWIFT_DRIVER_SWIFT_FRONTEND_EXEC to the original swift-frontend. Inside Xcode, add a custom build setting named SWIFT_EXEC that points at the same link.

### Can swift-driver be built with CMake instead of SwiftPM?

Yes, and the README suggests it for environments where the Swift package manager is not yet available. It requires swift-corelibs-foundation on non-Apple platforms, llbuild and swift-argument-parser to be built first with CMake, along with the swift-tools-support-core CMake modules.

### How is swift-driver tested?

With swift test --parallel, and its continuous integration runs against the most recent trunk development snapshot of the Swift compiler. The README also documents a Linux Docker setup for debugging and a cross-repository smoke test for patches that interact with the compiler frontend.

## Sources

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

---

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