swift-llbuild: a build engine for people who are writing a build system
A low-level build system, used by Xcode and the Swift Package Manager
At a glance
- What is it?
- llbuild is the low-level build system behind Xcode and the Swift Package Manager, and unlike most build system projects it is not about a syntax for describing builds, it is a reusable engine, a Ninja-compatible front end and a C API for embedding. This looks at the three products and where the design draws its line.
- Who is it for?
- llbuild fits a team writing its own build system, or one that needs a build engine it can embed and drive through an API rather than a command line, and it fits projects that have outgrown a manifest format and want to describe work in code. It does not fit a team that wants a working build today, because the value is in the engine and the surrounding format is deliberately yours to write.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.
Editorial analysis
An engine, where most projects ship a language
llbuild is described as a set of libraries for building build systems, and the readme draws the distinction immediately. Unlike most build system projects which focus on the syntax for describing the build, llbuild is designed around a reusable, flexible and scalable general purpose build engine capable of solving many build system-like problems.
That reframing is the whole design. A typical build system gives you a language, a manifest, and a fixed set of rules for how to describe a target. llbuild gives you the machinery: how to represent a task, how to decide what is out of date, how to run work in parallel, how to record results so a later run can skip it, and how to notice that a new piece of work has appeared because of what you just built. The description language, if there is one, is a separate concern.
The project includes additional libraries on top of the engine that provide support for constructing bespoke build systems, like `swift build`, or for building from Ninja manifests. So there are two routes in, and they are not equivalent: you can drive llbuild from an existing Ninja manifest, or you can describe the build in llbuild's own format.
The motivation section makes the LLVM lineage explicit. The design of llbuild is a continuation of the LLVM philosophy of applying library-based design to traditional developer tools, with Clang as the example: a high performance compiler delivered as a library, enabling tools like clang-format and the libclang interfaces, while the rigid command line interface between traditional build systems and the compiler still limits what can be optimised. The argument is that letting a build system and the tools it drives communicate through APIs instead of command lines opens up optimisation opportunities and more robust build systems, and the linked talk, A New Architecture for Building Software from the 2016 LLVM Developer's Conference, is the extended version of that argument.
The five properties the engine is built around
The philosophy section lists four properties that a build system is used to perform a task while also being, and it is worth reading them as a specification.
Incremental: outputs should be efficiently rebuilt given a small change to the inputs, by leveraging the ability to save partial outputs from a prior build. Consistent: equivalent inputs should always produce the same result as building from clean. Persistent: results should be stored so that builds can be interrupted and resumed after failure without redoing the full computation. Parallel and efficient: it must be possible to perform independent elements of the computation in parallel, to compute the result as efficiently as possible.
The last point of the section is the one that makes the project interesting beyond building software. The core technology of a build system is applicable to any complex, long-running computation in which the user commonly modifies only a small portion of the input before wanting the result recomputed, and the readme gives the example of a movie editor that has to re-render small portions of the overall movie in response to interactive edits, noting that such applications frequently do not take full advantage of the ability to store and partially recompute results because of the complexity of correctly managing the dependencies between parts of the computation. Part of the goal of designing llbuild around a general purpose build engine is to allow its use in contexts which are not traditionally thought of as requiring a build system.
That framing is also a hint about the limits. The engine is general, but the four properties are stated for the case where a user changes a small part of the input. A workload that is compute-bound rather than dependency-bound does not get much from incremental rebuilds, and the incremental and consistent properties pull against each other in exactly the places where a general engine has to make policy decisions that a specialised system would hard-code.
Three products, and the Ninja compatibility path
The project produces three top-level products: `llbuild`, `swift-build-tool`, and `libllbuild` with `llbuild.framework`.
The `llbuild` command line tool exposes various features of the libraries through subtools. The important one is Ninja build support:
$ llbuild ninja buildThe tool supports a subset of the command line arguments supported by Ninja itself, to allow it to be used as a compatible replacement, even by tools like CMake that depend on particular Ninja command line flags during their configuration process. That last clause is the practical constraint, and it is the one to test first if you are considering it as a Ninja replacement: CMake's configure step passes flags that Ninja accepts, and llbuild accepts a subset of them.
There is a convenience that says a lot about how the project sees itself. If you invoke `llbuild` via a symlink called `ninja`, it automatically uses this subtool, which supports installing llbuild as `ninja` into your `PATH` and then using it as an alternative to Ninja for building arbitrary projects like LLVM, Clang and Swift. This is also how the project self-hosts, via the CMake Ninja generator.
The Ninja subtool also provides additional commands primarily useful for developers working on the Ninja support, which allow testing the lexer, parser and manifest loading components independently, and they are used as part of the test suite.
The `swift-build-tool` product is the command line interface to the build system used by the Swift Package Manager. It is built as part of the Swift project build and incorporated into the Swift language snapshots, and it sits on top of the BuildSystem library documented in `docs/buildsystem.rst`.
Tracing a build, and the C API for embedding
Two features are worth pulling out of the documentation because they are the ones a user touches.
The first is build trace files. Inspired by Buck, `llbuild ninja` supports a `--profile PATH` option to generate a Chromium trace for visualising where time is spent during a build, and the readme includes a graph of a build of llbuild itself. The format being Chromium's trace event format is a practical choice, since it means the output can be dropped into a tool people already use, and it is the same format the other major build systems emit, so a team can compare a build under one engine against a build under another.
The second is the C API. The `libllbuild` library exposes a C API for the llbuild libraries, which can be used directly by third parties or to build additional language bindings, and the `bindings/` directory holds example Swift and Python bindings that use it. The readme also notes that this API is what is used in Xcode as the basis for the new build system introduced in Xcode 9.
That last point is the strongest single piece of evidence about the design's maturity, and it is the reason to believe the library-based approach was the right call rather than a stylistic preference. A C API is a commitment: once a third party links against it, the layout of the structures and the semantics of the functions become somebody's compatibility problem. The project accepted that cost because the alternative, a command line interface, was the thing it was trying to remove.
The repository is a build system that builds itself
The tree is a good map of what the project has to be.
There is `include/` and `lib/` for the public headers and the library implementations, `src/` for the core, `products/` for the shipped binaries, `bindings/` for the language bindings, `examples/` with `GameOfLife/`, `c-api/`, `simple-make/` and `swift-bindings/`, and `tests/` alongside `unittests/` and `perftests/`. The `docs/` directory holds the technical documentation, published at llbuild.readthedocs.io.
The build system story in the tree is the interesting part. There is a `CMakeLists.txt` at the root, a `Makefile` whose job is narrower than the name suggests, since its comment says it is a helper makefile for generating llbuild3 protobuf files. That target removes the generated `*.pb.*` files under `src`, runs `protoc` for the C++ output and then runs it again with the Swift plugin to produce Swift sources with `Visibility=Public` and the module map mappings, and a `proto-toolchain` target builds the toolchain itself with `utils/build_proto_toolchain.sh`.
There is also a `Package.swift`, so the project builds with the Swift Package Manager as well, an `llbuild.podspec` for CocoaPods, an `llbuild.xcodeproj/` for Xcode, and a `vcpkg.json` for the Windows package manager. A `Vagrantfile` is there for reproducible development environments, and `README.llbuild3.md` at the root suggests work on a third generation of the system alongside the current one.
So the project ships a library, three binaries, bindings in two languages, a Ninja front end, a C API and a native build description format, and it builds itself with the tool it provides.
Where llbuild is the wrong tool
Three limits are clear.
The first is that it is an engine and you have to drive it. There is no manifest to copy and no community package catalogue, because the point is that the description is yours. A team that wants a working build this afternoon is looking at a manifest-based tool, and the effort of evaluating llbuild is the effort of writing a build description, not the effort of installing a binary.
The second is the Ninja subset. The `llbuild ninja` subtool supports a subset of Ninja's command line arguments, and it is pitched as a compatible replacement even for tools like CMake that depend on particular Ninja flags during configuration. That is a qualified claim, and the qualification is exactly the risk. A build system that is a drop-in for the generator but not for the flags is a build system you have to test across every tool in your pipeline.
The third is the maintenance question. The releases here are Swift releases, swift-6.4.0-RELEASE, swift-6.2.4-RELEASE and swift-6.2.3-RELEASE, which tells you that llbuild is versioned as part of the Swift toolchain rather than on its own cadence. That is sensible for the Swift ecosystem and awkward for anyone who wants to track llbuild independently, because the version number of the engine is the version number of a language release. The last push to the repository was on 2026-10-15, and the licence is Apache-2.0, with the file named `LICENSE.txt`.
The documented contributions path is the Swift project's own, with the requirement to test your changes and follow the Swift project guidelines, which is a sensible bar for a component that Xcode and the Swift Package Manager both depend on.
Editorial conclusion
llbuild fits a team writing its own build system, or one that needs a build engine it can embed and drive through an API rather than a command line, and it fits projects that have outgrown a manifest format and want to describe work in code. It does not fit a team that wants a working build today, because the value is in the engine and the surrounding format is deliberately yours to write. It is also the wrong choice if the requirement is to drop in a drop-in replacement for Ninja across a whole toolchain, since the `llbuild ninja` subtool supports only a subset of Ninja's command line arguments. Before you start, read the build system documentation at llbuild.readthedocs.io and decide whether you want the Ninja path or the native one.
Frequently asked questions
What is llbuild and who uses it?
It is a set of libraries for building build systems, a reusable build engine rather than a build description language. It is used by Xcode, where its C API is the basis of the build system introduced in Xcode 9, and by the Swift Package Manager through the swift-build-tool product.
Can llbuild replace Ninja?
The `llbuild ninja` subtool supports a subset of Ninja's command line arguments, so it works as a compatible replacement for tools like CMake that depend on particular Ninja flags. It supports only a subset, so the flags your pipeline passes have to be checked.
What are the three products llbuild produces?
The `llbuild` command line tool with its subtools, the `swift-build-tool` command line interface to the Swift Package Manager's build system, and the `libllbuild` library with `llbuild.framework`.
How can I profile a build with llbuild?
The `llbuild ninja` subtool supports a `--profile PATH` option, inspired by Buck, which generates a Chromium trace for visualising where time is spent during a build. The readme includes a graph of a build of llbuild itself.
Can I embed llbuild in another tool?
Yes. The libllbuild library exposes a C API that third parties can use directly or to build additional language bindings, and the bindings/ directory in the repository contains example Swift and Python bindings. The documentation is published at llbuild.readthedocs.io.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/swiftlang-swift-llbuild)