# Build Tools Used by the Apple Container Project: A Complete Technical Guide

> Explore the build tools powering the apple/container project including Swift Package Manager Protocol Buffers protoc swift-format hawkeye and llvm-cov Get a comprehensive technical guide.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: deep-dive
- Published: 2026-06-27

---

**The apple/container project relies on Swift 6.2, Swift Package Manager (SPM), and Make as its primary build tools, augmented by Protocol Buffers compilers (protoc), swift-format, hawkeye for license compliance, and llvm-cov for test coverage analysis.**

The apple/container repository is a pure-Swift implementation of container management tooling that requires a specific, reproducible build environment. Understanding the build tools used by the apple/container project is essential for contributors compiling the CLI, running integration tests, or generating installer packages. This guide examines the complete toolchain based on the actual source files in the repository.

## Core Build Stack

### Swift 6.2 and Swift Package Manager

The foundation of the build system is **Swift 6.2**, declared at the top of [`Package.swift`](https://github.com/apple/container/blob/main/Package.swift) using the Swift tools version directive:

```swift
// swift-tools-version: 6.2

```

This declaration enforces the minimum compiler version required to parse the package manifest. **Swift Package Manager (SPM)** drives the entire dependency graph and compilation process. In [`Package.swift`](https://github.com/apple/container/blob/main/Package.swift), the `Package` initializer defines all products, executable targets, and external dependencies:

```swift
let package = Package(
    name: "container",
    products: [...],
    targets: [...]
)

```

The SPM handles the resolution of remote Swift packages, incremental builds, and target dependency ordering automatically.

## Build Orchestration with Make

While SPM manages Swift compilation, **Make** serves as the primary build orchestrator. The root `Makefile` provides a unified interface for developers, wrapping SPM invocations and coordinating auxiliary tools.

Key targets defined in `Makefile` include:

- `make build` – invokes `swift build -c debug` to compile the default debug configuration
- `make release` – produces a signed installer package (`.pkg`) after running a release build
- `make install` – copies built artifacts to system directories
- `make protos` – triggers Protocol Buffer generation via the included `Protobuf.Makefile`

The `Makefile` also defines `.PHONY` targets to ensure these commands always execute regardless of file timestamps.

## Protocol Buffer Generation Pipeline

The project uses **Protocol Buffers** for communication between the Container Builder shim and the CLI. The `Protobuf.Makefile` handles the complex toolchain required for Swift code generation.

### The protoc Toolchain

The build pipeline downloads **protoc** (version 26.1) and builds two custom plugins from the same repository:

- **protoc-gen-swift** – generates Swift structs from `.proto` definitions
- **protoc-gen-grpc-swift-2** – generates gRPC client/server code for Swift

These plugins are defined as SPM targets in [`Package.swift`](https://github.com/apple/container/blob/main/Package.swift) and built before the main compilation phase.

### Generating Stubs

Running `make protos` executes the following logic from `Protobuf.Makefile`:

```make
protos: $(PROTOC) protoc-gen-swift
	@$(PROTOC) $(LOCAL_DIR)/container-builder-shim/pkg/api/Builder.proto \
		--plugin=protoc-gen-grpc-swift=$(BUILD_BIN_DIR)/protoc-gen-grpc-swift-2 \
		--plugin=protoc-gen-swift=$(BUILD_BIN_DIR)/protoc-gen-swift \
		--grpc-swift_out="Sources/ContainerBuild" \
		--swift_out="Sources/ContainerBuild"

```

This command clones the *container-builder-shim* repository at the version pinned in [`Package.swift`](https://github.com/apple/container/blob/main/Package.swift) and generates Swift source files under `Sources/ContainerBuild`.

## Code Quality and Compliance Tools

The build system enforces strict code style and licensing standards through automated checks.

### swift-format

**swift-format** handles automatic code formatting and linting. The `Makefile` defines the `swift-fmt` target:

```make
swift-fmt:
	@$(SWIFT) format --recursive --configuration .swift-format -i $(SWIFT_SRC)

```

Configuration is stored in `.swift-format` and `.swift-format-nolint` files at the repository root. The `make fmt` target combines formatting with license updates.

### Hawkeye License Verification

**hawkeye** ensures every source file contains a valid Apache-2.0 license header. The `Makefile` provides two targets:

- `make update-licenses` – adds or updates license headers across the source tree
- `make check-licenses` – validates headers and fails the build if any are missing

The `check-licenses` target invokes a helper script to ensure the tool is installed:

```make
check-licenses:
	@./scripts/ensure-hawkeye-exists.sh
	@.local/bin/hawkeye check --fail-if-unknown

```

## Testing and Coverage Reporting

For test execution and coverage analysis, the build tools integrate with LLVM's coverage infrastructure.

### llvm-cov and llvm-profdata

The `Makefile` provides `coverage*` recipes that leverage **llvm-cov** and **llvm-profdata** to generate detailed reports. Running `make coverage` builds the project with instrumentation enabled, executes the test suite via `swift test`, and aggregates coverage data into human-readable reports.

This integration allows the CI pipeline to track code coverage metrics across unit and integration tests.

## Typical Development Workflow

Working with the apple/container project follows a standardized four-step process managed entirely through Make:

1. **Initialize Protocol Buffers** – Run `make protos` to download protoc, build the Swift plugins, and generate gRPC stubs from `.proto` definitions.

2. **Compile the CLI** – Execute `make build` to invoke `swift build -c debug`, or use `make cli` to build only the `container` executable target:

```make
cli:
	@$(SWIFT) build -c $(BUILD_CONFIGURATION) $(SWIFT_CONFIGURATION) --product container
	@install "$(BUILD_BIN_DIR)/container" "bin/container"

```

3. **Create Release Artifacts** – Run `make release` to produce a signed `.pkg` installer suitable for distribution.

4. **Validate Changes** – Execute `make coverage` to run the full test suite with coverage instrumentation, or run `make fmt` to auto-format code and update license headers before submitting.

## Summary

- **Swift 6.2 and SPM** form the compilation core, defined in [`Package.swift`](https://github.com/apple/container/blob/main/Package.swift) with the `// swift-tools-version: 6.2` directive.
- **Make** orchestrates the entire pipeline through `Makefile` and `Protobuf.Makefile`, managing dependencies beyond Swift compilation.
- **protoc** with custom Swift plugins generates gRPC code from Protocol Buffer definitions in the Container Builder shim.
- **swift-format** and **hawkeye** enforce code style and Apache-2.0 license compliance automatically.
- **llvm-cov** generates coverage reports when running `make coverage`.
- All tools are invocable through standard `make` commands without manual setup on macOS 26+ systems with a Swift toolchain installed.

## Frequently Asked Questions

### What version of Swift is required to build the apple/container project?

The project requires **Swift 6.2** or later, as declared by the `// swift-tools-version: 6.2` directive at the top of [`Package.swift`](https://github.com/apple/container/blob/main/Package.swift). This version requirement ensures compatibility with the package manifest syntax and language features used throughout the codebase.

### How do I generate the Protocol Buffer Swift files?

Run `make protos` from the repository root. This target downloads protoc (v26.1), builds the `protoc-gen-swift` and `protoc-gen-grpc-swift-2` plugins using SPM, and generates Swift source files under `Sources/ContainerBuild` from the `.proto` definitions in the container-builder-shim dependency.

### What build command produces the release installer?

Execute `make release` to generate a signed `.pkg` installer. This target configures SPM for release mode (`swift build -c release`), compiles the `container` executable, and assembles the final macOS installer package using the build configuration defined in the root `Makefile`.

### Can I build the project without using Make?

While possible by running `swift build` directly, using Make is strongly recommended. The `Makefile` handles prerequisite steps like protobuf generation, license verification, and proper binary installation paths that pure SPM commands do not automatically manage.