SPM¶
Swift Package Manager(简称:SPM)用于构建项目源码以及各种依赖。它类似于 Cocoapods、Ruby gems、和 NPM 。大多数情况下,Vapor 应用直接使用 Vapor Toolbox 即可,toolbox 内部将会与 SPM 进行交互。不过,理解基础概念还是很重要的。
提示
想了解更多关于 SPM ,可访问 Swift.org
Package Manifest¶
首先看下 package 配置文件。它位于项目根目录中,并被命名为 Package.swift 。
// swift-tools-version:5.6
import PackageDescription
let package = Package(
name: "ExampleHello",
platforms: [
.macOS(.v12)
],
dependencies: [
// 💧 A server-side Swift web framework.
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
.package(url: "https://github.com/vapor/fluent.git", from: "4.0.0"),
.package(url: "https://github.com/vapor/fluent-sqlite-driver.git", from: "4.0.0"),
],
targets: [
.target(
name: "App",
dependencies: [
.product(name: "Fluent", package: "fluent"),
.product(name: "FluentSQLiteDriver", package: "fluent-sqlite-driver"),
.product(name: "Vapor", package: "vapor")
],
swiftSettings: [
// Enable better optimizations when building in Release configuration. Despite the use of
// the `.unsafeFlags` construct required by SwiftPM, this flag is recommended for Release
// builds. See <https://github.com/swift-server/guides/blob/main/docs/building.md#building-for-production> for details.
.unsafeFlags(["-cross-module-optimization"], .when(configuration: .release))
]
),
.executableTarget(name: "Run", dependencies: [.target(name: "App")]),
.testTarget(name: "AppTests", dependencies: [
.target(name: "App"),
.product(name: "XCTVapor", package: "vapor"),
])
]
)
Tools Version¶
第一行表示当前使用的 swift tools 版本号。
// swift-tools-version:5.6
Package Name¶
name 字段代表当前 package 的名字。
Platforms¶
platforms 字段代表当前支持的最低系统版本号。比如, .macOS(.v12) 表示当前支持的系统版本号是 v12 及以上。
Dependencies¶
dependencies 字段代表需要依赖的 SPM package。所有 Vapor 应用都依赖于 Vapor package ,当然你也可以添加其它想要的 dependency 。
上面这个示例可见,Vapor 4.0+ 版本是这个 package 的 dependency 。
提示
只要修改了 package manifest,都需要调用
vapor update来让变更内容生效。
Targets¶
Targets 包含了 target、executableTarget 以及 testTarget 。
// swift-tools-version:5.6
import PackageDescription
let package = Package(
......
targets: [
.target(
name: "App",
dependencies: [
.product(name: "Fluent", package: "fluent"),
.product(name: "FluentSQLiteDriver", package: "fluent-sqlite-driver"),
.product(name: "Vapor", package: "vapor")
],
swiftSettings: [
// Enable better optimizations when building in Release configuration. Despite the use of
// the `.unsafeFlags` construct required by SwiftPM, this flag is recommended for Release
// builds. See <https://github.com/swift-server/guides/blob/main/docs/building.md#building-for-production> for details.
.unsafeFlags(["-cross-module-optimization"], .when(configuration: .release))
]
),
.executableTarget(name: "Run", dependencies: [.target(name: "App")]),
.testTarget(name: "AppTests", dependencies: [
.target(name: "App"),
.product(name: "XCTVapor", package: "vapor"),
])
]
)
示例中,App 这个 target 里包含了 Fluent、FluentSQLiteDriver 以及 Vapor 这些依赖项。
提示
executableTarget(包含main.swift文件的 target) 不能被其它module导入。这就是为什么Vapor会有App和Run两种 target。任何包含在App中的代码都可以在AppTests中被测试验证。
目录结构¶
以下是典型的 SPM package 目录结构。
.
├── Sources
│ ├── App
│ │ └── (Source code)
│ └── Run
│ └── main.swift
├── Tests
│ └── AppTests
└── Package.swift
每个 .target 对应 Sources 中的一个文件夹。每个 .testTarget 对应 Tests 中的一个文件夹。
Package.resolved¶
第一次构建成功后,SPM 将会自动创建一个 Package.resolved 文件。Package.resolved 保存了当前项目所有用到的 dependency 版本,这样以后每次 Build 都将使用相同的版本号。
Package.resolved 示例如下:
{
"pins" : [
{
"identity" : "async-http-client",
"kind" : "remoteSourceControl",
"location" : "https://github.com/swift-server/async-http-client.git",
"state" : {
"revision" : "7a4dfe026f6ee0f8ad741b58df74c60af296365d",
"version" : "1.9.0"
}
},
{
"identity" : "async-kit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/vapor/async-kit.git",
"state" : {
"revision" : "e2f741640364c1d271405da637029ea6a33f754e",
"version" : "1.11.1"
}
},
......
],
"version" : 2
}
提示
如果想更新
dependency版本,可执行swift package update。
遇到问题¶
如果你遇到 SPM 相关的问题,可以尝试 clean 下工程项目试试。
vapor clean