Xcodeのスキームは、.xcschemeのファイルに保存される。xcodebuild -schemeでビルドやテストをするCIでは、スキームを共有して、.xcschemeのファイルをGitで管理しておくと確実である。
[プロジェクト名].xcodeproj/xcshareddata/xcschemes/[スキーム名].xcscheme
Xcode 27のxcodebuildは、.xcschemeのファイルがなくても、暗黙のスキームでビルドできる。ただし、暗黙のスキームには、テストターゲットが含まれない。
実行例はXcode 27.0、macOS 27.0.1のもの。
スキームを一覧する
プロジェクトのターゲットとスキームは、xcodebuild -listで確認できる。
$ xcodebuild -list -project [プロジェクト名].xcodeproj
Information about project "[プロジェクト名]":
Targets:
[アプリ名]
[アプリ名]Tests
Build Configurations:
Debug
Release
If no build configuration is specified and -scheme is not passed then "Release" is used.
Schemes:
[アプリ名]
-schemeに指定できる名前は、Schemes:に表示された名前である。存在しない名前を指定すると、終了コード65で失敗する。
xcodebuild: error: The project named "[プロジェクト名]" does not contain a scheme named "Nope". The "-list" option can be used to find the names of the schemes in the project.
ローカルのパッケージを使うプロジェクトでは、パッケージのスキームも一覧に表示される。
スキームの種類
スキームには、次の3種類がある。
| 種類 | 保存先 | Gitで管理 |
|---|---|---|
| 共有スキーム | xcshareddata/xcschemes/[スキーム名].xcscheme | する |
| ユーザーのスキーム | xcuserdata/[ユーザー名].xcuserdatad/xcschemes/ | しない |
| 暗黙のスキーム | ファイルなし | なし |
Xcodeは、ファイルのない暗黙のスキームを、ターゲットから自動で作る。Scheme Managerの「Autocreate schemes」が、この動作の設定である。
共有スキームがないとき
共有スキームの.xcschemeを削除したプロジェクトでも、xcodebuild -listは、暗黙のスキームを表示した。
$ find . -name "*.xcscheme"
$ xcodebuild -list -project [プロジェクト名].xcodeproj
...
Schemes:
[アプリ名]
[アプリ名]Tests
実行後も、.xcschemeとxcuserdataは作成されなかった。暗黙のスキームは、ファイルとして保存されない。-schemeに指定したビルドも、成功した。
$ xcodebuild build-for-testing -project [プロジェクト名].xcodeproj -scheme [アプリ名] -destination 'platform=macOS'
...
** TEST BUILD SUCCEEDED **
参考: 【xcodebuild】MACOSX_DEPLOYMENT_TARGETの優先関係を-showBuildSettingsで確認する
暗黙のスキームにテストターゲットは含まれない
共有スキームのTestActionには、実行するテストターゲットがTestablesとして登録されている。
<TestAction
buildConfiguration = "Debug"
...
<Testables>
<TestableReference
...
BlueprintName = "[アプリ名]Tests"
同じプロジェクトを、共有スキームがある状態と、ない状態でビルドした。build-for-testingの結果は次のとおりである。
| 共有スキーム | -scheme [アプリ名]のbuild-for-testing | [アプリ名]Tests.xctest |
|---|---|---|
| あり | 成功 | 作成される |
| なし | 成功 | 作成されない |
暗黙のスキームでは、テストターゲットが、[アプリ名]Testsという別のスキームになる。-scheme [アプリ名]でテストを実行したいCIでは、共有スキームが必要である。
自動作成をオフにすると見つからない
ワークスペースの設定IDEWorkspaceSharedSettings_AutocreateContextsIfNeededをfalseにすると、暗黙のスキームは作られない。この設定は、project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettingsに保存される。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
</plist>
共有スキームがないプロジェクトは、スキームが空になる。
$ xcodebuild -list -project [プロジェクト名].xcodeproj
...
This project contains no schemes.
$ xcodebuild -project [プロジェクト名].xcodeproj -scheme [アプリ名] build
xcodebuild: error: The project named "[プロジェクト名]" does not contain a scheme named "[アプリ名]". The "-list" option can be used to find the names of the schemes in the project.
$ echo $?
65
共有スキームがあるプロジェクトは、共有スキームだけが一覧に表示される。暗黙のスキームの[アプリ名]Testsは表示されない。
共有スキームをGitで管理する
Xcodeでは、「Product」メニューの「Scheme」から「Manage Schemes…」を開き、スキームの「Shared」にチェックを入れる。スキームは、xcshareddata/xcschemes/に.xcschemeのファイルとして保存される。
参考: Shared Schemes and Source Control(Apple Documentation Archive)
.xcschemeのファイルは、通常のファイルと同じようにコミットする。
$ git add [プロジェクト名].xcodeproj/xcshareddata/xcschemes/[スキーム名].xcscheme
$ git commit -m "Add shared scheme"
xcuserdataは、ユーザーごとの設定なので、.gitignoreに追加する。
xcuserdata/
xcuserdataの中には、Scheme Managerでのスキームの並び順を保存するxcschememanagement.plistがある。
$ plutil -p [プロジェクト名].xcodeproj/xcuserdata/[ユーザー名].xcuserdatad/xcschemes/xcschememanagement.plist
{
"SchemeUserState" => {
"[スキーム名].xcscheme_^#shared#^_" => {
"orderHint" => 1
}
}
}
xcschememanagement.plistは、共有スキームの.xcschemeの代わりにならない。
CIで使う
共有スキームをコミットしたリポジトリは、cloneした直後でも、xcodebuild -schemeでビルドできる。スキーム名が分からないときは、ワークフローに-listのステップを入れておくと、ログで確認できる。
- name: List schemes
run: xcodebuild -list -project [プロジェクト名].xcodeproj
- name: Build
run: xcodebuild build -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'platform=macOS'
参考: 【GitHub Actions,Xcode】CIで使うXcodeのバージョンを固定する (xcode-select)
古い情報との違い
古い情報には、xcodebuildはスキームを自動で作らないため、共有してコミットしないと使えない、と書かれたものがある。
参考: Project does not contain a scheme(Bitrise Discuss、2017年)
Xcode 27のxcodebuildは、前述のとおり、暗黙のスキームでビルドできた。動作は、Xcodeのバージョンや自動作成の設定で変わる可能性がある。
どちらの方法を選ぶか
| 状況 | 方法 |
|---|---|
| CIでテストを実行する | 共有スキームをコミットする |
| スキームの設定(ビルド構成、引数)をチームで揃える | 共有スキームをコミットする |
| ビルドだけできればよい | 暗黙のスキームでも動く |
CIでは、Xcodeのバージョンや設定に左右されないよう、共有スキームをコミットする。ユーザーごとの設定であるxcuserdataは、.gitignoreに追加する。
