From 41462e951349544dff3423067e74ce33bbc4f4ea Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Fri, 13 Nov 2026 15:08:52 +0900 Subject: [PATCH 01/11] 0.28.0: Linux's thirty-two bit row (i686-linux-musl); the group on openkal 0.25.1 The hosted arrangement serves i686-linux-musl: openkal-musl 0.29.5 over openkal-linux 0.26.3's i386 system-call layer, with openkal-llvm-runtime 0.20.2 above it. CI builds and runs the hosted program on Linux x86_64 and runs the specification's conformance suite through the platform over openkal-linux at the group's version. The group follows openkal 0.25.1; its implementations declare the specification by its minor version (openkal-macos 0.23.2, openkal-windows 0.21.2, openkal-freebsd 0.1.2; openkal-image 0.6.2). --- .github/workflows/ci.yml | 53 +++++++++++++++++++++++++++++++++++++++ README.md | 10 ++++++++ checks/hosted/mcpp.toml | 5 ++++ mcpp.toml | 54 ++++++++++++++++++++++------------------ 4 files changed, 98 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed95549..f3ea78b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,8 @@ name: CI # and self-contained), one target alone, a single file and an okb # hosted the machine's own triple takes the platform's hosted arrangement # host-graph a build program is compiled as an ok image and run by okrun +# i686 Linux's thirty-two bit row: the hosted program and the +# specification's conformance suite, run on Linux x86_64 # freebsd the musl rows of FreeBSD are built here and run in a FreeBSD VM, # with okrun built for them running an ok image there # @@ -224,6 +226,57 @@ jobs: # programs; the x86_64 one runs in a FreeBSD virtual machine, beside okrun # built for the same row from the openkal-image release this group names, # which runs an ok image there. + # I686 (0.28.0): Linux's thirty-two bit row, which a Linux x86_64 machine runs + # itself: the hosted program, and the specification's conformance suite through + # the platform, over the implementation at the group's version. + i686: + name: i686-linux-musl (built and run on Linux x86_64) + runs-on: ubuntu-24.04 + timeout-minutes: 90 + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v4 + + - name: Install xlings and mcpp + run: | + curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \ + | bash -s "$XLINGS_VERSION" + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" + for attempt in 1 2 3 4 5 6; do + xlings update > /dev/null 2>&1 || true + if xlings install "mcpp@$MCPP_VERSION" -y -g; then break; fi + [ "$attempt" = 6 ] && { echo "::error::mcpp could not be installed"; exit 1; } + sleep 60 + done + mcpp --version + mcpp self config --mirror GLOBAL + + - name: The hosted program, thirty-two bit + working-directory: checks/hosted + run: | + mcpp run --target i686-linux-musl -- one two | tee run.log + grep -q "hosted ok: hosted" run.log || { echo "::error::the hosted program's output"; exit 1; } + grep -q "hosted args: 3 two" run.log || { echo "::error::the hosted program's arguments"; exit 1; } + p=$(find target/i686-linux-musl -path '*bin/hosted' -type f | head -1) + file "$p" + file "$p" | grep -q 'ELF 32-bit' && file "$p" | grep -q 'Intel 80386' && file "$p" | grep -q 'statically linked' \ + || { echo "::error::i686-linux-musl is not a static i386 program"; exit 1; } + + - name: The specification's conformance suite + run: | + set -euo pipefail + spec=$(sed -n 's/^openkal *= *"\(.*\)"/\1/p' mcpp.toml | head -1) + impl=$(sed -n 's/^openkal-linux *= *"\(.*\)"/\1/p' mcpp.toml | head -1) + git clone --quiet --depth 1 --branch "$spec" https://github.com/mcpplibs/openkal.git .spec + git clone --quiet --depth 1 --branch "$impl" https://github.com/mcpplibs/openkal-linux.git .impl + bash .spec/tools/run-conformance.sh openkal-linux .impl full,optional \ + --target i686-linux-musl --platform "path:$GITHUB_WORKSPACE" | tee conformance.log + grep -qE '^observations: [0-9]+ held, 0 did not hold' conformance.log \ + || { echo "::error::an observation did not hold on i686-linux-musl"; exit 1; } + freebsd: name: freebsd (built for x86_64 and aarch64, run in a VM) runs-on: ubuntu-24.04 diff --git a/README.md b/README.md index eb678b2..a6eabfd 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,16 @@ does; before, a program that polls before each `recv` took a stream one byte per call (openkal-musl#52). The group stays on openkal-windows 0.21, the line openkal-run and mcpplibs.os name. The platform's statements are those of 0.27.0. +Platform 0.28.0 adds Linux's thirty-two bit row, `i686-linux-musl`, to the hosted +arrangement (openkal 0.25.1, clause 5.5): openkal-musl 0.29.5 over openkal-linux +0.26.3's i386 system-call layer, with openkal-llvm-runtime 0.20.2 above it. A +Linux x86_64 machine runs its programs itself; CI builds and runs a hosted +program there and the specification's conformance suite through the platform. +The group follows openkal 0.25.1, and its implementations declare the +specification by its minor version (openkal-macos 0.23.2, openkal-windows 0.21.2, +openkal-freebsd 0.1.2; openkal-image 0.6.2), so a project that names openkal +0.25.1 resolves with them. + A project overrides any group under `[target.]`, for example `[target.'cfg(platform = "openkal")'.layers] "c++-abi" = false`, and selects another platform, or none, with `platform = "..."` or `--platform`. diff --git a/checks/hosted/mcpp.toml b/checks/hosted/mcpp.toml index fc0e637..ba7933d 100644 --- a/checks/hosted/mcpp.toml +++ b/checks/hosted/mcpp.toml @@ -15,3 +15,8 @@ toolchain = "llvm@23.1.3" [target.aarch64-freebsd-musl] toolchain = "llvm@23.1.3" + +# Linux's thirty-two bit row (0.28.0): an mcpp that registers the row as planned +# takes it when the toolchain is named. +[target.i686-linux-musl] +toolchain = "llvm@23.1.3" diff --git a/mcpp.toml b/mcpp.toml index 8cbca29..c61172a 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -12,7 +12,7 @@ [package] namespace = "mcpplibs" name = "openkal-platform" -version = "0.27.1" +version = "0.28.0" description = "The platform of ok images (-openkal): their toolchain, C library and C++ run-time, tools, compile and link conventions, seal, runner and carrier, as one versioned statement mcpp reads." license = "Apache-2.0" authors = ["mcpplibs"] @@ -39,7 +39,7 @@ toolchain = "llvm@23.1.3" runner = { cmd = ["okrun", "{}"], host = "same-arch", hosts = ["linux-x86_64", "linux-aarch64", "macos-aarch64", "windows-x86_64", "freebsd-x86_64", "freebsd-aarch64"], built-as = { "freebsd-x86_64" = "x86_64-freebsd-musl", "freebsd-aarch64" = "aarch64-freebsd-musl" } } # `mcpp pack --mode self-contained`: a program of the packing machine that # carries the image in a section and runs it through libokrun (M3). -carrier = { package = "openkal-run@0.6.1", section = ".oke", main = "carrier/main.cpp" } +carrier = { package = "openkal-run@0.6.2", section = ".oke", main = "carrier/main.cpp" } # The `okb` package format (`mcpp pack --pkg-format okb`): the images of every # architecture as one file okrun runs (openkal-image docs/okb.md). plugin = "build.mcpp" @@ -51,18 +51,18 @@ debuggee = ["okrun", "--debugger", "{}"] # The C library and the C++ run-time inside an image. A package of the graph # that provides a layer takes its place (`provides`), and `false` leaves it out. [platform.layers] -compiler-runtime = "openkal-llvm-runtime@0.20.1" -"c++-abi" = "openkal-llvm-runtime@0.20.1" -c-abi = { name = "openkal-musl", version = "0.29.4", default-features = false, features = ["posix", "malloc-mimalloc"] } +compiler-runtime = "openkal-llvm-runtime@0.20.2" +"c++-abi" = "openkal-llvm-runtime@0.20.2" +c-abi = { name = "openkal-musl", version = "0.29.5", default-features = false, features = ["posix", "malloc-mimalloc"] } # Built for the building machine: `okld` writes and checks the notes, `okrun` # runs an image, `okprof` reads what a measured run recorded (0.23.0: the # order of a start's first executions, which a producer lays its code out by # and writes as the touch note). [platform.tools] -okld = "openkal-tools@0.6.1" -okrun = "openkal-tools@0.6.1" -okprof = "openkal-tools@0.6.1" +okld = "openkal-tools@0.6.2" +okrun = "openkal-tools@0.6.2" +okprof = "openkal-tools@0.6.2" # Every unit of an image (SPEC 12.2): # -fPIC the image is ET_DYN and has no text relocation; @@ -171,15 +171,17 @@ seal = [["okld", "note", "{}"], ["okld", "place", "{}"], ["okld", "check", "{} # On FreeBSD (0.26.0) the C library's implementation is openkal-freebsd in its # standalone arrangement, which openkal-musl names for that system: the rows # `-freebsd-musl` are the system with no C library of its own beneath. +# `i686-linux-musl` (0.28.0) is the thirty-two bit row of Linux (openkal 0.25.1, +# clause 5.5): openkal-linux's i386 system-call layer beneath openkal-musl's. targets = ["x86_64-linux-gnu", "aarch64-linux-gnu", "x86_64-linux-musl", "aarch64-linux-musl", "x86_64-macos", "aarch64-macos", "x86_64-windows-gnu", "x86_64-windows-musl", - "x86_64-freebsd-musl", "aarch64-freebsd-musl"] + "x86_64-freebsd-musl", "aarch64-freebsd-musl", "i686-linux-musl"] toolchain = "llvm@23.1.3" [platform.hosted.layers] -compiler-runtime = "openkal-llvm-runtime@0.20.1" -"c++-abi" = "openkal-llvm-runtime@0.20.1" -c-abi = { name = "openkal-musl", version = "0.29.4", default-features = false, features = ["posix", "malloc-mimalloc"] } +compiler-runtime = "openkal-llvm-runtime@0.20.2" +"c++-abi" = "openkal-llvm-runtime@0.20.2" +c-abi = { name = "openkal-musl", version = "0.29.5", default-features = false, features = ["posix", "malloc-mimalloc"] } # The family released together for openkal 0.17 (the 0.17.2 round: okb, the # runner's bundle and library interfaces, musl's renameat2; the 0.17.3 round: @@ -225,27 +227,31 @@ c-abi = { name = "openkal-musl", version = "0.29.4", default-features # openkal-llvm-runtime 0.20.1 on FreeBSD; 0.27.1, the implementations retire a # handle before closing it (openkal-linux 0.26.1, openkal-macos 0.23.1, # openkal-windows 0.21.1) and openkal-musl 0.29.4 delivers what a readiness -# enquiry held with the rest): one version of each in a build. From 0.24.1 the members name one another by +# enquiry held with the rest; 0.28.0, openkal 0.25.1 and i386: openkal-linux +# 0.26.3, openkal-musl 0.29.5 and openkal-llvm-runtime 0.20.2 for `i686-linux-musl`, +# and the implementations by the specification's minor version (openkal-macos +# 0.23.2, openkal-windows 0.21.2, openkal-freebsd 0.1.2, openkal-image 0.6.2)): +# one version of each in a build. From 0.24.1 the members name one another by # compatible ranges (`^0.28.0`) and this group chooses the versions: mcpp # 2026.11.7.1 resolves within it, and a fix of one member is that member's # release and a patch of this group, released together through one index change # (tools/family_release.py, .github/workflows/family-release.yml). [platform.versions] -openkal = "0.25.0" -openkal-linux = "0.26.1" -openkal-macos = "0.23.1" -openkal-windows = "0.21.1" -openkal-freebsd = "0.1.0" -openkal-musl = "0.29.4" -openkal-llvm-runtime = "0.20.1" -openkal-ld = "0.6.1" -openkal-run = "0.6.1" -openkal-tools = "0.6.1" +openkal = "0.25.1" +openkal-linux = "0.26.3" +openkal-macos = "0.23.2" +openkal-windows = "0.21.2" +openkal-freebsd = "0.1.2" +openkal-musl = "0.29.5" +openkal-llvm-runtime = "0.20.2" +openkal-ld = "0.6.2" +openkal-run = "0.6.2" +openkal-tools = "0.6.2" # The plugin's tool, `okld bundle`, which writes the okb, and its library, the # provider of a package format (mcpp.plugins.platform). [build-dependencies] -openkal-tools = { version = "0.6.1", tools = ["okld"] } +openkal-tools = { version = "0.6.2", tools = ["okld"] } [build-dependencies.mcpp] plugins = { version = "0.20.0", features = ["plugins-platform"], host-module = true } From ae739510bcf2ec478b258b3ce5805d928fe20201 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Fri, 13 Nov 2026 18:08:42 +0900 Subject: [PATCH 02/11] ci: the i686 conformance build names its toolchain, as checks/hosted does The released mcpp registers i686-linux-musl as planned and takes the row when the toolchain is named; the conformance step named none and was refused. --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f3ea78b..49fd61e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -272,8 +272,10 @@ jobs: impl=$(sed -n 's/^openkal-linux *= *"\(.*\)"/\1/p' mcpp.toml | head -1) git clone --quiet --depth 1 --branch "$spec" https://github.com/mcpplibs/openkal.git .spec git clone --quiet --depth 1 --branch "$impl" https://github.com/mcpplibs/openkal-linux.git .impl + # The toolchain is named, as checks/hosted names it: an mcpp that + # registers the row as planned takes it when the toolchain is named. bash .spec/tools/run-conformance.sh openkal-linux .impl full,optional \ - --target i686-linux-musl --platform "path:$GITHUB_WORKSPACE" | tee conformance.log + --target i686-linux-musl --platform "path:$GITHUB_WORKSPACE" --toolchain llvm@23.1.3 | tee conformance.log grep -qE '^observations: [0-9]+ held, 0 did not hold' conformance.log \ || { echo "::error::an observation did not hold on i686-linux-musl"; exit 1; } From 7588292671eff9f0a138877d68641de8fe0c1dae Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Fri, 13 Nov 2026 21:39:31 +0900 Subject: [PATCH 03/11] 0.28.0: UEFI applications (x86_64-uefi) over openkal-uefi; the family on openkal-musl 0.29.6, openkal-llvm-runtime 0.20.3 and openkal-image 0.6.3; mcpp 2026.11.13.1 --- .github/workflows/ci.yml | 43 +++++++++++++++- .github/workflows/family-release.yml | 2 +- README.md | 24 +++++++++ board/qemu-exit.S | 30 +++++++++++ checks/uefi/mcpp.toml | 12 +++++ checks/uefi/src/main.cpp | 10 ++++ mcpp.toml | 75 +++++++++++++++++++++------- 7 files changed, 175 insertions(+), 21 deletions(-) create mode 100644 board/qemu-exit.S create mode 100644 checks/uefi/mcpp.toml create mode 100644 checks/uefi/src/main.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 49fd61e..d493f61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ on: env: MCPP_SOURCE_REF: ${{ github.event.inputs.mcpp_ref || vars.MCPP_SOURCE_REF || '' }} - MCPP_VERSION: 2026.11.10.1 + MCPP_VERSION: 2026.11.13.1 XLINGS_VERSION: v2026.10.26.1 XLINGS_NON_INTERACTIVE: '1' @@ -279,6 +279,47 @@ jobs: grep -qE '^observations: [0-9]+ held, 0 did not hold' conformance.log \ || { echo "::error::an observation did not hold on i686-linux-musl"; exit 1; } + uefi: + name: x86_64-uefi (built on Linux x86_64, run under OVMF) + runs-on: ubuntu-24.04 + timeout-minutes: 90 + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v4 + + - name: Install xlings and mcpp + run: | + curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \ + | bash -s "$XLINGS_VERSION" + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" + for attempt in 1 2 3 4 5 6; do + xlings update > /dev/null 2>&1 || true + if xlings install "mcpp@$MCPP_VERSION" -y -g; then break; fi + [ "$attempt" = 6 ] && { echo "::error::mcpp could not be installed"; exit 1; } + sleep 60 + done + mcpp --version + mcpp self config --mirror GLOBAL + + # The provider's runner: dirun, xim's OVMF with its profile, and QEMU, installed by the + # first run; the status returns through the board's exit. + - name: The application, built and booted + working-directory: checks/uefi + run: | + set +e + mcpp run --release --target x86_64-uefi | tee run.log + status=${PIPESTATUS[0]} + set -e + grep -q "uefi ok: \[1, 2, 3\] 1" run.log || { echo "::error::the application's output"; exit 1; } + [ "$status" -eq 42 ] || { echo "::error::the application returned $status, not 42"; exit 1; } + p=$(find target/x86_64-uefi -path '*bin/uefi.efi' -type f | head -1) + file "$p" + file "$p" | grep -q 'PE32+' && file "$p" | grep -q 'EFI application' \ + || { echo "::error::x86_64-uefi is not a PE32+ EFI application"; exit 1; } + freebsd: name: freebsd (built for x86_64 and aarch64, run in a VM) runs-on: ubuntu-24.04 diff --git a/.github/workflows/family-release.yml b/.github/workflows/family-release.yml index 2815f26..07039d8 100644 --- a/.github/workflows/family-release.yml +++ b/.github/workflows/family-release.yml @@ -40,7 +40,7 @@ defaults: shell: bash env: - MCPP_PREVIOUS: 2026.11.10.1 + MCPP_PREVIOUS: 2026.11.13.1 MCPP_SOURCE_REF: ${{ github.event.inputs.mcpp_ref || vars.MCPP_SOURCE_REF || '' }} XLINGS_VERSION: v2026.10.26.1 XLINGS_NON_INTERACTIVE: '1' diff --git a/README.md b/README.md index a6eabfd..4bdd9a1 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,30 @@ own openkal implementation (`checks/hosted`). `[host] platform` selects it for the host graph: build programs are then compiled as ok images of the machine's architecture and run by okrun (`checks/host-graph`). +## UEFI applications (0.28.0) + +`x86_64-uefi` is a row this platform defines and serves (`[[platform.define]]`, +`[[platform.provider]] name = "uefi"`): an application the firmware loads, on +the same C library and C++ run-time over openkal-uefi, so it is written in C++23 +with `import std`: + +```toml +[target.x86_64-uefi] +platform = "openkal-platform@0.28.0" +``` + +The row is PE. mcpp 2026.11.13.1 realises the C environment by the container, as +for Windows, and ld.lld's MinGW driver (`link-emulation = "i386pep"`) links an +EFI application entered at `efi_main`. The provider states the row's own link, +layers and runner over `base = "none"`, so none of the ok images' conventions +reach it: `mcpp run` boots the application with dirun, xim's OVMF and its +profile (`{pkg:ovmf}/dirun.toml`) and QEMU, and `board/qemu-exit.S` returns the +status through QEMU's debug-exit port. A program that wants no C library states +`c-abi = false` for the row. Measured: `std::println` and `std::ranges::sort`, a +1.2 MB application, printed and returned 42 under OVMF in 0.8 s. The row and its +runner were openkal-uefi-platform 0.1.0, which is folded here and into +openkal-uefi's example. + ## Version group `[platform.versions]` names one version of each package of the family. From diff --git a/board/qemu-exit.S b/board/qemu-exit.S new file mode 100644 index 0000000..f237ddf --- /dev/null +++ b/board/qemu-exit.S @@ -0,0 +1,30 @@ +/* THE BOARD'S EXIT: a status leaves the machine through QEMU's `isa-debug-exit' device (port 0xf4), + * whose write ends the emulator with (status << 1) | 1. openkal-uefi calls this before Exit + * (okuefi_board_exit); its own definition does nothing. + * + * Only under QEMU. The processor states a hypervisor in CPUID leaf 1 (ECX bit 31) and names it in + * leaf 0x40000000 ("TCGTCGTCGTCG" for QEMU's translator, "KVMKVMKVM" under KVM); on a machine + * that is neither, nothing is written and the status leaves through Exit alone. The Microsoft x64 + * convention: the status arrives in ECX. */ + .text + .globl okuefi_board_exit + .def okuefi_board_exit; .scl 2; .type 32; .endef +okuefi_board_exit: + push %rbx + mov %ecx, %r8d + mov $1, %eax + cpuid + bt $31, %ecx + jnc 1f + mov $0x40000000, %eax + cpuid + cmp $0x54474354, %ebx /* "TCGT" */ + je 2f + cmp $0x4b4d564b, %ebx /* "KVMK" */ + jne 1f +2: mov %r8d, %eax + and $0xff, %eax + mov $0xf4, %dx + out %eax, %dx +1: pop %rbx + ret diff --git a/checks/uefi/mcpp.toml b/checks/uefi/mcpp.toml new file mode 100644 index 0000000..df87570 --- /dev/null +++ b/checks/uefi/mcpp.toml @@ -0,0 +1,12 @@ +# The UEFI row (0.28.0): an application the firmware loads, on the family's C +# library and C++ run-time over openkal-uefi. The platform is the directory above. +[package] +name = "uefi" +version = "0.1.0" + +[targets.uefi] +kind = "bin" +main = "src/main.cpp" + +[target.x86_64-uefi] +platform = { path = "../.." } diff --git a/checks/uefi/src/main.cpp b/checks/uefi/src/main.cpp new file mode 100644 index 0000000..a3a4203 --- /dev/null +++ b/checks/uefi/src/main.cpp @@ -0,0 +1,10 @@ +// The C++ a UEFI application is written in: the standard library's text, ranges and containers +// over openkal-musl and openkal-llvm-runtime, and its status returned to the machine that ran it. +import std; + +int main(int argc, char** argv) { + std::vector v{3, 1, 2}; + std::ranges::sort(v); + std::println("uefi ok: {} {}", v, argc); + return 42; +} diff --git a/mcpp.toml b/mcpp.toml index c61172a..b8fe92a 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -21,7 +21,10 @@ repo = "https://github.com/mcpplibs/openkal-platform" # implementation provides (MCPP_KERNEL_ABI_INTERFACES), and FreeBSD's rows are # built-in. 2026.11.9.1: openkal-run (from 0.5.4) states its openkal implementation as a # capability with a default per system (`[defaults]`). -mcpp = ">=2026.11.10.1" +# 2026.11.13.1: the UEFI row (the PE rows' C environment by the container, a +# provider's link and runner over `base = "none"', a row's link emulation +# without its machine), and `--toolchain' opts the planned i686 row in. +mcpp = ">=2026.11.13.1" [platform] targets = ["x86_64-openkal", "aarch64-openkal"] @@ -39,7 +42,7 @@ toolchain = "llvm@23.1.3" runner = { cmd = ["okrun", "{}"], host = "same-arch", hosts = ["linux-x86_64", "linux-aarch64", "macos-aarch64", "windows-x86_64", "freebsd-x86_64", "freebsd-aarch64"], built-as = { "freebsd-x86_64" = "x86_64-freebsd-musl", "freebsd-aarch64" = "aarch64-freebsd-musl" } } # `mcpp pack --mode self-contained`: a program of the packing machine that # carries the image in a section and runs it through libokrun (M3). -carrier = { package = "openkal-run@0.6.2", section = ".oke", main = "carrier/main.cpp" } +carrier = { package = "openkal-run@0.6.3", section = ".oke", main = "carrier/main.cpp" } # The `okb` package format (`mcpp pack --pkg-format okb`): the images of every # architecture as one file okrun runs (openkal-image docs/okb.md). plugin = "build.mcpp" @@ -51,18 +54,18 @@ debuggee = ["okrun", "--debugger", "{}"] # The C library and the C++ run-time inside an image. A package of the graph # that provides a layer takes its place (`provides`), and `false` leaves it out. [platform.layers] -compiler-runtime = "openkal-llvm-runtime@0.20.2" -"c++-abi" = "openkal-llvm-runtime@0.20.2" -c-abi = { name = "openkal-musl", version = "0.29.5", default-features = false, features = ["posix", "malloc-mimalloc"] } +compiler-runtime = "openkal-llvm-runtime@0.20.3" +"c++-abi" = "openkal-llvm-runtime@0.20.3" +c-abi = { name = "openkal-musl", version = "0.29.6", default-features = false, features = ["posix", "malloc-mimalloc"] } # Built for the building machine: `okld` writes and checks the notes, `okrun` # runs an image, `okprof` reads what a measured run recorded (0.23.0: the # order of a start's first executions, which a producer lays its code out by # and writes as the touch note). [platform.tools] -okld = "openkal-tools@0.6.2" -okrun = "openkal-tools@0.6.2" -okprof = "openkal-tools@0.6.2" +okld = "openkal-tools@0.6.3" +okrun = "openkal-tools@0.6.3" +okprof = "openkal-tools@0.6.3" # Every unit of an image (SPEC 12.2): # -fPIC the image is ET_DYN and has no text relocation; @@ -179,9 +182,38 @@ targets = ["x86_64-linux-gnu", "aarch64-linux-gnu", "x86_64-linux-musl", "aarc toolchain = "llvm@23.1.3" [platform.hosted.layers] -compiler-runtime = "openkal-llvm-runtime@0.20.2" -"c++-abi" = "openkal-llvm-runtime@0.20.2" -c-abi = { name = "openkal-musl", version = "0.29.5", default-features = false, features = ["posix", "malloc-mimalloc"] } +compiler-runtime = "openkal-llvm-runtime@0.20.3" +"c++-abi" = "openkal-llvm-runtime@0.20.3" +c-abi = { name = "openkal-musl", version = "0.29.6", default-features = false, features = ["posix", "malloc-mimalloc"] } + +# UEFI (0.28.0): applications the firmware loads, on the same C library and C++ +# run-time over openkal-uefi (openkal-musl names it, `standalone', on +# `cfg(os = "uefi")'). The row is PE: the C environment is the PE rows' +# (mcpp 2026.11.13.1 realises it by the container, as on Windows), linked by +# ld.lld's MinGW driver (`link-emulation = "i386pep"') as an EFI application. +# The provider states the row's own conventions (`base = "none"': none of the +# ok images' compile, link or seal), its layers and its runner: dirun boots the +# application with xim's OVMF and its profile, and the board's exit +# (board/qemu-exit.S, QEMU's debug-exit port) returns the status. A program that +# wants no C library states `c-abi = false' for the row and is linked over +# openkal-uefi alone. +[[platform.define]] +triple = "x86_64-uefi" +clang-triple = "x86_64-unknown-uefi" +object-format = "pe" +execution = "uefi" +exe-suffix = ".efi" +link-emulation = "i386pep" + +[[platform.provider]] +name = "uefi" +serves = ["x86_64-uefi"] +base = "none" +hosted = true + +layers = { compiler-runtime = "openkal-llvm-runtime@0.20.3", "c++-abi" = "openkal-llvm-runtime@0.20.3", c-abi = { name = "openkal-musl", version = "0.29.6", default-features = false, features = ["posix", "malloc-mimalloc"] } } +link = { driver = "lld", start = "efi_main", flags = ["--subsystem", "efi_application", "--gc-sections"], exe = "{name}.efi", inputs = [{ file = "board/qemu-exit.S" }], seal = [] } +runner = { cmd = ["dirun", "--payload", "{}", "--profile", "{pkg:ovmf}/dirun.toml", "--emulator", "{pkg:qemu-x86}/bin/qemu-system-x86_64"], hosts = ["linux-x86_64", "linux-aarch64", "macos-aarch64", "windows-x86_64"], requires = ["xim:dirun@0.3.2", "xim:qemu-x86@9.2.4-1", "xim:ovmf@9.2.4-1"] } # The family released together for openkal 0.17 (the 0.17.2 round: okb, the # runner's bundle and library interfaces, musl's renameat2; the 0.17.3 round: @@ -230,8 +262,12 @@ c-abi = { name = "openkal-musl", version = "0.29.5", default-features # enquiry held with the rest; 0.28.0, openkal 0.25.1 and i386: openkal-linux # 0.26.3, openkal-musl 0.29.5 and openkal-llvm-runtime 0.20.2 for `i686-linux-musl`, # and the implementations by the specification's minor version (openkal-macos -# 0.23.2, openkal-windows 0.21.2, openkal-freebsd 0.1.2, openkal-image 0.6.2)): -# one version of each in a build. From 0.24.1 the members name one another by +# 0.23.2, openkal-windows 0.21.2, openkal-freebsd 0.1.2, openkal-image 0.6.2), and +# UEFI: openkal-uefi 0.10.0 beneath openkal-musl 0.29.6 and openkal-llvm-runtime +# 0.20.3, which take the optional interfaces from the implementation (or, in an +# image, at run time) and serve the PE rows by their container, and openkal-image +# 0.6.3, whose runner has a core for an implementation without files, processes +# or threads): one version of each in a build. From 0.24.1 the members name one another by # compatible ranges (`^0.28.0`) and this group chooses the versions: mcpp # 2026.11.7.1 resolves within it, and a fix of one member is that member's # release and a patch of this group, released together through one index change @@ -242,16 +278,17 @@ openkal-linux = "0.26.3" openkal-macos = "0.23.2" openkal-windows = "0.21.2" openkal-freebsd = "0.1.2" -openkal-musl = "0.29.5" -openkal-llvm-runtime = "0.20.2" -openkal-ld = "0.6.2" -openkal-run = "0.6.2" -openkal-tools = "0.6.2" +openkal-uefi = "0.10.0" +openkal-musl = "0.29.6" +openkal-llvm-runtime = "0.20.3" +openkal-ld = "0.6.3" +openkal-run = "0.6.3" +openkal-tools = "0.6.3" # The plugin's tool, `okld bundle`, which writes the okb, and its library, the # provider of a package format (mcpp.plugins.platform). [build-dependencies] -openkal-tools = { version = "0.6.2", tools = ["okld"] } +openkal-tools = { version = "0.6.3", tools = ["okld"] } [build-dependencies.mcpp] plugins = { version = "0.20.0", features = ["plugins-platform"], host-module = true } From f89d2ff80cef3e96ba540828f5840ce293b41416 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Fri, 13 Nov 2026 22:33:10 +0900 Subject: [PATCH 04/11] 0.28.0: an ok image packs for UEFI; the board makes standard error the console; the UEFI machine has 2 GiB The runner's hosts include uefi-x86_64, so a single-file pack for that system builds the carrier as an application of the x86_64-uefi row. The board defines okuefi_board_errors_to_console (OVMF's StdErr reaches no serial reader). dirun boots the row with 2 GiB: the carrier's allocator and the image's each place an arena at a 256 MiB alignment, which 512 MiB did not hold twice. Measured: a carried image that prints, writes to standard error, throws and catches returned status 7 under OVMF in 0.4 s. --- README.md | 11 +++++++++++ board/qemu-exit.S | 8 ++++++++ mcpp.toml | 14 ++++++++++---- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4bdd9a1..22f53f7 100644 --- a/README.md +++ b/README.md @@ -241,6 +241,17 @@ status through QEMU's debug-exit port. A program that wants no C library states runner were openkal-uefi-platform 0.1.0, which is folded here and into openkal-uefi's example. +An ok image runs on firmware as it runs on the other systems: the runner's +`hosts` include `uefi-x86_64`, so `mcpp pack --pkg-format single-file --systems +uefi-x86_64` builds the carrier for the row and places the image in its `.oke` +section, and the core runner (openkal-image 0.6.3) places the image through +`openkal.exec`. The board makes standard error the console (OVMF's `StdErr` +reaches no serial reader), and the machine has 2 GiB: memory is backed when the +allocator reserves it, and the carrier's allocator and the image's each place a +32 MiB arena at a 256 MiB alignment (openkal-musl 0.29.6, openkal-uefi 0.10.0). +Measured: an image that prints, writes to standard error, throws and catches, +carried by a 2.4 MB application, returned its status 7 under OVMF in 0.4 s. + ## Version group `[platform.versions]` names one version of each package of the family. From diff --git a/board/qemu-exit.S b/board/qemu-exit.S index f237ddf..7ae3beb 100644 --- a/board/qemu-exit.S +++ b/board/qemu-exit.S @@ -28,3 +28,11 @@ okuefi_board_exit: out %eax, %dx 1: pop %rbx ret + +/* THE BOARD'S ERROR CONSOLE: OVMF's StdErr writes nothing to the serial console the runner reads, + * so standard error is ConOut on this board (openkal-uefi 0.10.0, okuefi_board_errors_to_console). */ + .globl okuefi_board_errors_to_console + .def okuefi_board_errors_to_console; .scl 2; .type 32; .endef +okuefi_board_errors_to_console: + mov $1, %eax + ret diff --git a/mcpp.toml b/mcpp.toml index b8fe92a..4a3133a 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -38,8 +38,10 @@ toolchain = "llvm@23.1.3" # as, where the engine holds no convention for the system. A package that # carries its runner (`mcpp pack --mode self-contained --systems all`) builds # FreeBSD's as the musl identity this platform's hosted arrangement serves: one -# static program, the same whichever machine packs it. -runner = { cmd = ["okrun", "{}"], host = "same-arch", hosts = ["linux-x86_64", "linux-aarch64", "macos-aarch64", "windows-x86_64", "freebsd-x86_64", "freebsd-aarch64"], built-as = { "freebsd-x86_64" = "x86_64-freebsd-musl", "freebsd-aarch64" = "aarch64-freebsd-musl" } } +# static program, the same whichever machine packs it. `uefi-x86_64` (0.28.0): +# the runner is a UEFI application of the row this platform defines below (the +# core runner, which carries what it runs), so an ok image packs for firmware. +runner = { cmd = ["okrun", "{}"], host = "same-arch", hosts = ["linux-x86_64", "linux-aarch64", "macos-aarch64", "windows-x86_64", "freebsd-x86_64", "freebsd-aarch64", "uefi-x86_64"], built-as = { "freebsd-x86_64" = "x86_64-freebsd-musl", "freebsd-aarch64" = "aarch64-freebsd-musl" } } # `mcpp pack --mode self-contained`: a program of the packing machine that # carries the image in a section and runs it through libokrun (M3). carrier = { package = "openkal-run@0.6.3", section = ".oke", main = "carrier/main.cpp" } @@ -194,7 +196,11 @@ c-abi = { name = "openkal-musl", version = "0.29.6", default-features # The provider states the row's own conventions (`base = "none"': none of the # ok images' compile, link or seal), its layers and its runner: dirun boots the # application with xim's OVMF and its profile, and the board's exit -# (board/qemu-exit.S, QEMU's debug-exit port) returns the status. A program that +# (board/qemu-exit.S, QEMU's debug-exit port) returns the status; the same file +# makes standard error the console (OVMF's StdErr reaches no serial reader). The +# machine has 2 GiB: memory is backed when the allocator reserves it, and the +# allocator of a carrier and of the image it carries each place an arena at a +# 256 MiB alignment (512 MiB, dirun's default, held one). A program that # wants no C library states `c-abi = false' for the row and is linked over # openkal-uefi alone. [[platform.define]] @@ -213,7 +219,7 @@ hosted = true layers = { compiler-runtime = "openkal-llvm-runtime@0.20.3", "c++-abi" = "openkal-llvm-runtime@0.20.3", c-abi = { name = "openkal-musl", version = "0.29.6", default-features = false, features = ["posix", "malloc-mimalloc"] } } link = { driver = "lld", start = "efi_main", flags = ["--subsystem", "efi_application", "--gc-sections"], exe = "{name}.efi", inputs = [{ file = "board/qemu-exit.S" }], seal = [] } -runner = { cmd = ["dirun", "--payload", "{}", "--profile", "{pkg:ovmf}/dirun.toml", "--emulator", "{pkg:qemu-x86}/bin/qemu-system-x86_64"], hosts = ["linux-x86_64", "linux-aarch64", "macos-aarch64", "windows-x86_64"], requires = ["xim:dirun@0.3.2", "xim:qemu-x86@9.2.4-1", "xim:ovmf@9.2.4-1"] } +runner = { cmd = ["dirun", "--payload", "{}", "--profile", "{pkg:ovmf}/dirun.toml", "--emulator", "{pkg:qemu-x86}/bin/qemu-system-x86_64", "--memory", "2048"], hosts = ["linux-x86_64", "linux-aarch64", "macos-aarch64", "windows-x86_64"], requires = ["xim:dirun@0.3.2", "xim:qemu-x86@9.2.4-1", "xim:ovmf@9.2.4-1"] } # The family released together for openkal 0.17 (the 0.17.2 round: okb, the # runner's bundle and library interfaces, musl's renameat2; the 0.17.3 round: From 42bf64be4887f271aa35f864b6d3fdc12561e286 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Sat, 14 Nov 2026 00:54:58 +0900 Subject: [PATCH 05/11] 0.28.0: DOS programs (i686-dos-musl, technical experiment only) over openkal-dos; the seal okdos --- README.md | 26 ++++++++++++++++++++++++++ mcpp.toml | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/README.md b/README.md index 22f53f7..683ba57 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,32 @@ allocator reserves it, and the carrier's allocator and the image's each place a Measured: an image that prints, writes to standard error, throws and catches, carried by a 2.4 MB application, returned its status 7 under OVMF in 0.4 s. +## DOS programs (0.28.0; technical experiment only) + +`i686-dos-musl` is a row this platform defines and serves (`[[platform.provider]] +name = "dos"`): a program a DPMI host runs, on the same C library and C++ +run-time over openkal-dos, so it is written in C++23 with `import std`: + +```toml +[target.i686-dos-musl] +platform = "openkal-platform@0.28.0" +``` + +The row is TECHNICAL EXPERIMENT ONLY (openkal-dos's README). A program is the +stub of openkal-dos followed by an ELF32 i386 executable linked at its address; +the seal `okdos` (openkal-dos-tools) writes the stub, and the stub enters 32-bit +protected mode through the machine's DPMI host or CWSDPMI beside the program. The +row's flags are its conventions: `-march=i586`, emulated thread-local storage +(there is no thread register the toolchain can address) and unwind tables for +every unit. The provider's link is `ld.lld -static --image-base=0x1000 -z norelro +--gc-sections --eh-frame-hdr`, entered at `okdos_entry`, over `base = "none"`, and +the platform's tools it carries are the one its seal names (mcpp 2026.11.13.1): +a DOS build builds `okdos` alone, and an ok image does not build it. `mcpp run` +runs the program with dirun and xim's DOSBox Staging profile, which places +CWSDPMI beside it. Measured: a C++23 program with `import std`, an exception +crossing a frame, `std::ranges::sort`, a sleep and `getenv` printed and returned +7 under DOSBox Staging. + ## Version group `[platform.versions]` names one version of each package of the family. From diff --git a/mcpp.toml b/mcpp.toml index 4a3133a..04d27a6 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -68,6 +68,8 @@ c-abi = { name = "openkal-musl", version = "0.29.6", default-features okld = "openkal-tools@0.6.3" okrun = "openkal-tools@0.6.3" okprof = "openkal-tools@0.6.3" +# The seal of the DOS row (0.28.0): the stub of openkal-dos before an executable. +okdos = "openkal-dos-tools@0.1.0" # Every unit of an image (SPEC 12.2): # -fPIC the image is ET_DYN and has no text relocation; @@ -221,6 +223,38 @@ layers = { compiler-runtime = "openkal-llvm-runtime@0.20.3", "c++-abi" = "openka link = { driver = "lld", start = "efi_main", flags = ["--subsystem", "efi_application", "--gc-sections"], exe = "{name}.efi", inputs = [{ file = "board/qemu-exit.S" }], seal = [] } runner = { cmd = ["dirun", "--payload", "{}", "--profile", "{pkg:ovmf}/dirun.toml", "--emulator", "{pkg:qemu-x86}/bin/qemu-system-x86_64", "--memory", "2048"], hosts = ["linux-x86_64", "linux-aarch64", "macos-aarch64", "windows-x86_64"], requires = ["xim:dirun@0.3.2", "xim:qemu-x86@9.2.4-1", "xim:ovmf@9.2.4-1"] } +# DOS (0.28.0; TECHNICAL EXPERIMENT ONLY, openkal-dos's README): programs a DPMI +# host runs, on the same C library and C++ run-time over openkal-dos +# (openkal-musl names it, `standalone', on `cfg(os = "dos")'). A program is the +# stub of openkal-dos followed by an ELF32 i386 executable linked at its address; +# `okdos seal' writes the stub. The row's flags are its conventions: there is no +# thread register the toolchain can address, so thread-local storage is emulated +# (openkal-llvm-runtime builds compiler-rt's `emutls.c' for the row), and a triple +# with no system has no unwind tables by default, which the unwinder's own frames +# need. The runner is dirun with DOSBox Staging and CWSDPMI beside the program +# (xim's `dosbox-staging'). The memory allocator is musl's own (`malloc-mallocng'): +# it asks openkal.memory for blocks and nothing else. +[[platform.define]] +triple = "i686-dos-musl" +clang-triple = "i386-unknown-none-elf" +object-format = "elf" +data-model = "ilp32" +exe-suffix = ".exe" +execution = "dos" +tier = "preview" +march = "i586" +flags = ["-femulated-tls", "-fasynchronous-unwind-tables", "-ffunction-sections", "-fdata-sections"] + +[[platform.provider]] +name = "dos" +serves = ["i686-dos-musl"] +base = "none" +hosted = true + +layers = { compiler-runtime = "openkal-llvm-runtime@0.20.3", "c++-abi" = "openkal-llvm-runtime@0.20.3", c-abi = { name = "openkal-musl", version = "0.29.6", default-features = false, features = ["posix", "malloc-mallocng"] } } +link = { driver = "lld", start = "okdos_entry", flags = ["-static", "--image-base=0x1000", "-z", "norelro", "--gc-sections", "--eh-frame-hdr"], seal = [["okdos", "seal", "{}"]] } +runner = { cmd = ["dirun", "--payload", "{}", "--profile", "{pkg:dosbox-staging}/dirun.toml", "--"], hosts = ["linux-x86_64", "macos-aarch64", "windows-x86_64"], requires = ["xim:dirun@0.3.2", "xim:dosbox-staging@0.83.0"] } + # The family released together for openkal 0.17 (the 0.17.2 round: okb, the # runner's bundle and library interfaces, musl's renameat2; the 0.17.3 round: # musl takes a program's arguments when it is entered; the 0.18.0 round: a @@ -285,6 +319,7 @@ openkal-macos = "0.23.2" openkal-windows = "0.21.2" openkal-freebsd = "0.1.2" openkal-uefi = "0.10.0" +openkal-dos = "0.1.0" openkal-musl = "0.29.6" openkal-llvm-runtime = "0.20.3" openkal-ld = "0.6.3" From 473f27402ffbf9b1c3dbf153fdb641d47ee6f98b Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Sat, 14 Nov 2026 01:41:17 +0900 Subject: [PATCH 06/11] i686-openkal: the ok image of i386; the stack aligned to sixteen bytes on the i386 rows The platform serves i686-openkal (openkal 0.25.1, clauses 5.5 and 12.2; openkal-image 0.6.3 loads it). The ok images' link states its addends (`-z rela`), which is i386's one difference from the linker's default. The row is compiled for the Pentium (`-march=i586`) with the stack aligned to sixteen bytes at a call (`-mstack-alignment=16`), the System V i386 convention SPEC 12.2 states; a triple with no system leaves clang at four, and okrun's code, built for Linux, faulted on a `movaps` when such an image called it (measured). The DOS row takes the same alignment: its code calls images and is called by them. The README states the row, how a project selects it while mcpp names it planned, and what openkal-dos's files give a DOS program. --- README.md | 38 +++++++++++++++++++++++++++++++++++--- mcpp.toml | 33 ++++++++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 683ba57..763ae47 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,33 @@ specification by its minor version (openkal-macos 0.23.2, openkal-windows 0.21.2 openkal-freebsd 0.1.2; openkal-image 0.6.2), so a project that names openkal 0.25.1 resolves with them. +Platform 0.28.0 also serves the ok image of the thirty-two bit class, +`i686-openkal` (openkal 0.25.1, clauses 5.5 and 12.2; openkal-image 0.6.3 reads, +checks, places, loads and debugs it). Its conventions are the ok images' own, +and three apply to every architecture or to i386 alone: +- `-z rela`: an image states its addends, which is i386's one difference from + its linker's default. +- `-march=i586`: the Pentium's instructions, the least machine an i386 image + runs on and the one DOS's emulators model. +- `-mstack-alignment=16`: the System V i386 convention's sixteen bytes at a call + (SPEC 12.2). The image's triple names no system, and for such a triple clang + keeps four. Measured: okrun's own code, built for Linux, faulted on a `movaps` + when an image built at four called it. + +An i386 image runs on an i386 runner (`i686-linux-musl` on Linux), never inside +a runner of another architecture. mcpp names the row `planned` until its pin of +this platform serves it, so a project opts in with the toolchain: + +```toml +[target.i686-openkal] +platform = "openkal-platform@0.28.0" +toolchain = "llvm@23.1.3" +``` + +Measured: a C++23 image with `import std` and an exception across a frame, +built so, runs under an okrun built for `i686-linux-musl` on x86_64 Linux and +returns its status. + A project overrides any group under `[target.]`, for example `[target.'cfg(platform = "openkal")'.layers] "c++-abi" = false`, and selects another platform, or none, with `platform = "..."` or `--platform`. @@ -268,15 +295,20 @@ stub of openkal-dos followed by an ELF32 i386 executable linked at its address; the seal `okdos` (openkal-dos-tools) writes the stub, and the stub enters 32-bit protected mode through the machine's DPMI host or CWSDPMI beside the program. The row's flags are its conventions: `-march=i586`, emulated thread-local storage -(there is no thread register the toolchain can address) and unwind tables for -every unit. The provider's link is `ld.lld -static --image-base=0x1000 -z norelro +(there is no thread register the toolchain can address), unwind tables for +every unit, and the stack aligned to sixteen bytes at a call, as an i386 ok +image's is (the row's code calls images and is called by them). The provider's link is `ld.lld -static --image-base=0x1000 -z norelro --gc-sections --eh-frame-hdr`, entered at `okdos_entry`, over `base = "none"`, and the platform's tools it carries are the one its seal names (mcpp 2026.11.13.1): a DOS build builds `okdos` alone, and an ok image does not build it. `mcpp run` runs the program with dirun and xim's DOSBox Staging profile, which places CWSDPMI beside it. Measured: a C++23 program with `import std`, an exception crossing a frame, `std::ranges::sort`, a sleep and `getenv` printed and returned -7 under DOSBox Staging. +7 under DOSBox Staging. Through openkal-dos's `fs`, `std::filesystem` and +`std::fstream` work on the FAT volumes: a program wrote, appended, read, renamed, +listed, resized and removed files and directories there (measured). openkal-dos +provides `abort`, `env`, `exec`, `fs`, `memory`, `stream`, `terminal` and +`time`. `region` is absent, because the DPMI host CWSDPMI is DPMI 0.90. ## Version group diff --git a/mcpp.toml b/mcpp.toml index 04d27a6..5afe5df 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -27,7 +27,11 @@ repo = "https://github.com/mcpplibs/openkal-platform" mcpp = ">=2026.11.13.1" [platform] -targets = ["x86_64-openkal", "aarch64-openkal"] +# `i686-openkal` (0.28.0): the image of the thirty-two bit class, i386 (openkal +# 0.25.1, clauses 5.5 and 12.2; openkal-image 0.6.3 reads, checks and loads it). +# mcpp names the row `planned' until its pin of this platform serves it: a +# project selects it with this platform and `--toolchain llvm@23.1.3`. +targets = ["x86_64-openkal", "aarch64-openkal", "i686-openkal"] toolchain = "llvm@23.1.3" # The loader runs an image of its own architecture on Linux, macOS and Windows; # `hosts` are the systems and architectures openkal-tools builds it for, which is @@ -138,6 +142,19 @@ cflags = ["-ffixed-x18", "-mno-outline-atomics", "-mbranch-protection=pac-ret+ cxxflags = ["-ffixed-x18", "-mno-outline-atomics", "-mbranch-protection=pac-ret+bti"] asmflags = ["-ffixed-x18", "-mno-outline-atomics", "-mbranch-protection=pac-ret+bti"] +# i386 (0.28.0): the Pentium's instructions (-march=i586) are the least machine +# an i386 image runs on, and the emulators that run DOS model no later one (no +# CMOV, no SSE); an image is then the same bytes on Linux, on Windows and beneath +# DOS's carrier. The floating point is the x87's, the convention's own (SPEC 12.2). +# The stack is aligned to sixteen bytes at a call (SPEC 12.2): the image's triple +# names no system, for which clang keeps four, and a loader's code built for its +# system relies on sixteen (measured: `movaps' of okrun's kal_time_monotonic, +# entered from an image built at four, faults). +[platform.build.'cfg(arch = "i686")'] +cflags = ["-march=i586", "-mstack-alignment=16"] +cxxflags = ["-march=i586", "-mstack-alignment=16"] +asmflags = ["-march=i586"] + # The link, by `ld.lld` itself: position-independent, every loadable segment # aligned to 64 KiB (the largest protection granularity among the systems), # bound now, no executable stack, both hash tables, what nothing reaches @@ -145,7 +162,10 @@ asmflags = ["-ffixed-x18", "-mno-outline-atomics", "-mbranch-protection=pac-ret+ # and the unwind index an unwinder finds through `dl_iterate_phdr`; the relative # relocations packed (`-z pack-relative-relocs`, SPEC 12.2's packed relative # form): a loader reads clangd's 164 000 of them from 32 KiB rather than 3.9 MB -# on every start, and the image is 4 MB smaller. +# on every start, and the image is 4 MB smaller. `-z rela`: i386's default is +# REL, whose addend is the word the relocation writes; an image states its +# addends (RELA) on every architecture, so a loader and a placement read one +# form (SPEC 12.2; the option is the default's form on the sixty-four bit ones). # An executable image is entered at `ok_main`, which its C library defines; its # notes come from `okld note-source`; `okld note` writes its requirements, # `okld place` its writable segments computed for the base it chooses from the @@ -158,7 +178,7 @@ asmflags = ["-ffixed-x18", "-mno-outline-atomics", "-mbranch-protection=pac-ret+ [platform.link] driver = "lld" start = "ok_main" -flags = ["-shared", "-z", "max-page-size=65536", "-z", "pack-relative-relocs", "-z", "now", "-z", "noexecstack", +flags = ["-shared", "-z", "max-page-size=65536", "-z", "pack-relative-relocs", "-z", "rela", "-z", "now", "-z", "noexecstack", "--hash-style=both", "--gc-sections", "--icf=safe", "--eh-frame-hdr", "--build-id=sha1", "--emit-relocs", "-mllvm", "-emulated-tls"] inputs = [{ from = ["okld", "note-source"], as = "ok-notes.S" }] @@ -231,7 +251,10 @@ runner = { cmd = ["dirun", "--payload", "{}", "--profile", "{pkg:ovmf}/dirun.tom # thread register the toolchain can address, so thread-local storage is emulated # (openkal-llvm-runtime builds compiler-rt's `emutls.c' for the row), and a triple # with no system has no unwind tables by default, which the unwinder's own frames -# need. The runner is dirun with DOSBox Staging and CWSDPMI beside the program +# need. The stack is aligned to sixteen bytes at a call, the System V i386 +# convention that openkal states for an i386 image (SPEC 12.2) and that a triple +# with no system leaves at four: the row's code calls images and is called by +# them. The runner is dirun with DOSBox Staging and CWSDPMI beside the program # (xim's `dosbox-staging'). The memory allocator is musl's own (`malloc-mallocng'): # it asks openkal.memory for blocks and nothing else. [[platform.define]] @@ -243,7 +266,7 @@ exe-suffix = ".exe" execution = "dos" tier = "preview" march = "i586" -flags = ["-femulated-tls", "-fasynchronous-unwind-tables", "-ffunction-sections", "-fdata-sections"] +flags = ["-femulated-tls", "-fasynchronous-unwind-tables", "-mstack-alignment=16", "-ffunction-sections", "-fdata-sections"] [[platform.provider]] name = "dos" From c0e38f18727b993eead57bb6080af9234bcd19c9 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Sat, 14 Nov 2026 02:26:41 +0900 Subject: [PATCH 07/11] The i386 rows are compiled for the 486; an i386 image packs for DOS (dos-i686) DOSBox Staging 0.83 executes RDTSC and not CMPXCHG8B under every cputype (measured), and an image's sixty-four bit atomics (mimalloc's statistics) were that instruction under -march=i586, so i686-openkal and i686-dos-musl are compiled for the 486 and such an atomic is compiler-rt's call. The runner's hosts include dos-i686: the core runner as a program of the DOS row, which mcpp 2026.11.13.1 builds as the row the platform defines for the system. Measured: an i686-openkal image packed so ran under DOSBox Staging and returned 7. --- README.md | 21 +++++++++++++++------ mcpp.toml | 27 +++++++++++++++++---------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 763ae47..0ec684d 100644 --- a/README.md +++ b/README.md @@ -134,8 +134,10 @@ checks, places, loads and debugs it). Its conventions are the ok images' own, and three apply to every architecture or to i386 alone: - `-z rela`: an image states its addends, which is i386's one difference from its linker's default. -- `-march=i586`: the Pentium's instructions, the least machine an i386 image - runs on and the one DOS's emulators model. +- `-march=i486`: the 486's instructions, the least machine an i386 image runs + on. DOSBox Staging 0.83, which runs the DOS row and its carrier, executes + RDTSC and not CMPXCHG8B under every `cputype` (measured), so a sixty-four bit + atomic is compiler-rt's call rather than the Pentium's instruction. - `-mstack-alignment=16`: the System V i386 convention's sixteen bytes at a call (SPEC 12.2). The image's triple names no system, and for such a triple clang keeps four. Measured: okrun's own code, built for Linux, faulted on a `movaps` @@ -153,7 +155,13 @@ toolchain = "llvm@23.1.3" Measured: a C++23 image with `import std` and an exception across a frame, built so, runs under an okrun built for `i686-linux-musl` on x86_64 Linux and -returns its status. +returns its status, unoptimised and optimised. + +The same image runs on DOS (technical experiment only): the runner's `hosts` +include `dos-i686`, so `mcpp pack --pkg-format single-file --systems dos-i686` +builds openkal-run's core runner as a program of the DOS row below, with the +image in its `.oke` section. Measured under DOSBox Staging: the image sorted its +arguments, caught its exception, read DOS's `PATH` and returned 7. A project overrides any group under `[target.]`, for example `[target.'cfg(platform = "openkal")'.layers] "c++-abi" = false`, and selects @@ -294,11 +302,12 @@ The row is TECHNICAL EXPERIMENT ONLY (openkal-dos's README). A program is the stub of openkal-dos followed by an ELF32 i386 executable linked at its address; the seal `okdos` (openkal-dos-tools) writes the stub, and the stub enters 32-bit protected mode through the machine's DPMI host or CWSDPMI beside the program. The -row's flags are its conventions: `-march=i586`, emulated thread-local storage +row's flags are its conventions: `-march=i486`, emulated thread-local storage (there is no thread register the toolchain can address), unwind tables for every unit, and the stack aligned to sixteen bytes at a call, as an i386 ok -image's is (the row's code calls images and is called by them). The provider's link is `ld.lld -static --image-base=0x1000 -z norelro ---gc-sections --eh-frame-hdr`, entered at `okdos_entry`, over `base = "none"`, and +image's is (the row's code calls images and is called by them). The provider's +link is `ld.lld -static --image-base=0x1000 -z norelro --gc-sections +--eh-frame-hdr`, entered at `okdos_entry`, over `base = "none"`, and the platform's tools it carries are the one its seal names (mcpp 2026.11.13.1): a DOS build builds `okdos` alone, and an ok image does not build it. `mcpp run` runs the program with dirun and xim's DOSBox Staging profile, which places diff --git a/mcpp.toml b/mcpp.toml index 5afe5df..af33eb7 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -45,7 +45,10 @@ toolchain = "llvm@23.1.3" # static program, the same whichever machine packs it. `uefi-x86_64` (0.28.0): # the runner is a UEFI application of the row this platform defines below (the # core runner, which carries what it runs), so an ok image packs for firmware. -runner = { cmd = ["okrun", "{}"], host = "same-arch", hosts = ["linux-x86_64", "linux-aarch64", "macos-aarch64", "windows-x86_64", "freebsd-x86_64", "freebsd-aarch64", "uefi-x86_64"], built-as = { "freebsd-x86_64" = "x86_64-freebsd-musl", "freebsd-aarch64" = "aarch64-freebsd-musl" } } +# `dos-i686` (0.28.0; technical experiment only): the core runner as a program +# of the DOS row below, so an i386 image packs for DOS (mcpp 2026.11.13.1 builds +# a system's runner as the row the platform defines for it). +runner = { cmd = ["okrun", "{}"], host = "same-arch", hosts = ["linux-x86_64", "linux-aarch64", "macos-aarch64", "windows-x86_64", "freebsd-x86_64", "freebsd-aarch64", "uefi-x86_64", "dos-i686"], built-as = { "freebsd-x86_64" = "x86_64-freebsd-musl", "freebsd-aarch64" = "aarch64-freebsd-musl" } } # `mcpp pack --mode self-contained`: a program of the packing machine that # carries the image in a section and runs it through libokrun (M3). carrier = { package = "openkal-run@0.6.3", section = ".oke", main = "carrier/main.cpp" } @@ -142,18 +145,21 @@ cflags = ["-ffixed-x18", "-mno-outline-atomics", "-mbranch-protection=pac-ret+ cxxflags = ["-ffixed-x18", "-mno-outline-atomics", "-mbranch-protection=pac-ret+bti"] asmflags = ["-ffixed-x18", "-mno-outline-atomics", "-mbranch-protection=pac-ret+bti"] -# i386 (0.28.0): the Pentium's instructions (-march=i586) are the least machine -# an i386 image runs on, and the emulators that run DOS model no later one (no -# CMOV, no SSE); an image is then the same bytes on Linux, on Windows and beneath -# DOS's carrier. The floating point is the x87's, the convention's own (SPEC 12.2). +# i386 (0.28.0): the 486's instructions (-march=i486) are the least machine an +# i386 image runs on: DOSBox Staging 0.83, which runs the DOS row and its +# carrier, executes RDTSC and not CMPXCHG8B under every `cputype' (measured), so +# a sixty-four bit atomic is compiler-rt's call (atomic.c) rather than the +# Pentium's instruction. An image is then the same bytes on Linux, on Windows and +# beneath DOS's carrier. The floating point is the x87's, the convention's own +# (SPEC 12.2). # The stack is aligned to sixteen bytes at a call (SPEC 12.2): the image's triple # names no system, for which clang keeps four, and a loader's code built for its # system relies on sixteen (measured: `movaps' of okrun's kal_time_monotonic, # entered from an image built at four, faults). [platform.build.'cfg(arch = "i686")'] -cflags = ["-march=i586", "-mstack-alignment=16"] -cxxflags = ["-march=i586", "-mstack-alignment=16"] -asmflags = ["-march=i586"] +cflags = ["-march=i486", "-mstack-alignment=16"] +cxxflags = ["-march=i486", "-mstack-alignment=16"] +asmflags = ["-march=i486"] # The link, by `ld.lld` itself: position-independent, every loadable segment # aligned to 64 KiB (the largest protection granularity among the systems), @@ -254,7 +260,8 @@ runner = { cmd = ["dirun", "--payload", "{}", "--profile", "{pkg:ovmf}/dirun.tom # need. The stack is aligned to sixteen bytes at a call, the System V i386 # convention that openkal states for an i386 image (SPEC 12.2) and that a triple # with no system leaves at four: the row's code calls images and is called by -# them. The runner is dirun with DOSBox Staging and CWSDPMI beside the program +# them. The processor is the 486, as for the i386 ok image (DOSBox Staging 0.83 +# executes no CMPXCHG8B, measured). The runner is dirun with DOSBox Staging and CWSDPMI beside the program # (xim's `dosbox-staging'). The memory allocator is musl's own (`malloc-mallocng'): # it asks openkal.memory for blocks and nothing else. [[platform.define]] @@ -265,7 +272,7 @@ data-model = "ilp32" exe-suffix = ".exe" execution = "dos" tier = "preview" -march = "i586" +march = "i486" flags = ["-femulated-tls", "-fasynchronous-unwind-tables", "-mstack-alignment=16", "-ffunction-sections", "-fdata-sections"] [[platform.provider]] From c21f7821713d0c417044fbad3be691b79c9245f0 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Sat, 14 Nov 2026 02:43:05 +0900 Subject: [PATCH 08/11] ci: check the ok image of i386 and the DOS row checks/i386 builds an i686-openkal image in both modes, checks it with okld and runs it with okrun built for i686-linux-musl from the openkal-image release the group names; packed with --systems dos-i686, the image runs as a DOS program under DOSBox Staging. checks/dos runs a program of i686-dos-musl in both modes through the provider's runner. Both return status 7. --- .github/workflows/ci.yml | 129 +++++++++++++++++++++++++++++++++++++++ README.md | 2 + checks/dos/mcpp.toml | 12 ++++ checks/dos/src/main.cpp | 12 ++++ checks/i386/mcpp.toml | 15 +++++ checks/i386/src/main.cpp | 12 ++++ 6 files changed, 182 insertions(+) create mode 100644 checks/dos/mcpp.toml create mode 100644 checks/dos/src/main.cpp create mode 100644 checks/i386/mcpp.toml create mode 100644 checks/i386/src/main.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d493f61..0f69df0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,9 @@ name: CI # host-graph a build program is compiled as an ok image and run by okrun # i686 Linux's thirty-two bit row: the hosted program and the # specification's conformance suite, run on Linux x86_64 +# i686-openkal the ok image of i386, run by okrun built for i686-linux-musl +# dos a DOS program, and the i386 image carried as one (technical +# experiment only), run under DOSBox Staging through dirun # freebsd the musl rows of FreeBSD are built here and run in a FreeBSD VM, # with okrun built for them running an ok image there # @@ -320,6 +323,132 @@ jobs: file "$p" | grep -q 'PE32+' && file "$p" | grep -q 'EFI application' \ || { echo "::error::x86_64-uefi is not a PE32+ EFI application"; exit 1; } + # I686-OPENKAL (0.28.0): the ok image of i386 (ELF32, REL), built from + # checks/i386 in both modes, checked by okld, and run by okrun built for + # i686-linux-musl from the openkal-image release this group names. + i686-openkal: + name: i686-openkal (an ok image of i386, run on Linux x86_64) + runs-on: ubuntu-24.04 + timeout-minutes: 90 + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v4 + + - name: Install xlings and mcpp + run: | + curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \ + | bash -s "$XLINGS_VERSION" + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" + for attempt in 1 2 3 4 5 6; do + xlings update > /dev/null 2>&1 || true + if xlings install "mcpp@$MCPP_VERSION" -y -g; then break; fi + [ "$attempt" = 6 ] && { echo "::error::mcpp could not be installed"; exit 1; } + sleep 60 + done + mcpp --version + mcpp self config --mirror GLOBAL + + - name: okrun for i686-linux-musl + run: | + tag=$(sed -n 's/^openkal-tools *= *"\(.*\)"/\1/p' mcpp.toml | head -1) + git clone --quiet --depth 1 --branch "$tag" https://github.com/mcpplibs/openkal-image.git "$RUNNER_TEMP/oi" + printf '\n[target.i686-linux-musl]\nplatform = { path = "%s" }\ntoolchain = "llvm@23.1.3"\n' "$GITHUB_WORKSPACE" >> "$RUNNER_TEMP/oi/tools/mcpp.toml" + (cd "$RUNNER_TEMP/oi/tools" && mcpp build --release --target i686-linux-musl) + okrun=$(find "$RUNNER_TEMP/oi/target/i686-linux-musl" -path '*bin/openkal-tools/okrun' -type f | head -1) + file "$okrun" + file "$okrun" | grep -q 'ELF 32-bit' || { echo "::error::okrun is not an i386 program"; exit 1; } + echo "OKRUN32=$okrun" >> "$GITHUB_ENV" + + - name: The image, built, checked and run (dev and release) + working-directory: checks/i386 + run: | + py=python3 + for mode in "" --release; do + rm -rf target/i686-openkal + mcpp build --target i686-openkal $mode + okld=$(mcpp self env --target i686-openkal --format json | $py -c 'import json,sys; print(json.load(sys.stdin)["data"]["tools"]["okld"])') + image=$(find target/i686-openkal -path '*bin*' -name i386.oke -type f | head -1) + "$okld" check "$image" + "$okld" inspect "$image" | tee inspect.log + grep -Eq '^architecture +i686' inspect.log || { echo "::error::the image does not state i686"; exit 1; } + set +e + "$OKRUN32" "$image" two one | tee run.log + status=${PIPESTATUS[0]} + set -e + grep -q 'i386 ok: \["one", "two"\]' run.log && grep -q 'caught: across a frame' run.log \ + || { echo "::error::the image's output ($mode)"; exit 1; } + [ "$status" -eq 7 ] || { echo "::error::the image returned $status, not 7 ($mode)"; exit 1; } + done + + # DOS (0.28.0; technical experiment only): a program of i686-dos-musl + # (openkal-musl over openkal-dos, run under CWSDPMI) built in both modes and + # run by the provider's runner, dirun with DOSBox Staging; and the i386 ok + # image packed as one DOS program, the core runner carrying it, and run there. + dos: + name: i686-dos-musl (built on Linux x86_64, run under DOSBox Staging) + runs-on: ubuntu-24.04 + timeout-minutes: 90 + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v4 + + - name: Install xlings and mcpp + run: | + curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \ + | bash -s "$XLINGS_VERSION" + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" + for attempt in 1 2 3 4 5 6; do + xlings update > /dev/null 2>&1 || true + if xlings install "mcpp@$MCPP_VERSION" -y -g; then break; fi + [ "$attempt" = 6 ] && { echo "::error::mcpp could not be installed"; exit 1; } + sleep 60 + done + mcpp --version + mcpp self config --mirror GLOBAL + + - name: The DOS program (dev and release) + working-directory: checks/dos + run: | + for mode in "" --release; do + set +e + mcpp run --target i686-dos-musl $mode -- two one | tr -d '\r' | tee run.log + status=${PIPESTATUS[0]} + set -e + grep -q 'dos ok: \["one", "two"\]' run.log && grep -q 'caught: across a frame' run.log \ + || { echo "::error::the DOS program's output ($mode)"; exit 1; } + [ "$status" -eq 7 ] || { echo "::error::the DOS program returned $status, not 7 ($mode)"; exit 1; } + done + p=$(find target/i686-dos-musl -path '*bin/dos.exe' -type f | head -1) + file "$p" + + - name: The i386 image carried as a DOS program + working-directory: checks/i386 + run: | + # `-o` names the file as written; DOS runs a program named .exe. + mcpp pack --target i686-openkal --pkg-format single-file --systems dos-i686 -o carried.exe + exe=target/dist/carried.exe + [ -f "$exe" ] || { echo "::error::no DOS program was packed"; ls target/dist; exit 1; } + file "$exe" + # The DOS row's runner, which the previous step installed: dirun, and + # the profile of the DOSBox Staging package beside it. + dirun=$(cd ../dos && mcpp self env --target i686-dos-musl --format json \ + | python3 -c 'import json,sys; print(json.load(sys.stdin)["data"]["runner"]["program"])') + root=$(cd "$(dirname "$dirun")/../../.." && pwd) + profile=$(find "$root"/xim-x-dosbox-staging -name dirun.toml -type f | sort | tail -1) + [ -n "$dirun" ] && [ -n "$profile" ] || { echo "::error::dirun or the DOSBox profile is not installed"; exit 1; } + set +e + "$dirun" --payload "$exe" --profile "$profile" -- two one | tr -d '\r' | tee carried.log + status=${PIPESTATUS[0]} + set -e + grep -q 'i386 ok: \["one", "two"\]' carried.log || { echo "::error::the carried image's output"; exit 1; } + [ "$status" -eq 7 ] || { echo "::error::the carried image returned $status, not 7"; exit 1; } + freebsd: name: freebsd (built for x86_64 and aarch64, run in a VM) runs-on: ubuntu-24.04 diff --git a/README.md b/README.md index 0ec684d..8e7847e 100644 --- a/README.md +++ b/README.md @@ -353,6 +353,8 @@ previous patch's. | `checks/hosted` | the hosted arrangement runs on Linux, macOS and Windows | | `checks/host-graph` | a build program runs as an ok image | | `checks/snapshot` | a C++ program starts from a snapshot of its initialisers, and a start whose named value differs does not | +| `checks/i386` | an ok image of i386 is built in both modes, checked by okld and run by okrun built for i686-linux-musl; packed with `--systems dos-i686`, it runs as a DOS program | +| `checks/dos` | a program of i686-dos-musl runs in both modes under DOSBox Staging (technical experiment only) | | family release | the group's members are tagged and mirrored, both mcpp releases resolve an image of it, and a patch removes no symbol | ## License diff --git a/checks/dos/mcpp.toml b/checks/dos/mcpp.toml new file mode 100644 index 0000000..0708af4 --- /dev/null +++ b/checks/dos/mcpp.toml @@ -0,0 +1,12 @@ +# A DOS program (0.28.0; technical experiment only): C++23 over the family's C library and C++ +# run-time over openkal-dos, run with dirun under DOSBox Staging. The platform is the directory above. +[package] +name = "dos" +version = "0.1.0" + +[targets.dos] +kind = "bin" +main = "src/main.cpp" + +[target.i686-dos-musl] +platform = { path = "../.." } diff --git a/checks/dos/src/main.cpp b/checks/dos/src/main.cpp new file mode 100644 index 0000000..b166791 --- /dev/null +++ b/checks/dos/src/main.cpp @@ -0,0 +1,12 @@ +// A DOS program: its arguments sorted, an exception across a frame, the environment, a status. +import std; + +int main(int argc, char** argv) { + std::vector v(argv + 1, argv + argc); + std::ranges::sort(v); + std::println("dos ok: {}", v); + try { throw std::runtime_error("across a frame"); } + catch (const std::exception& e) { std::println("caught: {}", e.what()); } + std::println("PATH set: {}", std::getenv("PATH") != nullptr); + return 7; +} diff --git a/checks/i386/mcpp.toml b/checks/i386/mcpp.toml new file mode 100644 index 0000000..0666687 --- /dev/null +++ b/checks/i386/mcpp.toml @@ -0,0 +1,15 @@ +# The ok image of i386 (0.28.0): C++23 over the family's C library and C++ run-time, built for +# i686-openkal and run by an okrun built for i686-linux-musl, and carried as a DOS program by the +# core runner (`mcpp pack --pkg-format single-file --systems dos-i686`). The platform is the +# directory above; the row is planned in mcpp until its pin serves it, so the toolchain is named. +[package] +name = "i386" +version = "0.1.0" + +[targets.i386] +kind = "bin" +main = "src/main.cpp" + +[target.i686-openkal] +platform = { path = "../.." } +toolchain = "llvm@23.1.3" diff --git a/checks/i386/src/main.cpp b/checks/i386/src/main.cpp new file mode 100644 index 0000000..4cf885f --- /dev/null +++ b/checks/i386/src/main.cpp @@ -0,0 +1,12 @@ +// An i386 image: its arguments sorted, an exception across a frame, the environment, a status. +import std; + +int main(int argc, char** argv) { + std::vector v(argv + 1, argv + argc); + std::ranges::sort(v); + std::println("i386 ok: {}", v); + try { throw std::runtime_error("across a frame"); } + catch (const std::exception& e) { std::println("caught: {}", e.what()); } + std::println("PATH set: {}", std::getenv("PATH") != nullptr); + return 7; +} From 55a0b273ef927ffcafa0b10442afaef61147eb85 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Sat, 14 Nov 2026 02:46:39 +0900 Subject: [PATCH 09/11] 0.28.0: openkal-dos-tools is a member of the group, released from openkal-dos's tag The family release checks its tag, mirror and index entry as it checks openkal-tools'. The README's statement table names i686-openkal and okdos. --- README.md | 4 ++-- mcpp.toml | 1 + tools/family_release.py | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8e7847e..1690a24 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,10 @@ mcpp pack --target x86_64-openkal --pkg-format okb # one file okrun runs | Group | Value | |---|---| -| targets | `x86_64-openkal`, `aarch64-openkal` | +| targets | `x86_64-openkal`, `aarch64-openkal`, `i686-openkal` (0.28.0) | | toolchain | `llvm@23.1.3` | | layers | `c-abi` openkal-musl (`posix`), `c++-abi` and `compiler-runtime` openkal-llvm-runtime | -| tools | `okld`, `okrun`, `okprof` (openkal-tools) | +| tools | `okld`, `okrun`, `okprof` (openkal-tools); `okdos` (openkal-dos-tools), the seal of the DOS row (0.28.0) | | build | `-fPIC -femulated-tls -fvisibility=hidden -fasynchronous-unwind-tables`, stack-clash protection, `-ffunction-sections -fdata-sections`; frame pointers, `-fstack-protector-strong -mstack-protector-guard=global`, `-ftrivial-auto-var-init=zero`, libc++'s fast hardening (0.23.0); on x86_64 `-fcf-protection=full`; on aarch64 `-ffixed-x18 -mno-outline-atomics -mbranch-protection=pac-ret+bti` (not `standard`, which clang 23 counts the guarded control stack in) | | link | `ld.lld`, entry `ok_main`, 64 KiB pages, relative relocations packed, `--gc-sections --icf=safe`, `--build-id=sha1`, retained debug relocations (0.24.0), the image notes produced by `okld note-source` | | seal | the selected LLVM toolchain's `llvm-objcopy` prunes ordinary static relocations (0.24.0); `okld note`; `okld place`, the writable segments computed for the base the image's bytes choose (openkal 0.23); then `okld check --with` the shared images the program needs | diff --git a/mcpp.toml b/mcpp.toml index af33eb7..6347978 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -350,6 +350,7 @@ openkal-windows = "0.21.2" openkal-freebsd = "0.1.2" openkal-uefi = "0.10.0" openkal-dos = "0.1.0" +openkal-dos-tools = "0.1.0" openkal-musl = "0.29.6" openkal-llvm-runtime = "0.20.3" openkal-ld = "0.6.3" diff --git a/tools/family_release.py b/tools/family_release.py index f07fdb6..3161b35 100644 --- a/tools/family_release.py +++ b/tools/family_release.py @@ -42,7 +42,8 @@ ROOT = Path(__file__).resolve().parents[1] # The packages one repository releases under one tag and one archive. REPOSITORY = {"openkal-ld": "openkal-image", "openkal-run": "openkal-image", - "openkal-tools": "openkal-image", "openkal-bind": "openkal-image"} + "openkal-tools": "openkal-image", "openkal-bind": "openkal-image", + "openkal-dos-tools": "openkal-dos"} INDEX_RAW = "https://raw.githubusercontent.com/mcpplibs/mcpp-index/main/pkgs/o/{}.lua" # The layers whose objects an image links, by the directory mcpp builds them into. LAYERS = ("mcpplibs_openkal-musl", "mcpplibs_openkal-llvm-runtime") From 600764e3bbe5ac7151f3dd40910ab3a6b652a43d Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Sun, 15 Nov 2026 01:04:16 +0900 Subject: [PATCH 10/11] The i686 rows are served by this platform's targets (mcpp 2026.11.14.1): no toolchain named by a project; --target openkal builds every leg --- .github/workflows/ci.yml | 7 +++---- README.md | 9 +++++---- checks/hosted/mcpp.toml | 14 ++------------ checks/i386/mcpp.toml | 5 ++--- mcpp.toml | 10 ++++++---- 5 files changed, 18 insertions(+), 27 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0f69df0..fb2894a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ on: env: MCPP_SOURCE_REF: ${{ github.event.inputs.mcpp_ref || vars.MCPP_SOURCE_REF || '' }} - MCPP_VERSION: 2026.11.13.1 + MCPP_VERSION: 2026.11.14.1 XLINGS_VERSION: v2026.10.26.1 XLINGS_NON_INTERACTIVE: '1' @@ -275,10 +275,9 @@ jobs: impl=$(sed -n 's/^openkal-linux *= *"\(.*\)"/\1/p' mcpp.toml | head -1) git clone --quiet --depth 1 --branch "$spec" https://github.com/mcpplibs/openkal.git .spec git clone --quiet --depth 1 --branch "$impl" https://github.com/mcpplibs/openkal-linux.git .impl - # The toolchain is named, as checks/hosted names it: an mcpp that - # registers the row as planned takes it when the toolchain is named. + # The platform serves the row mcpp registers as planned (mcpp 2026.11.14.1+). bash .spec/tools/run-conformance.sh openkal-linux .impl full,optional \ - --target i686-linux-musl --platform "path:$GITHUB_WORKSPACE" --toolchain llvm@23.1.3 | tee conformance.log + --target i686-linux-musl --platform "path:$GITHUB_WORKSPACE" | tee conformance.log grep -qE '^observations: [0-9]+ held, 0 did not hold' conformance.log \ || { echo "::error::an observation did not hold on i686-linux-musl"; exit 1; } diff --git a/README.md b/README.md index 1690a24..7e2ab9a 100644 --- a/README.md +++ b/README.md @@ -144,13 +144,14 @@ and three apply to every architecture or to i386 alone: when an image built at four called it. An i386 image runs on an i386 runner (`i686-linux-musl` on Linux), never inside -a runner of another architecture. mcpp names the row `planned` until its pin of -this platform serves it, so a project opts in with the toolchain: +a runner of another architecture. mcpp registers the row `planned`; this +platform lists it among its targets with its toolchain, which serves it (mcpp +2026.11.14.1+), so a project names only the platform, and `--target openkal` +builds the three architectures: ```toml [target.i686-openkal] -platform = "openkal-platform@0.28.0" -toolchain = "llvm@23.1.3" +platform = "openkal-platform@0.28.0" ``` Measured: a C++23 image with `import std` and an exception across a frame, diff --git a/checks/hosted/mcpp.toml b/checks/hosted/mcpp.toml index ba7933d..c876c45 100644 --- a/checks/hosted/mcpp.toml +++ b/checks/hosted/mcpp.toml @@ -8,15 +8,5 @@ version = "0.1.0" [target.'cfg(any(linux, macos, windows, os = "freebsd"))'] platform = { path = "../.." } -# FreeBSD's musl rows are served from mcpp 2026.11.10.2; an earlier mcpp lists -# them as planned and takes them when the toolchain is named. -[target.x86_64-freebsd-musl] -toolchain = "llvm@23.1.3" - -[target.aarch64-freebsd-musl] -toolchain = "llvm@23.1.3" - -# Linux's thirty-two bit row (0.28.0): an mcpp that registers the row as planned -# takes it when the toolchain is named. -[target.i686-linux-musl] -toolchain = "llvm@23.1.3" +# Linux's thirty-two bit row (0.28.0) is registered as planned in mcpp and +# served by this platform's hosted targets (mcpp 2026.11.14.1+). diff --git a/checks/i386/mcpp.toml b/checks/i386/mcpp.toml index 0666687..49ecabd 100644 --- a/checks/i386/mcpp.toml +++ b/checks/i386/mcpp.toml @@ -1,7 +1,7 @@ # The ok image of i386 (0.28.0): C++23 over the family's C library and C++ run-time, built for # i686-openkal and run by an okrun built for i686-linux-musl, and carried as a DOS program by the # core runner (`mcpp pack --pkg-format single-file --systems dos-i686`). The platform is the -# directory above; the row is planned in mcpp until its pin serves it, so the toolchain is named. +# directory above, which serves the row mcpp registers as planned (mcpp 2026.11.14.1+). [package] name = "i386" version = "0.1.0" @@ -11,5 +11,4 @@ kind = "bin" main = "src/main.cpp" [target.i686-openkal] -platform = { path = "../.." } -toolchain = "llvm@23.1.3" +platform = { path = "../.." } diff --git a/mcpp.toml b/mcpp.toml index 6347978..1b1bbc5 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -23,14 +23,16 @@ repo = "https://github.com/mcpplibs/openkal-platform" # capability with a default per system (`[defaults]`). # 2026.11.13.1: the UEFI row (the PE rows' C environment by the container, a # provider's link and runner over `base = "none"', a row's link emulation -# without its machine), and `--toolchain' opts the planned i686 row in. -mcpp = ">=2026.11.13.1" +# without its machine). 2026.11.14.1: a planned row is served by the platform +# chosen for it when the platform lists the row with a toolchain, so the i686 +# rows below need no toolchain named by the project. +mcpp = ">=2026.11.14.1" [platform] # `i686-openkal` (0.28.0): the image of the thirty-two bit class, i386 (openkal # 0.25.1, clauses 5.5 and 12.2; openkal-image 0.6.3 reads, checks and loads it). -# mcpp names the row `planned' until its pin of this platform serves it: a -# project selects it with this platform and `--toolchain llvm@23.1.3`. +# mcpp registers the row `planned'; this list, with `toolchain', serves it +# (mcpp 2026.11.14.1), and `--target openkal' builds every leg. targets = ["x86_64-openkal", "aarch64-openkal", "i686-openkal"] toolchain = "llvm@23.1.3" # The loader runs an image of its own architecture on Linux, macOS and Windows; From 9af7b9de884aeb8c16f18928b9084eb143fcfccd Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Sun, 15 Nov 2026 04:40:29 +0900 Subject: [PATCH 11/11] 0.28.0: the group on openkal 0.25.3 and openkal-macos 0.23.3 --- README.md | 9 +++++---- mcpp.toml | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7e2ab9a..033fd77 100644 --- a/README.md +++ b/README.md @@ -123,10 +123,11 @@ arrangement (openkal 0.25.1, clause 5.5): openkal-musl 0.29.5 over openkal-linux 0.26.3's i386 system-call layer, with openkal-llvm-runtime 0.20.2 above it. A Linux x86_64 machine runs its programs itself; CI builds and runs a hosted program there and the specification's conformance suite through the platform. -The group follows openkal 0.25.1, and its implementations declare the -specification by its minor version (openkal-macos 0.23.2, openkal-windows 0.21.2, -openkal-freebsd 0.1.2; openkal-image 0.6.2), so a project that names openkal -0.25.1 resolves with them. +The group follows openkal 0.25.3, whose conformance suite keeps the surface under +a link that discards what nothing reaches, and its implementations declare the +specification by its minor version (openkal-macos 0.23.3, openkal-windows 0.21.2, +openkal-freebsd 0.1.2; openkal-image 0.6.2), so a project that names any patch of +openkal 0.25 resolves with them. Platform 0.28.0 also serves the ok image of the thirty-two bit class, `i686-openkal` (openkal 0.25.1, clauses 5.5 and 12.2; openkal-image 0.6.3 reads, diff --git a/mcpp.toml b/mcpp.toml index 1b1bbc5..a54615d 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -331,10 +331,11 @@ runner = { cmd = ["dirun", "--payload", "{}", "--profile", "{pkg:dosbox-staging} # openkal-llvm-runtime 0.20.1 on FreeBSD; 0.27.1, the implementations retire a # handle before closing it (openkal-linux 0.26.1, openkal-macos 0.23.1, # openkal-windows 0.21.1) and openkal-musl 0.29.4 delivers what a readiness -# enquiry held with the rest; 0.28.0, openkal 0.25.1 and i386: openkal-linux +# enquiry held with the rest; 0.28.0, openkal 0.25.3 (its suite keeps the surface +# under a discarding link and is an mtest project of its own) and i386: openkal-linux # 0.26.3, openkal-musl 0.29.5 and openkal-llvm-runtime 0.20.2 for `i686-linux-musl`, # and the implementations by the specification's minor version (openkal-macos -# 0.23.2, openkal-windows 0.21.2, openkal-freebsd 0.1.2, openkal-image 0.6.2), and +# 0.23.3, which supplies its libSystem stub only to a link without an SDK, openkal-windows 0.21.2, openkal-freebsd 0.1.2, openkal-image 0.6.2), and # UEFI: openkal-uefi 0.10.0 beneath openkal-musl 0.29.6 and openkal-llvm-runtime # 0.20.3, which take the optional interfaces from the implementation (or, in an # image, at run time) and serve the PE rows by their container, and openkal-image @@ -345,9 +346,9 @@ runner = { cmd = ["dirun", "--payload", "{}", "--profile", "{pkg:dosbox-staging} # release and a patch of this group, released together through one index change # (tools/family_release.py, .github/workflows/family-release.yml). [platform.versions] -openkal = "0.25.1" +openkal = "0.25.3" openkal-linux = "0.26.3" -openkal-macos = "0.23.2" +openkal-macos = "0.23.3" openkal-windows = "0.21.2" openkal-freebsd = "0.1.2" openkal-uefi = "0.10.0"