docs: describe command-scoped package test builds

This commit is contained in:
2026-08-12 13:54:28 +09:00
parent f709a2c440
commit 8dfff85388

View File

@@ -2852,38 +2852,55 @@ The test coordinator still discovers requested directories, enumerates the
test package names, selects variants, executes independent binaries, and emits test package names, selects variants, executes independent binaries, and emits
captured results in byte-sorted package order. It no longer concatenates a captured results in byte-sorted package order. It no longer concatenates a
generated production/test root, resolves imports, or starts one package graph generated production/test root, resolves imports, or starts one package graph
per binary. Instead it sends one ordered build request per directory to the per binary or directory. Instead it sends one ordered build request containing
Cstage or WWstage command. Its semantic selections are only the directory and every selected directory/variant root to the Cstage or WWstage command. Its
the selected variant/package identities; it also carries output destinations, semantic selections are only the directory and selected variant/package
coordinator-private completion paths, import search roots, and the optional identities; it also carries output destinations, coordinator-private completion
shared work-directory policy. The command owns source selection, paths, import search roots, and the optional command-scoped work-directory
package loading, compiler inputs, archive construction, and linking for both policy. The command owns source selection, package loading, compiler inputs,
non-importable roots: archive construction, and linking for every non-importable root:
- `same-test` selects the byte-sorted production files followed by the - `same-test` selects the byte-sorted production files followed by the
byte-sorted matching `package p` test files. They form one compiler unit, so byte-sorted matching `package p` test files. They form one compiler unit, so
tests can use private production declarations. tests can use private production declarations.
- `external-test` selects only matching `package p_test` files. Its `import p` - `external-test` selects only matching `package p_test` files. Its `import p`
is a direct edge to a distinct production node for the same canonical is a direct edge to the canonical production action for that directory.
directory. That node selects every production file, emits `p.wwi` and `p.a`, That action compiles with module qualifier `p`, selects every production
and exposes no private declaration to the external root. file, emits compiler export data and an archive, and exposes no private
declaration to the external root. If the action is first reached through
the external product, its collision-proof artifact key is derived from the
owning root, such as `__ww-test-001-external-production`; a normal import of
the same `p` and canonical directory reuses that action rather than creating
a second compilation.
The command loads those roots into one command-scoped package universe. The The command loads all roots into one command-scoped package universe. Each root
roots retain distinct artifact keys (`__ww-test-same` and retains an injective artifact key derived from its deterministic request ordinal
`__ww-test-external`) that cannot collide with a legal import identity, and variant, such as `__ww-test-000-same` or
while imports of the same canonical production directory intern to one `__ww-test-003-external`. Hyphens make that namespace illegal as a WW import
production node. A deterministic dependency-first traversal of the union identity. Imports of the same canonical production directory intern to one
therefore invokes the compiler and archiver once for every reachable canonical production node across every selected test directory. A deterministic
production package, even when both test products need it. Each root is still dependency-first traversal of the complete union therefore invokes the
compiled once with its own selected sources and linked separately. The shared compiler and archiver once for every reachable canonical production package,
plan is deliberately package-test-specific: it is not a generalized scheduler, even when many directory products need it. Each root is still compiled once
action schema, cache, or protocol. with its own selected sources and linked separately. The shared plan is
deliberately package-test-specific: it is not a generalized scheduler, action
schema, cache, or protocol.
Each selected directory retains the ordinary entry-directory-first resolution
context from the local package slice: its directory, explicit `-I` roots in
command order, then the toolchain source root. Same and external variants of
one directory share that context; unrelated directory roots never acquire
lookup precedence from their request order. When multiple contexts reach one
canonical production package, the loader verifies that every directory,
folded-file, and inline import binding is identical before reusing its compile
action. A different binding is a deterministic package-resolution failure for
the roots that reach it, rather than a first-root-wins build.
A production action failure blocks exactly the roots that reach it. A A production action failure blocks exactly the roots that reach it. A
root-local compile or link failure does not suppress a successfully built root-local compile or link failure does not suppress a successfully built
sibling product: the command records completion per product, and the sibling product: the command records completion per product, and the
coordinator can run and report successful siblings while attributing each coordinator can run and report successful siblings while attributing each
missing product as a build failure. Directory builds and completed test missing product as a build failure. The single union build and completed test
products share the coordinator's existing `-j` process bound; captured output products share the coordinator's existing `-j` process bound; captured output
is still emitted only in byte-sorted directory/package order. is still emitted only in byte-sorted directory/package order.
@@ -2895,9 +2912,11 @@ test link still receives the root object and the complete reverse-topological
archive closure. The compiler-generated `-T` dispatcher owns the implicit archive closure. The compiler-generated `-T` dispatcher owns the implicit
direct test-runtime support edge and remains embedded in each independently direct test-runtime support edge and remains embedded in each independently
compiled test root; it is the narrow test-main variant, not a compiled test root; it is the narrow test-main variant, not a
coordinator-generated graph package. The shared plan compiles the common coordinator-generated graph package. The command-scoped plan compiles the
runtime production package once. The command resolves that edge from the common runtime production package once for the complete test request. The
selected toolchain source tree, not the user search path. Normally its graph command resolves that edge from the selected toolchain source tree, not the
user search path; the support package's own imports are also loaded in that
toolchain context. Normally its graph
qualifier is `test`, so an explicit source `import test` coalesces with the same qualifier is `test`, so an explicit source `import test` coalesces with the same
canonical package. When a real user package occupies that identity, the command canonical package. When a real user package occupies that identity, the command
presents the runtime edge to the compiler under the reserved `__wwtest` presents the runtime edge to the compiler under the reserved `__wwtest`
@@ -2905,29 +2924,61 @@ qualifier. This keeps a production package named `test` available to external
tests while preserving raw `w6c -T` compatibility, whose default unresolved tests while preserving raw `w6c -T` compatibility, whose default unresolved
qualifier remains `test`. qualifier remains `test`.
The reserved support action and an ordinary source-imported toolchain `test`
action may coexist in the command universe because their compiler qualifiers
are `__wwtest` and `test`. An external-first colocated production action uses
an owning-root artifact key so it remains collision-proof if the command also
loads a different physical package bearing the same compiler qualifier.
Same-qualifier, same-canonical normal and external-production actions always
coalesce; different logical identities for one ordinary physical directory
remain an error. These are the
only narrow action-role exceptions: each product closure is checked to contain
at most one importable action for a compiler module qualifier, so unrelated
roles can never introduce duplicate linked package symbols.
The selected test roots and a production variant reached by their imports or The selected test roots and a production variant reached by their imports or
test-runtime closure are the only sanctioned graph nodes that may share a test-runtime closure are the only sanctioned graph nodes that may share a
physical directory. This also lets a toolchain package's own tests coexist with physical directory. This also lets a toolchain package's own tests coexist with
the production variant required by the test runtime. A same-package root the production variant required by the test runtime. A same-package root
already defines those production symbols, so the production archive is omitted already defines those production symbols, so the production archive is omitted
from that product's final link while the production node's dependency archives from that product's final link while the production node's dependency archives
remain in its closure. The external product includes the production archive. remain in its closure. A reserved compiler-support action at that same physical
directory is still retained. The external product includes the production
archive.
Variant-only archives are never linked into the other product. All ordinary Variant-only archives are never linked into the other product. All ordinary
logical and physical package-identity collision checks remain unchanged. logical and physical package-identity collision checks remain unchanged.
The Cstage linker, like the WWstage linker, passes the root object, every
reachable archive, the runtime, and explicit `-L`/`-l` values through a
structured argument vector; no fixed flattened command buffer can truncate a
large closure. WWstage emits joined `-Ldir` and `-lname` arguments accepted by
its native linker, while Cstage preserves the equivalent split forms. Generated
artifact paths are bounds-checked before any unit is opened, so distinct root
keys cannot alias by truncation.
Recursive discovery groups by physical directory before sorting filenames, and Recursive discovery groups by physical directory before sorting filenames, and
persistent coordinator work directories use one injective escaped directory one stable escaped request key names the persistent command work directory.
plan key. Every `*_test.ww` package variant is built even when a file only Every `*_test.ww` package variant is built even when a file only
declares helpers and contains no `@test`, so its package clause and imports are 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 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]`. compiler-owned dispatcher with empty output is reported as `[no tests]`.
Persistent workdirs keep a global 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
have freshly committed units, whereas failed or no-longer-requested actions
cannot be reused. A retry therefore recompiles the failed action without
discarding unchanged canonical packages built for independent products.
This ownership split follows Go 1.26.5's separation of production, This ownership split follows Go 1.26.5's separation of production,
same-package-test, external-test, and generated test-main inputs in same-package-test, external-test, and generated test-main inputs in
[`cmd/go/internal/load/test.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/load/test.go), [`cmd/go/internal/load/test.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/load/test.go),
while retaining WW's compiler-owned dispatcher. Go's loader returns the same while retaining WW's compiler-owned dispatcher. Go's loader returns the same
cached package pointer for repeated imports, and its command-scoped builder cached package pointer for repeated imports, and `PackageList` walks arbitrary
deduplicates compile actions by package identity; WW borrows that one-universe, multiple roots with pointer-based deduplication in
multi-root ownership boundary without borrowing Go's cache machinery. Direct [`cmd/go/internal/load/pkg.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/load/pkg.go).
Its command-scoped builder deduplicates compile actions by package identity. WW
borrows that one-universe, multi-root ownership boundary without borrowing Go's
cache machinery. Direct
compile dependencies and the separately expanded link closure follow the compile dependencies and the separately expanded link closure follow the
boundary in boundary in
[`cmd/go/internal/work/action.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/action.go), [`cmd/go/internal/work/action.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/action.go),