ww build: discard exact null outputs
This commit is contained in:
@@ -6405,6 +6405,134 @@ injected late-link request rollback over old files and modes; occupied-stage
|
||||
rejection; simultaneous builds with different umasks; diagnostic parity;
|
||||
artifact and binary byte identity; and absence of `.new` or umask-probe residue.
|
||||
|
||||
### 11.29 Implemented exact null-output discard for builds
|
||||
|
||||
Exact `ww build -o /dev/null` now removes output installation while preserving
|
||||
the ordinary load and action graph. It is not a request to create an archive,
|
||||
executable, interface, or scratch tree at the null-device pathname.
|
||||
|
||||
#### Pinned Go evidence and fact classification
|
||||
|
||||
The sole authority is official Go 1.26.5 at commit
|
||||
`c19862e5f8415b4f24b189d065ed739517c548ba`:
|
||||
|
||||
- `runBuild` loads packages and reports load errors first, then recognizes the
|
||||
null output and clears `BuildO` before any output-directory, multi-package,
|
||||
or install-action branch. It finally constructs ordinary `ModeBuild` actions
|
||||
for every selected package
|
||||
([`cmd/go/internal/work/build.go`, lines 459–558](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L558)).
|
||||
- `AutoAction` maps a main package in that ordinary mode to a link action and a
|
||||
non-main package to a compile action
|
||||
([`cmd/go/internal/work/action.go`, lines 450–455](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L450-L455)).
|
||||
- On the pinned Unix target, `IsNull` accepts exact `os.DevNull`, which is
|
||||
`/dev/null`; its only additional spelling rule is the Windows-only
|
||||
case-insensitive `NUL` exception
|
||||
([`cmd/go/internal/base/path.go`, lines 81–92](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/base/path.go#L81-L92)).
|
||||
- The test builder treats a nonempty `-o` as a binary-retention request, exempts
|
||||
the null device from multi-package output rejection, and makes a null target
|
||||
use the private build action instead of an install action
|
||||
([`cmd/go/internal/test/test.go`, lines 631–646, 771–804, and 1259–1294](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1259-L1294)).
|
||||
- Official `devnull.txt` requires `go test -c -o $devnull` and a non-main
|
||||
package `go build -o $devnull` to succeed without changing the device
|
||||
([lines 3–25](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/devnull.txt#L3-L25)).
|
||||
`build_dash_o_dev_null.txt` requires a command-line source build to succeed
|
||||
without its default executable
|
||||
([lines 1–12](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_dash_o_dev_null.txt#L1-L12)).
|
||||
`build_cache_link.txt` requires a cold null build to compile and link and an
|
||||
unchanged warm null build to skip compilation but link again
|
||||
([lines 4–22](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_cache_link.txt#L4-L22)).
|
||||
`TestRemoveDevNull` requires cleanup never to remove the device
|
||||
([`cmd/go/internal/work/build_test.go`, lines 22–35](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build_test.go#L22-L35)).
|
||||
|
||||
The load-before-output order, exact spelling, absence of installation, normal
|
||||
command link, normal non-command compile, cold/warm link behavior, raw-source
|
||||
behavior, and device preservation are directly implemented or asserted by the
|
||||
pinned sources above. Acceptance of multiple mixed package roots and an empty
|
||||
matched set is derived from clearing `BuildO` before the output-cardinality
|
||||
branches and then iterating the ordinary package action list. That conclusion
|
||||
applies to WW's manifest-free local package set without importing Go's module,
|
||||
cache, or distribution model. No installed host Go behavior is authority.
|
||||
|
||||
#### Direct pre-fix measurements
|
||||
|
||||
Fresh public-driver probes measured both stages before production edits:
|
||||
|
||||
- raw source, one command directory, and one non-main library directory each
|
||||
failed with exit 1 and `ww: cannot create scratch /dev/null.sepwork`;
|
||||
- a two-command-plus-library request failed with exit 2 and
|
||||
`wwtest package: cannot use -o with multiple packages`;
|
||||
- a persistent command request reached the linker but failed through
|
||||
`/dev/null.new`: Cstage reported `w6l: cannot open /dev/null.new`, WWstage
|
||||
reported `w6l: cannot open output`, and both left the caller workdir empty;
|
||||
- raw `ww test -c -o /dev/null FILE` and its running form failed at the same
|
||||
adjacent-scratch acquisition, while directory `test -c` and running test
|
||||
requests already built privately, discarded the retained copy, and preserved
|
||||
their compile-only versus run distinction;
|
||||
- a blank import of a missing package produced the same positioned
|
||||
`cannot find package missing.pkg` diagnostic in Cstage and WWstage before
|
||||
output setup; and
|
||||
- `/dev/null` remained the same character device, mode, device/inode, and size
|
||||
throughout the failed probes.
|
||||
|
||||
Those are directly measured WW facts. The externally observable gap was thus
|
||||
the build/raw-driver interpretation of exact null as an artifact stem, plus the
|
||||
coordinator's ordinary multi-output rejection, rather than a loader, compiler,
|
||||
linker, or device-write defect.
|
||||
|
||||
#### Ownership, actions, publication, and identity
|
||||
|
||||
`internal/wwpackage.packagecommand` owns the shared package-request output
|
||||
policy. After argument parsing and before output planning it records exact Unix
|
||||
null discard. Loading, source classification, package/import validation,
|
||||
canonical grouping, graph construction, and diagnostic precedence remain
|
||||
unchanged. The coordinator suppresses default names, output-directory setup,
|
||||
ordinary non-directory fan-out rejection, caller publication, and the
|
||||
visibility-only `-S` workdir requirement, then gives every selected group a
|
||||
request-private plan product. Commands still link; libraries still compile and
|
||||
archive; mixed and repeated roots still use their canonical graph/action
|
||||
deduplication. A recursive pattern matching no package emits its ordinary
|
||||
warning and has no output-cardinality error.
|
||||
|
||||
The direct Cstage and WWstage drivers own raw or single-directory requests that
|
||||
do not enter the coordinator. For exact null they allocate a private command
|
||||
product, run the unchanged separate-compilation pipeline, and remove that
|
||||
product and its scratch on every return. Their raw-test paths use the existing
|
||||
unretained private test binary rather than setting `/dev/null` as output and
|
||||
object stem. `-c` still suppresses execution; a running request still reports
|
||||
ordinary pass, assertion, signal, and harness outcomes. Directory tests retain
|
||||
their previously established private-runnable/null-publication behavior.
|
||||
|
||||
There is no caller-visible stage or destination to commit, occupy, replace, or
|
||||
chmod. Producer failure or signal removes private plan state; persistent action
|
||||
rollback preserves every prior unit, interface, assembly, object, archive,
|
||||
tool record, and stamp. Successful persistent requests commit semantic actions
|
||||
normally, unchanged actions are warm-reused, source changes invalidate their
|
||||
owners, and command links still run for each request. Separate simultaneous
|
||||
Cstage and WWstage requests own disjoint private products and workdirs. Exact
|
||||
lookalikes remain normal caller-owned outputs and retain their existing
|
||||
fan-out, `.sepwork`, permission, occupied-stage, transaction, and diagnostic
|
||||
rules.
|
||||
|
||||
Output disposition remains request metadata. Dotted package identity, declared
|
||||
name, physical source directory, import binding, graph edges, action/storage
|
||||
keys, compiler/assembler/linker semantic argv, symbols, `.wwi`, unit and
|
||||
artifact bytes, and persistent invalidation are unchanged. No persisted byte
|
||||
contract changed: build workdir format remains `18`, test workdir format remains
|
||||
`19`, and semantic storage remains `3`.
|
||||
|
||||
The WW-native owner `exact_null_output_discards_build_products` covers Cstage
|
||||
and WWstage command, library, mixed-root, raw-build, assembly-only, and raw-test
|
||||
routes; load/import precedence; empty-pattern warning; exact lookalike
|
||||
rejection/publication; cold, warm, and invalidated persistence; normal link
|
||||
actions and captured runnable bytes; injected linker failure and signal;
|
||||
persistent rollback; concurrent stage isolation; device preservation; private
|
||||
path and `.new` cleanup; semantic-artifact and captured-binary byte identity;
|
||||
and diagnostic/output parity. Existing directory-test owners cover test-product
|
||||
parallelism, timeout, child-setup failure, retained-output transactions, and
|
||||
runtime cwd/environment/stdin. Build runtime behavior is inapplicable, and
|
||||
caller-output rollback, occupied caller stages, and output permissions are
|
||||
inapplicable to the exact discard branch because it creates no public inode.
|
||||
|
||||
## 12. Candidate architectures and hard-gate decision
|
||||
|
||||
Five candidates were developed as coherent systems, not as feature bins.
|
||||
|
||||
19
docs/spec.md
19
docs/spec.md
@@ -319,6 +319,19 @@ ImportPath = ident { "." ident } .
|
||||
build therefore reuses unchanged semantic actions while refreshing the
|
||||
caller-visible output with the current invocation's mode. Assembly-only
|
||||
builds publish no executable or archive.
|
||||
- On the Unix target, exact `-o /dev/null` is a build-output discard request,
|
||||
not an ordinary output filename. Package loading, import validation, graph
|
||||
construction, compilation, assembly, archiving, command linking, failure,
|
||||
and persistent invalidation proceed normally; only installation of a
|
||||
caller-visible command, archive, interface, default basename, or adjacent
|
||||
scratch tree is omitted. One such request may select any number of command
|
||||
and non-command packages, and an empty recursive match is successful after
|
||||
its normal warning. `-S` likewise needs no caller workdir merely to retain
|
||||
discarded assembly. Raw-file and directory roots use the same rule. A
|
||||
non-exact spelling is an ordinary output and keeps all established fan-out,
|
||||
rejection, permission, scratch, and publication behavior. Output discard is
|
||||
request metadata; it does not change package, import, graph, action,
|
||||
artifact, symbol, `.wwi`, or persistence identity.
|
||||
- Only names marked `export` (§5) are visible across module boundaries.
|
||||
|
||||
Import paths remain unquoted and dotted. Grouped imports, quoted import paths,
|
||||
@@ -662,7 +675,11 @@ directory. An output ending in `/` or naming an existing directory receives
|
||||
that basename and may have missing parent directories created. One
|
||||
non-directory output may name only one package. Multiple packages whose
|
||||
visible import leaves would produce the same test-binary name reject before
|
||||
tools or output creation; exact `/dev/null` is the discard exception. Declared
|
||||
tools or output creation; exact `/dev/null` is the discard exception. It keeps
|
||||
the ordinary private link and, unless `-c` is present, the ordinary execution,
|
||||
but installs no retained copy. The raw single-file compatibility route uses
|
||||
the same private-output rule and never treats `/dev/null` as an explicit
|
||||
artifact or adjacent-scratch stem. Declared
|
||||
package names, test variants, source filenames, physical directories, output
|
||||
paths, and retained binary names remain presentation or loader metadata and do
|
||||
not become canonical package or action identity.
|
||||
|
||||
@@ -227,7 +227,10 @@ naming an existing directory receives one such name per selected package and
|
||||
missing parents are created. A single non-directory output is legal for one
|
||||
package only. Multi-package non-directory output and duplicate visible binary
|
||||
names reject before tools; exact `/dev/null` discards every copy and permits
|
||||
duplicate names. A package with no selected test source validates production
|
||||
duplicate names. The private test link still runs unless `-c` suppresses it;
|
||||
the raw single-file compatibility route also links into driver-owned private
|
||||
storage instead of using `/dev/null` as an artifact or `.sepwork` stem. A
|
||||
package with no selected test source validates production
|
||||
but publishes nothing and does not create an otherwise unneeded output
|
||||
directory. Successful `-c` output is silent apart from no-test reporting.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user