Xcode 26.3 + xcodebuild CLI: builtin-SwiftDriver bypasses swift-frontend wrapper via swiftc symlink redirect
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 38/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- swift
- Domain
- build-system, tooling
Research direction
Start with the compiler patching and symlink setup described in the issue, then inspect InjectionLite/Sources/InjectionLite/LogParser.swift and the Xcode 26.3 CLI build behavior. Reproduce with the supplied xcodebuild flags and verify whether the build cache mtime advances and newly compiled files are captured. Done means the supported xcodeless flow captures current Swift compile commands without the misleading lookup failure.
Written by the indexing model from the issue text.
Description
Summary
On Xcode 26.3 + InjectionNext 2.0.0RC5, hot-reload from a pure xcodebuild-CLI workflow is broken at an architectural level. Even with Patch Compiler correctly applied AND all three documented build flags set, the feedcommands call inside the swift-frontend wrapper is never reached, so the compile-command cache (/tmp/InjectionNext_iPhoneSimulator_builds.json.gz) never updates for the current build. Saves never produce /tmp/injectionNext_*.o and the RC5 console reports Could not locate command for <file>. InjectionNext is not compatible with "Whole Module" Compilation Mode. (the warning text is misleading — SWIFT_COMPILATION_MODE is singlefile).
Environment
- macOS 26.x (Darwin 25.3.0)
- Xcode 26.3 (post-Feb-20 toolchain ship)
- InjectionNext 2.0.0RC5 (build 14492)
- Inject SPM 1.6.0 (
@ObserveInjection+.enableInjection()) - Workflow: xcodeless — builds via
xcodebuildCLI, app launched on simulator withSIMCTL_CHILD_DYLD_INSERT_LIBRARIESpointing atiOSInjection.bundle. - Project: large iOS workspace with CocoaPods + SPM.
SWIFT_ENABLE_EXPLICIT_MODULES=YES(required by targets).
Reproduction
- Apply "Patch Compiler" via RC5 menu → Settings → Compiler. Confirm "Compiler State: Intercepted".
- Verify on disk:
Yields:ls -la "/Applications/Xcode 26.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend"*-rwxr-xr-x swift-frontend (374-byte bash wrapper) -rwxr-xr-x swift-frontend.save (169 MB original binary) - Truncate
/tmp/feedcommands.logand note the mtime/size of/tmp/InjectionNext_iPhoneSimulator_builds.json.gz. - Run a clean
xcodebuildwith all three flags:xcodebuild -workspace … -scheme … -configuration Debug \ -destination "platform=iOS Simulator,id=…" \ EMIT_FRONTEND_COMMAND_LINES=YES \ COMPILATION_CACHE_ENABLE_CACHING=NO \ CLANG_CACHE_FINE_GRAINED_OUTPUTS=NO \ build - Build succeeds. 513
swift-frontendcommand lines emitted to log, ~358 of them-frontend -c -primary-file ….swift-frontend.savesubprocesses are observable inpsduring build. - Result:
json.gzmtime DID NOT advance. New.swiftfiles (e.g. a freshly-createdMyView.swift) are NOT in the cache. Saving any file produces no/tmp/injectionNext_*.o. RC5 console shows the "Could not locate command" warning.
Root cause (verified empirically)
RC5's "Patch Compiler" performs three actions:
- Renames
swift-frontend(binary) →swift-frontend.save. - Installs
swift-frontend.shas newswift-frontend. - Re-points the swift- symlinks (
swift,swiftc,swift-api-digester,swift-cache-tool,swift-symbolgraph-extract) to →swift-frontend.save* (the original), deliberately bypassing the wrapper.
Confirmed by ls -la:
swiftc -> swift-frontend.save
swift -> swift-frontend.save
swift-api-digester -> swift-frontend.save
swift-cache-tool -> swift-frontend.save
swift-symbolgraph-extract -> swift-frontend.save
swift-synthesize-interface -> swift-frontend
(That last one is the only symlink still routing through the wrapper.)
This was sensible pre-Xcode-26 when Xcode invoked swift-frontend directly. But Xcode 26.3 uses builtin-SwiftDriver, which invokes swiftc directly. Through the symlink, that resolves straight to swift-frontend.save — the wrapper is never executed and feedcommands is never called. The compile cache never learns about the current build.
The xcactivitylog fallback path in InjectionLite/Sources/InjectionLite/LogParser.swift also fails on this configuration: xcodebuild from CLI on Xcode 26.3 emits a ~479-byte effectively-empty xcactivitylog, with no -primary-file lines and no builtin-Swift-Compilation lines that the v26.3 fallback grep can match.
What I tried (didn't work)
SWIFT_USE_INTEGRATED_DRIVER=NO— Xcode rejects it on this project: "Enabling Swift explicit modules also requires: SWIFT_USE_INTEGRATED_DRIVER". Targets require explicit modules; circular dependency.- Setting all three documented flags (
COMPILATION_CACHE_ENABLE_CACHING=NO,CLANG_CACHE_FINE_GRAINED_OUTPUTS=NO,EMIT_FRONTEND_COMMAND_LINES=YES) — flags applied successfully but the wrapper still isn't reached because the bypass is at symlink-resolution time, not at cache time. - Re-applying Patch Compiler (multiple times) — the wrapper is correctly installed each time; the symlink-bypass is by design.
- Downgrading to InjectionNext 1.6.0 — same compile-discovery code (PR #125 shipped in both), so same gap.
feedcommands.log is not a useful diagnostic for this issue, by the way — feedcommands is silent on both success and most failure paths. The reliable diagnostic is /tmp/InjectionNext_iPhoneSimulator_builds.json.gz mtime: if it doesn't advance after a build, the wrapper isn't reaching feedcommands.
Question for maintainers
What's the intended xcodeless flow on Xcode 26.3? Specifically:
- Is the
swiftc → swift-frontend.savesymlink redirect intentional on Xcode 26+? If so, how isfeedcommandssupposed to capture commands when builtin-SwiftDriver invokesswiftcinstead ofswift-frontend? - Would re-pointing
swiftc → swift-frontend(the wrapper) and creating aswiftc.save → swift-frontend.savesymlink be a viable patch shape, or does it break driver-mode invocations? (Specifically for cases whereswiftcis invoked without-frontend.) - Is the
LogParser.swiftxCode26_3fallback expected to handle CLIxcodebuildbuilds? Empirically the xcactivitylog from CLI builds is ~479 bytes with no usable per-file lines — happy to attach a sample if useful.
I'm happy to test patch candidates on this project — it's a real-world large workspace (CocoaPods + SPM, ~500 swift-frontend invocations per clean build) and reliably reproduces the gap. cc @maatheusgois-dd @johnno1962
- Dominant language
- Swift
- Stars
- 437
- Forks
- 32
- PR merge metrics
- No merged PRs in 30d
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from johnno1962/InjectionNext
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
johnno1962/InjectionNext#175 · 2 comments ·
-
Difficulty 4/5 3-5 days Newbie friendliness 56/100
johnno1962/InjectionNext#173 · 2 comments ·
-
Difficulty 3/5 1-2 days Newbie friendliness 65/100
johnno1962/InjectionNext#167 ·
-
Issue injecting on real device – Code signature invalid & Unhide Symbols restart loopMay be free again A pull request for this issue was closed without being merged. Open
Difficulty 4/5 3-5 days Newbie friendliness 38/100
johnno1962/InjectionNext#81 · 18 comments · 2 reactions ·
All issues in johnno1962/InjectionNext
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
type: cleanup
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
googleapis/google-cloud-swift#1477 ·
Maintainers usually reply within 1 day
-
product / auth product / console product / databases product / messaging product / self-hosted product / sites product / storage
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
P1 status: first-line-handled status: needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
a2ui-project/a2ui#3282 · 1 comment ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
element-hq/element-x-ios#6357 ·
Maintainers usually reply within 1 day