🌐

既存のプロジェクトにXcodeGenを入れる

2022/01/25に公開

XcodeGenとは?

XcodeGenとはXcodeのプロジェクトファイルをyamlで管理できるようにしたものです。
Xcodeのプロジェクトファイルは人間が目で見てわかるものではなく、競合が発生すると差分がとてもわかりにくく、レビューがとても大変です。

そこで私が所属するVoicyでもXcodeGenによってこの競合と変更差分をわかりやすくしたいと思い導入しました。

https://github.com/yonaskolb/XcodeGen

設定用YAMLファイルの生成

XcodeGenの公式ReadMeには新規導入の方法は書かれていますが、既存のプロジェクトからYMLを生成する方法は2022年1月現在確立されていません。

そこでまだマージされていないプルリクを活用し生成していきます。

https://github.com/yonaskolb/XcodeGen/pull/735

こちらについてはクレインさんの記事がとてもわかりやすくまとまっていますので、ご一読ください

https://qiita.com/hcrane/items/501100ee9abd5d3b1295

ここでは実際に私がやった手順を見ていきましょう

既存プロジェクトファイルからYAMLの生成

下記のコマンドを叩きプロジェクトファイルをYMLファイルを生成します

xcodegen migrate --project xxx.xcodeproj --spec project.yml

ここで生成されたymlファイルには大きく2つの問題がありました

プロジェクト構造が1階層しか保持されない

xcodegen generate によってプロジェクトファイルを生成してみると、全てのディレクトリグループが同列階層に表示されてしまいました。

みるとSourcesが山のように書かれているのでプロジェクトフォルダを指定してあげましょう。

これで全ての階層が表示できるようになります(1敗)

sources:
    - Voicy

SPMの設定が保持されない

Swift Package Managerを利用している場合に設定が書き出されませんでした。

SPMに関してYMLファイルで別途定義する必要があるのでしましょう(2敗)

packages:
  Collections:
    url: https://github.com/apple/swift-collections
    exactVersion: 1.0.1

また、追加したSPMの設定をtargetsから依存関係を指定する必要があります。忘れずにやりましょう

targets:
  Voicy:
    platform: iOS
    dependencies:
      - package: Collections

FirebaseCrashlyticsの初期設定

またFirebaseCrashlyticsの設定をCocoaPods上で設定しました。

FirebaseCrashlyticsの初期化はビルドフェーズの最後で実施する必要があるためです。(1敗)

https://firebase.google.com/docs/crashlytics/get-started?hl=ja&platform=ios

ここでやらなくてもYMLで設定しても良いと思います

script_phase :name=> 'FirebaseCrashlytics',
                 :script=> '"${PODS_ROOT}/FirebaseCrashlytics/run"',
                 :input_files=> ['"${SRCROOT}/Voicy/GoogleService-Info.plist','$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)','${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}']

MakeFileの設定

XcodeGenの本筋と外れるのですが、XcodeGenの導入によって多くのライブラリ管理ツールを使用することになったので初期セットアップ手順をMakeFileで統一しました(0敗)

またMakeFileはuhooiさんのものを参考にしました

https://qiita.com/uhooi/items/7b14b5ce413989c751c3

.PHONY: help
help:
	@grep -E '^[a-zA-Z_-]+:.*?# .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":[^#]*? #| #"}; {printf "%-42s%s\n", $$1 $$3, $$2}'

.PHONY: setup
setup:
	$(MAKE) install-ruby
	$(MAKE) install-bundler
	$(MAKE) install-mint
	$(MAKE) generate-xcodeproj
	$(MAKE) open

.PHONY: install-bundler
install-bundler: # Install Bundler dependencies
	bundle install

.PHONY: install-mint
install-mint: # Install Mint dependencies
	brew install mint

.PHONY: install-cocoapods
install-cocoapods: # Install CocoaPods dependencies and generate workspace
	bundle exec pod install

.PHONY: install-ruby
install-ruby:
	cat .ruby-version | xargs rbenv install --skip-existing
	eval "$(rbenv init -)"

.PHONY: generate-xcodeproj
generate-xcodeproj: # Generate project with XcodeGen
	mint run xcodegen xcodegen generate
	$(MAKE) install-cocoapods

.PHONY: open
open: # Open workspace in Xcode
	open `find . -maxdepth 1 -mindepth 1 -iname "*.xcworkspace"`

Bitrise CIの変更

CIの変更をしましたここでは主に Generate Xcode project とその後に Run CocoaPods installをしています。ここまで読んだ方であればご存知かもしれませんが、XcodeGenの後にCocoaPodsのinstallが必要です

またCIのところで気づいたのですが、「FirebaseCrashlyticsの初期設定」で指定した位置が全スキーマを指定する位置に書いており下記のエラーが出まくりました。(6敗)

みなさんはそんな間違いないようにしましょう。

Could not get GOOGLE_APP_ID in Google Services file from build environment

完成

これで完成。
あとはReadMeにちゃんとMakeflieを導入したことがわかる文言があるといいですよね。

これでレビューで大量のプロジェクトファイルをみることはなくなります!
みなさんも良いiOS開発ライフを!

Discussion