Build Tools Used by the Apple Container Project: A Complete Technical Guide
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 using the Swift tools version directive:
// 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, the Package initializer defines all products, executable targets, and external dependencies:
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– invokesswift build -c debugto compile the default debug configurationmake release– produces a signed installer package (.pkg) after running a release buildmake install– copies built artifacts to system directoriesmake protos– triggers Protocol Buffer generation via the includedProtobuf.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
.protodefinitions - protoc-gen-grpc-swift-2 – generates gRPC client/server code for Swift
These plugins are defined as SPM targets in Package.swift and built before the main compilation phase.
Generating Stubs
Running make protos executes the following logic from Protobuf.Makefile:
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 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:
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 treemake 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:
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:
-
Initialize Protocol Buffers – Run
make protosto download protoc, build the Swift plugins, and generate gRPC stubs from.protodefinitions. -
Compile the CLI – Execute
make buildto invokeswift build -c debug, or usemake clito build only thecontainerexecutable target:
cli:
@$(SWIFT) build -c $(BUILD_CONFIGURATION) $(SWIFT_CONFIGURATION) --product container
@install "$(BUILD_BIN_DIR)/container" "bin/container"
-
Create Release Artifacts – Run
make releaseto produce a signed.pkginstaller suitable for distribution. -
Validate Changes – Execute
make coverageto run the full test suite with coverage instrumentation, or runmake fmtto auto-format code and update license headers before submitting.
Summary
- Swift 6.2 and SPM form the compilation core, defined in
Package.swiftwith the// swift-tools-version: 6.2directive. - Make orchestrates the entire pipeline through
MakefileandProtobuf.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
makecommands 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. 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →