Setting the Swift Language mode for an SPM Package

Published on: August 21, 2024

When you create a new Swift Package in Xcode 16, the Package.swift contents will look a bit like this:

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

import PackageDescription

let package = Package(
    name: "AppCore",
    products: [
        // Products define the executables and libraries a package produces, making them visible to other packages.
        .library(
            name: "AppCore",
            targets: ["AppCore"]),
    ],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .target(
            name: "AppCore"
        )
    ]
)

Notice how the package's Swift tools version is set to 6.0. If you want your project to reference iOS18 for example, you're going to need to have you Swift tools version set to 6.0. A side effect of that is that your package will now build in the Swift 6 language mode. That means that you're going to get Swift's full suite of sendability and concurrency checks in your package, and that the compiler will flag any issues as errors.

You might not be ready to use Swift 6.0 in your new packages yet. In those cases you can either set the Swift tools version back to 5.10 if you're not using any features from the 6.0 toolchain anyway or you can set your package's language mode to Swift 5 while keeping the 6.0 toolchain:

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

import PackageDescription

let package = Package(
    name: "AppCore",
    platforms: [.iOS(.v18)],
    // ... the rest of the package description
    swiftLanguageModes: [.v5]
)

It's also possible to assign the swift language mode for specific targets in your package instead. Here's what that looks like:

targets: [
  // Targets are the basic building blocks of a package, defining a module or a test suite.
  // Targets can depend on other targets in this package and products from dependencies.
  .target(
    name: "AppCore",
    swiftSettings: [.swiftLanguageMode(.v5)]
  )
]

By using the Swift 5 language mode you can continue to write your code as usual until you're ready to start migrating to Swift 6. For example, you might want to start by enabling strict concurrency checks.

Subscribe to my newsletter