Create docs/CONTRIBUTING.md (build/verify workflow, coding style, kernel gotchas, commit & PR conventions), docs/SECURITY.md (supported versions, private vulnerability reporting, documented caveats), and docs/ROADMAP.md (shipped in v1.0.0 plus near/mid/long-term plans). Add a Documentation and Contributing section to the README pointing at all four docs. Note: used the conventional CONTRIBUTING.md / SECURITY.md filenames (in docs/) so GitHub auto-detects them as community-health files. Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01Fh5z6V7nGPbHvqVG5p4CXX
6.8 KiB
Thanks for your interest in SUB-OS — a multi-architecture, modular monolithic,
Linux-compatible operating system written from scratch in C, C++17, Assembly,
freestanding Rust (no_std), and the native SUB Language. This guide covers how
to build, the conventions we follow, and how to get a change merged.
Table of Contents
- Ground rules
- Development environment
- Building
- Running & verifying
- Coding style
- Kernel gotchas
- Commit & PR conventions
- Reporting bugs
Ground rules
- Verify before you claim. Nothing is "done" until it builds and boots. Every crypto primitive and codec is tested against a reference vector (RFC or a PIL-generated fixture) before it enters the kernel. Hold new code to the same bar.
- No libc, no POSIX host. The kernel is freestanding. No floating point in
kernel space (
-mno-sse); all math is integer. - Small, reviewable changes. One feature or fix per pull request, with a clear description of what you verified and how.
- Be kind. Assume good faith, keep discussion technical, and respect reviewers' time.
Development environment
The project targets x86_64, aarch64, and armv8i (AArch32). On a Debian/
Ubuntu host, install the toolchains and emulators:
sudo apt update
sudo apt install build-essential g++ nasm qemu-system-x86 qemu-system-arm \
gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu \
gcc-arm-linux-gnueabihf binutils-arm-linux-gnueabihf \
rustc cargo dialog python3
For the freestanding Rust layer:
rustup target add x86_64-unknown-none
The x86_64 kernel is normally built with an
x86_64-elf-cross toolchain. A stockx86_64-linux-gnu-GCC also works — pass it viaCROSS_COMPILE=.
Building
SUB-OS uses a Linux-style Kconfig + Kbuild flow. The version/codename lives at
the top of the Makefile (VERSION/PATCHLEVEL/SUBLEVEL/EXTRAVERSION/
NAME) and in include/init/version.h — keep the
two in sync when you bump a release.
# Configure (interactive) or pick an architecture preset:
make configure # or: make menuconfig
make x86_64_defconfig # x86_64 (Intel / AMD)
make aarch64_defconfig # 64-bit ARM (Cortex-A57)
make armv8i_defconfig # 32-bit ARM (Cortex-A15)
# Build:
make # builds the configured/default ARCH
make ARCH=aarch64 # or target one explicitly
Always
make cleanwhen switchingARCH. Object files from another architecture link into a "file in wrong format" error otherwise.
Running & verifying
make run # x86_64 disk image in QEMU
make run-gui # windowed graphical desktop
make run-fullscreen # fullscreen desktop
make run-vnc # headless: VNC on localhost:5900
make ARCH=aarch64 run # ARM targets
Default login is SUB / SUB. Pass nogui, text, emergency, or
single on the kernel command line to boot to the TTY instead of the desktop.
Headless verification (what CI and reviewers use): boot with
-serial file:serial.log -monitor unix:mon.sock,server,nowait -display none,
drive the login over the monitor sendkey interface, and capture the screen
with screendump. For a code path with no UI, add a temporary CLI applet under
userland/lazybox/ that exercises it over serial, verify, then revert the
temporary hook.
When you submit a change, state plainly what you ran and what you saw — build output, boot log excerpt, screenshot, or reference-vector comparison.
Coding style
- C: freestanding C11. Match the surrounding file — 4-space indent, K&R
braces,
snake_casefor functions and variables,SCREAMING_SNAKEfor macros/constants. Keep comment density and idiom consistent with the module you're editing. - Assembly: per-arch under
arch/<arch>/..Sfiles run throughcpp, so no nested/* ... */comments. - Rust:
no_std, no allocator assumptions beyond what the kernel provides. - C++: freestanding C++17, no exceptions/RTTI, no host STL.
- Headers: public interfaces in
include/, with an include guard. - No new external dependencies in kernel space.
Kernel gotchas
These bite newcomers — internalize them before touching the relevant subsystem:
printk/vsprintfare minimal. Supported conversions arec s d i u o x X p %only — no length modifiers (l,ll) and no field width. Cast toint/unsigned/void*at the call site.list_del()NULLs both links, solist_empty()is not a reliable "is this node still queued?" test after a delete — inspect the links directly.- Preemption is armed after boot. A context switch must never run while a
plain spinlock is held: wrap such sections with
sched_preempt_disable/enable(asprintkdoes).weave_locksections usearch_irq_save/restoreso the timer tick cannot fire inside them. - Dead tasks/stacks are not reclaimed yet. Prefer one long-lived worker thread over spawning a task per request.
- Network checksums are byte-wise on purpose — word-at-a-time reads get
reordered around the caller's
hdr->checksum = 0store under-O2. - Ethernet frames are padded to 60 bytes — trim payloads to the IP
total_length, never the frame length.
Commit & PR conventions
- Commit messages follow Conventional-Commits-style prefixes:
feat(scope): …,fix(scope): …,build: …,docs: …,release(vX.Y.Z): …. Write the subject in the imperative and add a body explaining what changed and what you verified. - Branch off
mainfor your work; open a pull request againstmain. - One logical change per PR. Rebase/squash noisy WIP commits before review.
- CI must pass (build + kernel verification) before merge.
- In the PR description, include: what the change does, which architectures you built, and how you verified boot behaviour.
Reporting bugs
Open a GitHub issue with:
- Architecture and how you built (
defconfig,ARCH, toolchain). - Exact command that reproduces it.
- What you expected vs. what happened — paste the serial log and, for
the desktop, attach a
screendump. - The commit SHA (
git rev-parse --short HEAD).
For security-sensitive reports, do not open a public issue — follow the Security Policy instead.
Happy hacking. 🐉
