Files
huntedbytheirsandSisyphus 5487bbc808 Add documentation
README introduces the project and build workflow; CONTRIBUTING covers the stub convention and syscall wrapper process; docs/ explains the architecture and the kernel ABI surface.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <[email protected]>
2026-08-30 04:09:49 -04:00

92 lines
4.2 KiB
Markdown

# nulsl-libc
A very lightweight, from-scratch C17 libc for Linux, built for
[Null Linux](https://github.com/The-Null-Linux-Project) and its 32 MB RAM
target.
**Status: skeleton. The structure is real, the code is honest stubs.** The
string core, the raw syscall layer, the entry point, and process teardown
work end to end; everything else declares its intent and returns `ENOSYS`
until it is implemented (see the [roadmap](docs/architecture.md#roadmap)).
## Why another libc?
Null Linux guideline #6: *"If it's small, if it's lean, you have ZERO
reason to link with libC at ALL. Linux specific syscalls can do you well."*
- **Static-only, by design.** Everything links with `-nostdlib -static`.
No dynamic linker is loaded, relocated, or kept in memory for the
lifetime of a process — that memory belongs to the GUI.
- **The kernel is the API.** One variadic `syscall()` is the only piece
of code that touches the kernel ABI; `read`, `write`, `_exit`, and
friends are thin wrappers around it.
- **Freestanding C17.** `-ffreestanding -fno-builtin`: the compiler never
injects its own `memcpy`, so what you read is what runs.
- **No dependencies.** No libtool, no glibc, no kernel UAPI headers.
## Requirements
- Linux on x86_64
- A C17 compiler (GCC ≥ 8 or Clang ≥ 6)
- autoconf ≥ 2.71, automake ≥ 1.16
- `bear` (optional, for LSP `compile_commands.json`)
## Building
```sh
./autogen.sh # or just run make — it regenerates when needed
make release # -> bin/release/, CFLAGS='-O2'
make debug # -> bin/debug/, CFLAGS='-O0 -g'
make check # smoke test (fully static, no glibc, no ld.so)
make bench # benchmark the release build
```
Release is **always** `-O2`, per Null Linux guideline #4. `make bench`
and `make check` run against the release build.
The repository root is never configured in-tree; `configure.ac` refuses it
so the committed driver `Makefile` (which dispatches into `bin/release`
and `bin/debug`) cannot be clobbered. `make distclean` removes both build
directories.
## What works today
| Area | Real | Stub (ENOSYS) |
|--------------|-----------------------------------------|-----------------------------|
| string | strlen, strcmp, strncmp, strcpy, | — |
| | strncpy, memcpy, memmove, memset, | |
| | memcmp | |
| syscall | syscall() (x86_64) | other architectures |
| unistd | read, write, close, getpid, _exit | unlink |
| stdio | puts, putchar, fflush (trivially) | printf, fopen, fclose, |
| | | fread, fwrite |
| stdlib | exit, abort, atoi | malloc, calloc, realloc, |
| | | free, strtol |
| crt | crt0.o `_start` (x86_64) | other architectures |
Stubs follow one convention: standard signature, documented error return,
`errno = ENOSYS`, and a `/* TODO */` comment naming what they need. See
[docs/architecture.md](docs/architecture.md) for the design and roadmap,
[docs/syscalls.md](docs/syscalls.md) for the kernel interface.
## Repository layout
```
Makefile driver: make release / make debug / make bench / ...
configure.ac autotools (C17 enforced, static-only)
autogen.sh autoreconf -i
include/ public headers — declarations only
src/ implementations; src/crt/crt0.S is the entry point
benchmarks/ make bench; must stay lean
tests/ make check; smoke test links -nostdlib -static
bin/release/ out-of-tree release build (-O2)
bin/debug/ out-of-tree debug build (-O0 -g)
docs/ architecture + syscall documentation
```
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md). Short version: C17, clang-format,
benchmarks for anything performance-relevant, and per project policy —
*AI drafts, humans ship.*