In order to better support distributed compilation caching with Swift open source toolchains, @akyrtzi , @cachemeifyoucan and I have requested a new swiftlang repository, swiftlang/toolchain-cas-plugin. This repository will contain an implementation of the LLVM CAS plugin API to support cross-platform distributed caching in SwiftPM and other swift build systems via a shared library distributed as part of the toolchain. In order to approve the repository, the ecosystem steering group has requested:
- A diagram that includes all components in a full setup including any remote component
- Any IPC or service protocol that developers are expected to implement
This post attempts to address those requests.
The following components are involved when using distributed caching via a SwiftPM build:
Toolchain components:
- SwiftPM - The tool users directly interact with. Maps user-specified caching configuration options to the build request provided to the underlying build system. Users interact with SwiftPM to configure the path to a socket used to communicate with their preferred caching daemon, and to initiate the build. Developers of distributed caching backends can choose to automate the setup process by scripting the SwiftPM CLI.
- Swift Build - Implementation detail of the toolchain. Uses the build request provided by SwiftPM to configure Swift/Clang tasks appropriately to enable caching and coordinates the scheduling of frontend, cache query, and upload tasks. When using compilation caching, interaction with the CAS is delegated to the compilers/compiler drivers and may fallback to the builtin LLVM CAS implementation if no LLVM CAS plugin is available. When using generic task caching for other build tools, Swift Build requires and uses the provided plugin’s API directly. Whether or not a plugin is available, it is important for all cached tasks in a build to share a CAS backend, to ensure size limits and eviction policies are consistently applied.
- Clang/Swift compilers - Implement support for dependency scanning and performing cached compiles. When configured to use remote caching, they load toolchain-cas-plugin at runtime and interact with it via the LLVM CAS plugin API.
- toolchain-cas-plugin - Implementation detail of the toolchain whose source is in the new repository. A shared library which implements the LLVM CAS plugin API described by llvm-project/llvm/include/llvm-c/CAS at next · swiftlang/llvm-project · GitHub. The CAS plugin provides both a local on-disk CAS and the ability to connect with a local caching daemon via a GRPC-based IPC mechanism. It is loaded at runtime by the compilers and/or build system. This repository will contain the canonical copy of the gRPC API used to communicate with caching daemon implementations.
Interchangeable user-provided components:
- Caching daemon - Handles GRPC requests from toolchain-cas-plugin. The implementation is expected to vary depending on the type of remote caching service being used and the context builds are running in. For example, a daemon running inside a CI environment’s ephemeral VM may handle cache uploads differently from a long lived daemon being used across many desktop builds.
- Remote caching service - Receives requests from the caching daemon via some implementation-defined mechanism. To allow remote caching to support a wide variety of potential use cases, the toolchain does not prescribe any particular API or authentication mechanism used to communicate between the caching daemon and remote service.
The gRPC protocol is defined by toolchain-cas-plugin and implemented by the caching daemon of a particular distributed caching implementation. The spec for this API is currently in swiftlang/llvm-project (llvm-project/llvm/lib/RemoteCachingService/RemoteCacheProto at next · swiftlang/llvm-project · GitHub) and is planned to move to swiftlang/toolchain-cas-plugin. Implementations may use any mechanism they choose to implement communication between a caching daemon and remote service.
