Self-hosting and bootstrap¶
About this chapter Self-hosting
In this chapter
- Self-hosting and bootstrap
- Scope
- Host bootstrap remains the root
- Native toolchain components
- KCC is not GCC
- Host KCC executable
- Host tool tests
- The misleading level-zero target
- In-guest KCC command
- In-guest assembler command
- The mk kernel path
- Manifest parser limits
- C-only internal build list
- Path translation
- Per-unit compilation
- Text-only merge limitation
- Link stage
- Kernel output
- mk clean
- mk install is not a boot install
- Boot artifact used elsewhere
- Seed workflow
- Broken seed dependency in this revision
- What BIN/KCC.ELF means
- Boot log marker
- Self-host evidence levels
- Current evidence classification
- Reproducibility versus self-hosting
- Required proof for a full claim
- Architectural next steps
- Revision note
Scope¶
ChrisOS contains a real in-guest native compilation path, but the current repository does not yet prove full self-hosting.
The important distinction is between three different claims:
- the running kernel contains compiler, assembler, object-format, and linker code that can produce native ELF files;
- the guest can attempt to compile selected kernel C sources into
BIN/KERNEL.ELF; - the system can rebuild, install, boot, and verify its complete current kernel without relying on a host toolchain.
The current source strongly supports the first claim and partially implements the second. It does not yet establish the third.
This chapter treats self-hosting as an evidence problem rather than a label.
Host bootstrap remains the root¶
The normal repository build still starts with the host toolchain.
The makefile defines:
The production kernel objects are compiled by host GCC and linked by host ld.
Assembly and boot-media preparation also depend on host-side tools such as NASM, xorriso, Limine tooling, Python scripts, and filesystem utilities.
Therefore the normal make iso path is not self-hosted.
It is the bootstrap root from which the in-guest tools are built and embedded.
Native toolchain components¶
The emerging native path is composed of:
KCC is a C-subset compiler.
It emits assembly text into an internal buffer and then calls chrisasm_assemble.
ChrisAsm produces a ChrisoImage.
ChrisO represents sections, symbols, and relocations.
ChrisLd resolves those objects and emits an ELF64 x86-64 executable.
These components are compiled into the ChrisOS kernel and can therefore execute inside the guest.
KCC is not GCC¶
KCC must not be described as a complete C compiler.
It implements a project-specific C subset targeted at the code patterns needed by ChrisOS experiments.
The source has explicit fixed limits for preprocessed text, assembly output, symbols, macros, structs, fields, typedefs, enums, initializers, and parameters.
Its diagnostics and tests are substantial, but language coverage is not equivalent to GCC or Clang.
A kernel source file compiling under host GCC does not automatically imply that KCC can compile it.
Host KCC executable¶
The makefile also builds:
through the host-kcc target.
That binary is compiled by HOST_CC from:
tools/kcc_main.c;- KCC;
- ChrisAsm;
- ChrisO support.
Its purpose is to exercise the same compiler path from the host and to create a bootstrap tool artifact.
This host executable is not itself evidence that KCC has compiled KCC.
It is still produced by host GCC.
Host tool tests¶
There are separate host tests for the emerging native toolchain:
host-chrisasm-test;host-chrisld-test;host-kcc-test;host-chriso-test.
These tests prove concrete pieces of functionality such as instruction encoding, malformed assembly rejection, ELF generation, relocations, section layout, KCC language features, and compiler diagnostics.
They are useful bootstrap evidence because they validate the tools before using them inside the guest.
They are not a proof that the entire kernel can be rebuilt by those tools.
The misleading level-zero target¶
The makefile defines:
This target currently aliases the general KCC test rather than compiling a complete kernel stage.
There is a source fixture named tools/kcc_fixtures/level0.c, but its own comment explicitly says it is not kernel/metal/serial.c and that it represents a deliberately tiny subset.
Thus "kernel-l0" is a bootstrap experiment, not a full kernel build level.
In-guest KCC command¶
The shell command:
does not launch BIN/KCC.ELF.
It directly calls the KCC library already linked into the running kernel:
The resulting ChrisO image is passed through the native linker helper to produce an ELF file.
This is meaningful in-guest compilation, but the compiler executing is part of the host-built kernel image.
That is an important provenance distinction.
In-guest assembler command¶
The shell also provides:
for .S or .ASM sources.
It reads source from ChrisFS, runs chrisasm_assemble, and links the resulting ChrisO image into a native ELF.
Like the KCC command, the assembler code is embedded in the currently running host-built kernel.
This proves the guest can perform native assembly/linking work without invoking host NASM at that moment.
It does not eliminate NASM from the bootstrap of the running kernel.
The mk kernel path¶
The central self-build function is:
The shell exposes it as:
The function reads:
from ChrisFS and parses a small custom manifest.
The defaults are:
The manifest may list C source paths under C_OBJECTS.
Manifest parser limits¶
The internal builder supports at most:
C source units.
The source buffer is:
bytes.
The final ELF buffer is bounded by:
These are hard implementation limits, not merely documentation recommendations.
C-only internal build list¶
The parser recognizes the start of C_OBJECTS.
When it encounters ASM_OBJECTS=, it stops collecting C paths.
It does not subsequently parse and assemble an assembly-object list.
Therefore the current chrisbuild_mk_kernel pipeline is not a complete replacement for the repository kernel build, which includes assembly units and generated assets.
This alone prevents a full-kernel self-host claim.
Path translation¶
Manifest paths are converted into ChrisFS paths.
For example, a host-style path beginning with:
is translated beneath:
and letters are uppercased.
This allows the guest builder to consume seeded source files from the ChrisFS workspace.
The self-host workspace is therefore a second source tree representation, not direct access to the host checkout.
Per-unit compilation¶
For every manifest C source, the builder:
- reads the source into the 64 KiB buffer;
- invokes
kcc_compile_source; - obtains one
ChrisoImage; - merges that image into a combined object.
Compilation failure aborts the build immediately.
The serial log identifies the file currently being compiled with an mk: kcc prefix.
Text-only merge limitation¶
The merge operation is:
Its behavior is narrower than its name might suggest.
It appends the TEXT section and adjusts TEXT symbols and relocations.
It does not merge RODATA, DATA, or BSS payloads from each source unit into the combined image.
The combined text buffer is also capped at 65536 bytes.
Consequently, the current internal kernel builder can only correctly combine a restricted class of units.
A general current ChrisOS kernel containing globals, static data, BSS, strings, generated tables, and other sections cannot be assumed to survive this merge path.
Link stage¶
After all selected C units are merged, the builder calls:
ChrisLd emits ELF64 for x86-64.
Its general linker implementation supports TEXT, RODATA, DATA, and BSS, symbol resolution, multiple relocation types, RX/RW load segments, and entry selection.
However, the mk kernel builder currently feeds it one already-merged image produced by the text-only merge path.
The linker's broader capabilities therefore do not remove the builder's earlier information loss.
Kernel output¶
On success, the generated ELF is written to the path selected by the manifest, normally:
The serial console prints:
This is useful evidence that selected units compiled and linked.
It is not evidence that the resulting binary has booted.
mk clean¶
The shell command:
deletes:
when present.
This part of the lifecycle is simple and deterministic.
mk install is not a boot install¶
The function named chrisbuild_mk_install currently:
- reads
BIN/KERNEL.ELF; - writes the same bytes back to
BIN/KERNEL.ELF; - prints
mk: install ok.
It does not copy that file to:
and it does not update the EFI System Partition or the ISO boot tree.
Therefore mk install does not currently establish that the next boot will execute the internally built kernel.
Its name overstates the current effect.
Boot artifact used elsewhere¶
The normal host-side disk population copies the host-built kernel into:
along with Limine configuration and EFI files.
This is a separate path from BIN/KERNEL.ELF.
Until the internally built ELF is deliberately promoted into the actual boot path and verified after reboot, self-hosted boot is unproven.
Seed workflow¶
The repository defines:
which depends on:
- ISO construction;
- disk image;
- host KCC;
- host seed utility.
The seed program mounts the ChrisFS disk and attempts to populate:
SYS/BUILD.MK;- selected kernel source files;
BIN/KCC.ELF.
This is intended to create the guest-side build workspace.
Broken seed dependency in this revision¶
The seed program tries to read:
from the host repository.
That path does not exist in the inspected source tree at revision e05a17fd76333114a3fb5c2452f38ca747d4ac56.
Because put_file treats failure to read that file as fatal, the current seed workflow cannot be considered complete/reproducible from the checked-in tree.
This is a concrete bootstrap break, not a theoretical limitation.
What BIN/KCC.ELF means¶
The seed utility copies:
to:
inside ChrisFS.
That source binary was produced by the host compiler.
The guest shell's kcc command does not execute this file; it calls the embedded KCC library.
Therefore presence of BIN/KCC.ELF should not be used as proof that ChrisOS runs a self-produced compiler binary.
The provenance chain remains host-rooted.
Boot log marker¶
Early in kstart, the kernel prints:
unconditionally.
This string does not test which compiler produced the running kernel.
It does not hash the booted image or compare it with BIN/KERNEL.ELF.
It is therefore a descriptive marker, not self-hosting evidence.
A real self-host proof must bind runtime identity to a specific internally generated artifact.
Self-host evidence levels¶
A practical evidence model for ChrisOS should separate milestones.
A useful progression is:
SH0 host-built KCC/ChrisAsm/ChrisLd pass host tests
SH1 embedded guest tools compile/link native programs
SH2 guest compiles selected real kernel units
SH3 guest builds a structurally complete kernel ELF
SH4 internally built ELF passes validation and boot packaging
SH5 machine reboots into that exact internally built ELF
SH6 repeated stage build demonstrates defined convergence/reproducibility
These names are documentation criteria, not claims that all stages are achieved.
Current evidence classification¶
At the inspected revision, strong evidence exists for SH0 and meaningful parts of SH1.
There is implementation toward SH2 through chrisbuild_mk_kernel, but the missing seed manifest and builder limitations prevent treating the whole workflow as a clean reproduced gate.
SH3 and higher are not established by the inspected source.
In particular, no checked source path proves that the complete current kernel is built by KCC and then booted.
Reproducibility versus self-hosting¶
Self-hosting asks what toolchain produces the artifact.
Reproducibility asks whether equivalent declared inputs produce equivalent outputs under a defined criterion.
The two properties are independent.
A host-built kernel can be reproducible.
A self-hosted kernel can be non-reproducible.
ChrisOS build IDs include Git revision and build date, so byte-for-byte convergence needs a policy for timestamps and metadata before identical hashes can be expected.
Required proof for a full claim¶
A strong future gate should record:
- source Git revision;
- exact bootstrap binary hashes;
- source-manifest hash;
- KCC/ChrisAsm/ChrisLd versions or hashes;
- generated
BIN/KERNEL.ELFhash; chrisld_validateresult;- exact promotion to the boot path;
- reboot;
- runtime build identity from the booted kernel;
- comparison showing runtime identity matches the internally produced artifact.
Without steps 7–10, "built a kernel ELF" is not the same as "self-hosted the running kernel."
Architectural next steps¶
The most important engineering work is:
- restore/check in the missing
SYS_BUILD.MKseed source; - make the manifest represent the complete kernel artifact graph;
- support assembly units and generated inputs;
- replace text-only object merging with full multi-object linking;
- raise or remove the 64 KiB merged-text bottleneck;
- validate the generated ELF with
chrisld_validate; - make install copy to the actual boot target atomically;
- add a reboot gate proving the exact artifact is running;
- make the compiler itself buildable by a previous KCC stage;
- define convergence and reproducibility criteria.
Revision note¶
This chapter was reconciled against ChrisOS revision e05a17fd76333114a3fb5c2452f38ca747d4ac56. The current tree contains genuine in-guest native compilation infrastructure, but it does not yet prove complete kernel self-hosting. The missing seed manifest, C-only manifest handling, text-only merge, and non-installing mk install are explicit blockers in the inspected revision.