Nuke 10->11のアップデートで詰まった。そこからPackage, Product, Moduleの区別が以前と比べてつくようになったので備忘録として残す。
モチベーション
Nuke 11.0でNukeUI*1がNukeに吸収され、UIImageView
などのextensionがNukeExtensionsという新規のターゲット*2に移動された。そのため、Nuke 10系から11へのアップデート時且つXcodeGenを使っている場合には project.yml
を以下のように更新する必要があった。自分はシュッと対応ができなかった。
packages: Nuke: url: https://github.com/kean/Nuke exactVersion: 11.0.0 targets: App: dependencies: - package: Nuke product: NukeUI - package: Nuke product: NukeExtensions
なぜシュッとできなかったのか?ひとえにProductというワードを知らなかった。もとい、SwiftPMの理解が浅かった。SwiftPMの仕様、仕組みを理解していればスムーズに対応できたかもしれない。Package? Product? Module? それらの区別をつけられていなかった。今回はこの反省をバネにSwiftPMについて学んだことをNukeに当てはめて整理した。
Package
Packages
A package consists of Swift source files and a manifest file. The manifest file, called Package.swift, defines the package’s name and its contents using the PackageDescription module.
(https://www.swift.org/package-manager/)
Nuke(https://github.com/kean/Nuke 自体)はSwift source files(Sources/
)とPackage.swiftから構成されるため、Packageに該当する。Packageは一つ以上のターゲットを持ち、各ターゲットは Product(後述) を指定する。 Package.swift
*3を見る。
// swift-tools-version:5.6 import PackageDescription let package = Package( name: "Nuke", platforms: [ .iOS(.v13), .tvOS(.v13), .macOS(.v10_15), .watchOS(.v6) ], products: [ .library(name: "Nuke", targets: ["Nuke"]), .library(name: "NukeUI", targets: ["NukeUI"]), .library(name: "NukeExtensions", targets: ["NukeExtensions"]) ], targets: [ .target(name: "Nuke"), .target(name: "NukeUI", dependencies: ["Nuke"]), .target(name: "NukeExtensions", dependencies: ["Nuke"]) ] )
Nuke PackageはNuke, NukeUI, NukeExtensionsのターゲットを持つ。 そして各ターゲットはProductを指定する。Productとは何か。
Product
Products
A target may build either a library or an executable as its product. A library contains a module that can be imported by other Swift code. An executable is a program that can be run by the operating system.
ターゲットは、そのproductとしてlibraryまたは実行可能ファイルをビルドできる。
- library: Swiftコードによってimportされるモジュールを含む概念(おそらくSwiftのコードの集合体のことだろう)
- 実行ファイル: OSで実行できるプログラム
Nukeのコードを見てみる。
- https://github.com/kean/Nuke/tree/master/Sources/Nuke
- https://github.com/kean/Nuke/tree/master/Sources/NukeExtensions
- https://github.com/kean/Nuke/tree/master/Sources/NukeUI/Gifu
上記のいずれにも実行可能ファイルは含まれていないので、それぞれのターゲットはlibraryとしてそれぞれNuke, NukeUI, NukeExtensionをビルドしてProductとする。
Module
importができる単位。Moduleで名前空間を指定して各コードでアクセス制御を行う。利用時にNuke, NukeUI, NukeExtensionsのそれぞれを利用箇所でimportするため、Nuke PackageはNuke, NukeUI, NukeExtensionsのModuleを持つ。
まとめ
- Package: 1つ以上のSwiftのソースファイルと
Package.swift
から構成される概念 - Product: ターゲットがlibraryまたは実行可能ファイルをビルドするもの
- Module: importができる単位。module単位で名前空間を持つ
平たく言うとおそらく、
- Package: SwiftPM文脈での最上位の概念。ターゲットを一つ以上持つ
- Product: ターゲットの成果物
- Module: importができる単位。Module単位で名前空間を持つ(もともと平たかった)
自分でPackage作ると理解深まりそうな気配を感じる。