Swift Package Manager

44.1 Package.swift

// swift-tools-version: 6.0
import PackageDescription

let package = Package(
    name: "WeatherKit",
    platforms: [.macOS(.v14), .iOS(.v17)],
    products: [
        .library(name: "WeatherKit", targets: ["WeatherKit"]),
        .executable(name: "weather-cli", targets: ["WeatherCLI"]),
    ],
    dependencies: [
        .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"),
        .package(url: "https://github.com/apple/swift-collections", from: "1.1.0"),
    ],
    targets: [
        .target(
            name: "WeatherKit",
            dependencies: [.product(name: "Collections", package: "swift-collections")],
            resources: [.process("Resources")],
            swiftSettings: [.enableUpcomingFeature("ExistentialAny")]
        ),
        .executableTarget(
            name: "WeatherCLI",
            dependencies: ["WeatherKit", .product(name: "ArgumentParser", package: "swift-argument-parser")]
        ),
        .testTarget(name: "WeatherKitTests", dependencies: ["WeatherKit"]),
    ],
    swiftLanguageModes: [.v6]
)

44.2 Commands

Concepts: products, targets, Package.resolved (lock file), resources (Bundle.module), binary targets (XCFrameworks), C/C++ targets, conditional dependencies by platform, plugins (build-tool plugins like SwiftGen/OpenAPI, command plugins like swift-format), local packages (.package(path:)), the Swift Package Index (swiftpackageindex.com), and registries.

swift package init --type library|executable|tool|macro|build-tool-plugin|command-plugin
swift build                    # debug build
swift build -c release
swift run weather-cli --city Pune
swift test --parallel
swift test --filter WeatherKitTests.ParserTests
swift package resolve | update | show-dependencies | describe
swift package add-dependency https://github.com/apple/swift-log --from 1.6.0   # (6.0)
swift package generate-documentation    # with the DocC plugin
swift build --swift-sdk x86_64-swift-linux-musl   # static Linux SDK (cross-compilation)

44.3 Command-Line Tools with ArgumentParser

import ArgumentParser

@main
struct Weather: AsyncParsableCommand {
    static let configuration = CommandConfiguration(abstract: "Fetch the weather for a city.")

    @Argument(help: "The city name.") var city: String
    @Option(name: .shortAndLong, help: "Units: metric or imperial.") var units = "metric"
    @Flag(help: "Show verbose output.") var verbose = false

    mutating func run() async throws {
        if verbose { print("Fetching \(city) in \(units)...") }
        print("☀️ 28°C in \(city)")
    }
}