Windows の Visual Studio 2022 から .NET MAUI/Xamarin.iOS の iOS アーカイブを作成する際に、Platforms/iOS/Entitlements.plist が見つからないというエラーで止まることがあります。本記事では「なぜ起きるのか」「どこを直せば良いのか」を、実務でそのまま使える手順とチェックリスト、具体的な設定例、検証方法までまとめて体系的に解説します。
症状
アーカイブ(IPA 生成)やデバイス向けビルド時に次のようなメッセージで失敗します。
Resources rules file 'Platforms/iOS/Entitlements.plist' not found
あるいは、CodeSign の直前で「entitlements を読み込めない」「ファイルが存在しない」といった趣旨のエラーが記録されます。多くの場合、Windows 側で <CodesignEntitlements> を設定したにもかかわらず、Mac ビルド ホストに正しいパスで渡せていないことが原因です。
結論(最短解)
- 物理配置:
Platforms/iOS/Entitlements.plistに置く(大文字小文字を厳密に)。 - ビルド アクション:BundleResource に設定する。
- csproj:
<CodesignEntitlements>Platforms/iOS/Entitlements.plist</CodesignEntitlements>を スラッシュ(/)で記述する。 - クリーン:
bin/objを削除してから再ビルド。 - Pair to Mac:接続状態とコピー結果(Mac 側ログ)を必ず確認。
まずは全体像(なぜ起きる?)
このエラーは、CodeSign が参照する Entitlements.plist の実ファイルとプロジェクト設定の間で、下記のいずれかがズレると発生します。
- フォルダ/ファイル名の大文字小文字が一致していない(
iOSとios、Entitlement.plistとEntitlements.plistなど)。 - Windows 由来のバックスラッシュ(
\)で csproj に書いたパスが、Mac 上で解釈できずに無視される。 - ビルド アクションが不適切で、アプリ バンドルに含まれず、CodeSign 時に見つからない。
- 旧ビルド成果物や中間生成物(
obj)に残ったキャッシュが、新しい設定を上書きしている。 - Windows→Mac のリモート ビルド同期で、最新ファイルがコピーされていない/古いファイルが参照されている。
早見表:原因と対処
| 症状/原因 | 見分け方 | 対処 |
|---|---|---|
| 大文字小文字の不一致 | ソリューション内のフォルダ名・ファイル名を目視。Git の差分でも要確認。 | Platforms/iOS/Entitlements.plist に統一。厳密に一致させる。 |
csproj のパス区切りが \ | csproj をテキストで開き、CodesignEntitlements の値を見る。 | 必ず / に修正(例:Platforms/iOS/Entitlements.plist)。 |
| ビルド アクションが不適切 | Solution Explorer → Properties → Build Action | BundleResource を選択。 |
| キャッシュの影響 | 直近でファイル名やパスを変更した。 | bin / obj を削除後、Clean → Rebuild。 |
| Mac への同期不全 | Pair to Mac 直後/回線不安定/一部ファイルだけが古い。 | 接続を張り直し、Mac 側のビルドログでコピー結果を確認。 |
正しい配置と設定(手順詳細)
物理配置
Entitlements.plist はプロジェクト ルート直下にある Platforms/iOS フォルダに配置します。必ず以下の階層と綴りを守ってください。
(ProjectRoot)/
Platforms/
iOS/
Entitlements.plist
フォルダ名 iOS の i, O, S は大文字です。小文字化した ios や、スペルミス(Entitlement.plist など)は不可です。
ビルド アクション
Solution Explorer で Entitlements.plist を選択し、Properties の Build Action を BundleResource に設定します。これにより MSBuild はファイルをバンドルに含め、CodeSign が参照できる状態になります。
csproj の設定(CodesignEntitlements)
プロジェクト ファイル(.csproj)に次のように追記します。区切りはスラッシュ(/)のみを使用してください。
<PropertyGroup>
<CodesignEntitlements>Platforms/iOS/Entitlements.plist</CodesignEntitlements>
</PropertyGroup>
構成やターゲットごとに異なる entitlements を使う場合は、条件付きで指定します。
<PropertyGroup Condition="'$(Configuration)'=='Debug' and '$(TargetFramework)'=='net8.0-ios'">
<CodesignEntitlements>Platforms/iOS/Entitlements.plist</CodesignEntitlements>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release' and '$(TargetFramework)'=='net8.0-ios'">
<CodesignEntitlements>Platforms/iOS/Entitlements.plist</CodesignEntitlements>
</PropertyGroup>
注意: マルチターゲットで net8.0-android なども含む場合、iOS 向けの PropertyGroup にだけ設定するのが安全です。
クリーン & リビルド
- Visual Studio の Clean を実行。
bin/objを手動で削除(フォルダごと)。- その後 Rebuild で再生成。
キャッシュに古いメタデータが残っていると、新しい設定が反映されず同じエラーが再発します。
Pair to Mac(リモート ビルド)の確認
- Visual Studio の Pair to Mac で接続状態が緑(正常)になっているか。
- 接続を一度切り、再接続後にビルドしてファイルコピーが走ることをログで確認。
- Mac 側のビルドログで
Entitlements.plistのパスがPlatforms/iOSになっているか。
リモート同期は「最新のファイルがコピーされている」ことが前提です。特にファイル名やパスを変更した直後は、古い中間生成物を参照していないか注意してください。
パス表記の落とし穴(\ と /)
Windows ではつい Platforms\iOS\Entitlements.plist と書きがちですが、csproj の CodesignEntitlements は スラッシュ(/)で統一してください。Mac 側で \ を正しく解釈できず、存在しないパスとして扱われる場合があります。
| 記述 | 評価 | 結果 |
|---|---|---|
Platforms/iOS/Entitlements.plist | OS 非依存で解決 | ◎ 正常 |
Platforms\iOS\Entitlements.plist | Mac で無効解釈の可能性 | × エラー要因 |
Entitlements.plist の基礎知識
Entitlements.plist は、アプリに付与する権限(Push 通知、iCloud、App Groups、Keychain 共有など)を宣言するファイルです。不要な権限を含めると審査で指摘される可能性が高まるため、必要最低限のみを記載してください。
最小サンプル(開発用 Push のみ):
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>
本番用では aps-environment の値を production に切り替えます。構成(Debug/Release)で値を変えたい場合は、別ファイルに分けるか、ビルド前に置換するスクリプト/ターゲットを用意するのが確実です。
.NET MAUI と Xamarin.iOS での注意点
- 二重設定禁止: 同じ権限を
Info.plistとEntitlements.plistの両方に書かない。基本はEntitlements.plistに集約。 - ターゲット フレームワークごとの指定:
net8.0-iosやnet7.0-iosなど、TFM ごとにPropertyGroupを分ける。 - XAML Hot Reload 等の開発時支援機能は、アーカイブ工程の CodeSign とは無関係。署名エラーはビルド設定の問題に集約して考える。
検証のしかた(「設定できたか」を証明する)
MSBuild でプロパティを可視化
ビルド ログに CodesignEntitlements の評価結果を明示的に出力すると把握が速くなります。例えば、カスタム ターゲットを追加して値を出力します。
<Target Name="PrintCodesignEntitlements" BeforeTargets="Build">
<Message Text="CodesignEntitlements=$(CodesignEntitlements)" Importance="High" />
</Target>
これでビルド出力に最終的なパスが表示されます。想定と違う場合は、条件(Condition)の書き方を見直してください。
binlog の取得
問題が再発する場合、binlog を取ると手がかりが増えます。
dotnet build -c Release -f net8.0-ios -bl:build.binlog
binlog を解析すると、いつ・どのターゲットで CodesignEntitlements が変更されたかが追えます。
Mac 側で実物を確認
アーカイブ生成後、Mac で CodeSign に埋め込まれた実際の entitlements を確認します。
codesign -d --entitlements :- "MyApp.app" | plutil -p -
想定のキーが含まれていれば、CodeSign は正しく entitlements を読めています。
Windows→Mac リモート ビルド特有の注意点
- 同期の整合性: ファイル名の大小文字を変更した場合、Git やエクスプローラーの挙動で意図通りに変更が反映されないことがあります。いったん別名にリネーム → コミット → 正しい大文字小文字にリネーム → コミットと段階を踏むと安全です。
- 古いファイルの残留: Mac 側の
~/Library/Caches/Xamarinや一時領域に古い中間生成物があり、最新のEntitlements.plistが反映されないケースがあります。ビルドや接続をやり直してクリアにします。 - 接続の品質: ネットワークが不安定だと一部ファイルだけコピーに失敗し、再利用されたキャッシュでビルドが進みます。エラーが断続的に出る場合はまず回線品質を疑うと近道です。
設定の「正しさ」をダブルチェック:チェックリスト
| 確認項目 | 期待値 | 判定 |
|---|---|---|
| ファイルの物理配置 | Platforms/iOS/Entitlements.plist | OK / NG |
| フォルダ/ファイル名の大小文字 | iOS は大文字、Entitlements.plist は綴り一致 | OK / NG |
| ビルド アクション | BundleResource | OK / NG |
| csproj のパス区切り | /(スラッシュ) | OK / NG |
| クリーン後の再ビルド | bin/obj を削除済み | OK / NG |
| Pair to Mac | 接続緑/ログでコピー成功を確認 | OK / NG |
よくある勘違いと対処
- 勘違い:
Info.plistに権限を書けば良い。
正解: 署名時に使われるのはEntitlements.plist。Info.plistはアプリのメタ情報で役割が異なります。 - 勘違い:
CodesignEntitlementsを設定すればビルド アクションは不要。
正解: ビルド アクションが不適切だとバンドルに含まれず、CodeSign が参照できません。BundleResource に。 - 勘違い: Windows のパス(
\)でも自動で直してくれる。
正解: Mac 側では解釈できず「存在しない」扱いになりがち。スラッシュ固定が安全です。
トラブル事例別の対処
ビルドは通るが、実機で Push が届かない
aps-environmentの値(development/production)と証明書の環境が一致しているか。- 同一 App ID/プロビジョニング プロファイルに Push が有効化されているか。
- Release と Debug で別 entitlements を使っていないか。
「署名の有効期限切れ/認証に失敗」系のエラー
- Mac の Xcode で Apple ID を再ログイン。
- プロビジョニングを Automatic に切り替えて再生成。
- Mac の日付/時刻を自動設定にしてタイムスタンプの不整合を解消。
実践テンプレート(そのまま流用可)
ディレクトリ構成
MyApp/
MyApp.csproj
Platforms/
iOS/
Entitlements.plist
Android/
MacCatalyst/
csproj(単一 TFM の例)
<Project Sdk="Microsoft.NET.Sdk">
net8.0-ios
Platforms/iOS/Entitlements.plist
Entitlements.plist(最小構成)
<plist version="1.0">
<dict>
<!-- 必要なキーだけを最小限で -->
</dict>
</plist>
原因切り分けのフロー
- ファイルの実在確認: エクスプローラーで
Platforms/iOS/Entitlements.plistを目視。 - ビルド アクション: BundleResource になっているか。
- csproj のパス:
/区切りになっているか。 - キャッシュ掃除:
bin/objを削除後、再ビルド。 - Pair to Mac: 接続やコピーに失敗していないかログで確認。
- 実物検証: Mac で
codesign -d --entitlements :-の結果を照合。
MAUI プロジェクトでのベストプラクティス
- 権限の最小化: 審査観点からも、使うものだけを列挙する。
- 設定の一元化: 権限は
Entitlements.plistのみに寄せ、重複・矛盾を避ける。 - 構成別ファイル: Debug/Release で値が変わるキー(例:
aps-environment)はファイルを分けると安全。 - レビュー用タスク: PR 時に
Entitlements.plistの差分を必ずレビューする運用を取り入れる。
「それでも解決しない」時の追加ポイント
- ファイルのエンコーディング: UTF-8 で保存されているか。不可解なパースエラーを避けるため、BOM なしが無難。
- 隠れた拡張子: エディタによっては
.plist.txtのように保存される誤りに注意。 - 重複定義: プロジェクトに複数の
Entitlements.plistが存在していないか(古いファイルが残っている)。 - CI とローカルの乖離: CI 側の環境変数/キャッシュをクリアし、ローカルと同じ msbuild コマンドで比較。
まとめ
Resources rules file 'Platforms/iOS/Entitlements.plist' not found は、配置・パス区切り・ビルド アクション・キャッシュ・リモート同期のいずれかが崩れると必ず起きる、原因がシンプルなエラーです。以下の 5 点を守れば確実に解消できます。
Platforms/iOS/Entitlements.plistに正しく配置(大小文字も含めて厳密一致)。- Build Action を BundleResource にする。
- csproj の
CodesignEntitlementsは/区切りで指定。 bin/objを削除してからクリーン&リビルド。- Pair to Mac の接続状態とコピー結果を確認。
これで Windows から Mac へのリモート アーカイブでも安定してビルドが通り、不要なハマりを避けられます。権限は最小限に保ち、構成・ターゲットごとに整然と管理する運用へ移行しておきましょう。

コメント