Migration Plan: swift-corelibs-foundation to swift-foundation
As we progress with our plans for the future of Foundation, it is time to consider in more detail how we will migrate the Swift ecosystem from swift-corelibs-foundation, which is part of the Swift toolchain, to swift-foundation, which is a standalone package. Please let us know your thoughts and questions in this thread.
First, let's define the requirements for a transition:
-
Packages which use
swift-corelibs-foundation
today must continue to build and run. -
Packages must be able to adopt the new
swift-foundation
package -- even if they depend on packages which useswift-corelibs-foundation
, or packages that useswift-corelibs-foundation
depend on them.
After some experimentation, we believe we have a path forward. At a high level, the plan is:
-
Enable building
swift-corelibs-foundation
as a package, in addition to building as part of the toolchain. -
Make the
swift-corelibs-foundation
package depend on theswift-foundation
package. Re-export the FoundationEssentials and FoundationInternationalization modules fromswift-corelibs-foundation
. -
Delete now-duplicated types from
swift-corelibs-foundation
.
With these changes, everyone in the ecosystem, no matter which of the packages they import, will be using one implementation of core types like Date
, Data
, and JSONDecoder
.
Detailed implementation
The main principle behind this plan is that there must be only one definition of the core types in a process. If there is only one Date
, for example, then there can be no mismatch between types that are otherwise identical but coming from two different modules. We took the same approach for the Darwin Foundation.framework
, which has been refactored to use the same Swift source code as swift-foundation
and provides a single implementation for the entire OS.
Module availability
This new structure gives package authors the flexibility to choose which dependency they wish to use. For example, an author can choose to minimize code size on non-Darwin platforms if features like networking or internationalization are not required.
Module | Package | Note |
---|---|---|
FoundationEssentials | swift-foundation | also re-exported from swift-corelibs-foundation |
FoundationInternationalization | swift-foundation | also re-exported from swift-corelibs-foundation |
FoundationNetworking | swift-corelibs-foundation | |
FoundationXML | swift-corelibs-foundation | |
Foundation (Non-Darwin) | swift-corelibs-foundation | Does not include Networking or XML |
Foundation (Umbrella, Darwin) | Foundation.framework (SDK) | Includes all Foundation features |
Preliminary testing shows that a simple command-line utility built for Ubuntu 22.04 can reduce its binary size by approximately 60 MB when using FoundationEssentials
vs FoundationInternationalization
, assuming it does not need the internationalization functionality provided by the latter module. The size reduction comes primarily from omitting the locale databases included with the ICU library.
swift-corelibs-foundation
will re-export FoundationEssentials
and FoundationInternationalization
from Foundation
. This will provide all of the new API from those modules (notably FormatStyle
) for clients of swift-corelibs-foundation
without requiring them to transition immediately to the new modules. It is possible that differences between swift-corelibs-foundation
and swift-foundation
will cause some behavioral change at runtime, but we expect the risk to be only slightly more than the library fixing bugs or adding features with any other regular Swift update.
In short, swift-corelibs-foundation
will play the role of a compatibility layer between the new implementations and existing packages. The focus of our development will be on the swift-foundation
package.
XCTest
A branch of swift-corelibs-xctest
will be added that depends on the swift-corelibs-foundation
package instead of the toolchain swift-corelibs-foundation
. Test targets will use this branch to ensure the prescence of only one of the core Foundation types at runtime.
Swift Package Manager changes
In order to maintain compatibility with existing packages, SwiftPM will be updated to automatically add an implict dependency on the swift-corelibs-foundation
package when it detects the use of Foundation in a package. If an explicit dependency on swift-corelibs-foundation
or swift-foundation
is specified, that will take precedence. In a future swift-tools-version
, SwiftPM will no longer add the dependency and it must be specified by the Package.swift
file, the same as any other package dependency. A swift-corelibs-xctest
package dependency must also be added for test targets.
We also anticipate some improvements to the PackageDescription
API to allow more C flags to be passed through to the compiler without the use of unsafeFlags
. For example, CoreFoundation requires the use of -fconstant-cfstrings
.
Cross-platform compatibility
Many contributions have been made to swift-corelibs-foundation
to port the project to non-Darwin, non-Linux platforms. As we migrate the project to rebase itself on top of swift-foundation
, we will preserve these changes where appropriate to maintain swift-corelibs-foundation
's cross-platform compatibility. We anticipate the need for help from the community to make sure we have testing and validation coverage for platforms that are not part of Swift's normal continuous integration or release testing process. In many cases, this will require code written in C for CoreFoundation to be rewritten in Swift for swift-foundation
.
Using Foundation in Package.swift
and plugins
In order to support import Foundation
in Package.swift
and plugins, a version of the Foundation library will be available in the toolchain for use at package manifest parsing time only. This version of Foundation is not intended to be used at runtime. Our goal is to build this library from the same sources as the package version of swift-corelibs-foundation
, using cmake
as it does today. To simplify maintenance of this code, we may choose to narrow the types available to the most common APIs used in Package.swift
files.