Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Linux Systems Programming — project conventions

Tutorial site: Linux systems programming in C++23, Go, and Rust for
intermediate→advanced developers. Jekyll/GitHub Pages (built in CI — no local
Ruby), examples in `examples/NN-slug/{cpp,go,rust}/`, chapters in
`_docs/NN-slug.md` with the same NN.

## Scope rules

- **eBPF is tooling only** (bcc-tools, bpftrace, bpftool) — we observe our own
userspace programs; we never write kernel eBPF.
- Examples run **locally** unless they need root, kernel observation, or a
second host — then the KVM lab: `systems-target` / `systems-peer`
(`scripts/lab/`, LAB_PREFIX=systems, Fedora 44 guests, snapshot `lab-ready`).
- Containers: multi-stage **Containerfile** (never "Dockerfile"), **UBI 10**
bases, rootless podman.

## Toolchain pins

- C++23 — system GCC (floor 14) primary, clang first-class alternate presets;
CMake ≥ 3.25, Presets v6, Ninja, `build/${presetName}`; Conan 2 only where
third-party deps exist.
- Go — `go.mod` `go 1.26` + `toolchain go1.26.5`.
- Rust — `rust-toolchain.toml` channel 1.97.1, edition 2024.
- Lua 5.4 (LuaJIT accepted locally) drives `verify.lua`; Python 3 drives
`scripts/test-all-examples.py` and `scripts/validate.py`.

## Chapter conventions

- Front matter: `title/order/part/description/duration`; `part:` must equal a
`_parts` `part_name` exactly; quote values containing colons.
- Spine: hook → figure → concept → "How the code works" → "Errors, three ways"
→ "Concurrency lens" → "Build, run, observe" → cross-check → "What you
learned" → status footer.
- **Tools used box (required)**: immediately after the intro/figure, a callout
listing every tool the chapter invokes and where it runs, e.g.
`> **Tools used** — `strace` (host), `gdbserver` (systems-target VM),
`podman` (host). All appear in `scripts/check-host.sh` or the VM cloud-init.`
Every tool named must actually be exercised in the chapter.
- Code tabs: `{% include codetabs.html langs="C++|Go|Rust" %}` + exactly one
fenced block per label, in order, each a **verbatim excerpt** of the real
example source.
- Command prefixes: `[host]$`, `[vm]$`, `[peer]$`.
- Wrap literal `{{ }}`/`{% %}` in `{% raw %}…{% endraw %}` in prose.
- Diagrams: paired SVG+Excalidraw via `scripts/generate_diagram.py`
(`g.OUT="assets/diagrams"`); catalogue every diagram in
`assets/diagrams/README.md`; embed via the `excalidraw.html` include with a
`Figure N.x` caption.
- **Verification discipline**: a demo is *verified* only when it produced its
claimed observable effect on the stated environment; footers
(`status--verified` / `status--unverified`) state the behavioral evidence.
Every number quoted as "from a run" must come from a real run.
- **Banned words**: never use "honest", "honestly", "to be honest" — write
"real", "practical", "accurate" instead.

## Examples

- Mint new examples with `scripts/new-example.sh NN-slug`; register in
`examples/manifest.yaml` (`mode: local|vm|vm-peer`, `requires: [lgtm]`).
- Identical observable behavior across the three languages — one `verify.lua`
(checks.lua API) asserts behavior, never merely exit 0.
- Demo contract: `./demo.sh [cpp|go|rust] [build|run]`; `TARGET=<vm>` deploys
via `scripts/lab/deploy-to-vm.sh` (`SUDO=1` for root demos).
- Runner: `python3 scripts/test-all-examples.py` — VM examples strictly
serial; SKIP (not FAIL) when lab/LGTM is down.

## Git

- One branch per iteration (`docs/rNN-…`), PR, squash merge to main, delete
branch. Never commit directly to main. Conventional Commits:
types docs/site/demo/ci/chore/fix/feat/refactor/style; scopes `§N`,
`demo-NN`, `rNN`.
- CI (`validate.yml`) checks site integrity + build smoke only; the
authoritative gate is a host run of the runner with the lab up, recorded in
`_plans/`.
19 changes: 14 additions & 5 deletions _docs/01-prerequisites.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ every later example reuses.
alt="Three toolchain stacks — GCC/CMake/gdb for C++, go1.26.5/go build/dlv for Go, rustc/cargo/clippy for Rust — each converging through its own demo.sh onto one shared demo.sh runner contract."
caption="Figure 1.1 — three toolchains, one demo.sh contract shared by every example in the book" %}

> **Tools used** — `gcc`, `cmake`, `ninja`, `go`, `cargo`, `rustup`, `strace`
> (all host — the toolchains are this chapter's subject). Everything here is
> checked by `scripts/check-host.sh`.

## One host, three toolchains

The book targets **Fedora 44** deliberately. Systems programming is the one
Expand Down Expand Up @@ -104,11 +108,16 @@ The hard requirements, and the reason each is hard:
script checks the device node itself.
- **`git` and `gh`** — the repo workflow.

The soft rows: **Conan 2.x** (only some C++ demos pull dependencies through
it), **ruby + bundler** (local Jekyll preview of this site only), and the Go
lint/debug trio **golangci-lint, staticcheck, dlv** (CI runs them; locally
they are nice-to-have). Membership in the `libvirt` group is also warn-only —
everything works with `sudo`, it is just tedious without the group.
Hard rows also cover the debug and observation tooling the cross-checks lean
on from here forward: **gdb, valgrind, perf, strace, ltrace**, and the
**sanitizer runtimes** (`libasan`/`libtsan` — without them the `asan` and
`tsan` presets compile but cannot link). The soft rows: **Conan 2.x** (only
some C++ demos pull dependencies through it) and the Go lint/debug trio
**golangci-lint, staticcheck, dlv** (CI runs them; locally they are
nice-to-have). Membership in the `libvirt` group is also warn-only —
everything works with `sudo`, it is just tedious without the group. There is
no Ruby row: the site builds and deploys in CI, so nothing local depends on
Jekyll.

## The demo contract

Expand Down
4 changes: 4 additions & 0 deletions _docs/02-lab-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ destroys the guests by name.
alt="Lab topology: a host band with libvirtd/KVM, the ~/.cache/systems-lab image cache holding the pristine Fedora Cloud Base image plus one qcow2 overlay per guest, and the scripts/lab directory; below it, the libvirt NAT network 192.168.124.0/24 containing systems-target (4 GB, .7) and systems-peer (2 GB, .95), both on kernel 6.19.10. An amber deploy arrow runs from the scripts to systems-target; a dashed line links the two guests for later two-host chapters; a note marks the lab-ready snapshot taken on both."
caption="Figure 2.1 — the systems-* lab: cached base image + per-VM overlays on the host, two guests on libvirt NAT, one amber deploy path" %}

> **Tools used** — `virt-install`, `qemu-img`, `cloud-localds`, `virsh`, `ssh`
> (host). Everything here is checked by `scripts/check-host.sh`; the guest
> toolset itself is installed by cloud-init.

## Why a disposable lab

Three kinds of chapters force the issue. **Privileged demos** — capabilities,
Expand Down
4 changes: 4 additions & 0 deletions _docs/03-observability-stack.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ Chapter 38 onward depends on what you stand up now.
alt="Telemetry pipeline: a host demo and a VM demo send OTLP HTTP to port 4318 on the lsp-lgtm container, where the OpenTelemetry Collector fans out to Loki for logs, Tempo for traces, and Mimir for metrics; Grafana on port 3000 queries all three and serves the developer's browser. The VM demo reaches the host at the libvirt gateway address 192.168.124.1."
caption="Figure 3.1 — one container, whole pipeline: OTLP in on :4318, Grafana out on :3000" %}

> **Tools used** — `podman`, `systemctl`, `curl`, `openssl`, `python3` (host);
> `ip` (systems-target VM). Everything here is checked by
> `scripts/check-host.sh`, ships with Fedora, or is preinstalled in the lab VMs.

## What LGTM is, and why one container

LGTM is Grafana Labs' acronym for its open-source backend quartet: **L**oki
Expand Down
Loading
Loading