Hello, I'd like to start a discussion of having the System module available in the Swift toolchain, rather than the current situation of it being available only on Darwin with SystemPackage available on other platforms. I wrote this up as a "pitch" or "proposal", but that's just the vehicle for the discussion as there's no formal pitch or proposal mechanism for toolchain inclusion (and I'm not convinced there should be one).
You can see the full gist here
Integrating Swift System into the Swift Toolchain
- Proposal: TBD
- Authors: Michael Ilseman, Guillaume Lessard
- Review Manager: TBD
- Status: Draft
Introduction
This proposal requests the inclusion of Swift System in official Swift toolchain releases for all supported platforms. Swift System provides idiomatic Swift interfaces to system calls and low-level currency types such as FilePath, serving as a foundational building block for the Swift ecosystem.
Motivation
Swift System provides idiomatic Swift interfaces to system calls and low-level currency types. It is the replacement for importing C system interfaces directly.
Swift is designed to have both the standard library and Foundation in the toolchain. System fits naturally alongside them, and toolchain libraries like Foundation can use System types in their API once System is in the toolchain.
Toolchain Versioning
Components in the Swift toolchain are versioned together with each Swift release. The standard library, Foundation, and imported platform interfaces all share this property: they come with the toolchain and their APIs are tied to Swift versions. This allows toolchain components to use the exact same types in their API as the application. The toolchain's Swift.Int is the same as the application's Swift.Int, even under separate compilation.
This is not true for types defined in packages. A type from one version of a package is a distinct type from a type with the same name from another version. If a toolchain library exposes a type in its API, then user code must have the exact same version of that type. If the toolchain were to use a type from a package, then the toolchain's version has to transitively constrain all other versions, leading to whole-ecosystem rev-locking.
Swift System belongs in the toolchain, versioned with the imported C interfaces and Foundation.
Platform Parity
Currently, Swift developers face an inconsistent experience across platforms:
- Darwin platforms:
import Systemworks out of the box via the Apple SDK - Linux/Windows: Developers must add Swift System as a package dependency and use
import SystemPackage
This inconsistency creates confusion and friction for developers writing cross-platform code. A library that works seamlessly on macOS requires additional configuration and a different import statement on Linux. Including Swift System in the toolchain would enable import System to work uniformly across all platforms.
Consider swift-build, which must work both when built into Xcode (where the SDK provides System) and when built as a standalone SwiftPM package on Linux (where it must depend on swift-system's SystemPackage):
// Package.swift
.target(
name: "SWBBuildService",
dependencies: [
"SWBBuildSystem",
"SWBServiceCore",
"SWBTaskExecution",
.product(name: "SystemPackage", package: "swift-system",
condition: .when(platforms: [.linux, .android, .windows])),
],
),
// BuildServiceEntryPoint.swift
#if canImport(System)
import System
#else
import SystemPackage
#endif
With System in the toolchain, this becomes:
import System
Deploying Updates
The current fragmentation has led some libraries to only use SystemPackage, meaning that the package's implementation is compiled into the application. Run-time updates and improvements, such as security fixes, cannot be applied without recompiling. This defeats the purpose of shared libraries and OS updates on platforms that vend the Swift toolchain as part of the OS.
Note on Server-Side Deployments
Toolchain inclusion means getting new System API requires a toolchain update. From a server-side perspective, toolchain inclusion might appear to be a regression if the server deployment uses older toolchains while adopting newer package versions. However, this is already the case for Foundation, which has a far larger API surface. Furthermore, server-side deployments already depend on toolchain updates for security patches and new functionality. System in the toolchain does not meaningfully change this situation.
Production Readiness
Swift System already ships as a source-stable and ABI-stable module on Darwin platforms, demonstrating its maturity and suitability for inclusion in official releases.
Proposed Solution
We propose that Swift System be added to official Swift toolchain releases, governed as part of the Swift project under the following structure:
| Aspect | Proposal |
|---|---|
| Repository | Move to the swiftlang GitHub organization |
| License | Apache 2.0 with Runtime Library Exception (current) |
| Governance | Foundation Workgroup |
| Evolution | Lightweight process for direct API additions, formal evolution for others |
Detailed Design
What Would Be Added
The toolchain would include all current Swift System API, including platform-specific interfaces such as IORing on Linux and Mach.Port on Darwin.
Repository
Swift System is currently developed at GitHub - apple/swift-system: Low-level system calls and types for Swift.
The repository is already structured consistently with other Swift project repositories (build system, CI infrastructure, documentation). We see no obstacles to moving it to the swiftlang GitHub organization and believe this transition is straightforward.
Licensing
Swift System is already licensed under the Apache 2.0 license with Runtime Library Exception. This is the same license used by the Swift project, so no licensing changes are required.
Governance
As a library providing fundamental types used by Foundation and other core libraries, Swift System would be managed by the Foundation Workgroup.
Swift Evolution Process
We propose a tiered review process appropriate to the nature of Swift System's API:
Pull request review: Small additions that follow established System conventions can be reviewed and approved directly in the pull request by the Foundation Workgroup. This includes adding a missing syscall wrapper, a new overload to an existing API family, or rounding out coverage gaps. These are straightforward translations of existing, documented platform APIs where the Swift interface follows patterns already established in System.
Forum review: Larger additions go through public discussion on the Swift forums before approval. This includes new topic areas (e.g. sockets), new abstractions or non-trivial types (e.g. TerminalAttributes), or anything that involves novel API design rather than direct translation. These benefit from more formal review and visibility, especially since they may establish patterns that future API will follow.
Versioning
Once included in the toolchain, Swift System would follow toolchain versioning rather than independent package versioning. New API would be tied to Swift releases.
Source Compatibility
This change is additive. Existing code is unaffected.
On Linux and Windows, code currently using import SystemPackage can migrate to import System for consistency with Darwin.
Migration from SystemPackage
While code can be written identically against System and SystemPackage (they are source-compatible), they define distinct types. A SystemPackage.FileDescriptor is not the same type as System.FileDescriptor. Code that passes a FileDescriptor across a module boundary must agree on which module it comes from.
Toolchain inclusion improves this situation, as all code in the same process sees the same System.FileDescriptor.
For gradual migration, SystemPackage will provide conversions between its types and the toolchain's System types. For example:
import System
import SystemPackage
let packageFD: SystemPackage.FileDescriptor = ...
let systemFD: System.FileDescriptor = System.FileDescriptor(converting: packageFD)
See the adaptors sketch.
ABI Compatibility
Swift System is already ABI-stable on Darwin. The toolchain-included version would maintain ABI stability across all platforms.
Alternatives Considered
Continue as a Package Only
We could continue shipping Swift System only as a package, requiring non-Darwin platforms to add it as a dependency. However, this perpetuates the platform inconsistency and prevents Foundation from depending on System types in a cross-platform manner. The fragmentation between System (Darwin SDK) and SystemPackage (Swift Package) creates ongoing friction for the ecosystem.
Include Only a Subset (e.g., FilePath without io_uring)
We considered including only the cross-platform subset of Swift System, omitting platform-specific APIs like IORing (Linux) and Mach.Port (Darwin). However, this would artificially limit the library's utility for systems programming. Platform-specific APIs are a natural part of a systems library and are already handled through conditional compilation. Developers expect to access platform-native capabilities when writing systems code.
Different Governance Structure
We considered placing Swift System under the Language Workgroup or creating a dedicated Systems Workgroup. However, Swift System's primary role is providing foundational types that Foundation and other core libraries depend on, making the Foundation Workgroup the natural home for governance decisions.
Sink Cross-Platform Types into Stdlib, Keep Syscall Wrappers in Package
We could add cross-platform types like FilePath to the standard library while keeping lower level types (e.g. FilePermissions) and syscall wrappers in a package. This would be reviewed on a case by case basis and more types might get moved over time. Each movement would cause some migration for users of SystemPackage to move off of a package defined type to the toolchain defined type.
However, a type without relevant operations is awkward to use and leaves developers unsure on where to look for them. Looking for this functionality inside the toolchain would likely lead them to using the imported C interfaces and all the problems therein: extracting rawValues and losing type safety, accessing raw pointers and losing memory safety, forgetting to check for errors or interrupts, etc.
This approach also risks fragmenting the ecosystem. We are adding a type to the stdlib, but it is a package that is ultimately defining the semantics and use of the type. That is, the package "owns" the API while the stdlib owns the type definition (and ABI representation, e.g. memory layout). We may need some mechanism to communicate to developers to look for the package to actually use the type, while also communicating to package authors that a certain package should be treated as the "base" definition for a type in the stdlib and their extensions should be layered on top of that other package.
While it might be the case that Swift is improved by moving types from one place to another (such as FilePath), that's a separate discussion and wouldn't fix the fundamental issues this proposal addresses.
Acknowledgments
Swift System was originally developed at Apple with contributions from the broader Swift community.