fix(build): force ProcessInfoPlistFile before pre-codesign
Symptom: app hard-blocks at boot with "JarvisEntitlementsVerified missing/false" after every incremental build, even though the build log shows pre-codesign writing YES into the bundle Info.plist. Root cause: Xcode 26's new build system schedules the built-in ProcessInfoPlistFile task (which copies App/Info.plist into Contents/Info.plist) independently from postBuildScripts. On incremental builds with no Swift compile work, ProcessInfoPlistFile ran AFTER pre-codesign, codesign, post-codesign, AND verify-codesign-settings — silently clobbering the bundle Info.plist with the source one. Source App/Info.plist carries <key>JarvisEntitlementsVerified</key><false/> by design as the static-state default; pre-codesign is supposed to flip it to <true/> inside the bundle. With the new ordering, the bundle ended every build at <false/> (and the signature was also stale relative to that plist, though codesign --verify happened to still pass). Fix: declare $(TARGET_BUILD_DIR)/$(INFOPLIST_PATH) as an inputFile of the pre-codesign phase, plus a per-build stamp file as its outputFile. This forces Xcode to make ProcessInfoPlistFile a prerequisite of pre-codesign, and chains codesign (also gaining the stamp as inputFile) deterministically behind it. Xcode 26's "mutable output but no other virtual output node" check rejects naming the plist as both input and output of the same phase, so the separate stamp file is required. Verified: clean and incremental builds both produce a bundle with JarvisEntitlementsVerified=true and a valid signature. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
1 parent
beb9d51aa5
commit
1557302e63
2 files changed
+49
-17
No files matched your search
@@ -8,8 +8,6 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
01787A3F29649644D0B3090D /* MCPAppleScriptMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5077B9E3E7541D72CE0EB1B /* MCPAppleScriptMain.swift */; };
|
||||
B0010002000000000000B002 /* BootHealthProbes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0010001000000000000B001 /* BootHealthProbes.swift */; };
|
||||
B0020002000000000000B002 /* StatusPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0020001000000000000B001 /* StatusPanel.swift */; };
|
||||
0288ABA48E6EC8450BE4BC5F /* BannerContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BF0892A5DFF2AD38A93834 /* BannerContent.swift */; };
|
||||
07E7F32B3857ED215DE59FBE /* Keychain in Frameworks */ = {isa = PBXBuildFile; productRef = 1440CCDB2CC412B099BD0310 /* Keychain */; };
|
||||
0B1E24FF2DB306F28A36680E /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = 8B5C832427B631F1F6EED6C2 /* Logging */; };
|
||||
@@ -25,6 +23,7 @@
|
||||
3649FFF2495A8C4DDDB3B65B /* Voice in Frameworks */ = {isa = PBXBuildFile; productRef = 254100776001B345FD91877C /* Voice */; };
|
||||
38E9EAF5506E27D6D47B1F52 /* VoiceOutputWiring.swift in Sources */ = {isa = PBXBuildFile; fileRef = E24DBC3C9C1B4A6BE1326CB2 /* VoiceOutputWiring.swift */; };
|
||||
3A6BFB4974C5891335CD12D5 /* Voice in Frameworks */ = {isa = PBXBuildFile; productRef = F8C32F1B64110815E54CFE4F /* Voice */; };
|
||||
3CB366DAB60188FE8DCCDCFD /* BootHealthProbes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B2C24637464D380D4450AF /* BootHealthProbes.swift */; };
|
||||
461A5FACC5A3C2025FB0A233 /* JarvisHUDPanelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3527AF52C1E81BAC4EF70766 /* JarvisHUDPanelTests.swift */; };
|
||||
4DF8C0C925F0D09AE39F3380 /* MCP in Frameworks */ = {isa = PBXBuildFile; productRef = B97DB4370CDF8433823F370C /* MCP */; };
|
||||
50C095E6F675D26E9C399179 /* AnthropicKeyValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77C5BF4E4B659B0A3325E647 /* AnthropicKeyValidator.swift */; };
|
||||
@@ -55,6 +54,7 @@
|
||||
8E4590089A7955545E2146D3 /* HudStateCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B7E85856B679CE0788D38DB /* HudStateCoordinatorTests.swift */; };
|
||||
8EF7109838AD91E95506BD1B /* MCPRuntimeWiring.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBF3EF4CDCC653EF50D99AF7 /* MCPRuntimeWiring.swift */; };
|
||||
8F0E066DCBA697FB0A2E59EA /* DevOverlay in Frameworks */ = {isa = PBXBuildFile; productRef = C50C1F6C67DE7D3A738845BD /* DevOverlay */; };
|
||||
8FE2F607ABF836C4727C372E /* StatusPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4688BCCE58DB54DE910F9844 /* StatusPanel.swift */; };
|
||||
925998B6DF1DB8263B4A6280 /* AppBusForwarderSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 528FED2A364DE6BD1F2BA20F /* AppBusForwarderSink.swift */; };
|
||||
92BBF98C9A7B9B7835FC0949 /* Replay in Frameworks */ = {isa = PBXBuildFile; productRef = 8E74C5DEAD36FEDB6342A54D /* Replay */; };
|
||||
93FDBFFCCEFC0848F1C5E630 /* AppDelegateBusWiringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA6BA7673B5FD73B588D9084 /* AppDelegateBusWiringTests.swift */; };
|
||||
@@ -146,8 +146,6 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
00C01D284ECCFC986C7F2E16 /* Keychain */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Keychain; path = packages/Keychain; sourceTree = SOURCE_ROOT; };
|
||||
B0010001000000000000B001 /* BootHealthProbes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BootHealthProbes.swift; sourceTree = "<group>"; };
|
||||
B0020001000000000000B001 /* StatusPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusPanel.swift; sourceTree = "<group>"; };
|
||||
024EE01ED6CC98A61A5CD96C /* WizardStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardStateTests.swift; sourceTree = "<group>"; };
|
||||
0358E0CAC1377752398FA3C4 /* ReplayingToolResultObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplayingToolResultObserver.swift; sourceTree = "<group>"; };
|
||||
096AD64E7DB48B0F1EE47F89 /* HUDBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUDBanner.swift; sourceTree = "<group>"; };
|
||||
@@ -174,6 +172,7 @@
|
||||
43886353ECED823D4CB689D3 /* WizardStageTCCView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardStageTCCView.swift; sourceTree = "<group>"; };
|
||||
4424DD9447F84F35372A48FF /* JarvisHUDPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JarvisHUDPanel.swift; sourceTree = "<group>"; };
|
||||
467AE2D19D58325D227E2F89 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
4688BCCE58DB54DE910F9844 /* StatusPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusPanel.swift; sourceTree = "<group>"; };
|
||||
46CB8B7693CEA625D7331C3E /* HudStateCoordinatorBusWiringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HudStateCoordinatorBusWiringTests.swift; sourceTree = "<group>"; };
|
||||
4AE91F0E707C480DE5724510 /* MemoryInstallWiringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryInstallWiringTests.swift; sourceTree = "<group>"; };
|
||||
4BC1E50BF31BB6CCF895FCA3 /* BrandColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrandColors.swift; sourceTree = "<group>"; };
|
||||
@@ -181,6 +180,7 @@
|
||||
510B6A716A10A8B7CEEC1D3F /* HudStateEnumTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HudStateEnumTests.swift; sourceTree = "<group>"; };
|
||||
511D7B2406F485ED0D4B9E0D /* HudStateIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HudStateIntent.swift; sourceTree = "<group>"; };
|
||||
528FED2A364DE6BD1F2BA20F /* AppBusForwarderSink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppBusForwarderSink.swift; sourceTree = "<group>"; };
|
||||
54B2C24637464D380D4450AF /* BootHealthProbes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BootHealthProbes.swift; sourceTree = "<group>"; };
|
||||
590D5A359A5C3E915D274436 /* VoiceOrchestratorAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceOrchestratorAdapter.swift; sourceTree = "<group>"; };
|
||||
5DE981947E40847F9BAF5641 /* Logging */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Logging; path = packages/Logging; sourceTree = SOURCE_ROOT; };
|
||||
604976A6CA41878D67AF7B71 /* CAAnimationFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CAAnimationFactory.swift; sourceTree = "<group>"; };
|
||||
@@ -318,7 +318,7 @@
|
||||
467AE2D19D58325D227E2F89 /* Assets.xcassets */,
|
||||
90D238B5CF4BD07EB47F84F0 /* JarvisApp.swift */,
|
||||
2C42ACA7552D565D9F198399 /* MCPBusGatewayAdapter.swift */,
|
||||
B0010000000000000000B000 /* Boot */,
|
||||
9583B00B0B1611E34589592F /* Boot */,
|
||||
F76520C565169D7547EE9608 /* HUD */,
|
||||
EE585F62F46C659EDFC48DE7 /* MCP */,
|
||||
35E7CF3C8F80086AD447480E /* MenuBar */,
|
||||
@@ -333,14 +333,6 @@
|
||||
path = App;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B0010000000000000000B000 /* Boot */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B0010001000000000000B001 /* BootHealthProbes.swift */,
|
||||
);
|
||||
path = Boot;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
153D019325D521C96685E1FC /* Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -372,7 +364,7 @@
|
||||
604976A6CA41878D67AF7B71 /* CAAnimationFactory.swift */,
|
||||
B5540C076C8C87A8060B8881 /* MenuBarContextMenu.swift */,
|
||||
4DFECDF801143C9F672B5FB7 /* MenuBarIconController.swift */,
|
||||
B0020001000000000000B001 /* StatusPanel.swift */,
|
||||
4688BCCE58DB54DE910F9844 /* StatusPanel.swift */,
|
||||
);
|
||||
path = MenuBar;
|
||||
sourceTree = "<group>";
|
||||
@@ -491,6 +483,14 @@
|
||||
path = Wizard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9583B00B0B1611E34589592F /* Boot */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
54B2C24637464D380D4450AF /* BootHealthProbes.swift */,
|
||||
);
|
||||
path = Boot;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A7065AE59E83DE43BF345747 /* mcp-time */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -918,15 +918,17 @@
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)",
|
||||
);
|
||||
name = "Verify entitlements (pre-codesign)";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/pre-codesign.stamp",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/scripts/verify-entitlements.sh\" --pre-codesign\n";
|
||||
shellScript = "\"${SRCROOT}/scripts/verify-entitlements.sh\" --pre-codesign\n# Stamp file for build-graph ordering (see comment above). The\n# script's real side effect is on Info.plist, but we expose this\n# stamp as the virtual output so Xcode 26 can sequence later\n# phases (codesign, post-codesign) behind us deterministically.\nmkdir -p \"${DERIVED_FILE_DIR}\"\n/usr/bin/touch \"${DERIVED_FILE_DIR}/pre-codesign.stamp\"\n";
|
||||
};
|
||||
45D1C390727A1C150595B1D8 /* Copy MCP helpers into Contents/Helpers/ */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@@ -1053,6 +1055,7 @@
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/pre-codesign.stamp",
|
||||
);
|
||||
name = "Codesign bundle (deepest-first)";
|
||||
outputFileListPaths = (
|
||||
@@ -1329,7 +1332,7 @@
|
||||
2245DEFA1E6C3880E3C78E56 /* AppDelegateContextBuilderAdapter.swift in Sources */,
|
||||
CCA51A998B128C9C03ED0662 /* AppDelegateFrameAttachAdapters.swift in Sources */,
|
||||
0288ABA48E6EC8450BE4BC5F /* BannerContent.swift in Sources */,
|
||||
B0010002000000000000B002 /* BootHealthProbes.swift in Sources */,
|
||||
3CB366DAB60188FE8DCCDCFD /* BootHealthProbes.swift in Sources */,
|
||||
C3917516BFFF438A4AD5CE80 /* BrandColors.swift in Sources */,
|
||||
A8F96FFF1766D44AA16665A3 /* CAAnimationFactory.swift in Sources */,
|
||||
E218ADC35078C6F26F0D0041 /* HUDBanner.swift in Sources */,
|
||||
@@ -1347,13 +1350,13 @@
|
||||
8EF7109838AD91E95506BD1B /* MCPRuntimeWiring.swift in Sources */,
|
||||
A20E24D0AB73FFBBE4AB9B9B /* MenuBarContextMenu.swift in Sources */,
|
||||
9933987292A1035BB048D0B9 /* MenuBarIconController.swift in Sources */,
|
||||
B0020002000000000000B002 /* StatusPanel.swift in Sources */,
|
||||
7EFA9CFF57B04C03347D3174 /* OnboardingWizardController.swift in Sources */,
|
||||
EF9A869A3403AF044999784F /* ProductionChunkPump.swift in Sources */,
|
||||
63C78894699F60D1DE3A6715 /* RejectReasonCopy.swift in Sources */,
|
||||
A30C09AE5D98B07A92945E1F /* ReplayingToolResultObserver.swift in Sources */,
|
||||
DB7800734578396AA72EADAF /* SettingsView.swift in Sources */,
|
||||
2C4F2BE06A3AC37B492486DD /* SettingsWindowController.swift in Sources */,
|
||||
8FE2F607ABF836C4727C372E /* StatusPanel.swift in Sources */,
|
||||
8684EF1EAC5D350C2CCAB3CF /* VoiceBusEmitterAdapter.swift in Sources */,
|
||||
B8F411ADE70402B71887E377 /* VoiceOrchestratorAdapter.swift in Sources */,
|
||||
38E9EAF5506E27D6D47B1F52 /* VoiceOutputWiring.swift in Sources */,
|
||||
|
||||
+29
@@ -346,11 +346,38 @@ targets:
|
||||
done
|
||||
runOnlyWhenInstalling: false
|
||||
basedOnDependencyAnalysis: false
|
||||
# Pre-codesign declares the bundle's Info.plist as an inputFile.
|
||||
# Why: Xcode's built-in `ProcessInfoPlistFile` task (which copies
|
||||
# App/Info.plist into Contents/Info.plist) has no implicit ordering vs.
|
||||
# postBuildScripts. With the new build system on Xcode 26, an
|
||||
# incremental build with no Swift compile work would schedule
|
||||
# `ProcessInfoPlistFile` AFTER every PhaseScriptExecution — including
|
||||
# codesign — silently clobbering the bundle Info.plist with the source
|
||||
# one (which carries `<key>JarvisEntitlementsVerified</key><false/>` by
|
||||
# design as the static-state default). The app then hard-blocks at boot
|
||||
# via the AppDelegate marker check. Declaring the bundle plist as an
|
||||
# inputFile forces Xcode to schedule `ProcessInfoPlistFile` before this
|
||||
# phase. We also emit a stamp file as the outputFile so the new build
|
||||
# system can build a clean dependency edge — declaring Info.plist as
|
||||
# both input and output trips Xcode 26's "mutable output but no other
|
||||
# virtual output node" check. The stamp file is the virtual output that
|
||||
# downstream phases (codesign, post-codesign) chain off via their own
|
||||
# inputFile, locking the rest of the postBuildScript chain behind us.
|
||||
- name: Verify entitlements (pre-codesign)
|
||||
script: |
|
||||
"${SRCROOT}/scripts/verify-entitlements.sh" --pre-codesign
|
||||
# Stamp file for build-graph ordering (see comment above). The
|
||||
# script's real side effect is on Info.plist, but we expose this
|
||||
# stamp as the virtual output so Xcode 26 can sequence later
|
||||
# phases (codesign, post-codesign) behind us deterministically.
|
||||
mkdir -p "${DERIVED_FILE_DIR}"
|
||||
/usr/bin/touch "${DERIVED_FILE_DIR}/pre-codesign.stamp"
|
||||
runOnlyWhenInstalling: false
|
||||
basedOnDependencyAnalysis: false
|
||||
inputFiles:
|
||||
- $(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)
|
||||
outputFiles:
|
||||
- $(DERIVED_FILE_DIR)/pre-codesign.stamp
|
||||
- name: Codesign bundle (deepest-first)
|
||||
script: |
|
||||
# Fall back to CODE_SIGN_IDENTITY (then ad-hoc "-") when CODE_SIGNING_ALLOWED=NO,
|
||||
@@ -359,6 +386,8 @@ targets:
|
||||
"${SRCROOT}/scripts/codesign.sh"
|
||||
runOnlyWhenInstalling: false
|
||||
basedOnDependencyAnalysis: false
|
||||
inputFiles:
|
||||
- $(DERIVED_FILE_DIR)/pre-codesign.stamp
|
||||
- name: Verify entitlements (post-codesign)
|
||||
script: |
|
||||
"${SRCROOT}/scripts/verify-entitlements.sh" --post-codesign
|
||||
|
||||
Reference in new issue
Block a user