update docs
This commit is contained in:
@@ -0,0 +1,315 @@
|
||||
# Working on FDS/OS
|
||||
|
||||
Development reference and historical context. For current operating instructions, use the [user manual](../README.md). Acceptance applies only to the source and artifacts identified in each record.
|
||||
|
||||
|
||||
[Documentation index](README.md) · [First build](getting-started.md) · [Troubleshooting](troubleshooting.md)
|
||||
|
||||
This guide is for someone who has completed the first build and wants to change
|
||||
or inspect the working code. Run commands from the repository root, as a normal
|
||||
user. M0–M12 software acceptance is complete; consult [AGENTS.md](../../AGENTS.md)
|
||||
and the [roadmap](roadmap.md) before adding components.
|
||||
|
||||
## Choose the smallest useful build
|
||||
|
||||
| You changed or want to do | Run |
|
||||
| --- | --- |
|
||||
| See the available entry points | `make help` |
|
||||
| Prepare a new checkout or restore missing host tools | `make bootstrap` |
|
||||
| Edit the Rust smoketest | The Rust build and validation sequence below |
|
||||
| Build/test the base display controller | `make dasung`, then `make dasung-test`; see [Dasung](dasung.md) |
|
||||
| Change the CLI, shared contracts or stage0 | `make tooling`, then `make tooling-test`; rebuild initramfs and run `make boot-test` for boot-path changes |
|
||||
| Change kernel configuration | `make kernel`, rebuild rootfs and boot images, then `make boot-test`; see [Boot images](boot.md) |
|
||||
| Change USB discovery, mapping or media writing | Build CLI images, then `make stress-test`; see [Stress tests](stress-testing.md) |
|
||||
| Change shutdown or DATA safety | Rebuild both profiles; run `make power-test` against development, plus `make data-test` and `make init-test`; see [Shutdown](power.md) |
|
||||
| Change init or boot services | `make rootfs PROFILE=cli`, `make rootfs-test`, then `make init-test`; see [Native init](init.md) |
|
||||
| Change base packages or rootfs assembly | `make rootfs PROFILE=cli`, `make rootfs-test`, then `make init-test`; see [Rootfs](rootfs.md) |
|
||||
| Build the native development toolset | `make rootfs PROFILE=development`, `make rootfs-test`, `make system-card PROFILE=development`, then `make development-test` |
|
||||
| Change internal storage or machine settings | Rebuild CLI and recovery, then `make internal-test`; see [Internal storage](internal-storage.md) |
|
||||
| Change release signing or verification | `make signing-test`; see [Release signatures](releases.md) |
|
||||
| Rebuild the test XBPS package | `./tools/build-package hello` |
|
||||
| Verify an M0 build-system change | `make bootstrap`, then `make smoke-test`, then `make check` |
|
||||
| Check Rust formatting and validation protections | `make check`, after building the Rust program |
|
||||
| Read or edit documentation | Check examples, links, and claims against the implementation |
|
||||
|
||||
Run builds sequentially. The scripts share one Void masterdir and package cache;
|
||||
starting bootstrap and package builds concurrently is not a supported workflow.
|
||||
`make packages` builds every FDS base package. `make all` builds the complete
|
||||
artifact set; two independent frozen offline builds passed with matching output. See
|
||||
[Frozen inputs and offline rebuilds](reproducible-builds.md). Use `make clean-preview`
|
||||
and `make clean` to remove obsolete workspaces and Rust compilation output while
|
||||
keeping published images, latest test fixtures, saved releases, inputs and
|
||||
caches. See [Cleanup](cleanup.md) for retention rules and rebuilding afterward.
|
||||
There is no generic `make test` target.
|
||||
|
||||
## Edit and rebuild the Rust program
|
||||
|
||||
The active program is [rust/fds-smoketest/src/main.rs](../../rust/fds-smoketest/src/main.rs).
|
||||
It is deliberately tiny: it establishes that the intended target and static
|
||||
linking work. `rust/dasungd/`, `rust/fds-common/`, `rust/fds-cli/`, and
|
||||
`rust/fds-stage0/`, `rust/fds-boottrace/`, and `rust/fds-cartridged/` are also active. Directories absent from the workspace member
|
||||
list remain reserved. Use the [tooling guide](tooling.md) for the FDS programs,
|
||||
[Cartridges](cartridges.md) for bay and metadata changes, and [DATA](data.md)
|
||||
for writable storage and managed jobs.
|
||||
|
||||
Use the shared `clap` workspace dependency for every Rust command-line interface.
|
||||
Declare commands and options with `Parser`, `Subcommand`, `Args`, and typed value
|
||||
parsers; do not match or consume raw argument vectors. Shared media syntax lives
|
||||
in `rust/fds-burn/src/cli.rs`; installed FDS aliases use Clap's multicall support
|
||||
in `rust/fds-cli/src/cli.rs`. Keep authorization and filesystem validation in the
|
||||
operation layer after parsing. Add parser tests when changing required options,
|
||||
conflicts, private s6 flags, aliases, or child-argument forwarding.
|
||||
|
||||
The disposable Rust VM workloads in `tests/helpers/` are a Cargo workspace
|
||||
member and use the same locked Clap dependency. They are never installed in
|
||||
the base packages. Their stress workload uses release optimization level 2;
|
||||
production executables retain the size-oriented release settings.
|
||||
|
||||
After editing the program:
|
||||
|
||||
```sh
|
||||
cargo fmt --all
|
||||
cargo build --locked --offline --release \
|
||||
--target aarch64-unknown-linux-musl -p fds-smoketest
|
||||
./tools/verify-elf target/aarch64-unknown-linux-musl/release/fds-smoketest aarch64 static
|
||||
make check
|
||||
```
|
||||
|
||||
Cargo writes to `target/aarch64-unknown-linux-musl/release/`. It does **not** refresh
|
||||
`out/fds-smoketest` or its manifest. Run `make smoke-test` when you need a freshly
|
||||
exported artifact and matching checksums.
|
||||
|
||||
If you installed optional QEMU, execute the freshly built file with:
|
||||
|
||||
```sh
|
||||
qemu-aarch64 target/aarch64-unknown-linux-musl/release/fds-smoketest
|
||||
```
|
||||
|
||||
The smoke-test contract expects exactly `FDS/OS M0: aarch64 static-musl OK`.
|
||||
Changing that text requires updating the runtime assertion and documentation as
|
||||
part of the same change. The crate also rejects the wrong architecture, libc,
|
||||
or missing static CRT at compile time. Do not bypass those checks to make an
|
||||
x86_64 build appear to pass.
|
||||
|
||||
The release profile and target configuration live in [Cargo.toml](../../Cargo.toml)
|
||||
and [.cargo/config.toml](../../.cargo/config.toml). Rust and target versions are
|
||||
selected through [rust-toolchain.toml](../../rust-toolchain.toml). This M0 crate has
|
||||
no external crate dependencies. `--offline` works after bootstrap has installed
|
||||
the toolchain; it is not a promise that the complete build pipeline is offline.
|
||||
|
||||
## Build and inspect a package
|
||||
|
||||
```sh
|
||||
./tools/build-package hello
|
||||
```
|
||||
|
||||
This checks the Void source pin, prepares configuration and overlays, invokes
|
||||
xbps-src's aarch64 cross build, and copies the resulting main package into
|
||||
`out/packages/`. Its log is `out/logs/xbps-hello.log`. Follow
|
||||
[Packages](packages.md) for indexing, querying, and extracting the output.
|
||||
|
||||
`hello` is the verified M0 package. The helper accepts other template names, but
|
||||
its exporter currently looks only for that main package in the top-level
|
||||
`hostdir/binpkgs/`. Packages emitted into subrepositories and separately named
|
||||
subpackages need additional handling; the helper is not yet a universal package
|
||||
export interface.
|
||||
|
||||
For diagnosis, this is the underlying command in its correct host environment:
|
||||
|
||||
```sh
|
||||
(
|
||||
export PATH="$PWD/.host/xbps/usr/bin:$PATH"
|
||||
export XBPS_ARCH=x86_64
|
||||
cd vendor/void-packages
|
||||
./xbps-src -a aarch64 pkg hello
|
||||
)
|
||||
```
|
||||
|
||||
The subshell keeps the directory and environment changes local. Prefer the FDS
|
||||
helper for normal work: it also checks the pin and exports the output. The raw
|
||||
command does neither. Do not run `xbps-install` against the Arch host or install
|
||||
an ARM package into the x86_64 build container.
|
||||
|
||||
## Change build configuration deliberately
|
||||
|
||||
The source of truth is [config/xbps-src.conf](../../config/xbps-src.conf).
|
||||
`XBPS_MAKEJOBS` controls package build parallelism; the current value is 4.
|
||||
`XBPS_CHROOT_CMD=bwrap` selects the supported container backend.
|
||||
|
||||
`tools/prepare-void` copies this file to the ignored
|
||||
`vendor/void-packages/etc/conf`. If the two differ, it stops instead of silently
|
||||
overwriting local settings. After intentionally editing the checked-in file,
|
||||
review the difference:
|
||||
|
||||
```sh
|
||||
diff -u vendor/void-packages/etc/conf config/xbps-src.conf
|
||||
```
|
||||
|
||||
A difference makes `diff` exit 1; that is expected. Once the checked-in version
|
||||
contains every setting you intend to keep, synchronize and prepare:
|
||||
|
||||
```sh
|
||||
cp config/xbps-src.conf vendor/void-packages/etc/conf
|
||||
./tools/prepare-void
|
||||
```
|
||||
|
||||
This overwrites the local generated configuration, so reconcile any intentional
|
||||
local edits before copying. Re-run the three M0 validation commands after a build
|
||||
configuration change. A mirror change does not lock the packages served by that
|
||||
mirror; see [input limitations](build-host.md#known-limitations).
|
||||
|
||||
## How future package overlays fit
|
||||
|
||||
FDS-owned package sources belong in `packages/fds-*/`, outside the upstream
|
||||
submodule. An overlay becomes active only when its directory contains a
|
||||
`template`. `fds-base`, `fds-base-files`, `fds-init`, `fds-dasungd`, `fds-cli`, `fds-kernel`,
|
||||
`fds-cartridged`, `fds-eink`, and `fds-dhcpcd` are active.
|
||||
|
||||
For active overlays and future templates, `tools/prepare-void` copies each
|
||||
active directory into `vendor/void-packages/srcpkgs/`. It allows an identical
|
||||
repeat copy, rejects a name that collides with a tracked upstream package, and
|
||||
stops if a previous generated copy differs. Edit the source under `packages/`,
|
||||
then reconcile the specific stale generated copy. Never put the only copy of an
|
||||
FDS change inside `vendor/`.
|
||||
|
||||
The [troubleshooting guide](troubleshooting.md#configuration-or-overlay-conflict)
|
||||
explains how to preserve and inspect a conflicting copy. Empty future directories
|
||||
are intentional; adding a fake template to silence a missing-package error does
|
||||
not implement that milestone.
|
||||
|
||||
## Preserve logs and identify inputs
|
||||
|
||||
The normal log filenames are reused. Before reproducing a failure that you need
|
||||
to retain, save the existing logs:
|
||||
|
||||
```sh
|
||||
log_archive=$(mktemp -d "$PWD/out/saved-logs.XXXXXX")
|
||||
cp -a out/logs/. "$log_archive/"
|
||||
printf 'Saved logs to %s\n' "$log_archive"
|
||||
```
|
||||
|
||||
After a successful smoke-test:
|
||||
|
||||
```sh
|
||||
cat VOID_PACKAGES_COMMIT
|
||||
rustc --version
|
||||
cargo --version
|
||||
cat out/manifests/void-build-packages.txt
|
||||
sha256sum -c out/manifests/artifacts.sha256
|
||||
```
|
||||
|
||||
The package inventory lists what remains installed in the build container after
|
||||
xbps-src cleans up temporary dependencies. Cached package digests and build logs
|
||||
provide additional input records. These records do not constitute a complete,
|
||||
immutable upstream package repository snapshot.
|
||||
|
||||
## Source updates and changes for review
|
||||
|
||||
Keep upstream tracked files unchanged. Updating Void is a deliberate change to
|
||||
both the submodule gitlink and `VOID_PACKAGES_COMMIT`, followed by the full M0
|
||||
checks. Updating host XBPS requires a matching archive URL and checksum. Updating
|
||||
Rust requires considering the pinned toolchain, target, and generated artifacts
|
||||
together. Do not use an unreviewed `git pull` inside the submodule as a repair.
|
||||
|
||||
For a change report, state what changed, which commands actually passed, and what
|
||||
was skipped. Include the failing command and relevant log when reporting a bug.
|
||||
Do not describe ELF inspection as execution, QEMU userspace execution as a Pi
|
||||
boot, or a target timing as a measured result. Use English for documentation,
|
||||
comments, diagnostics, and project discussions.
|
||||
|
||||
## Desktop verification
|
||||
|
||||
Build `make rootfs PROFILE=development`, then run `make desktop-test`. This
|
||||
executes the actual ARM WindowMaker, terminal, cartridge daemon, and DHCP client
|
||||
in disposable VMs. Its Xvfb backend and root test console exist only in generated
|
||||
fixtures. The normal SYSTEM configuration uses Xorg and the ordinary FDS user.
|
||||
|
||||
VM helpers place QEMU in a private network namespace. The test's virtual DHCP
|
||||
server can advertise DNS while remaining unable to reach host interfaces or the
|
||||
Internet. QEMU diagnostics have separate `*.stderr.log` files, keeping host
|
||||
emulator messages out of guest serial/JSON responses. Screenshots and measured
|
||||
activation timestamps are retained under `out/m8-vm.*`.
|
||||
|
||||
To return to a console image after desktop development, rebuild
|
||||
`make rootfs PROFILE=cli` and `make system-card PROFILE=cli`. A SYSTEM image cannot
|
||||
be relabeled as another profile without rebuilding the matching filesystem.
|
||||
|
||||
## Use the development SYSTEM
|
||||
|
||||
`profiles/development.list` extends the same immutable base with native aarch64
|
||||
**glibc** development tools. FDS control programs retain their static-musl build.
|
||||
Build and verify the profile on the x86_64 workstation:
|
||||
|
||||
```sh
|
||||
make rootfs PROFILE=development
|
||||
make rootfs-test
|
||||
make system-card PROFILE=development
|
||||
make development-test
|
||||
```
|
||||
|
||||
These commands do not install compilers on the Pi's read-only SYSTEM at runtime.
|
||||
The profile must be built into a new SYSTEM image. Store source code and build
|
||||
outputs on an active DATA cartridge, or under `/tmp` for disposable experiments.
|
||||
The ordinary user's home is temporary in this profile too.
|
||||
|
||||
At native startup, FDS advances an older wall clock to the image's fixed source
|
||||
timestamp in `/usr/share/fds/build-epoch`. A newer kernel/RTC clock is retained.
|
||||
This prevents immutable compiler and CMake inputs from appearing to be in the
|
||||
future when a machine boots without a usable RTC. It requires no network,
|
||||
time server or waiting. `/run/fds/clock.json` records which case occurred.
|
||||
The floor is an approximate lower bound, **not the current date**. Set the date
|
||||
explicitly from a trusted time source when accurate timestamps or certificate
|
||||
validity matter. Physical Pi RTC behavior remains to be tested. Boot-duration
|
||||
measurements continue to use `CLOCK_BOOTTIME`, independent of wall-clock changes.
|
||||
`make development-test` checks the older-clock case while compiling real projects;
|
||||
`make clock-test` checks preservation of a newer clock in a disposable VM.
|
||||
|
||||
| Selected package(s) | Purpose |
|
||||
| --- | --- |
|
||||
| `gcc`, `glibc-devel` | Native C/C++ compilation, libc headers and startup files; GCC selects its matching support libraries and C++ headers |
|
||||
| `make`, `cmake`, `meson`, `ninja`, `pkg-config` | Common project build systems and dependency discovery; Meson brings its Python runtime |
|
||||
| `rust`, `cargo` | Native Rust development and package builds; Rust selects its standard library and LLVM runtime dependencies |
|
||||
| `git` | Local source history and optional remote checkout when networking is explicitly enabled |
|
||||
| `gdb`, `strace` | Interactive debugging and syscall inspection |
|
||||
| `vim` | Terminal editing, with no graphical session required |
|
||||
| Xvfb and the existing X11 diagnostic tools | Virtual desktop integration tests; they remain opt-in |
|
||||
|
||||
No development package is added to the boot service bundle. The profile uses
|
||||
GCC for C/C++ and Rust for Rust; additional compilers and physical performance
|
||||
profilers can be considered separately when there is a concrete need.
|
||||
|
||||
For a disposable first C program at `FDS>`:
|
||||
|
||||
```sh
|
||||
mkdir -p /tmp/hello
|
||||
cd /tmp/hello
|
||||
printf '#include <stdio.h>\nint main(void) { puts("Hello from FDS"); }\n' >hello.c
|
||||
cc -g -o hello hello.c
|
||||
./hello
|
||||
gdb ./hello
|
||||
```
|
||||
|
||||
Within GDB, use `break main`, `run`, `next`, and `quit`. For persistent work,
|
||||
use `/data/projects` after selecting a healthy DATA cartridge. Stop programs and
|
||||
leave that directory before `fds eject BAY`.
|
||||
|
||||
For a dependency-free Rust example:
|
||||
|
||||
```sh
|
||||
cargo new --vcs none /tmp/hello-rust
|
||||
cd /tmp/hello-rust
|
||||
cargo run --offline
|
||||
```
|
||||
|
||||
`--offline` avoids contacting a registry. Projects with third-party crates need
|
||||
those sources prepared beforehand or an explicit network connection. To preserve
|
||||
Cargo downloads, put `CARGO_HOME` on DATA and stop related builds before ejecting.
|
||||
An ordinary development program uses the target's glibc environment; rebuilding
|
||||
the FDS distribution and its static control plane still follows the documented
|
||||
x86_64 cross-build workflow.
|
||||
|
||||
`make development-test` runs native C, C++ and Rust compiler/linker executions,
|
||||
CMake/Meson/Ninja/Make builds, GDB and strace, a local Git commit, and a headless Vim
|
||||
edit in a disposable ARM VM. It verifies read-only SYSTEM, absent optional
|
||||
services and native shutdown. Test results are recorded in
|
||||
[M12 validation](m12-validation.md); they do not establish Pi compiler throughput.
|
||||
Reference in New Issue
Block a user