docs: record persistent builder identity

This commit is contained in:
2026-08-12 15:51:55 +09:00
parent badde25fa9
commit c4bdc5dc4f
2 changed files with 71 additions and 22 deletions

View File

@@ -2606,11 +2606,11 @@ commit and are implementation evidence, not requirements for the replacement.
`-L` and `-l` values, losing their original interleaving (C driver, lines
10951249 and 13681460).
- `-w DIR` is a caller-owned mutable reuse directory, not a cache. Freshness is
exact composed-unit bytes, copied compiler/assembler bytes, a text mode stamp,
and artifact existence/nonzero size. The graph and units are rebuilt in
memory and the final executable is relinked on every invocation. Publication
through `.new` files with the unit committed last is usefully atomic (C driver,
lines 867952, 10161059, and 11101213).
exact composed-unit bytes, copied driver/compiler/assembler bytes, a text mode
stamp, and artifact existence/nonzero size. The graph and units are rebuilt
in memory and the final executable is relinked on every invocation.
Publication through `.new` files with the unit committed last is usefully
atomic (C driver, lines 867952, 10161059, and 11101213).
- Without `-w`, a build creates and deliberately retains
`<output-stem>.sepwork`; repeating while it exists fails. With `-w`, the caller
must create and serialize the directory. Normal driver products are always
@@ -2696,10 +2696,11 @@ flags, compiler built-ins, assembler/linker defaults,
inferred `argv[0]` library locations, current working directory, file mode, runtime
archive, linker binary, native-library resolution, host libc/CRT/loader, SDK,
CPU, target, and environment. Make does not invalidate existing C objects when
the host compiler or C flags change. Workdir reuse also omits the driver binary/
graph and archive semantics, relying on a manually bumped text format stamp; a
driver change can therefore reuse stale outputs. WW has no target triple, sysroot, conditional
source, generator, manifest, lock, source digest, or frozen/offline concept.
the host compiler or C flags change. Persistent package workdirs now bind the
exact driver executable, conservatively covering its graph, unit, archive, and
commit semantics; the remaining ambient inputs are not thereby promoted into a
cache protocol. WW has no target triple, sysroot, conditional source, generator,
manifest, lock, source digest, or frozen/offline concept.
### 11.4 Measurements and disposable experiments
@@ -2965,7 +2966,7 @@ declares helpers and contains no `@test`, so its package clause and imports are
still checked by the shared loader. Every built variant is run, and a successful
compiler-owned dispatcher with empty output is reported as `[no tests]`.
Persistent workdirs keep a global compiler/assembler/stamp identity and
Persistent workdirs keep a global driver/compiler/assembler/stamp identity and
per-action committed units. When that global identity is stale, the command
first removes every old `.unit.ww` voucher while leaving artifacts recoverable.
It can then commit the new identity even if one root fails: successful actions
@@ -3076,6 +3077,52 @@ tests remain real package variants in
and direct compile dependencies are expanded separately for linking in
[`cmd/go/internal/work/action.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/action.go#628).
### 11.10 Implemented persistent-workdir driver identity slice
The package driver is now an explicit content input to every persistent
`-w DIR` package action. Both stages copy the exact invoking executable to
`.wwtool.ww`, alongside `.wwtool.w6c`, `.wwtool.w6a`, and the mode/format
stamp. A warm invocation byte-compares all applicable live executables before
considering any committed unit reusable. A missing or changed driver copy
invalidates every `.unit.ww` voucher before compilation; old artifacts may
remain recoverable, but none can be reused without a freshly committed unit.
The workdir format revisions are 5 for ordinary builds and 6 for tests.
This closes a real hidden-input boundary. The driver, rather than `w6c`, owns
canonical directory interning, source-derived graph construction, direct-export
unit composition, deterministic dependency ordering, single-member package
archive serialization, and the artifact commit sequence. Unit equality alone
cannot identify changes to those algorithms, and a manually maintained format
number can be forgotten. Exact driver bytes conservatively cover them during
the transitional plain-file reuse scheme. This may rebuild after an unrelated
driver change, but it cannot falsely reuse a package after a relevant one.
The linker remains outside the recorded package identity because persistent
reuse never skips a final link: each invocation reconstructs the complete
reachable `.a` closure, selects current runtime inputs and link flags, and runs
the selected linker. Thus a linker or runtime change affects the requested
binary immediately without forcing unrelated package compilation.
Repository-native coverage runs a three-directory import graph through copied,
independently mutable Cstage and WWstage drivers. Exact compiler, assembler,
and linker wrappers prove a cold dependency-first build, an unchanged warm
compile/assemble skip with a deliberate relink, and full package invalidation
after only the invoking driver's bytes change. The test inspects direct
`.unit.ww` inputs, `.wwi`, `.a`, identity files, exact tool arguments,
transitive link order, diagnostics before tool execution, published binary
bytes, runtime exit, and stage equivalence.
Go 1.26.5 draws the same semantic line with a richer cache: its build action ID
binds compiler/assembler tool identities, configuration, selected source
content, and direct dependency content IDs in
[`cmd/go/internal/work/exec.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/exec.go#261),
while its link action ID separately binds linker configuration and the package
closure in
[`cmd/go/internal/work/exec.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/exec.go#1504).
WW adopts only the correctness boundary in its existing inspectable `cmp`-based
workdir. It does not add build IDs, hashes, a CAS, an action graph, a scheduler,
or a manifest.
## 12. Candidate architectures and hard-gate decision
Five candidates were developed as coherent systems, not as feature bins.

View File

@@ -236,18 +236,20 @@ tools in invocation-owned directories and apply the same exact cleanup rule.
`ww build -w DIR` and single-file `ww test -w DIR` replace that scratch with a
caller-owned persistent package-artifact workdir: the directory must already
exist, is never cleaned by the driver, and holds one committed unit, `.wwi`,
`.s`, `.o`, and dep `.a` per package plus byte copies of the compiler and
assembler and a small mode stamp. A package is reused only when its freshly
composed unit byte-equals the committed unit and the recorded tool copies
byte-equal the live tools — content identity only, no mtimes, no hashes, every
decision reproducible with `cmp` against plain files. Recompiled artifacts
land at staged `.new` names and commit by rename with the unit renamed last,
so an interrupted build forces a recompile rather than a false reuse; the
link always reruns. One workdir serves one invocation at a time and one
(root, mode) shape; both driver stages implement the identical contract.
This is build staleness in the Make/mk/Go sense, not a result cache: tests
always run, and the byte-identity and bootstrap gates keep building on fresh
scratch. `make clean` reclaims every workdir under `out/`.
`.s`, `.o`, and dep `.a` per package plus byte copies of the invoking driver,
compiler, and assembler and a small mode stamp. A package is reused only when
its freshly composed unit byte-equals the committed unit and every applicable
recorded executable byte-equals the live executable — content identity only,
no mtimes, no hashes, every decision reproducible with `cmp` against plain
files. The driver identity covers the graph, unit-composition, archive, and
commit algorithms that neither unit bytes nor compiler identity can name.
Recompiled artifacts land at staged `.new` names and commit by rename with the
unit renamed last, so an interrupted build forces a recompile rather than a
false reuse; the link always reruns. One workdir serves one invocation at a
time and one (root, mode) shape; both driver stages implement the identical
contract. This is build staleness in the Make/mk/Go sense, not a result cache:
tests always run, and the byte-identity and bootstrap gates keep building on
fresh scratch. `make clean` reclaims every workdir under `out/`.
On a package or tree target, `ww test -w DIR` forwards to the coordinator,
which keys one persistent driver workdir per package group under `DIR`