何かあったら追記していくかも
ブランチを切り替える際にファイルが追加/削除されていてもプロジェクトに反映されない
まあproject.pbxが管理されないので当然である(
とはいえgit checkout
を走らせる度に毎回XcodeGenとpod install
走らせるのめんどい
そこでGit hooksなる仕組みを発見したのでこれを使うことにしました
#!/bin/sh
# エラーになった時点で終了
set -e
echo "Post Checkout"
/usr/local/bin/mint run xcodegen
/usr/local/bin/pod install
これでgit checkout
の度に自動でプロジェクト構成を更新してくれるようになりました。
ちなみになぜmint
とpod
をフルパスで書いてるかって言うと、GUIツールでブランチを切り替える時にPATHがターミナル実行時と違うために、/usr/local/bin
がPATHとして認識されなかったためです。
(SourceTreeも使うのでその度にエラー吐かれて鬱陶しい)
$ gout
Switched to branch 'hoge'
Post Checkout
🌱 XcodeGen 2.1.0 already installed
🌱 Running xcodegen 2.1.0...
(中略)
Analyzing dependencies
Downloading dependencies
(中略)
Generating Pods project
Integrating client project
Sending stats
Pod installation complete! There are 11 dependencies from the Podfile and 14 total pods installed.
2020/02/13 追記
本当に毎回走られると流石に鬱陶しくなってくるので、git checkout
時にcheckout前後の差分に応じて走らせるようにしてみました。
#!/bin/zsh
# エラーになった時点で終了
set -e
# GUIツール対策
PATH=$HOME/.rbenv/shims:/usr/local/bin:$PATH
PREV_COMMIT=$1
POST_COMMIT=$2
DIFF=$(git diff $PREV_COMMIT..$POST_COMMIT --name-status --diff-filter=ADR | grep -e project.yml -e .swift)
if [[ $DIFF != "" ]]; then
while read line
do
echo "$line"
done <<END
$DIFF
END
mint run xcodegen
pod install
fi
CI上でR.swift等の自動生成系がコケる
project.pbxが(ry
最初のアプローチ
*project.yml*
preBuildScripts:
- name: Lint
script: |
if which swiftlint >/dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
- name: BuildConfig.swift
script: |
if [ "${CONFIGURATION}" = 'Release' ]; then
ENVIRONMENT='production'
else
ENVIRONMENT='staging'
fi
${PODS_ROOT}/BuildConfig.swift/buildconfigswift -o ${SRCROOT}/Libs/BuildConfig_swift -e $ENVIRONMENT ${SRCROOT}/Resources/Config
inputFiles:
- $(TEMP_DIR)/buildconfigswift-lastrun
outputFiles:
- $(SRCROOT)/Libs/BuildConfig_swift/BuildConfig.generated.swift
- $(SRCROOT)/Libs/BuildConfig_swift/BuildConfig.plist
- name: R.swift
script: ${PODS_ROOT}/R.swift/rswift generate ${SRCROOT}/Libs/R_swift/R.generated.swift
inputFiles:
- $(TEMP_DIR)/rswift-lastrun
outputFiles:
- $(SRCROOT)/Libs/R_swift/R.generated.swift
outputFiles
に合わせて初期化用のlaneを作り、そこで自動生成ファイルを先に作るようにしました
desc "Initialize project"
lane :init_project do
lib_dir = 'Libs'
sh("cd .. && mkdir -p #{lib_dir}/R_swift #{lib_dir}/BuildConfig_swift && touch #{lib_dir}/R_swift/R.generated.swift #{lib_dir}/BuildConfig_swift/BuildConfig.generated.swift #{lib_dir}/BuildConfig_swift/BuildConfig.plist")
carthage(
cache_builds: true,
platform: 'iOS'
)
sh("cd .. && mint run xcodegen")
cocoapods(repo_update: false)
end
これでCI上でも自動生成系のファイルがXcodeGenの実行よりも先に生成されるのでproject.pbxprojに取り込まれるようになりました。
また、新しいメンバーが入ってきた際の開発環境構築でも同じ問題に遭遇するので、fastlaneに疎い人でも構築しやすいようにMakefile
を用意しました
init:
bundle install --quiet
bundle exec fastlane init_project
2019/5/15追記
@yosshi4486さんからブログ記事を紹介してもらいました。
project.ymlで完結できるのでこちらの方が良さそうですね😃
最終的にsources
に以下のように追加することで解決しました。
- path: Libs/R_swift/R.generated.swift
optional: true
createIntermediateGroups: true
- path: Libs/BuildConfig_swift/BuildConfig.generated.swift
optional: true
createIntermediateGroups: true
- path: Libs/BuildConfig_swift/BuildConfig.plist
optional: true
createIntermediateGroups: true
createIntermediateGroups
をtrueにしないとLibs
グループで括ってくれないので注意。
Swift Package Manager使いたいけどPackage.lockがgitで管理できない
XcodeGenを導入したての時、多くの人(主語デカ)は.gitignore
にこのように書くのではないでしょうか
*.xcodeproj/*
今まではこれでも問題なかったのですが、Swift Package Managerを使おうとすると話が変わってきます。
Xcode11からiOS/macOSプロジェクトでもSwift Package Managerが使えるようになりましたが、依存性を解決した結果を格納するPackage.resolvedファイルは
○○.xcodeproj
├ project.pbxproj
├ project.xcworkspace
│ ├ contents.xcworkspacedata
│ ├ xcshareddata
│ │ ├ IDEWorkspaceChecks.plist
│ │ └ swiftpm
│ │ └ Package.resolved ← ココにいます。
│ └ xcuserdata
│ └ {username}.xcuserdatad
│ └ UserInterfaceState.xcuserstate
├ xcshareddata
│ ├ xcdebugger
│ └ xcschemes
└ xcuserdata
└ {username}.xcuserdatad
├ xcdebugger
│ └ Breakpoints_v2.xcbkptlist
└ xcschemes
└ xcschememanagement.plist
先に書いた.gitignoreの書き方だと、これらが丸ごとgit管理されなくなります。
そこで、Package.resolvedだけgit管理するためにこのように追記してみます。
*.xcodeproj/*
!*.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
一見これで良さそうに見えますが、この状態で実際にPackage.resolvedをgit add
しようとすると以下のように怒られます
$ git add ○○.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
The following paths are ignored by one of your .gitignore files:
○○.xcodeproj/project.xcworkspace
Use -f if you really want to add them.
Package.resolved自体を無視対象から外そうとしても、その上の階層のフォルダが無視されてしまっているためにその下にいるPackage.resolvedまで見てくれないようです。
エラー文言に言われた通りgit add -f
で追加してもいいんですがその後間違ってgit rm
とかしたら面倒なことになりそうなので、どうにかしてPackage.resolved
を無視対象から外したいところ。
解決策
愚直に途中のフォルダを無視対象から外してそのフォルダ内のファイルを無視するような記述をする必要があります。
最終的には以下のようになります。
*.xcodeproj/*
!*.xcodeproj/project.xcworkspace/
*.xcodeproj/project.xcworkspace/*
!*.xcodeproj/project.xcworkspace/xcshareddata/
*.xcodeproj/project.xcworkspace/xcshareddata/*
!*.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/
*.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/*
!*.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
参考