Skip to content

Fix stale direct-mode cache hits when a source file's own body changes - #52

Merged
Yaraslaut merged 1 commit into
masterfrom
fix/direct-mode-tu-self-hash
Aug 20, 2026
Merged

Fix stale direct-mode cache hits when a source file's own body changes#52
Yaraslaut merged 1 commit into
masterfrom
fix/direct-mode-tu-self-hash

Conversation

@Yaraslaut

Copy link
Copy Markdown
Member

fastcache-cc's direct mode records a manifest of everything a translation
unit's compile depends on, then re-validates that manifest on the next
compile by re-hashing each recorded entry. That entry list was built purely
from the compiler's include notes (/showIncludes) or a GNU depfile —
neither of which ever names the primary translation unit itself:
/showIncludes only emits notes for #include targets, and a depfile
rule's own target is excluded from its dependency list.

As a result, editing a .cpp file's own body — without touching any header
it includes — left every recorded hash unchanged, so ValidateManifest
kept reporting the manifest as valid and the launcher replayed the
previously cached object forever, reporting fake compile success. Because
the manifest and object live in the persisted disk cache tier, this
survived daemon/service restarts.

Changes

  • RecordManifest now appends the TU's own source path to the list handed
    to BuildManifest, alongside the headers reported by the compiler.
    BuildManifest already canonicalizes, hashes, sorts, and dedupes every
    path it receives, so this makes the TU's own content hash a checked
    manifest entry with no format or schema change.
  • Added a regression test reproducing the MSVC /showIncludes scenario:
    builds a manifest from headers only, edits the source file's own body,
    and asserts ValidateManifest now correctly invalidates it.

Fixes #51
Fixes #49

RecordManifest built a direct-mode manifest purely from the compiler's
include notes (/showIncludes) or a GNU depfile. Neither ever names the
primary translation unit itself: /showIncludes only emits notes for
#include targets, and a depfile rule's own target is excluded from its
dependency list. So a manifest never got an entry that changed when the
.cpp file's own body was edited without touching any header, and
ValidateManifest kept validating a stale object indefinitely -- served
with a fake compile success, surviving daemon/service restarts since
the manifest and object live in the persisted disk tier.

Fix: RecordManifest now appends the TU's own source path to the list it
hands to BuildManifest, alongside the headers. BuildManifest already
canonicalizes, hashes, sorts, and dedupes every path it is given, so
this makes the TU's own content hash a checked manifest entry with no
format or schema change.

Fixes #51
Fixes #49

Signed-off-by: Yaraslau Tamashevich <y.tamashevich@lastrada.net>
@Yaraslaut
Yaraslaut merged commit 762994f into master Aug 20, 2026
19 checks passed
@Yaraslaut
Yaraslaut deleted the fix/direct-mode-tu-self-hash branch August 20, 2026 13:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant