fix: classify Swift compilation steps from Xcode 14 and later - #256
Open
AgapovOne wants to merge 2 commits into
Open
fix: classify Swift compilation steps from Xcode 14 and later#256AgapovOne wants to merge 2 commits into
AgapovOne wants to merge 2 commits into
Conversation
Xcode renamed the Swift compilation tasks: `CompileSwift` became `SwiftCompile` and `CompileSwiftSources` became `SwiftDriver`. `getDetailType` still matches only the old spellings, so on a current log every Swift step is reported as `.other`, and reporters that group by step type lose the compilation entirely. The guard in `getSwiftIndividualSteps` is keyed to the same old name. Fixing the classification alone would make it worse: a batch compilation names its files in the command and the log already carries a subSection per file, so with the step recognized as `.swiftCompilation` and the guard missing the modern name, every file gets reported twice. Both places are updated together. Measured on an Xcode 26.5 log of a ~400 module iOS app (5.9 min build), same log before and after, release build from source: other 314.4 min -> 9.0 min swiftCompilation 0 min -> 282.8 min swiftAggregatedCompilation 0 min -> 22.6 min detail steps 24869 -> 24869 The step count and the sum of durations stay identical, so nothing is duplicated or dropped; only the type of the existing steps changes. `SwiftEmitModule`, `EmitSwiftModule` and `CodeSign` account for the 9 minutes that remain unclassified. They have no matching case in `DetailStepType`, so they are left for a separate change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AgapovOne
requested review from
CognitiveDisson,
aleksandergrzyb,
ecamacho and
polac24
as code owners
August 12, 2026 06:57
A single Xcode 26.5 log carries both: 86884 steps signed `CompileSwift` from targets that compile whole module, next to 666 `SwiftCompile` and 457 `SwiftDriver` steps from the integrated driver. Calling the old spelling a leftover of older Xcode versions was wrong, and the comments said so. Behaviour is unchanged; this only rewrites comments and two test names. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is broken
getDetailTypematchesCompileSwiftandCompileSwiftSources, but the Swift driver signs the same workSwiftCompileandSwiftDriver. Those steps come out as.other, so a reporter that groups by step type loses the Swift compilation — nearly the whole build.Both spellings appear in one log: in a 457-target build, every target emits a
SwiftDriverplanning job and 423 of them are also signedCompileSwift. So this PR adds the driver's names, it does not replace the existing ones.The fix
Two prefixes in
getDetailType, plus the same two spellings in the guard ofgetSwiftIndividualSteps— that guard is keyed toCompileSwifttoo, and fixing only the classification duplicates every file (see below).Two logs of the same app, Xcode 26.5, upstream 0.2.49 vs this branch:
otherswiftCompilationswiftAggregatedCompilationStep counts and totals are unchanged — nothing is duplicated or dropped, only the type of existing steps changes.
What the driver changes about the log
Without the integrated driver, a target's Swift compilation is one build task that shells out to
swiftcand decides internally what to compile — hence one section per target, andgetSwiftIndividualStepsrecovering the per-file detail from the command line.With the driver, Xcode's build engine calls its planning phase and turns every planned job into a build task. One target then produces five kinds of section, none of which
getDetailTypeknows (paths and module names pseudonymized):This is not a project opting into something unusual:
SWIFT_USE_INTEGRATED_DRIVER, the flag that used to control it, appears nowhere in an Xcode 26.5 installation — neither that name norIntegratedDriveris present in the app bundle, so there is nothing left to switch off.Why the guard has to change together with the classification
A batch compilation names its files in
commandDetailDescand carries asubSectionper file.getSwiftIndividualStepssynthesizes per-file steps for whole-module builds that lack them, and skips that whencommandDetailDescalready names a file — via^CompileSwift\s\w+\s\w+\s.+\.swift\s, the old spelling again. Recognize the step without fixing the guard and every file is reported twice. Log A, three runs:Checked against a real batch section from log A:
A match means "the command already names the files, do not synthesize". A single-file command matches too (nothing to synthesize), and a whole-module
swiftccommand still does not, so that synthesis is untouched.Per-log measurements
Same app, same toolchain (Xcode 26.5.0, verified from the toolchain path recorded inside each log), assembled two different ways. Aggregated by the first word of the signature, as classified by upstream 0.2.49.
Log A — only the driver's spellings appear:
Log B — both spellings appear, and the change is purely additive: the 95.5 minutes that leave
otherare exactly theSwiftCompileandSwiftDriversteps.Grouped by the target named in the signature, log B:
The sums exceed the build durations — 5.9 min for log A, 12.4 for log B — because every file in a batch reports the batch's span. That is Xcode's own accounting, not something this change introduces; it does become possible to tell the aggregate apart from the per-file steps and pick one level, which was impossible while both were
.other.Full aggregates for every run are attached in the thread.
Tests
DetailStepTypeTests— both driver spellings, both legacy spellings as regression guards, andSwiftDriverJobDiscoveryasserted to stay.other. That one is why the prefix keeps its trailing space:SwiftDriverwithout it also swallowsSwiftDriverJobDiscovery, which is not a compilation step.SwiftIndividualStepsTests— no synthesis when the command names the files, synthesis still happens for a whole-module command.swift test— 96 tests, 0 failures.swiftlint --strictreports nothing on the touched files.I left
Tests/XCLogParserTests/XCTestManifests.swiftalone: it is marked autogenerated and already omits several existing test classes. Happy to add entries if you would rather keep it in sync.Left out:
SwiftEmitModule,EmitSwiftModuleandCodeSign, most of the 9 minutes still unclassified in log A. None has a matching case inDetailStepType, and adding public enum cases felt like a separate decision — glad to follow up.🤖 Generated with Claude Code