Skip to main content

Swift Package Commands

Introduction

Swift Package Manager (SPM) is a powerful tool for managing dependencies in Swift projects. It comes with a set of commands that help developers build, test, manage dependencies, and distribute Swift packages. These commands are executed through the swift package command-line interface.

In this guide, we'll explore the most commonly used Swift Package Manager commands, their options, and how to use them effectively in your development workflow. Whether you're new to Swift or looking to deepen your understanding of package management, this guide will help you become proficient with SPM commands.

Basic Swift Package Commands

Initializing a Package

To create a new Swift package, you can use the swift package init command:

bash
swift package init --type executable

This creates a new executable Swift package in the current directory with the following structure:

.
├── Package.swift
├── README.md
├── Sources
│ └── YourPackageName
│ └── main.swift
└── Tests
└── YourPackageNameTests
└── YourPackageNameTests.swift

You can specify different types of packages with the --type flag:

  • executable: Creates a package with a main.swift file (default)
  • library: Creates a package without a main.swift file, intended to be used as a dependency

Example output:

Creating executable package: MyPackage
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/MyPackage/main.swift
Creating Tests/
Creating Tests/MyPackageTests/
Creating Tests/MyPackageTests/MyPackageTests.swift

Building a Package

To build a Swift package, use the swift build command:

bash
swift build

This compiles the sources in your package and creates an executable (if it's an executable package).

Options:

  • -c, --configuration: Specify the build configuration (debug or release)
  • -v, --verbose: Show verbose output

Example with release configuration:

bash
swift build -c release

Testing a Package

To run the tests for a package:

bash
swift test

Options:

  • --filter: Run specific tests (e.g., swift test --filter MyTests)
  • --parallel: Run tests in parallel
  • -v, --verbose: Show verbose output

Example running a specific test:

bash
swift test --filter MyPackageTests.MyTestCase/testExample

Output:

Test Suite 'Selected tests' started at 2023-09-15 14:30:45.123
Test Suite 'MyPackageTests.xctest' started at 2023-09-15 14:30:45.456
Test Suite 'MyTestCase' started at 2023-09-15 14:30:45.789
Test Case 'MyTestCase.testExample' started at 2023-09-15 14:30:45.901
Test Case 'MyTestCase.testExample' passed (0.023 seconds)
Test Suite 'MyTestCase' passed at 2023-09-15 14:30:46.012
Test Suite 'MyPackageTests.xctest' passed at 2023-09-15 14:30:46.123
Test Suite 'Selected tests' passed at 2023-09-15 14:30:46.234

Dependency Management Commands

Resolving Dependencies

To resolve dependencies without building:

bash
swift package resolve

This updates the Package.resolved file with the appropriate versions of dependencies.

Updating Dependencies

To update your package dependencies to their latest versions:

bash
swift package update

This updates all dependencies to the latest allowed versions according to the constraints specified in your Package.swift file.

Showing Dependencies

To see a list of all dependencies and their versions:

bash
swift package show-dependencies

Example output:

example-package
├── swift-algorithms 1.0.0
└── swift-numerics 1.0.0
└── swift-system 1.0.0

Adding Dependencies

While there's no direct command to add dependencies, you need to manually edit your Package.swift file:

swift
// swift-tools-version: 5.7
import PackageDescription

let package = Package(
name: "MyPackage",
dependencies: [
.package(url: "https://github.com/apple/swift-algorithms.git", from: "1.0.0"),
],
targets: [
.executableTarget(
name: "MyPackage",
dependencies: [
.product(name: "Algorithms", package: "swift-algorithms"),
]),
.testTarget(
name: "MyPackageTests",
dependencies: ["MyPackage"]),
]
)

After editing, run swift package resolve to fetch the dependencies.

Advanced Commands

Cleaning the Build Directory

To clean your build directory:

bash
swift package clean

This removes the .build directory, which can be useful when you want to perform a clean build.

Generating an Xcode Project

To generate an Xcode project for your package:

bash
swift package generate-xcodeproj

This creates an Xcode project file that you can open to develop your package in Xcode.

With newer Xcode versions, you can also open the package directory directly:

bash
open Package.swift

Running Swift Tools

The Swift Package Manager can run tools provided by the package:

bash
swift run tool-name

For example, if your package includes an executable target named "Formatter":

bash
swift run Formatter

Checking Swift Package Manager Version

To check the version of your Swift Package Manager:

bash
swift package --version

Output example:

Swift Package Manager - Swift 5.7.0

Real-World Examples

Example 1: Creating and Building a Command Line Tool

Let's create a simple command line tool that uses the Swift Argument Parser library:

bash
# Create a new executable package
swift package init --type executable --name CommandLineTool

# Edit Package.swift to add dependencies
# Add the following to your dependencies array:
# .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.0.0"),
# And to your target dependencies:
# .product(name: "ArgumentParser", package: "swift-argument-parser"),

# Resolve dependencies
swift package resolve

# Edit Sources/CommandLineTool/main.swift

Now update main.swift to use the ArgumentParser:

swift
import ArgumentParser

struct Greet: ParsableCommand {
@Argument(help: "The name to greet")
var name: String

func run() throws {
print("Hello, \(name)!")
}
}

Greet.main()

Build and run the tool:

bash
swift build
swift run CommandLineTool Alice

Output:

Hello, Alice!

Example 2: Creating a Library Package and Using It in Another Project

First, create a library:

bash
# Create a library package
swift package init --type library --name MathLibrary

# Edit Sources/MathLibrary/MathLibrary.swift

Update MathLibrary.swift:

swift
public struct MathLibrary {
public init() {}

public func add(_ a: Int, _ b: Int) -> Int {
return a + b
}

public func subtract(_ a: Int, _ b: Int) -> Int {
return a - b
}
}

Now create an executable that uses this library:

bash
# In a different directory
swift package init --type executable --name MathApp

# Edit Package.swift to add a dependency to your local MathLibrary
# .package(path: "../MathLibrary")

Update main.swift in the new app:

swift
import MathLibrary

let math = MathLibrary()
print("2 + 3 = \(math.add(2, 3))")
print("5 - 2 = \(math.subtract(5, 2))")

Build and run:

bash
swift build
swift run MathApp

Output:

2 + 3 = 5
5 - 2 = 3

Summary

Swift Package Manager commands provide a powerful set of tools for creating, building, testing, and managing Swift packages. In this guide, we've covered:

  • Creating packages with swift package init
  • Building packages with swift build
  • Testing packages with swift test
  • Managing dependencies with commands like resolve and update
  • Advanced commands for generating Xcode projects and running tools
  • Real-world examples of creating and using packages

By mastering these commands, you can efficiently manage your Swift projects and dependencies, making your development workflow smoother and more productive.

Additional Resources

Exercises

  1. Create a new library package and implement a string utility with functions like capitalizing words and counting characters.

  2. Create an executable package that uses your string utility library.

  3. Add a third-party dependency to your project (like Swift Algorithms) and explore how to use it in your code.

  4. Write tests for your string utility functions and run them using swift test.

  5. Try building your package in release mode and compare the performance with debug mode.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)