What's new in Swift Package Manager in Swift 5.4

Swift Scripting
27 April 2021

Along with the brand new Xcode 12.5, Swift 5.4 and its associated Swift Package Manager (SPM from now on) are now officially released. While 5.4 might look like a small release for SPM, there are actually a lot of changes, in this article let's have a look at the main ones.

The biggest release so far (?)

Even before talking about the actual changes, this release is one of the biggest (if not the biggest) for SPM to date, this is also justified by the recent expansion of the dedicated team at Apple and the new support for Windows.

Here are all the stats of the most recent releases:

Since we're at it, here's a sneak peek at SPM 5.5, which is still a few months away:

  • Swift 5.5 vs 5.4: 374 changed files with 28,185 additions and 6,539 deletions (at the time of writing).

While these stats alone don't mean much, it's clear that a lot is happening on this project, let's have a look at the actual changes next.

External changes

Targets declaration

Up to Swift 5.3 targets declarations were separated in:

  • .target(...) for regular and executable targets
  • .binaryTarget(...) for binary targets that reference an artifact on disk
  • .testTarget(...) for testing targets
  • .systemLibrary(...) for system library targets

Where the difference between a regular target and an executable one was the presence (or not) of a main.swift file, which was then used as the entry point for an executable target.

In Swift 5.3 we've seen the introduction of the @main attribute, explicitly defining a new application entry point, regardless of the where its declaration is located.

In Swift 5.4 SPM gains a new .executableTarget(...) target, exclusively dedicated to executables, where SPM will support either having a main.swift entry point or a @main declaration (at any location).

From now on .target(...) will be used only for regular targets and nothing else, improving the package manifest readability.

(Linux) Test discovery

Until Swift 5.3 every package supporting Linux needed to have a LinuxMain.swift file in the Tests folder root: this file was needed to explicitly declare/list all the tests to be executed. From SPM 5.4 this LinuxMain.swift is no longer necessary.

This same file was previously not needed/used in macOS platforms, as macOS relies on the Objective-C runtime for such discovery, like it does for .xcodeproj test suites.

The way it now works is by building an IndexStore of the tests and run the outcome through a TestDiscoveryCommand, which will then generate the LinuxMain.swift file at build time.

This functionality was previously available via a --enable-test-discovery flag to be passed on a $ swift test command, it's now enabled by default.

Package dependency cache

Prior to Swift 5.4, if we had two completely separate packages with the same dependency, that dependency would have been downloaded twice and put in the .build folder of each of our packages.

From Swift 5.4 SPM keeps a per-user cache in a new ~/.swiftpm/cache folder (or equivalent in other platforms), which will then be queried before fetching anything from the Internet: this will be a huge time/data saver, especially when using the same dependency in multiple, independent packages.

Internal changes

Argument parser

Apple's ArgumentParser has been released a little over an year ago, during this time it became the de-facto standard for every swift CLI tool out there: it should come with no surprise that SPM has now adopted it.

Previously SPM used TSCUtility's ArgumentParser which we covered here.

Good bye swift-tools-support-core

swift-tools-support-core is a collection of utilities used within SPM and llbuild: SPM kept a vendored copy of this package in its own repository, for CI/testing purposes.

Keeping this copy meant that every change had to be synced between the two repositories: fortunately this is no longer the case, as SPM no longer needs such vendored copy.

New module: Basics

Basics is a new module that contains SPM specific utilities that shouldn't be part of swift-tools-support-core. For example the per-user cache location can be found in this module.

This module name is a blast from the past: swift-tools-support-core's TSCBasic was originally called Basic.

New module: PackageCollections

Package Collections is the first module out of three of a new package discovery functionality being added into SPM, the other two being Package Registry and Package Index.

Package Collections focuses on handpicked packages lists, and provides a CLI tool, $ swift package-collection, in order to read and explore such lists.

While this functionality is officially being added in Swift 5.5, the ground work is already part of SPM as of Swift 5.4 (note that $ swift package-collection is not exposed in 5.4, making it inaccessible)

For more details on PackageCollections, refer to its Swift Evolution proposal and documentation.

Conclusions

SPM has gotten a lot of attention in the last couple of years, and its development pace seems to be only increasing!

In this article we took a sneak peek to its main changes of the upcoming release, however there are many other changes not highlighted here: feel free to explore them yourself!

What are you most excited about SPM future? Let me know via email or twitter!

⭑⭑⭑⭑⭑

Related articles

More Swift articles

Browse all

More Scripting articles

Browse all