Skip to content

fix(pace-cc): apply -fmacro-prefix-map on clang workers compiling preprocessed input - #1726

Merged
christianparpart merged 2 commits into
masterfrom
fix/clang-macro-prefix-map-on-preprocessed-input
Oct 22, 2026
Merged

christianparpart merged 2 commits into
masterfrom
fix/clang-macro-prefix-map-on-preprocessed-input

Conversation

@christianparpart

@christianparpart christianparpart commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Problem

Building contour through pace-cc with distributed compilation on, every dispatched clang compile printed

clang++: warning: argument unused during compilation: '-fmacro-prefix-map=...'

That warning is not noise. pace-cc sends a worker preprocessed text and forwarded the client's -fmacro-prefix-map verbatim. clang's driver drops that flag on preprocessed input and never hands it to -cc1, so __builtin_FILE() and every std::source_location in an object a clang worker compiled named the client's absolute path — and that object was stored under the key a mapped compile uses. A later hit on another machine (or another checkout) reproduces the wrong path. It is a wrong-object bug. gcc applies the plain spelling on preprocessed input, so gcc workers were unaffected.

Fix

  • DriverSpec::preprocessedSourceMapCarrier (CmdLine.hpp) names the spelling each driver needs: -Xclang= for clang, none for gcc. RemoteCompileArgs emits -Xclang=-fmacro-prefix-map=<rule> for clang and the plain spelling for gcc. The fused -Xclang= form keeps the worker judging one argument at a time.
  • CarriedSourcePrefixMap is the ONE exact carve-out from the -Xclang denial. It is asked inside FindDeniedArgument (ArgumentDenials.hpp), so client and worker agree. The worker (JudgeBuiltIn, CompileJob.cpp) admits it only for the clang driver. Bare -Xclang and -Xclang=<anything else> stay denied by row.
  • Rulebook text in .agent/rules/compile-cache.md.

Cache generations bumped: objkey-v9, manifest-v10 (second commit). This retires the wrong objects already in caches, because nothing in a stored value says which entries are affected. The key construction is unchanged: the golden vectors move for the tag alone, and objkey-v8 / manifest-v9 join the retired rows. Cost: every user does one cold rebuild after upgrading.

A clang too old for -Xclang=: the remote compile fails and is retried locally, so the cost is a lost dispatch rather than a wrong object.

Verification

Measured on Linux:

  • pace-cc-tests: 1038 pass / 4 skip / 0 fail. pace-node-tests: 1541 pass / 2 skip / 0 fail.
  • New cases in CmdLine_test, CompileJob_test and Dispatch_test. New e2e case 7c in scripts/dist-compile-e2e.sh checks that a dispatched __builtin_FILE() matches a local compile's under the same map. It passes with clang++, where it is the regression test, and a g++ leg is its control.
  • Neuter check: with the carrier removed, exactly the new assertions and case 7c failed, and nothing else did.
  • Pinned clang-format and clang-tidy (22.1.8) sweep clean. Rulebook and hygiene ctests pass.
  • bash scripts/local-gate.sh on the committed tree (second run, about 4.5 minutes incremental): LOCAL GATE PASSED. gate-clang-debug: 6929 of 6929. gate-gcc-release: 6928 of 6928, including dist-compile-e2e with g++. The first run failed. See the next section.

Observed during the local gate

The first local gate run (about 17 minutes) failed on one test: dist-compile-e2e on the gcc-release leg. The clang-debug leg passed, 6929 of 6929.

Measured:

  • The failure, reproduced once more right after on the same binaries: dist-compile-e2e FAILED: worker and launcher disagree on the toolchain fingerprint: '89774c206d5cea5704051af91f89689d' vs 'a069fc8108e5fb3adf1fd3be2f672f0c'.
  • That check runs before any compile case, so case 7c was not reached in either failing run.
  • Later re-runs of the same binaries passed 6 of 6: 2 on an idle host and 4 under 2×nproc CPU load. Those runs did reach 7c, and it passed with g++.
  • Every pace-cc on this machine (both gate trees, a dev tree, /usr/bin) gives a069… for /usr/bin/g++, and so does a hand-started gate pace-node. No compiler here (g++, c++, gcc, cc, clang++, clang, x86_64-redhat-linux-g++) produces 89774c….
  • This branch changes no fingerprint input: no banner, DriverGrammarName or schema change.

Inferred, not shown: the worker derived a different fingerprint from its environment or toolchain survey at that moment, not because of this change. The passing re-runs do not explain the failure.

Tracked in #1727.

…ang=

pace-cc dispatches a compile as preprocessed text and forwarded the
client's -fmacro-prefix-map verbatim. clang's driver discards that flag
on preprocessed input ("argument unused during compilation") and never
hands it to -cc1, so __builtin_FILE() and std::source_location in a
clang worker's object named the client's absolute path, stored under the
key a mapped compile uses. gcc applies the plain spelling there.

The spelling a driver needs is now a DriverSpec column,
preprocessedSourceMapCarrier ("-Xclang=" for clang, fused so the worker
still judges one argument at a time). CarriedSourcePrefixMap is the one
exact carve-out from the -Xclang denial, asked inside FindDeniedArgument
so client and worker agree; the worker admits it only for the clang
driver. Bare -Xclang and -Xclang=<anything else> stay denied by row.

Covered by CmdLine, CompileJob and Dispatch cases and by
dist-compile-e2e case 7c, which compares a dispatched object with a
local one (a gcc leg is its control).

Signed-off-by: Christian Parpart <christian@parpart.family>
Retires every object a clang worker compiled under a
-fmacro-prefix-map before the previous commit: those embed the client's
absolute path under the mapped key, and nothing in a stored value says
which entries are affected. The key construction is unchanged; the
golden vectors move for the tag alone and objkey-v8 / manifest-v9 join
the retired rows. Costs every user one cold rebuild.

Signed-off-by: Christian Parpart <christian@parpart.family>
@christianparpart christianparpart added the type/bug Behaves incorrectly against its stated contract label Oct 22, 2026
@github-actions github-actions Bot added area/launcher apps/fastcache-cc/ - the compiler launcher and its cache key area/distributed Distributed/, apps/fastcache-compile-node/ - dispatch, workers, scheduler labels Oct 22, 2026
@christianparpart
christianparpart merged commit fd64ef3 into master Oct 22, 2026
32 checks passed
@christianparpart
christianparpart deleted the fix/clang-macro-prefix-map-on-preprocessed-input branch October 22, 2026 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/distributed Distributed/, apps/fastcache-compile-node/ - dispatch, workers, scheduler area/launcher apps/fastcache-cc/ - the compiler launcher and its cache key type/bug Behaves incorrectly against its stated contract

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant