Swift Package Manager Skill
Dependency management, package creation, and distribution with Swift Package Manager.
Prerequisites
- Swift 5.5+ toolchain
- Xcode 14+ or VS Code with Swift extension
- Git for version control
Parameters
parameters:
swift_tools_version:
type: string
default: "5.9"
platforms:
type: array
items: [iOS, macOS, watchOS, tvOS, visionOS, linux]
default: [iOS, macOS]
package_type:
type: string
enum: [library, executable, plugin]
default: library
Topics Covered
Package.swift Structure
| Element |
Purpose |
name |
Package name |
platforms |
Supported platforms/versions |
products |
Libraries/executables exposed |
dependencies |
External packages |
targets |
Build targets |
Dependency Specification
| Format |
Example |
| Version range |
.upToNextMajor(from: "1.0.0") |
| Exact version |
.exact("1.2.3") |
| Branch |
.branch("main") |
| Commit |
.revision("abc123") |
| Path |
.package(path: "../LocalPkg") |
Target Types
| Type |
Purpose |
.target |
Library code |
.executableTarget |
Command-line tool |
.testTarget |
Unit tests |
.plugin |
Build tool plugin |
.macro |
Swift macro |
Code Examples
Complete Package.swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "NetworkKit",
platforms: [
.iOS(.v15),
.macOS(.v12),
.watchOS(.v8),
.tvOS(.v15)
],
products: [
.library(
name: "NetworkKit",
targets: ["NetworkKit"]
),
.library(
name: "NetworkKitMocks",
targets: ["NetworkKitMocks"]
)
],
dependencies: [
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.0"),
.package(url: "https://github.com/apple/swift-collections.git", from: "1.0.0")
],
targets: [
.target(
name: "NetworkKit",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "OrderedCollections", package: "swift-collections")
],
resources: [
.process("Resources")
],
swiftSettings: [
.enableExperimentalFeature("StrictConcurrency")
]
),
.target(
name: "NetworkKitMocks",
dependencies: ["NetworkKit"]
),
.testTarget(
name: "NetworkKitTests",
dependencies: [
"NetworkKit",
"NetworkKitMocks"
],
resources: [
.copy("Fixtures")
]
)
]
)
Library with Multiple Targets
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "FeatureKit",
platforms: [.iOS(.v16), .macOS(.v13)],
products: [
// Main library
.library(name: "FeatureKit", targets: ["FeatureKit"]),
// Individual features for selective import
.library(name: "AuthFeature", targets: ["AuthFeature"]),
.library(name: "ProfileFeature", targets: ["ProfileFeature"])
],
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-composable-architecture", from: "1.0.0")
],
targets: [
// Core shared code
.target(
name: "Core",
dependencies: []
),
// Auth feature
.target(
name: "AuthFeature",
dependencies: [
"Core",
.product(name: "ComposableArchitecture", package: "swift-composable-architecture")
]
),
// Profile feature
.target(
name: "ProfileFeature",
dependencies: [
"Core",
.product(name: "ComposableArchitecture", package: "swift-composable-architecture")
]
),
// Umbrella target
.target(
name: "FeatureKit",
dependencies: ["AuthFeature", "ProfileFeature"]
),
// Tests
.testTarget(
name: "AuthFeatureTests",
dependencies: ["AuthFeature"]
),
.testTarget(
name: "ProfileFeatureTests",
dependencies: ["ProfileFeature"]
)
]
)
Command-Line Tool
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "swift-format-tool",
platforms: [.macOS(.v13)],
products: [
.executable(name: "swift-format-tool", targets: ["swift-format-tool"])
],
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.2.0"),
.package(url: "https://github.com/apple/swift-syntax", from: "509.0.0")
],
targets: [
.executableTarget(
name: "swift-format-tool",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "SwiftSyntax", package: "swift-syntax"),
.product(name: "SwiftParser", package: "swift-syntax")
]
)
]
)
Local Development Package
// In your app's Package.swift or Xcode project
// Use local path during development
// Package.swift with local override
let package = Package(
name: "MyApp",
dependencies: [
// Production: Use remote
// .package(url: "https://github.com/company/SharedKit", from: "1.0.0")
// Development: Use local
.package(path: "../SharedKit")
],
targets: [
.target(name: "MyApp", dependencies: ["SharedKit"])
]
)
Swift Macro Package
// swift-tools-version: 5.9
import PackageDescription
import CompilerPluginSupport
let package = Package(
name: "MacroKit",
platforms: [.macOS(.v10_15), .iOS(.v13)],
products: [
.library(name: "MacroKit", targets: ["MacroKit"])
],
dependencies: [
.package(url: "https://github.com/apple/swift-syntax", from: "509.0.0")
],
targets: [
// Macro implementation
.macro(
name: "MacroKitMacros",
dependencies: [
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
.product(name: "SwiftCompilerPlugin", package: "swift-syntax")
]
),
// Library that exposes the macro
.target(
name: "MacroKit",
dependencies: ["MacroKitMacros"]
),
// Tests for the macro
.testTarget(
name: "MacroKitTests",
dependencies: [
"MacroKitMacros",
.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax")
]
)
]
)
CLI Commands
# Create new package
swift package init --type library
swift package init --type executable
swift package init --type macro
# Build
swift build
swift build -c release
# Test
swift test
swift test --filter MyTests
# Update dependencies
swift package update
swift package update PackageName
# Resolve dependencies
swift package resolve
# Show dependencies
swift package show-dependencies
swift package show-dependencies --format json
# Generate Xcode project (deprecated but useful)
swift package generate-xcodeproj
# Clean
swift package clean
swift package reset
# Dump package description
swift package dump-package
Troubleshooting
Common Issues
| Issue |
Cause |
Solution |
| "No such module" |
Missing dependency |
Add to target dependencies |
| Version conflict |
Incompatible requirements |
Use version that satisfies all |
| Build fails on CI |
Different Swift version |
Pin swift-tools-version |
| Resources not found |
Wrong resource rule |
Use .process or .copy correctly |
| Xcode not seeing changes |
Cache stale |
Clean derived data |
Debug Tips
# Verbose build
swift build -v
# Check resolved versions
cat Package.resolved
# Dependency tree
swift package show-dependencies --format dot | dot -Tpng -o deps.png
# Rebuild from scratch
rm -rf .build Package.resolved
swift package resolve
swift build
Validation Rules
validation:
- rule: pin_versions
severity: warning
check: Use version ranges, not branch/revision in production
- rule: semantic_versioning
severity: error
check: Follow semver for your packages
- rule: platform_support
severity: info
check: Declare minimum platform versions
Usage
Skill("swift-spm")
Related Skills
swift-fundamentals - Language basics
swift-testing - Package testing
swift-architecture - Package design