首页 / Swift 编程语言教程 / Swift Package Manager 入门

Swift 编程语言教程

Swift Package Manager 入门

本教程共 93 篇 · 第 88 篇 · 更新于 2026-08-08 · 约 7 分钟阅读

SwiftSwift 编程语言教程Swift Package ManagerSPMPackage.swifttarget依赖管理

本节目标:搞懂 SPM 是什么,能用命令行创建一个 Swift 包,并看懂 Package.swift 里 target、product、依赖这些概念。

写代码迟早要复用别人的成果。你想用一个好用的网络库、命令行参数解析库,总不能每次都去复制粘贴源码。Swift 官方自带了一个工具,专门帮你创建工程、管理依赖、编译运行,它就是 Swift Package Manager,大家习惯叫它 SPM。

SPM 不需要你额外安装。只要你装了 Swift 工具链(macOS 上的 Xcode 命令行工具,或 Linux 上的 swift 包),swift package 这条命令就已经在手上。它既能管你自己写的库,也能从 GitHub 这类地方拉取别人发布的包。

1-1 什么是 Swift Package Manager

SPM 是苹果从 Swift 3 时代就内置的官方包管理器。它把三件事合在了一起:定义包的结构、下载并管理依赖、调用编译器构建产物。换句话说,它既是工程的”目录规范”,也是”下载器”,还是”构建器”。

Note

在 Swift 6.3.2 里,SPM 已经非常成熟。日常写命令行工具、写服务端 Swift、或者把一段逻辑打成可复用库,基本都靠它。Xcode 工程也能直接用 SPM 添加依赖。

你可能听过 CocoaPods、Carthage,那是早期的第三方方案。现在苹果生态里,SPM 是官方首选,资料最多、接入也最简单。

1-2 创建一个新包

最直观的方式是敲几行命令。先建个空目录,再用 swift package init 初始化。

$ mkdir hello-pkg && cd hello-pkg
$ swift package init --type executable
$ swift build
$ swift run
Hello, world!

--type executable 表示你要做一个能直接运行的程序。如果你省略类型,默认也是创建可执行包;想做纯库则改用 --type library

swift build 负责编译,swift run 编译并立刻运行生成的二进制文件。第一次构建会慢一点,因为要下载并编译依赖(哪怕现在还没有依赖),之后就有缓存了。

1-3 包的目录长什么样

执行完 init,目录里会出现一套约定俗成的结构。你不用死记,但得知道每样东西干嘛用。

hello-pkg/
├── Package.swift      # 包的清单文件,最核心
├── Sources/           # 你的源码放这里
│   └── hello-pkg/
│       └── main.swift
├── Tests/             # 测试代码放这里
│   └── hello-pkgTests/
│       └── hello_pkgTests.swift
└── .gitignore

Package.swift 是包的”说明书”,SPM 全部行为都照它来。Sources 放正式代码,每个子目录通常对应一个 target。Tests 放单元测试,后面讲测试那章会细说。

初学者常在这里踩坑:把文件放错目录,SPM 找不到源码。记住,源码必须进 Sources 下对应 target 的文件夹,SPM 不会去外面乱翻。

1-4 读懂 Package.swift

清单文件第一行的 swift-tools-version 声明了你用的 SPM 版本特性。Swift 6.x 工具链对应 6.0

// swift-tools-version:6.0
import PackageDescription

let package = Package(
    name: "hello-pkg",
    products: [
        .executable(name: "hello-pkg", targets: ["hello-pkg"]),
    ],
    dependencies: [
        // .package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0")
    ],
    targets: [
        .executableTarget(
            name: "hello-pkg",
            dependencies: []
        )
    ]
)

最上面 import PackageDescription 是必须的,清单本身也是 Swift 代码,它调用了 Package(...) 这个构造器。name 是包名,后面 product 和依赖都靠名字引用。

1-5 target、product、dependency 三件套

这三个词是 SPM 的骨架,必须分清。

target 是编译的最小单元,对应 Sources 里的一个模块。一个 target 里的源码一起编译、一起产出。可以是可执行 target(.executableTarget),也可以是库 target(.target)。

product 是你对外”发布”的东西,是别人能 import 或用到的成果。它分两种:可执行文件(executable)和库(library)。一个 product 可以由一个或多个 target 组成。

dependency 是你要用的外部包,或者本包内部 target 之间的依赖关系。

打个比方:你开了一家餐馆(包),厨房里分了凉菜间、热菜间(target),摆在大厅卖给客人的是套餐(product),而做菜要用到的调料是从供货商进的(dependency)。target 是内部怎么组织,product 是对外给什么,dependency 是你依赖谁。

1-6 可执行包与库包的区别

可执行包有一个特殊入口:带 @main 标记的类型,或者老式的 main.swift 顶层代码。编译后它产出能直接跑的程序,swift run 就用得上。

库包没有入口,它只产出可以被别人 import 的模块。它的 product 写成 .library(name: "MyLib", targets: ["MyLib"])。别人把你的包当成依赖加进去后,就能 import MyLib 使用里面的公开 API。

// 库包的 product 写法
products: [
    .library(name: "MathTools", targets: ["MathTools"]),
],
targets: [
    .target(name: "MathTools", dependencies: []),
]
Tip

初学阶段,先做可执行包体会 SPM 最省事:写几行 printswift run 立刻看到结果。等你想把一段逻辑分享给别人,再改成库包。

1-7 常用的 SPM 命令

除了 build 和 run,还有几条值得记住。

$ swift package resolve   # 拉取/更新依赖到最新解析结果
$ swift package clean     # 清掉构建缓存,从头编译
$ swift package update    # 按版本规则更新依赖

resolve 在你刚改完 Package.swift 加依赖时很有用;clean 在构建行为诡异、怀疑缓存出错时,是排错第一招。

Warning

swift package clean 会删掉编译产物,下次 build 会全量重编,比较慢,别在赶时间时随手敲。

1-8 把代码拆成多个 target

一个稍大的包,常常把功能拆成几个 target,彼此通过依赖关联。比如核心逻辑放 Core target,命令行界面放 CLI target,让 CLI 依赖 Core。

targets: [
    .target(name: "Core", dependencies: []),
    .executableTarget(name: "CLI", dependencies: ["Core"]),
]

这样 Core 里写纯逻辑,CLI 只管接收参数、调用 Core,结构清楚也好测试。SPM 会自动按依赖顺序编译,你不用手动管先后。

1-9 构建配置与运行参数

swift build 默认是调试模式,带优化关闭、断言生效。要打发布版,加 --configuration release,编译更慢但跑起来更快。

$ swift build -c release
$ swift run hello-pkg --verbose

swift run 后面跟的 --verbose 这类参数,会原样传给你的程序,而不是给 SPM。想看 SPM 自己的 verbose 日志,则写在 swift 和子命令之间,比如 swift package --verbose resolve。这种”参数归谁”的区分,初学时容易搞混。

Tip

本地试功能用默认 debug 构建(快、断言能抓 bug);给别人用的成品再用 -c release。别把 debug 二进制当正式发布。

1-10 新手常踩的坑

第一个坑是目录结构。SPM 严格按 Sources/<target名>/ 找源码。你若把 main.swift 随手丢在 Sources 根下而不是 target 子目录,构建会告诉你找不到入口。target 名和文件夹名默认要对上。

第二个坑是 Package.swift 改了却没生效。SPM 有缓存,改完依赖后记得 swift package resolve 让它重新拉取,必要时 swift package clean 清缓存再 build。

第三个坑是把 SPM 和 Xcode 的工程文件混为一谈。纯 SPM 包不需要 .xcodeproj,它靠 Package.swift 描述一切。你在纯命令行环境(Linux、CI)里跑的就是这套,不依赖 Xcode。

1-11 什么时候该用 SPM

并不是所有代码都要包成 SPM 包。一行小脚本,直接 swift run 一个文件更轻。但凡出现下面任一情况,就该上 SPM:要复用一段逻辑、要引入第三方库、要分模块组织、要写测试。它把”工程该有的样子”标准化了,省去你自己定规范。

1-12 小结

SPM 把”建工程、拉依赖、编译运行”三件事统一了。记住四个落地点:用 swift package init 起手,Package.swift 是总管家,target 是编译单元、product 是对外成果、dependency 是外部依赖,最后用 swift buildswift run 看到结果。下一章我们专门讲怎么在 dependencies 里加别人的包,以及版本号该怎么写。