m³OS docs GitHub

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.

Complete

Learning goal

Understand how BSD ports and Gentoo portage work: source-based package management.

Category

infrastructure

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.sh shell 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 port command.
  • Implement install manifest generation and package tracking.
  • Verify end-to-end: port install lua produces 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

xtask/src/main.rs L4150-L4173

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

kernel/tests/*.rs See file

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

ports/port.sh See file

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