swift package resolveは、Package.swiftに書いたパッケージの依存関係を解決する。パッケージの取得とPackage.resolvedの更新だけを実行し、ビルドはしない。
$ swift package resolve
Fetching https://github.com/jpsim/Yams from cache
Fetched https://github.com/jpsim/Yams from cache (0.56s)
Computing version for https://github.com/jpsim/Yams
Computed https://github.com/jpsim/Yams at 6.2.2 (0.63s)
Creating working copy for https://github.com/jpsim/Yams
Working copy of https://github.com/jpsim/Yams resolved at 6.2.2
swift package resolveは、Package.swiftのあるフォルダで実行する。Xcodeプロジェクト(.xcodeproj)の依存関係には使えない。Xcodeプロジェクトの依存関係は、xcodebuild -resolvePackageDependenciesで解決する。
参考: 【xcodebuild】SwiftPMの依存関係の解決だけを先に実行する (-resolvePackageDependencies)
実行例はSwift 6.4、macOS 27.0.1のもの。
作られるファイル
Package.resolvedが、パッケージのルートに作られる。取得したパッケージは、.buildフォルダに保存される。
$ ls -A
.build
Package.resolved
Package.swift
Sources
$ ls .build
artifacts
CACHEDIR.TAG
checkouts
repositories
workspace-state.json
.buildの中のartifacts、checkouts、repositories、workspace-state.jsonは、xcodebuildがDerivedDataのSourcePackagesに保存するファイルと同じ構成である。
Package.resolvedのバージョンは維持される
Package.resolvedに記録済みのバージョンが、Package.swiftの要件を満たしているときは、より新しいバージョンがあっても、記録されたバージョンのまま解決される。要件が6.0.0以上のパッケージで、Package.resolvedを6.0.0に書き換えて解決すると、6.0.0が維持された。
$ swift package resolve
Working copy of https://github.com/jpsim/Yams resolved at 6.0.0
Package.swiftの要件をfrom: "6.1.0"に変更すると、記録されたバージョンが要件を満たさなくなる。この状態で解決すると、Package.resolvedが更新された。
$ swift package resolve
Updating https://github.com/jpsim/Yams
Computed https://github.com/jpsim/Yams at 6.2.2 (0.60s)
Working copy of https://github.com/jpsim/Yams resolved at 6.2.2
最新のバージョンに更新する
swift package updateは、Package.resolvedのバージョンを無視して、要件を満たす最新のバージョンに更新する。Package.resolvedを6.0.0にした状態で実行すると、6.2.2になった。
$ swift package update
Updating https://github.com/jpsim/Yams
Updated https://github.com/jpsim/Yams (0.51s)
Computing version for https://github.com/jpsim/Yams
Computed https://github.com/jpsim/Yams at 6.2.2 (0.57s)
Working copy of https://github.com/jpsim/Yams resolved at 6.2.2
| コマンド | Package.resolvedのバージョン |
|---|---|
swift package resolve | 要件を満たしていれば維持する |
swift package update | 要件を満たす最新のバージョンに更新する |
バージョンを指定して解決する
swift package resolveにパッケージ名と--versionを指定すると、そのバージョンで解決する。Package.swiftは変更されない。
$ swift package resolve Yams --version 6.1.0
Updating https://github.com/jpsim/Yams
Updated https://github.com/jpsim/Yams (0.52s)
Computing version for https://github.com/jpsim/Yams
Computed https://github.com/jpsim/Yams at 6.1.0 (0.57s)
Working copy of https://github.com/jpsim/Yams resolved at 6.1.0
--versionの代わりに、--branchと--revisionも指定できる。
Package.resolvedの更新を禁止する
swift buildに--force-resolved-versionsを付けると、Package.resolvedに記録されたバージョン以外には解決しない。--disable-automatic-resolutionと--only-use-versions-from-resolved-fileは、--force-resolved-versionsの別名である。
.buildのないクリーンな状態で、Package.resolvedがないと、ビルドは終了コード1で失敗する。
$ swift build --force-resolved-versions
error: a resolved file is required when automatic dependency resolution is disabled and should be placed at [パッケージのパス]/Package.resolved. Running resolver because the following dependencies were added: ...
$ echo $?
1
swift package resolveの後にPackage.resolvedだけを削除した状態では、.build/workspace-state.jsonに解決済みの状態が残っているので、同じコマンドが成功した。CIのクリーンな環境では、Package.resolvedをコミットしておく。
Package.swiftの要件を変更して、Package.resolvedが古くなったときも、終了コード1で失敗する。
error: an out-of-date resolved file was detected at [パッケージのパス]/Package.resolved, which is not allowed when automatic dependency resolution is disabled; please make sure to update the file to reflect the changes in dependencies. ...
Package.resolvedが要件を満たしていれば、ビルドは成功する。
$ swift build --force-resolved-versions
Build complete!
--force-resolved-versionsを付けないswift buildは、Package.resolvedがなくても、自動で依存関係を解決してビルドに成功する。Package.resolvedも作られる。
パッケージの保存先を指定する
--scratch-pathは、.buildの代わりに使うフォルダを指定する。解決とビルドで同じフォルダを指定すると、ビルドでは取得が実行されない。
$ swift package --scratch-path [保存先のフォルダ] resolve
Working copy of https://github.com/jpsim/Yams resolved at 6.1.0
$ swift build --scratch-path [保存先のフォルダ] --force-resolved-versions
Build complete!
実行例のビルドは、FetchingやCreating working copyは出力されずに成功した。
Package.swiftがないとき
Package.swiftがないフォルダで実行すると、エラーで終了コード1になる。
$ swift package resolve
error: Could not find Package.swift in this directory or any of its parent directories.
$ echo $?
1
.xcodeprojだけがあるフォルダも同じである。
どちらの方法を選ぶか
| やりたいこと | xcodebuild(Xcodeプロジェクト) | swift(Package.swift) |
|---|---|---|
| 依存関係の解決だけを実行する | -resolvePackageDependencies | swift package resolve |
Package.resolvedのバージョンだけで実行する | -disableAutomaticPackageResolution | --force-resolved-versions |
| 保存先を指定する | -clonedSourcePackagesDirPath | --scratch-path |
| 失敗時の終了コード | 74 | 1 |
Package.swiftのあるパッケージは、CIの最初のステップにswift package resolveを置き、ビルドには--force-resolved-versionsを付ける。Xcodeプロジェクトは、xcodebuildのオプションを使う。
