Hive Hive
Sign in

fix(cli): stop emitting -Xcc @resp into OTHER_SWIFT_FLAGS (Xcode 26 “expected exactly one compiler job”)

GitHub issue · Closed

Metadata
Source
tuist/tuist #11023
Updated
Jun 24, 2026
Domains
Generated projects
Details

What changed

In LinkGenerator.setupFrameworkSearchPath, the framework-search-path response file is now injected into OTHER_SWIFT_FLAGS as a bare @<resp> token instead of -Xcc @<resp>. OTHER_CFLAGS and OTHER_LDFLAGS are unchanged (they keep @<resp>).

Why

Users on Xcode 26 hit a hard build failure after the CLI starts consolidating framework search paths into a response file:

error: unable to handle compilation, expected exactly one compiler job in '...'
error: clang importer creation failed

Root cause

When a target has at least 20 unique precompiled framework search paths (the consolidation threshold introduced for ARG_MAX relief), Tuist writes those -F paths to Derived/FrameworkSearchPaths/<Target>.resp and references the file via @resp in the compiler/linker flags.

For OTHER_SWIFT_FLAGS the reference was emitted as -Xcc @resp. -Xcc forwards the next token verbatim to Swift’s ClangImporter. Under Xcode 26, ClangImporter’s createInvocation no longer expands @file response files, so the @resp path survives as a literal positional Objective-C input. clang then sees two inputs (the real translation unit plus @resp), produces two -cc1 jobs, and the importer asserts that it expected exactly one — surfacing as the two errors above.

Passing the response file as a bare @resp (no -Xcc) routes it through swift-driver instead, which does expand the response file and forwards the contained -F flags to the clang importer as proper search-path flags. clang never receives a @file token as an input, so only one -cc1 job is produced.

OTHER_CFLAGS (clang driver) and OTHER_LDFLAGS (ld) both expand @file correctly and still need it to stay under ARG_MAX, so those are left as-is.

When this regressed

The -Xcc @resp injection was introduced in #10228 (commit 319f3d8391, 2026-05-26), which added the whole framework-search-path consolidation — the threshold, the .resp file, and the OTHER_SWIFT_FLAGS line — in one change. It first shipped in CLI 4.195.7 and has been latent ever since.

It is not a regression in the generation code in the usual sense: setupFrameworkSearchPath is byte-identical across 4.195.7 → 4.195.12, and for a triggering project the generated pbxproj + resp + deps-modulemap are identical too. The defect only manifests under Xcode 26, whose ClangImporter stopped expanding @file; on earlier Xcode the same -Xcc @resp was harmless.

This also explains why per-version bisections do not point at this file — the only CLI commits in the relevant window are #10984 (cache content-hash change, 4.195.11) and #10996. The likely surfacing mechanism is that #10984 changed the cache content hash, which on upgrade invalidates and repopulates the binary cache (the source of the >= 20 precompiled frameworks), forcing cold rebuilds and shifting which targets cross the consolidation threshold, thereby re-exposing the latent Xcode 26 bug.

Validation

  • Unit test test_setupFrameworkSearchPath_consolidatesIntoResponseFile_whenManyPrecompiledPaths updated to assert OTHER_SWIFT_FLAGS references the bare @resp and contains no -Xcc; passes.
  • Built the CLI (xcodebuild -scheme tuist) — succeeds; lint clean.
  • End-to-end on a generated macOS app with 22 precompiled frameworks plus a SwiftPM external dependency (the exact trigger shape), regenerated with the patched CLI and built on Xcode 26.4.1 with a cold module cache:
    • OTHER_SWIFT_FLAGS now ends in the bare @.../App.resp (the only -Xcc left is the unrelated explicit-modules -fmodule-map-file flag).
    • Zero expected exactly one compiler job / clang importer creation failed errors, and the .resp path is never handed to a clang -cc1 invocation as an input. Swift compilation completes and the build proceeds past it.

Impact

Restores buildability for Xcode 26 projects that cross the framework-search-path consolidation threshold (commonly via Tuist binary caching, where each cached target contributes one search path).

Flights

Investigate, reproduce, or fix this item in an isolated repository. Each Flight preserves its outcome and agent session.

New Flights are paused Configure model inference, GitHub, and a sandbox provider to start another Flight. Existing results remain available below.
No Flights yet

Start a Flight and preserve its objective, outcome, and session here.

Comments
TA
tuist-atlas[bot] Jun 3, 2026

The fix for the Xcode 26 “expected exactly one compiler job” error, by stopping the emission of -Xcc @resp into OTHER_SWIFT_FLAGS, is now available in 4.195.13. Update to get the fix.