Swift Package Manager: understand resolve, reset and update

Swift Package Manager: understand resolve, reset and update

Β·

3 min read

Table of contents

I will explain the operations

  • resolve
  • reset
  • update

and how these commands affect a Swift Package. I will further show how to invoke those operations from the command line or within Xcode.

I use the following example: a package with a single package dependency pinned to an exact version (Alamofire 5.4.0). The Package.swift manifest file:

// swift-tools-version: 5.6
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "Package1",
    products: [
        .library(
            name: "Package1",
            targets: ["Package1"]),
    ],
    dependencies: [
        .package(url: "https://github.com/Alamofire/Alamofire", .exactItem("5.4.0")),
    ],
    targets: [
        .target(
            name: "Package1",
            dependencies: [
                "AlamoFire"
            ])
    ]
)

Initially the package, created with swift package init command, had no Package.resolved file.

When I opened the package in Xcode and added the following line in Package.swift

    dependencies: [
        .package(url: "https://github.com/Alamofire/Alamofire", .exactItem("5.4.0")),
    ],

then Xcode automatically started the dependency resolution and created a Package.resolved file in the top level of the package to record the result of the dependency resolution.

{
  "pins" : [
    {
      "identity" : "alamofire",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/Alamofire/Alamofire",
      "state" : {
        "revision" : "9e0328127dfb801cefe8ac53a13c0c90a7770448",
        "version" : "5.4.0"
      }
    }
  ],
  "version" : 2
}

If I had edited the Package.swift file in a text editor, I would have had to manually trigger the dependency resolution. See the next chapter :)

Resolve

swift package resolve

The swift package resolve command resolves the dependencies, taking into account the current version restrictions in the Package.swift manifest and Package.resolved resolved versions file, and issuing an error if the graph cannot be resolved.

Source: SPM Documentation

Key takeaway:

  • no changes to an existing Package.resolved file !!
  • creates a Package.resolved file if such does not exist.

The equivalent Xcode option is named "Resolve Package Versions".

Resolve Package Versions

When changing the Package.manifest to use a different version requirement, e.g.

    dependencies: [
        // Dependencies declare other packages that this package depends on.
        .package(url: "https://github.com/Alamofire/Alamofire", .upToNextMinor(from: "5.4.0"))
    ],

and running swift package resolve, then you need to understand that this will not bring any changes! Because Package.resolved was not changed.

Reset

swift package reset

This will reset the complete cache/build directory. For SPM (command-line) this will affect the .build folder.

The equivalent Xcode option is named "Reset Package Caches". This will affect the SourcePackages of the related folder in DerivedData.

Reset Package Caches

Update

The swift package update command will touch the Package.resolved file.

Running swift package update updates all dependencies to the latest eligible versions and updates the Package.resolved file accordingly.

Source: SPM Documentation

Remember I changed Package.swift to use a newer version of my package dependency:

    dependencies: [
        // Dependencies declare other packages that this package depends on.
        .package(url: "https://github.com/Alamofire/Alamofire", .upToNextMinor(from: "5.4.0"))
    ],

Running swift package update will change Package.resolved

{
  "pins" : [
    {
      "identity" : "alamofire",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/Alamofire/Alamofire",
      "state" : {
        "revision" : "d120af1e8638c7da36c8481fd61a66c0c08dc4fc",
        "version" : "5.4.4"
      }
    }
  ],
  "version" : 2
}

and will download the new version.

In Xcode the same can be achieved from the top-level menu

Update to Latest Package Versions

but also in the Package Dependency pane you can select "Update Package" on an individual package.

Update Package is the same as Update to Latest Package Versions

"Update Package" actually affects the whole Package.resolved file and is not truly package-specific.

Summary

  • If a download was interrupted then use "reset" and "resolve".

  • If you want to use a newer version or you changed version requirements in your Package.swift file then use "update".

Did you find this article valuable?

Support Marco Eidinger by becoming a sponsor. Any amount is appreciated!