Phase 45
Ports System
A simple BSD-style ports system enables building and installing third-party software inside the OS from source recipes. A port is a directory containing a Makefile, patches, and a Portfile that automates extracting, compiling, and installing a piece of software. At least 5 ports build and install successfully, with dependency resolution.
Learning goal
Understand how BSD ports and Gentoo portage work: source-based package management.
Category
infrastructure
Components touched
Builds on
Unlocked by this phase
Why this phase matters
A simple BSD-style ports system enables building and installing third-party software inside the OS from source recipes. A port is a directory containing a Makefile, patches, and a Portfile that automates extracting, compiling, and installing a piece of software. At least 5 ports build and install successfully, with dependency resolution.
How it works in m3OS
Phase 45 adds a BSD-style ports system for building and installing a bounded set of third-party software from source inside m3OS. Each port is a directory containing a Portfile (metadata), a Makefile (build rules), bundled source code, and optional patches. The port shell command automates the full lifecycle: dependency resolution, source extraction, compilation with TCC, installation to /usr/local/, and package tracking with file manifests for clean removal.
Phase 53 keeps this capability in the headless/reference story as a documented manual validation surface rather than a mandatory smoke/regression gate. The important convergence work is therefore predictability: the in-repo baseline must always ship, and the host-cached Lua/zlib expansion path must be explicit instead of silently assumed.
How it builds on earlier phases
This phase builds on Rust Cross Compilation and turns that foundation into Ports System.
Implementation outline
- Design the Portfile format (shell variables) and Makefile target contract.
- Create the
ports/directory structure with category/program/ hierarchy. - Write the
port.shshell script with list/info/install/remove/clean subcommands. - Add
populate_ports_tree()to xtask for mirroring ports into the ext2 image. - Fetch Lua and zlib sources at build time; bundle other port sources in-repo.
- Create Portfiles and Makefiles for all initial ports.
- Implement dependency resolution in the
portcommand. - Implement install manifest generation and package tracking.
- Verify end-to-end:
port install luaproduces a working Lua binary.
Task progress snapshot
101 of 101 tracked tasks are complete.
Documentation targets
- Documentation deliverables have not been listed yet.
Deferred follow-on work
- Binary package format (precompiled packages)
- Package signing and verification
- Version conflict resolution
- Automatic updates
- Mirror/repository support
- Network fetching of source tarballs
- Cross-compilation of ports on the host
Source materials
Important code
Code spotlight cards
Code spotlight
Add `populate_ports_tree()` function to xtask
into the ext2 data partition during cargo xtask image. This follows the same. Why it matters: The ports tree and bundled source archives must be placed. Focus on `populate_ports_tree` and `populate_tcc_files` in `xtask/src/main.rs` while you trace the snippet.
/// Phase 45: Populate the ports tree into `/usr/ports/` on the ext2 partition.
///
/// Mirrors the host-side `ports/` directory (Portfiles, Makefiles, patches) and
/// downloaded source files into the ext2 image. Also installs the `port` command
/// at `/usr/bin/port` and creates `/usr/local/` and `/var/db/ports/` directories.
fn populate_ports_tree(part_path: &Path, workspace_root: &Path, ports_src: &Path) {
let ports_dir = workspace_root.join("ports");
if !ports_dir.is_dir() {
return;
}
let mut dirs: Vec<String> = Vec::new();
let mut files: Vec<(String, PathBuf)> = Vec::new();
// Collect port metadata files (Portfiles, Makefiles, patches, .gitkeep).
collect_ports_entries(&ports_dir, "usr/ports", &mut dirs, &mut files);
// Collect downloaded source files into the port tree.
// Source files go to usr/ports/<category>/<name>/src/
if ports_src.is_dir() {
for category in &["lang", "lib", "math", "core", "doc", "util"] {
let cat_dir = ports_src.join(category);
if !cat_dir.is_dir() {
continue; Code spotlight
Verify no regressions in existing tests
directories or xtask code must not break existing functionality. Why it matters: Adding the ports tree to the disk image and any new. Focus on `kernel/tests/*.rs` while you trace the snippet.
Code spotlight
The port command — installed at /usr/bin/port
The port command — installed at /usr/bin/port
Key files
- ports/port.sh — The port command — installed at /usr/bin/port
- ports/lang/lua/Portfile — Lua port metadata
- ports/lang/lua/Makefile — Lua build rules (TCC compilation)
- ports/lib/zlib/Portfile — zlib port metadata
- ports/lib/zlib/Makefile — zlib build rules (static library)
- ports/math/bc/src/bc.c — Self-contained bc calculator implementation
- ports/core/sbase/Makefile — Multi-binary build for 15 sbase utilities
- ports/doc/mandoc/src/mandoc.c — Simplified man page formatter
- ports/util/minizip/Portfile — minizip port with DEPS=zlib for dep testing
- xtask/src/main.rs — Lua source download at build time
How real OSes differ
- Binary package distribution (apt, pacman, pkg) — precompiled packages avoid build times.
- Cryptographic signing for package integrity.
- Version constraints and conflict resolution.
- Automatic security updates.
- Mirror networks for distribution.
- Build farms for cross-compilation.
- BSD ports (FreeBSD, OpenBSD) are the closest model: source-based, Makefile-driven, with patches. Our version is much simpler: no version conflict resolution, no binary packages, no signing.
Success criteria
- `port install lua` builds Lua from source inside the OS and installs it.
- `lua -e "print('hello from m3os')"` runs successfully.
- `port list` shows available ports.
- `port info lua` shows Lua's version and description.
- `port remove lua` uninstalls the package.
- At least 5 ports build and install successfully.
- Dependency resolution works: installing minizip builds zlib first.
Related phases
Keep exploring the roadmap
Phase 44
CompleteRust Cross Compilation
Rust programs compiled on the host run natively inside the OS. A documented toolchain setup enables writing Rust code on the host, cross-compiling to an x86-64 ELF binary linked against musl, and deploying it to the OS's disk image. Stretch goal: a minimal Rust program compiles inside the OS itself.
Phase 46
CompleteSystem Services
The OS has a service manager, system logging, and scheduled task execution. Services (sshd, telnetd, etc.) are managed by a unified init/service system that handles startup ordering, restart on failure, and clean shutdown. The OS behaves like a real server that can be administered remotely.