1. What is Swift Package Manager?

The Swift Package Manager (SPM) is a tool for managing the distribution of source code, aimed at making it easy to share your code and reuse others code. Swift Package Manager provides a convention-based system for building libraries and executables, and sharing code across different packages.

2. Create a Library Package using Swift Package Manager

To create a new Swift package, open Terminal and first create a directory named SPMDemo, then enter in SPMDemo :

mkdir SPMDemo
cd SPMDemo

A library package contains code which other packages can use and depend on. To create run:

swift package init # or swift package init --type library

By default the init command creates a library package directory structure:

3. Package Overview

A package consists of Swift source files and a manifest file. The manifest file, called Package.swift, defines the package's name and its contents using the PackageDescription module. Here the Package.swift of SPMDemo package: (Read comments for description.)

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

import PackageDescription

let package = Package(
    name: "SPMDemo",
    products: [
        // Products define the executables and libraries produced by a package, and make them visible to other packages.
        .library(
            name: "SPMDemo",
            targets: ["SPMDemo"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        // .package(url: /* package url */, from: "1.0.0"),
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages which this package depends on.
        .target(
            name: "SPMDemo",
            dependencies: []),
        .testTarget(
            name: "SPMDemoTests",
            dependencies: ["SPMDemo"]),
    ]
)

4. Write Code

If you are using macOS you can create Xcode project for package using this command -

swift package generate-xcodeproj

This command will generate SPMDemo.xcodeproj file in package root directory. Now, you can open generated Xcode project and start writing code of your package inside Sources/SPMDemo/SPMDemo.swift file. But, if you are using Windows or Linux or even macOS, you can use Visual Studio Code. Here the guide to Install Swift in Windows 10 using WSL(Windows Subsystem Linux).

5. Build and Test Package

You can use swift build to build a package. This will download, resolve and compile dependencies mentioned in the manifest file Package.swift.

swift build

To run the tests for a package, use: swift test

swift test

6. Define Package Dependencies

If you want to add some other package dependencies in your package For e.g. if you want to use https://github.com/developerinsider/SPMDeveloperInsider as a dependency, add the GitHub URL in dependencies of your Package.swift and define tag. Also, don't forget to add this dependency in your target -

// swift-tools-version:4.0

import PackageDescription

let package = Package(
    name: "SPMDemo",
    products: [
        .library(
            name: "SPMDemo",
            targets: ["SPMDemo"]),
    ],
    dependencies: [
        .package(url: "https://github.com/developerinsider/SPMDeveloperInsider", from: "1.0.4"),
    ],
    targets: [
        .target(
            name: "SPMDemo",
            dependencies: ["SPMDeveloperInsider"]),
        .testTarget(
            name: "SPMDemoTests",
            dependencies: ["SPMDemo"]),
    ]
)

Now you can import the dependency and use in your package.

7. Publish your Package

To publish your package, create and push a version tag. You can use any familiar GUI based tool or console to publish your package.

git init
git add .
git remote add origin [github-URL]
git commit -m "Initial Commit"
git tag 1.0.0
git push origin master --tags

Now other packages can depend on version 1.0.0 of your package using the github url. Example of a published package: https://github.com/developerinsider/SPMDeveloperInsider

8. Version Specific Package/Logic

The Swift Package Manager is designed to support packages which work with a variety of Swift project versions, including both the language and the package manager version.

8.1 Version-specific tag selection

The package manager supports following marked tags, in order of preference:

  • MAJOR.MINOR.PATCH (e.g., 1.2.0@swift-4.1.2)
  • MAJOR.MINOR (e.g., 1.2.0@swift-4.1)
  • MAJOR (e.g., 1.2.0@swift-4)

8.2 Version-specific manifest selection

The package manager will additionally look for a version-specific marked manifest version when loading the particular version of a package, by searching for a manifest in the form of Package@swift-3.swift.

9. Create and Run an executable package

Swift Package Manager can create native binary which can be executed from command line. The process is exactly the same as we create library package, you just need to run this command to create an executable package -

swift package init --type executable

And, to run executable package, use:

swift build
swift run

10. Build Configurations

Swift Package Manager allows us two build configurations: Debug (default) and Release.

10.1 Debug

By default, running swift build will build in debug configuration. The build artifacts are located in directory called debug under build folder. A Swift target is built with following flags in debug mode:

  • -Onone: Compile without any optimization.
  • -g: Generate debug information.
  • -enable-testing: Enable Swift compiler's testability feature.

10.2 Release

To build in release mode, run:

swift build -c release

The build artifacts are located in directory called release under build folder. A Swift target is built with following flags in release mode:

  • -O: Compile with optimizations.
  • -whole-module-optimization: Optimize input files (per module) together instead of individually.

References