Skip to content
Merged
22 changes: 22 additions & 0 deletions issues/build/a-compiler-key-reads-no-symbolic-link.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
status: open
kind: tooling
opened: 2026-10-01
---

# A compiler key reads no symbolic link

`compiler::key` reads `compiler/`, `src/tools/`, `src/stage0` and
`Cargo.lock` through `sysroot::tree_identity` with `Links::Skipped`, so a
symbolic link there is in no key: retargeting one, or editing what it names
outside those trees, keeps the old compiler. Refusing a link there, as the
freestanding key does, refuses every compiler build:
`git -C rust ls-files -s compiler src/tools src/stage0 Cargo.lock` at fork
commit `aca5f527f` lists 5 entries of mode `120000`, all under `src/tools`
(clippy's and rust-analyzer's `LICENSE-APACHE` and `LICENSE-MIT`, and
rust-analyzer's `AGENTS.md`). Hashing a link's target text instead moves the
key of every compiler of a worktree's own once.

**Exit**: `Links::Skipped` is deleted and the compiler key hashes a link's
target text, landed with the next change to `compiler.rs`'s `RECIPE`, which
moves every compiler key anyway.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
status: open
kind: tooling
opened: 2026-10-01
---

# A sysroot builds both architectures' userland for a build of one

A sysroot is a whole toolchain for every guest target (`toolchain::GUEST_TARGETS`),
so a new key builds the std set of `x86_64-unknown-toyos` and of
`aarch64-unknown-toyos`, libc for both, and the C++ runtime for both, even when
the build that asked for it is `cargo run -- --build-only`, which links only
x86_64. Measured on the `wt/toyos-rebuild` branch, one item added to
`toyos-abi/src/clock.rs`: the aarch64 std set took 2m18s of a 4m12s std
build at load 41.

**Exit**: a build makes the libraries of only the architectures it builds for,
and the sysroot's key and identity still name exactly what is in it.
21 changes: 0 additions & 21 deletions issues/build/cleans-deps-stamp-write-is-swallowed.md

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
status: open
kind: tooling
opened: 2026-10-01
---

# Every sysroot key compiles userland's `core` and `alloc` again

`sysroot::build_std` empties each userland target's `stage0-std/` before it
builds (`prepare_std_build`), so every new sysroot key compiles `core`, `alloc`
and `compiler_builtins` for both userland targets from nothing, although they
read nothing of the worktree: in this branch's build of
`x86_64-unknown-toyos`, cargo's dep-info for them (`dist/libcore.d`,
`liballoc.d`, `libcompiler_builtins.d`) names 411, 714 and 630 paths, none in
the worktree outside its fork, where `libstd.d` names 42. The emptying rests
on the claim, in a comment there, that bootstrap does not see a path
dependency outside the fork move; nobody has measured a build that keeps the
directory. Measured on the `wt/toyos-rebuild` branch, one item added to
`toyos-abi/src/clock.rs`, from the timestamped build log: `core` and `alloc`
were the first 37 s of the 91 s `x86_64-unknown-toyos` std build, and 91 s of
the 158 s `aarch64-unknown-toyos` one, at a load that peaked at 186.

**Exit**: one item added to `toyos-abi/src/clock.rs` after a build, and the
next `cargo run -- --build-only` prints no `Compiling core` and no
`Compiling alloc`.
18 changes: 18 additions & 0 deletions issues/build/the-cxx-runtime-is-rebuilt-for-every-sysroot-key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
status: open
kind: tooling
opened: 2026-10-01
---

# The C++ runtime is rebuilt for every sysroot key

`sysroot::build` builds libc++, libc++abi and libunwind for both userland
targets into every new sysroot (`libcxx::build`), so every `toyos-abi` edit
pays for them. Their inputs are the compiler's LLVM, `libcxx::OPTIONS` and the
C sysroot they compile and link against: libc's headers and its staticlib. An
ABI edit moves only the staticlib. Measured on the `wt/toyos-rebuild` branch,
one item added to `toyos-abi/src/clock.rs`: 27 s and 38 s at load 41, 47 s and
54 s at load 68.

**Exit**: one item added to `toyos-abi/src/clock.rs` after a build, and the
next `cargo run -- --build-only` prints no `Building the C++ runtime`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
status: open
kind: tooling
opened: 2026-10-01
---

# The C++ runtime's scratch removal dies on a Finder file

`libcxx::build` ends with a plain `fs::remove_dir_all(scratch)`. On this host
Finder writes a `.DS_Store` into a directory while it is being emptied. A
`cargo run -- --build-only` on `wt/toyos-rebuild` died with `remove
…/rust/build/sysroots/d9ce291c409918f4.libcxx-x86_64: Directory not empty (os
error 66)`, and afterwards the directory held only that `.DS_Store`. The
sysroot was left at `<key>.partial`, so the next build made it again.
`worktree::remove_tree` is the removal that outlasts it.

**Exit**: every removal of a build product outlasts a writer that adds a
file while it runs, with a test that adds one.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ the new rustc refuses their metadata: `error[E0463]: can't find crate` for
`cursor_icon`, `smol_str`, `raw_window_handle`, `keyboard_types` in winit-core.
Recorded at the first external use of the `sdk-0.2.0` alias: Japabu/gbae run
33960322229 restored a target directory built by `5009ee0d7ea1cfad` and built
with `3845b80c8ba72421`. Inside this tree `src/build.rs`'s
`external_fingerprint` is the belt that hides it; a consumer has no belt.
with `3845b80c8ba72421`.

Reproduce with any consumer: build with one release, swap the linked toolchain
to another, build again in the same target directory.
Expand Down
2 changes: 1 addition & 1 deletion src/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Loads when you read a file under `src/` — the root cargo project, package name

## The host's locks

- **Sysroots are content-addressed** (`src/sysroot.rs`): one per key — the identity (`src/identity.rs`, so a comment is no change) of `toyos-abi/src`, `toyos/src`, `userland/libc/src` and their manifests, the std fork's `rust/library/` and `rust/src/bootstrap/`, and the compiler — at `rust/build/sysroots/<key>/`, made by whichever worktree first needs it. Every build compiles against its own key's, so two worktrees with different ABIs never refuse or wait for each other; the only shared step is the primary's compiler, which a sysroot build reads under the global lock in shared mode. A new key costs one std build of the three guest targets; `--worktree remove` sweeps the keys no worktree records.
- **Sysroots are content-addressed** (`src/sysroot.rs`): one per key — the identity (`src/identity.rs`, so a comment is no change) of `toyos-abi/src`, `toyos/src`, `userland/libc/src` and their manifests, the std fork's `rust/library/` and `rust/src/bootstrap/`, and the compiler — at `rust/build/sysroots/<key>/`, made by whichever worktree first needs it. Every build compiles against its own key's, so two worktrees with different ABIs never refuse or wait for each other; the only shared step is the primary's compiler, which a sysroot build reads under the global lock in shared mode. `--worktree remove` sweeps the keys no worktree records.
- **The std fork is built per worktree, and nothing but the primary's own sync moves the primary's `rust/`.** A linked worktree's `rust/` becomes, on its first build, a git worktree of the primary's fork repository at the commit its tree pins — that is where the fork is edited, committed and pinned. A worktree whose fork `compiler/` differs from the one the primary built builds its own compiler, keyed by that source and placed beside the primary's without touching it. If that checkout later falls behind the commit its tree pins (a merge moved the pin), the build moves the checkout to it itself, fetching from the primary's repository first if it holds the commit, unless the checkout has local changes, which it refuses to move out from under.
- `src/buildlock.rs` serialises the stateful phases in two scopes: `Global` (the primary's compiler and the rustup link — one directory in `.git/`, shared by every worktree) and `Worktree` (the crate-target cleans, and this worktree's std build). Only `./x.py` typed by hand in `rust/` escapes it.
- **Never kill a build that has taken the global lock** — the kill removes the shell wrappers, not the bootstrap, which inherits the file descriptor and runs on regardless; a toolchain rebuild interrupted or unobserved this way can leave `stage2/bin` without a `cargo`.
Expand Down
Loading
Loading