XcodeでiOS・macOS AppをBuildやArchiveした際に、次のようなErrorが表示されることがあります。
Entitlements file "MyApp.entitlements" was modified during the build, which is not supported.
さらに:
You can disable this error by setting 'CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION' to 'YES', however this may cause the built product's code signature or provisioning profile to contain incorrect entitlements.
このErrorは、Code Signingに利用する.entitlements Fileが、XcodeがBuildを開始してからSigning処理までの間に変更されたことを意味します。
代表的な原因は、Run Script Phase、CI Script、Fastlane、PlistBuddy、sedなどがBuild途中でEntitlements Fileを書き換えているケースです。
一時的にErrorだけを消すのではなく、EntitlementsをBuild中に直接書き換えず、Debug・Release・StagingなどConfigurationごとに固定したEntitlements Fileを用意して切り替えるのが安全な解決方法です。
- Entitlements Fileとは
- 「modified during the build」とは
- 代表的な発生状況
- まず確認すること
- 主な原因
- 解決方法1:Clean Build Folderを実行する
- 解決方法2:DerivedDataを削除する
- 解決方法3:Build中のEntitlements書き換えをやめる
- 解決方法4:ConfigurationごとにEntitlements Fileを分ける
- 解決方法5:.xcconfigでEntitlements Fileを切り替える
- 解決方法6:XcodeのSigning & Capabilitiesから管理する
- 解決方法7:Build前に生成し、Build開始後は変更しない
- 解決方法8:生成先をSource Entitlementsとは別Fileにする
- 解決方法9:Build Phaseの順序を確認する
- 解決方法10:Entitlements Fileの変更をGitで確認する
- 解決方法11:FileのTimestampを確認する
- 解決方法12:CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATIONを使用する場合
- 解決方法13:Temporary WorkaroundとしてDebugだけ許可する
- 解決方法14:Provisioning Profileとの一致を確認する
- 解決方法15:実際に署名されたEntitlementsを確認する
- 解決方法16:Provisioning Profile側のEntitlementsを確認する
- 解決方法17:App Groupsの動的書き換えをやめる
- 解決方法18:Associated DomainsもConfigurationごとに分離する
- 解決方法19:複数TargetでEntitlementsを共有しすぎない
- 解決方法20:CIでSource Treeを書き換えない
- Clean Build Folderで直った場合
- DerivedData削除でも再発する場合
- Archive時だけ発生する場合
- やってはいけない対処
- 最短で確認するチェックリスト
- まとめ
Entitlements Fileとは
Entitlementsは、Appが利用する特別なCapabilityや権限をCode Signatureへ含めるための設定です。
例えば:
- Push Notifications
- App Groups
- Keychain Sharing
- iCloud
- Associated Domains
- Sign in with Apple
- App Sandbox
などで利用されます。
Entitlements Fileは一般的に:
MyApp.entitlements
のようなProperty List Fileです。
例:
<?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>com.apple.developer.associated-domains</key> <array> <string>applinks:example.com</string> </array> </dict> </plist>
「modified during the build」とは
XcodeはBuild開始時にEntitlements FileをSigning Inputとして読み込みます。
ところがBuild途中でそのFileが書き換えられると、最初に読み込んだ内容とSigning時の内容が一致しなくなります。
そのためXcodeは:
Entitlements file was modified during the build
としてBuildを停止します。
重要:EntitlementsはCode Signingへ直接影響するため、普通のResource Fileとは違い、Build途中で内容を変更する設計は避ける必要があります。
代表的な発生状況
- Run Script Phaseで.entitlementsを変更している
- PlistBuddyでApp Groupsを書き換えている
- sedでEnvironmentごとの値を置換している
- DebugとReleaseで同じEntitlements Fileを動的に書き換えている
- Fastlane Scriptが.entitlementsを変更している
- CI ScriptがBuild直前または途中でFileを書き換えている
- 複数Targetが同じEntitlements Fileを同時に変更している
- Code Generation Toolが.entitlementsを生成している
- Git CheckoutやScriptでBuild中にFile内容が戻されている
- DerivedDataに古いSigning情報が残っている
まず確認すること
1. CODE_SIGN_ENTITLEMENTSを確認する
Xcodeで:
Target → Build Settings → Code Signing Entitlements
を確認します。
Build Setting名は:
CODE_SIGN_ENTITLEMENTS
です。
例えば:
MyApp/MyApp.entitlements
となっているなら、そのFileがBuild中に変更されていないか調べます。
2. Build PhasesのRun Scriptを確認する
次を開きます。
Target → Build Phases
Run Script Phaseに:
PlistBuddy sed cp mv echo cat
など、Entitlements Fileを変更する処理がないか確認します。
3. Project全体からentitlementsへの書き込み処理を検索する
Terminalなら:
grep -R "\.entitlements" .
PlistBuddyを探すなら:
grep -R "PlistBuddy" .
sedを探すなら:
grep -R "sed .*entitlements" .
主な原因
1. Run ScriptでEntitlementsを直接編集している
例えば:
/usr/libexec/PlistBuddy \ -c "Set :com.apple.developer.associated-domains:0 applinks:staging.example.com" \ MyApp.entitlements
のようなScriptです。
Build途中でSigning Inputそのものを変更するため、Errorの原因になります。
2. Debug・Releaseで同じFileを書き換えている
例えば:
Debug: group.com.example.debug
Release:
group.com.example
のような差分を1つのFileへ動的に書き込んでいる場合です。
3. CIでBuild番号やEnvironment名と一緒にEntitlementsを書き換えている
CI ScriptがSource Tree内のEntitlements Fileを変更してからXcode Buildを走らせる構成では、Timingによって変更検出が発生することがあります。
4. Fastlane ActionやCustom ScriptがFileを書き換えている
Signing自動化の一部でEntitlementsを直接編集している場合があります。
5. 複数Targetが同じEntitlements Fileを共有している
Main App、Widget、Notification Service Extensionなどで同じFileを共有し、どれかが変更すると他Targetへ影響します。
6. Build中に生成FileをSource FileへCopyしている
例えば:
cp generated.entitlements MyApp.entitlements
のようなScriptです。
7. Build SystemのCacheが古い
Fileを正しく修正した後でも、古いDerivedDataやBuild Artifactによって変更検出が残る場合があります。
解決方法1:Clean Build Folderを実行する
まず:
Product → Clean Build Folder
を実行します。
一時的なBuild Cacheが原因なら、これだけで解決する場合があります。
注意:毎回Cleanしないと再発する場合は、根本原因が別にあります。Run ScriptなどがEntitlements Fileを書き換えていないか確認してください。
解決方法2:DerivedDataを削除する
Clean Build Folderで直らない場合:
rm -rf ~/Library/Developer/Xcode/DerivedData/*
を実行してBuild Cacheを削除できます。
その後Xcodeを再起動し、Buildし直します。
解決方法3:Build中のEntitlements書き換えをやめる
問題のある例:
/usr/libexec/PlistBuddy \ -c "Set :com.apple.security.application-groups:0 group.com.example.staging" \ MyApp.entitlements
このようにSource Entitlements Fileを直接書き換える処理は削除します。
解決方法4:ConfigurationごとにEntitlements Fileを分ける
例えば:
MyApp-Debug.entitlements MyApp-Staging.entitlements MyApp-Release.entitlements
を用意します。
Debug:
CODE_SIGN_ENTITLEMENTS = MyApp/MyApp-Debug.entitlements
Release:
CODE_SIGN_ENTITLEMENTS = MyApp/MyApp-Release.entitlements
のようにBuild Settingsで切り替えます。
解決方法5:.xcconfigでEntitlements Fileを切り替える
Debug.xcconfig:
CODE_SIGN_ENTITLEMENTS = MyApp/MyApp-Debug.entitlements
Release.xcconfig:
CODE_SIGN_ENTITLEMENTS = MyApp/MyApp-Release.entitlements
とすれば、File自体をBuild途中で変更する必要がなくなります。
解決方法6:XcodeのSigning & Capabilitiesから管理する
標準Capabilityなら:
Target → Signing & Capabilities
から設定します。
例えば:
- Push Notifications
- App Groups
- Associated Domains
- Keychain Sharing
などです。
Xcodeに管理させることで、手動ScriptによるEntitlements変更を減らせます。
解決方法7:Build前に生成し、Build開始後は変更しない
どうしてもEntitlementsを自動生成する必要がある場合は、Xcode Buildの前に生成してください。
例えばCIで:
./Scripts/generate-entitlements.sh
xcodebuild
-project MyApp.xcodeproj
-scheme MyApp
-configuration Release
archive
という順番にします。
重要なのは、xcodebuild開始後にFileを書き換えないことです。
解決方法8:生成先をSource Entitlementsとは別Fileにする
例えば:
Generated/MyApp-Release.entitlements
をBuild前に生成し、CODE_SIGN_ENTITLEMENTSでそのFileを指定します。
Source Control上のEntitlementsを直接変更しない構成にします。
解決方法9:Build Phaseの順序を確認する
Run ScriptがSigning処理に関係する場合:
Target → Build Phases
でScriptの実行Timingを確認します。
ただし、順序変更だけでSource EntitlementsをBuild途中に変更する設計を維持するより、Fileを固定化する方が安全です。
解決方法10:Entitlements Fileの変更をGitで確認する
Build前:
git status
Build後:
git status
を比較します。
差分を見るなら:
git diff -- MyApp/MyApp.entitlements
Build後に差分が出るなら、何らかの処理がFileを書き換えています。
解決方法11:FileのTimestampを確認する
Build前後で:
stat MyApp/MyApp.entitlements
を実行します。
内容が同じでもTimestampが変わっている場合、ScriptがFileを再生成・再Copyしている可能性があります。
解決方法12:CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATIONを使用する場合
XcodeのError Messageでは:
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES
を設定すると検査を無効化できると案内されます。
User-defined Build Settingとして設定することはできます。
ただしXcode自身が:
this may cause the built product's code signature or provisioning profile to contain incorrect entitlements
と警告しています。
重要:CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION=YESは基本的に最後の手段です。Signing InputをBuild途中で変更する根本原因を修正する方を優先してください。
解決方法13:Temporary WorkaroundとしてDebugだけ許可する
どうしてもDevelopment中だけ必要なら:
Debug: CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES
Release:
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = NO
のようにReleaseでは無効にする方法があります。
ただし、これも根本解決ではありません。
解決方法14:Provisioning Profileとの一致を確認する
Entitlements Fileを固定しても、Provisioning Profileが対応Capabilityを含んでいなければCode Signing Errorになります。
例えばApp Groupsを使うなら、Developer Portal側でも対応App GroupとCapability設定が必要です。
解決方法15:実際に署名されたEntitlementsを確認する
Build後のAppから確認できます。
codesign -d \ --entitlements :- \ /path/to/MyApp.app
これにより、最終的なCode Signatureへ入っているEntitlementsを確認できます。
解決方法16:Provisioning Profile側のEntitlementsを確認する
Embedded Profileがある場合:
security cms -D \ -i /path/to/MyApp.app/embedded.mobileprovision \ > /tmp/profile.plist
確認:
/usr/libexec/PlistBuddy \ -c "Print :Entitlements" \ /tmp/profile.plist
AppのEntitlementsとProfile側を比較できます。
解決方法17:App Groupsの動的書き換えをやめる
例えばEnvironmentごとに:
group.com.example.debug group.com.example.staging group.com.example
を切り替えるなら、それぞれ固定Entitlements Fileを用意する方が安全です。
解決方法18:Associated DomainsもConfigurationごとに分離する
例えば:
Debug: applinks:staging.example.com
Release:
applinks:example.com
をBuild中に書き換えず、別Entitlements Fileとして管理します。
解決方法19:複数TargetでEntitlementsを共有しすぎない
Main AppとExtensionは必要なCapabilityが違うことがあります。
例えば:
MyApp.entitlements MyWidget.entitlements NotificationService.entitlements
のように分離します。
解決方法20:CIでSource Treeを書き換えない
CIでは:
sed -i ... PlistBuddy ... cp ... MyApp.entitlements
のような処理をxcodebuildと並行またはBuild途中で実行しないようにします。
必要な生成処理はBuild開始前に完了させます。
Clean Build Folderで直った場合
一度だけ発生し、Clean Build Folder後に再発しないならCacheの不整合だった可能性があります。
しかし毎回:
Product → Clean Build Folder
を実行しないとBuildできない場合、Build ScriptなどがEntitlementsを変更している可能性が高いため、Root Causeを調査してください。
DerivedData削除でも再発する場合
DerivedDataを削除しても再発するなら、CacheではなくSource TreeやBuild Scriptの問題と考えます。
次を優先して確認してください。
- Run Script Phase
- Fastlane
- CI Script
- PlistBuddy
- sed
- cpやFile Generation
- 複数Targetからの共有File書き込み
Archive時だけ発生する場合
Debug Buildでは正常でArchiveだけErrorになる場合:
- Release用Run Script
- Release.xcconfig
- Archive用Environment Variable
- Distribution Signing設定
- Release用Entitlements File
を確認します。
やってはいけない対処
原因を調べずにCODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION=YESだけ設定するのは避けてください。
Errorは消えても:
- Code Signature
- Provisioning Profile
- App Groups
- Push Notifications
- Associated Domains
などのEntitlementsが意図と違う状態になる可能性があります。
特にApp Store配布用Release Buildでは、Signing Inputを固定する構成へ直す方が安全です。
最短で確認するチェックリスト
- CODE_SIGN_ENTITLEMENTSのPathを確認する
- Product → Clean Build Folderを実行する
- DerivedDataを削除する
- Build PhasesのRun Scriptを確認する
- PlistBuddyでEntitlementsを書き換えていないか確認する
- sedで置換していないか確認する
- Build前後のgit diffを確認する
- Build前後のFile Timestampを確認する
- Debug・Releaseで別Entitlements Fileを使用する
- .xcconfigでCODE_SIGN_ENTITLEMENTSを切り替える
- Signing & Capabilitiesから標準Capabilityを管理する
- CIではBuild前に生成処理を完了する
- 複数Targetで同じFileを変更していないか確認する
- Provisioning ProfileとEntitlementsを一致させる
- CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATIONは最後の手段にする
まとめ
Xcodeの「Entitlements file was modified during the build」は、Code Signingに利用するEntitlements FileがBuild途中で変更された場合に発生します。
最も多い原因はRun Script、PlistBuddy、sed、CI、Fastlaneなどによる.entitlements Fileの直接書き換えです。
まずClean Build FolderやDerivedData削除を試し、再発する場合はBuild Scriptを確認してください。
EnvironmentごとにEntitlementsが異なる場合は、1つのFileを動的に変更するのではなく、Debug・Staging・Releaseごとに固定したEntitlements Fileを用意し、CODE_SIGN_ENTITLEMENTSで切り替える方法が安全です。
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION=YESでError検査を回避することはできますが、Xcode自身もCode SignatureやProvisioning Profileへ不正なEntitlementsが入る可能性を警告しています。
そのため、恒久対策としてはBuild中のEntitlements変更をなくし、Signingに使うFileをBuild開始前から終了まで固定することが最も重要です。
