2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Swift による CLI 構築 - アップル公式チュートリアル

Last updated at Posted at 2024-08-13

この記事では、アップル公式ドキュメントのブートストラップを日本語で整理した
コマンドラインツールを構築すれば、例えばこんなものが作れる ↓

  • 開発者向けツール: ソースコードのフォーマットや静的解析を行うツール
  • 自動化スクリプト: 複数のコマンドをまとめて実行するスクリプト
  • デプロイツール: サーバーへのアプリケーションのデプロイを自動化するツール

Swift でコマンドラインツールを構築する

以下のコマンドを実行し、SwiftPM による新規プロジェクトを作成する。

$ mkdir MyCLI
$ cd MyCLI
$ swift package init --name MyCLI --type executable

すると、下記の構成で MyCLI ディレクトリができる。

.
├── Package.swift
└── Sources
    └── main.swift

Package.swift はマニフェストファイルで、依存関係のようなプロジェクトのメタデータが記載される。Sources/main.swift は SwiftCLI のエントリーポイントとして実行コードが記載される。初期設定で "Hello, world" を出力する状態になっているので、以下のコマンドを実行して確認することができる。

$ swift run MyCLI
Building for debugging...
[3/3] Linking MyCLI
Build complete! (0.68s)
Hello, world!

依存関係を追加する

Package.swift を拡張して、依存関係を追加する。ここでは、ASCII アートを作成してみることとする。

Package.swift
import PackageDescription

let package = Package(
    name: "MyCLI",
    dependencies: [
        .package(url: "https://github.com/apple/example-package-figlet", branch: "main"),
    ],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .executableTarget(
             name: "MyCLI",
             dependencies: [
                 .product(name: "Figlet", package: "example-package-figlet"),
             ],
             path: "Sources"
        ),
    ]
)

以下のコマンドを実行すると、SwiftPM が立ち上がり、先ほどの依存関係を追加、並びにコードがビルドされる。

$ swift build

すると、下記の構成でディレクトリが更新される。Package.resolved は、現在使用している依存関係のバージョンが載ったスナップショットである。

.
├── Package.swift
├── Package.resolved
└── Sources
    └── main.swift

ASCII アートを表示する

エントリーポイントの実行コードを編集し、先ほど追加した Figlet (↑)を使用する。ここで、main.swift あるいは @main の修飾子の記載されたファイルがエントリーポイントになることができる。試しに main.swift を消して、新たに myCLI.swift ファイルを作成し、以下のように編集する。

myCLI.swift
import Figlet

@main
struct FigletTool {
  static func main() {
    Figlet.say("Hello, Swift!")
  }
}
$ swift run MyCLI
...
  _   _          _   _                 ____               _    __   _     _ 
 | | | |   ___  | | | |   ___         / ___|  __      __ (_)  / _| | |_  | |
 | |_| |  / _ \ | | | |  / _ \        \___ \  \ \ /\ / / | | | |_  | __| | |
 |  _  | |  __/ | | | | | (_) |  _     ___) |  \ V  V /  | | |  _| | |_  |_|
 |_| |_|  \___| |_| |_|  \___/  ( )   |____/    \_/\_/   |_| |_|    \__| (_)
                                |/                                          

コマンドライン引数を取れるようにする

コマンドラインツールで引数をパースできるようにするために、新たな依存関係として Swift Argument Parser(↑)を追加する。Swift Argument Parser は、Swiftでのコマンドライン引数解析を型安全かつ簡単にする公式ライブラリで、自動ヘルプ生成や複数コマンドのサポートも提供されている。

Package.swift
import PackageDescription

let package = Package(
    name: "MyCLI",
    dependencies: [
        .package(url: "https://github.com/apple/example-package-figlet", branch: "main"),
        .package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0"),
    ],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .executableTarget(
            name: "MyCLI",
            dependencies: [
                .product(name: "Figlet", package: "example-package-figlet"),
                .product(name: "ArgumentParser", package: "swift-argument-parser"),
            ],
            path: "Sources"
        ),
    ]
)

ParsableCommand に準拠させて、@Option などの修飾子をプロパティに付加することで引数を処理できる。例えば、@Option(help:) を使用すると、コマンドラインツールのオプションに対して説明文を付加できる。

myCLI.swift
import Figlet
import ArgumentParser

@main
struct FigletTool: ParsableCommand {
  @Option(help: "Specify the input")
  public var input: String

  public func run() throws {
    Figlet.say(self.input)
  }
}
$ swift run MyCLI --input 'Hello, world!'

  _   _          _   _                                           _       _   _ 
 | | | |   ___  | | | |   ___         __      __   ___    _ __  | |   __| | | |
 | |_| |  / _ \ | | | |  / _ \        \ \ /\ / /  / _ \  | '__| | |  / _` | | |
 |  _  | |  __/ | | | | | (_) |  _     \ V  V /  | (_) | | |    | | | (_| | |_|
 |_| |_|  \___| |_| |_|  \___/  ( )     \_/\_/    \___/  |_|    |_|  \__,_| (_)
                                |/                                             
$ MyCLI --help

USAGE: MyCLI [--verbose] [--filePath <filePath>]

OPTIONS:
  --input                 Specify the input
  -h, --help              Show help information.

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?