ww build: name current directory output

This commit is contained in:
2026-08-21 17:38:00 +09:00
parent 17b2879c3e
commit b03bbb1428
5 changed files with 436 additions and 23 deletions

View File

@@ -8119,6 +8119,133 @@ This is runtime/coordinator presentation, not a persisted-byte contract. Build
workdir format remains `18`, test workdir format remains `19`, and semantic
storage format remains `3`.
### 11.40 Implemented current-directory default build names
An empty `ww build` package list selects the current directory just as an
explicit `.`, `./`, or equivalent sequence of single-dot components does. For
one command package and no explicit `-o`, the public executable is now named by
the selected directory's final component. The selector is loading syntax; it
is not the literal output pathname. Thus a command built while the current
directory is `tool` publishes `tool`, not `.`, and cold private build artifacts
use `tool.sepwork`, not `..sepwork`.
A non-main current-directory package uses the same corrected cold scratch stem,
but still has no link or public installation action. An explicit `-o`, exact
`-o /dev/null`, an ordinary non-current directory operand, and a contextual
dotted package request keep their established output rules.
#### Pinned Go evidence and fact classification
The sole semantic authority is official Go 1.26.5 at commit
`c19862e5f8415b4f24b189d065ed739517c548ba`:
- `search.CleanPatterns` turns an empty package-pattern list into exactly `.`;
`ImportPathsQuiet` then treats that local pattern as a directory selection
([`cmd/go/internal/search/search.go`, lines 441480](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/search/search.go#L441-L480)).
- `work.runBuild` loads packages and checks load errors before output planning.
With exactly one loaded `main` package and no `-o`, it selects
`DefaultExecName`
([`cmd/go/internal/work/build.go`, lines 459478](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L478)).
- `load.(*Package).exeFromImportPath` takes the final loaded import-path
element, while `DefaultExecName` uses a source basename only for a
command-line-files package
([`cmd/go/internal/load/pkg.go`, lines 17271769](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1727-L1769)).
- Official command testdata distinguishes module naming from the manifest-free
GOPATH case and requires bare `go build` to create the directory-named `src`
executable
([`clean_binary.txt`, lines 1528](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/clean_binary.txt#L15-L28)).
A second manifest-free script changes to `m`, runs bare `go build`, and
requires executable `m`
([`gccgo_m.txt`, lines 414](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/gccgo_m.txt#L4-L14));
`build_static.txt` likewise builds and executes the default `hello`
([lines 1114](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_static.txt#L11-L14)).
Those selection, loading, default-name branches and script assertions are
**behavior directly implemented or asserted by pinned Go**. WW has no module
or manifest identity for a literal root, so using the selected local directory
leaf as its already-specified presentation fallback is **behavior derived from
the pinned implementation**. The directory remains loader metadata and does
not become canonical package or import identity.
#### Fresh four-axis audit and direct pre-fix measurements
The bounded audit examined every permanent axis before choosing this build
presentation difference. Both public stages were measured at the same source
paths:
- **Go-like build:** multi-command directory selection without `-o` was already
aligned. For a valid command in directory `a`, however, bare `build`,
`build .`, and `build ./` each exited 1 in both stages with empty stdout and
the same 55 stderr bytes (SHA-256
`2e8030a9eeb7187fbc1cb4ee9d794c352f1c31c92c884f8ae09a57e39bfe86db`):
`ww: build output "." already exists and is a directory`. Explicit `-o`
succeeded and produced byte-identical runnable binaries, proving that only
default presentation was wrong. This was the selected gap.
- **Go-like test:** an ordinary valid zero-match directory run exited 0 in both
stages with identical warning, accounting, and `[no tests to run]` result
bytes. The selected build branch does not enter test product naming,
filtering, capture, execution, result annotation, or retained test output.
- **Go-like package:** a directory containing two selected declared package
names was rejected in both stages with identical diagnostics. The selected
change occurs after package loading and does not alter source eligibility,
declaration checks, package kind, graph nodes, or actions.
- **Go-like import:** a dotted `cyclea -> cycleb -> cyclea` graph was rejected
in both stages with identical cycle diagnostics. The selected change does
not alter spelling, search, visibility, resolution, canonical identity, or
graph edges.
The pre-fix statuses, streams, hashes, diagnostics, artifacts, and runtime
results are **directly measured WW behavior**. The cited implementation and
testdata are **behavior directly implemented or asserted by pinned Go**. The
cross-axis non-effects follow from the bounded post-load output branch and are
**behavior derived from the pinned implementation**.
#### Ownership, final behavior, and preserved boundaries
`cmd/ww.do_build` and `selfhost/cmd/ww.dobuild` are semantic twins and the sole
owners of this rule. Their current-directory predicate accepts only relative
paths whose components are all exactly `.`. Only in that branch do they
canonicalize the selected directory and take its final component for output and
cold scratch presentation. Ordinary literal directory operands retain their
lexical leaf, and contextual roots retain their dotted identity leaf.
Direct post-fix probes through both stages show that bare, dot, and dot-slash
builds exit 0 with empty stdout/stderr, publish mode-executable binaries named
`a`, and produce `a.sepwork` with no `..sepwork`. All six binaries are
byte-identical (SHA-256
`866c1eb875dad271d37572f43fb9d9b0eb6a2344d2e61646e655bb09f7909bf6`).
Their unit, interface, assembly, object, archive, and init artifacts are also
byte-identical between stages and spellings. Current-directory library builds
still publish nothing and link nothing; their unit, interface, assembly,
object, and archive bytes remain stage-identical under `libcurrent.sepwork`.
Loading and source selection precede this branch. A missing dotted import
therefore retains its byte-identical diagnostic and creates neither output nor
scratch. Graph and action construction, compiler/assembler/archiver/linker
semantics, runtime behavior, and artifact content are unchanged. A genuine
directory occupying the derived output still rejects before tools and names
the derived leaf in its diagnostic.
Cold and warm persistent builds retain their existing keys and reuse rules. A
source invalidation reruns producers; an injected compiler failure preserves
the prior executable and committed persistent generation, publishes no stage,
and leaves no `.new`, `.install`, or `.wwtxn.*` residue. Restoring producer
success installs the changed executable. Existing concurrency, interruption,
process-group, rollback, publication, and cleanup owners gain no shared state or
new process path.
The WW-native `current_directory_build_default_output` observer proves both
stages, all three current-directory spellings, executable mode/runtime/byte
parity, explicit and null output controls, non-main non-publication, corrected
cold scratch, missing-import precedence, cold/warm reuse, invalidation,
producer-failure rollback, prior-output preservation, genuine collision, and
residue absence. Existing package/import graph, byte-identity, concurrent
transaction, and interruption observers remain authoritative for mechanisms
this presentation rule does not change.
No persisted-byte contract changed. Build workdir format remains `18`, test
workdir format remains `19`, and semantic storage format remains `3`.
## 12. Candidate architectures and hard-gate decision
Five candidates were developed as coherent systems, not as feature bins.