Sixty-five headers sat side by side in include/, so `#include "irq.h"` said nothing about where irq.h was or what it belonged to, and errno.h, stat.h and fcntl.h at the top shadowed the system's for any host tool built with -I./include. They are in folders now -- arch/ core/ fs/ dev/ gfx/ net/ uapi/ (and ldls/ for the Linux driver layer) -- and every include names the folder, as Linux's do: "core/proc.h". Done mechanically and checked the hard way: the kernel built from this tree disassembles identically to the one built from the tree before it. The full image boots, and userland is the same set of programs. Paths in docs and comments follow; docs/guides/layout.md has a table of what is where, and tools/fix-includes.py rewrites old-style includes from the folders in the tree, for code written before this. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
2.6 KiB
2.6 KiB
| name | description | metadata | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| schunix-build-speed | The build is fast now (no-op ~2s); the four things that made it slow and the traps that will make it slow again |
|
A no-op make went from 1m48s to ~2s on 2026-08-04, and a full kernel
rebuild from ~110s to ~7s. Almost none of it was compilation — with only 2.4s
of CPU in that 1m48, it was I/O across WSL's /mnt/d boundary. Four causes,
all still worth not reintroducing:
tools/mkfsbuilt the image on the file, onelseek+ one 512-bytewriteper block: 300,000 syscall pairs, 150,000 of them just to zero it. It now assembles the image in RAM and writes once. It also stops at the last non-zero block andftruncates, so ~2 MB is written instead of 147 MB.- The image was rebuilt on every invocation.
sysroot-installis phony, so everything depending on it always ran. There is now abuild/sysroot.stampwhose mtime only advances when afind-based summary of the staged tree actually changes (thecmp -s ... || mvidiom — do not add atouch, and notetouch -cstill updates an existing file's mtime, which is exactly the bug I wrote and had to remove). ports/toyboxre-linked its 236 applets every build, because port.mk declaresinstall.PHONY for every port. It hangs off$(BUILDDIR)/toybox.installednow. This was the sneaky one: it bumped the mtime of 236 files insysroot/and so invalidated the stamp above.- mkfs and mkschfs re-read every file to dedup it. They now check
(st_dev, st_ino)first — toybox's applets are real hard links, so 236 of them are settled by onefstatinstead of ~500 MB of reads.
Two real bugs found in the Makefile while doing this:
$(BUILD)/kernel/**/*.donly matched one directory level. make's wildcard has no recursive**.arch/x86_64/andfs/schfs/therefore had no header dependency tracking at all — editinginclude/fs/schfs.hleft stale objects that linked fine. It uses$(shell find ...)now.CFLAGSis recursively expanded and had a$(shell)appended, so the stack-protector probe re-ran on every expansion: one extra gcc per object file. Probed once intoNO_SSP :=now.
schunix.img is no longer .PHONY (it is a real file), and MAKEFLAGS += -j$(nproc) is on by default — use make -j1 for readable output from a
failing build.
Verify with make schfs-check plus schunix-verify-by-driving-shell; the
superblock checksum is printed by mkfs and should not change when only build
mechanics change.