XcodeGen と Mint を使った R.swift の導入方法

XcodeGen と Mint を使って R.swift を導入する際の手順をこの記事で紹介する。

導入手順としては、大きく分けて以下の手順がある。

  1. Mintfile に R.swift を追加してローカルにインストールする
  2. XcodeGen の設定を変更する
    1. ビルド時に R.swift が実行されるようにする
    2. 自動生成ファイルをプロジェクトで読み込む
  3. .gitignore で自動生成ファイルを無視するようにする
  4. Swift Package Manager (SPM) で R.Swift.Library をインストールする

ただし、今回は公式にあるやり方のように $SRCROOT に自動生成していくのではなく、 $SRCROOT/${メインのソースコードがあるディレクトリ}/Generated というディレクトリに自動生成し、 Git でディレクトリだけ管理するやり方を紹介する。

では、それぞれ詳しく解説する。

Mintfile に R.swift を追加する

SwiftLint は Homebrew や CocoaPods でインストールが可能だが、今回は Mint 経由でローカルの開発環境にインストールする。

リポジトリ にあるように $ mint install mac-cain13/R.swift でインストール可能。
Mintfile をプロジェクトに入れて Git 管理している場合もあると思うので、その場合は以下のように記述する。

バージョンを固定しているが、リリースバージョンは Releases を参照。

mac-cain13/[email protected]

これで $ mint bootstrap を叩けばインストールされる。

XcodeGen を設定する

R.swift が実行されるようにする

次に、ビルド時に SwiftLint による静的解析が実行されるようにする。
XcodeGen の yml によって prebuildScripts で設定を行う。

以下のような project.yml があるとする。

name: YourApp
options: ...
configs: ...
settings: ...
targets:
  YourApp:
    dependencies: ...
    info: ...
    platform: iOS
    setting: ...
    ...

この YourApp ターゲットに対して以下のような prebuildScripts を設定する。
冒頭で述べたように $SRCROOT/YourApp/Generated 下に生成するように OutputFiles を指定する。

targets:
  YourApp:
    prebuildScripts:
      - name: Run R.swift
        inputFiles:
        - $TEMP_DIR/rswift-lastrun
        outputFiles:
        - $(SRCROOT)/YourApp/Generated/R.generated.swift
        script: |
          if mint list | grep -q 'R.swift'; then
            mint run R.swift rswift generate "$SRCROOT/R.generated.swift"
          else
            echo "error: R.swift not installed; run 'mint bootstrap' to install"
            return -1
          fi          

これでビルド時に R.swift が実行されるようになった。

自動生成ファイルが読み込まれるようにする

$SRCROOT/YourApp/Generated/R.generated.swift に生成されたファイルを Xcode に追加する。
そのために project.yml に以下のように追記する。

targets:
  YourApp:
    sources:
      - path: YourApp
      - path: YourApp/Generated/R.generated.swift
        group: YourApp/Generated
        optional: true

このようにすることで、たとえ XcodeGen 実行時に R.generated.swift が存在せずとも、ディレクトリツリーに場所が作られるので、 prebuildScripts によって生成されたタイミングで正しく読み込まれる。

.gitignore で自動生成ファイルを無視するようにする

Git 管理してない場合はこの工程は不要である。

自動生成ファイルはビルドすれば生成されるし、余計な diff を出さないためにも Generated 以下のファイルは Git 管理したくない。
一方で、 Generated というディレクトリ自体は Git で管理しておきたいが、ディレクトリが空の場合 Git に乗らない。

これを解決するには .gitkeep ファイルを置いて、それ以外を無視するという方法を取る。

.gitkeep.gitignore の違い等の詳細は Qiita, 空のディレクトリを維持するための、 .gitkeep と .gitignore の使い分け に譲るが、簡単にいえばダミーファイルである。

以下の手順で設定できる。

  1. .gitkeep という空ファイルを YourApp/Generated/.gitkeep として配置する
  2. .gitignoreGenerated を無視するように記述する
  3. .gitignore で先程よりも後の行で .gitkeep は無視しないようにする

2 と 3 の手順の具体例は、以下のようになる。

# 今まであった gitignore

# 自動生成ファイル
YourApp/Generated/*

# gitkeep
!.gitkeep

!.gitkeep とすることで、「.gitkeep は無視しない」となる。

次に、このファイルは Git 管理のためのダミーファイルなので、 Xcode プロジェクトに存在する必要がないため、 .gitkeep ファイルを Xcode プロジェクトから除外する。
除外するには sources: excludes: に追加していく。

現在の project.yml は以下のような形をしていると思う。

targets:
  YourApp:
    sources:
      - path: YourApp
      - path: YourApp/Generated/R.generated.swift
        group: YourApp/Generated
        optional: true

現在 YourApp ディレクトリ下すべてが対象となってしまっているので、この sources から Generated.gitkeep を以下のようにして除外する。

targets:
  YourApp:
    sources:
      - path: YourApp
        excludes:
          - "**/.gitkeep"
          - Generated
      - path: YourApp/Generated/R.generated.swift
        group: YourApp/Generated
        optional: true

これで .gitkeep が Xcode プロジェクト上に乗らなくなった。

BeforeAfter
Before
After

Swift Package Manager (SPM) で R.Swift.Library をインストールする

最後に、 R.Swift.Library を SPM 経由で Xcode に導入して完了となる。

以下のように project.yml を設定する。

packages:
  Rswift:
    url: https://github.com/mac-cain13/R.swift.Library.git
    version: 5.4.0
targets:
  YourApp:
    dependencies:
      - package: Rswift

これで R.Swift.Library が Xcode プロジェクトに追加され、 YourApp ターゲットの dependency として認識される。

最後にビルドをしてみて、 YourApp/Generated にファイルが生成された上で、ビルドが通れば完了となる。

参考文献

  1. GitHub, Mint
  2. GitHub, R.swift
  3. Qiita, 空のディレクトリを維持するための、 .gitkeep と .gitignore の使い分け
Built with Hugo
テーマ StackJimmy によって設計されています。