SchOS/docs/guides/building.md
Nexoniarz 26bca020b6 licence: SchOS is GPL-2.0-or-later, no longer Apache-2.0
Nexoniarz is the sole author and SchOS was never published under
Apache-2.0, so this is a straight relicence. LICENSE is the FSF GPLv2 text,
every first-party SPDX header moves to GPL-2.0-or-later, and NOTICE,
README.md, docs/licensing.md and the site say so. projects/schfs-linux
follows the rest of the tree.

The GPL gives copyleft: a fork has to ship its source. It also lifts the
old "Linux drivers, never" rule, since GPL-2.0-only code combines with
GPL-2.0-or-later. "Or later" leaves room for GPLv3, but one binary still
has to pick one version, so docs/licensing.md now keeps Apache-2.0 and
GPLv3 code out of the kernel to keep Linux code possible there. BSD
4-clause code goes from "avoid" to "no", because the advertising clause
is GPL-incompatible.

LDLS still ships no .ko. That boundary is now project policy rather than
a legal requirement, and ldls.md, devices.md and licensing.md section 6
say so. refmod declares license=GPL, and ldls-check passes (27 checks).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 08:48:45 +02:00

144 lines
5.9 KiB
Markdown

<!-- SPDX-License-Identifier: GPL-2.0-or-later -->
# Building SchOS
Supported hosts: **Linux, macOS, FreeBSD/OpenBSD/NetBSD, and Windows** (under
Git Bash or MSYS2). The build is developed from both Windows and Linux, so a
change that only works on one of them is a bug.
```sh
make # kernel + UEFI loader + root filesystem
make qemu # build and boot it
```
## Prerequisites
| Need | Why | Windows | Linux | macOS | BSD |
|---|---|---|---|---|---|
| `clang`, `ld.lld`, `llvm-objcopy`, `llvm-objdump` | cross-compiles the kernel, the 16/32-bit boot code, and musl userland | LLVM installer | `clang lld llvm` | `brew install llvm` | `pkg install llvm` |
| `make` | — | Git Bash | `make` | Xcode CLT | `gmake` |
| `perl` | generates the interrupt vector table | Git Bash | usually present | present | `pkg install perl5` |
| `python3` | boot logo, crash-screen QR | python.org (`python`) | `python3` | `brew install python` | `pkg install python3` |
| `qemu-system-x86_64` | running and testing | `scoop install qemu` | `qemu-system-x86` | `brew install qemu` | `pkg install qemu` |
| `curl`, `tar` | fetching ports | Git Bash | present | present | present |
| `xorriso` **or** `mkisofs` | `make iso` only | `scoop install cdrtools` | `xorriso` | `brew install xorriso` | `pkg install xorriso` |
On NixOS, `nix-shell` supplies every row above — see below.
## NixOS
```sh
nix-shell # then: make, make qemu, make iso
```
`shell.nix` in the repository root declares the lot. Worth using rather than
assembling it by hand, for one specific reason: **`make` falls back to the GNU
toolchain for the kernel but the UEFI loader genuinely cannot be built without
clang and `lld-link`.** A machine with only gcc therefore produces a kernel that
builds and a loader that silently stays whatever it already was — which left a
stale boot splash on this tree for half a day before anyone looked at the
screen rather than the build output.
PowerShell is the one thing the shell does not supply, and `tools/windows/`
needs it. See the note at the end of this file.
A host C compiler (`cc`) is also needed, for the tools that build the disk
images. On Windows that must be **mingw-w64's gcc**, not clang: clang defaults
to an MSVC target there, and `tools/mkfs.c` needs `<unistd.h>` and `<dirent.h>`,
which the Windows SDK does not have.
## Why clang rather than a cross-gcc
clang is a cross-compiler by construction, so one ordinary LLVM install targets
everything this tree needs — bare-metal ELF, code linked below one megabyte, and
Linux/musl userland — from any host. A cross binutils+gcc would be a day of
setup per platform that then rots, and on macOS it means brewing
`x86_64-elf-gcc` before anything builds at all.
The Makefile selects clang+lld whenever both are on `PATH`. To force the GNU
toolchain instead:
```sh
make USE_GNU=1 # needs a cross toolchain that emits x86_64 ELF
make USE_GNU=1 TOOLPREFIX=x86_64-elf-
```
## Testing
```sh
tools/windows/bootcheck.ps1 # boots, drives the shell, asserts on output
tools/windows/bootcheck.ps1 -Tty -Ps # plus terminal behaviour and process listing
make schfs-check # SchFS unit, object and image suites
```
`bootcheck` is PowerShell, and PowerShell 7 (`pwsh`) runs on Linux, macOS and
the BSDs as well as Windows — `brew install powershell`, or your distribution's
`powershell` package. It finds QEMU on `PATH`.
Booting to a prompt proves nothing on its own: a filesystem can mount and still
fail the first real command, which has happened here. `bootcheck` types commands
at the serial console and greps the transcript for the answers they should
produce.
## Ports
`musl`, `toybox` and `mksh` are built from source into `sysroot/`. **This does
not work on a Windows host** — `make` prints `ports: skipped` and uses whatever
is already staged in `sysroot/`. Building them needs a Linux host (or any other
Unix); do it once and the staged result serves the Windows builds.
## Where the tools live
`tools/` is grouped by what runs the file, so it is obvious at a glance which
tools a given host can use:
```
tools/
windows/ .ps1 PowerShell (pwsh runs these on Linux and macOS too)
posix/ .sh shell
python/ .py
*.c host programs -- compiled by the build, run everywhere
*.pl perl, likewise
```
The `.c` and `.pl` files stay at the top level because they are not
host-specific: the build compiles or invokes them on every platform.
A script that needs the repo root derives it from its own location, so anything
moved between these directories has to have that adjusted — the PowerShell tools
use `Split-Path (Split-Path $PSScriptRoot -Parent) -Parent`, two levels up.
## Known host differences, already handled
Listed because they are the shape of the next such bug, not because anything is
outstanding:
- `<sys/sysmacros.h>` is glibc/musl only. macOS and the BSDs take `major()` and
`minor()` from `<sys/types.h>`.
- `sha256sum` exists on Linux and Git Bash; macOS has `shasum -a 256`,
FreeBSD/NetBSD `sha256`, OpenBSD `cksum -a sha256`. `tools/posix/sha256check.sh`
finds whichever is present.
- `nproc` is coreutils, so absent on macOS and BSD, where it is
`sysctl -n hw.ncpu`.
- In the PowerShell tools, path literals must use forward slashes:
`Join-Path $root 'build\x'` produces a *filename containing a backslash* on a
Unix host.
## Fedora, in one command
```sh
tools/posix/setup-fedora.sh --check # what is missing
tools/posix/setup-fedora.sh # install it
```
Moving an existing checkout to a Linux machine: see
[../history/moving-to-linux.md](../history/moving-to-linux.md).
## Working on two machines
Claude Code's project memory is kept in the repo and moved with:
```sh
tools/posix/memory-sync.sh status
tools/posix/memory-sync.sh export # after a session that learned something; then commit
tools/posix/memory-sync.sh import # after cloning or pulling elsewhere
```