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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .github/actions/mtest/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: mtest
description: >
The mtest engine the conformance suite reports to: the release .github/versions.env pins (MTEST_VERSION), an
xlings package (xim:mtest) that the index verifies, else the release bundle checked against MTEST_SHA256;
MTEST names its launcher. A job that has no xlings yet gets the pinned one first (XLINGS_VERSION).
runs:
using: composite
steps:
- name: xlings, where the job has none
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
command -v xlings > /dev/null 2>&1 && exit 0
curl -fsSL --retry 3 --retry-all-errors --retry-delay 2 \
https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
- name: xlings, where the job has none (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
if (Get-Command xlings -ErrorAction SilentlyContinue) { exit 0 }
irm https://d2learn.org/xlings-install.ps1.txt | iex
"$env:USERPROFILE\.xlings\subos\current\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
. .github/versions.env # MTEST_VERSION, MTEST_SHA256: no workflow states the pin
# xlings by the configured mirror (GLOBAL), then by CN (GitCode first), each with a refreshed index
# (a cached index can predate the release, and xlings keeps it when an anonymous refresh fails); else
# the release bundle itself, checked against MTEST_SHA256: the web address, then the API's, which
# answered 200 while the web one answered 504 (GitHub's 2026-11-09 incident).
launcher=""
for mirror in GLOBAL CN; do
xlings config --mirror "$mirror" > /dev/null 2>&1 || true
xlings update > /dev/null 2>&1 || true
if xlings install "mtest@$MTEST_VERSION" -y -g; then launcher=$(command -v mtest); break; fi
done
# The package's own launcher, not the xvm shim: on Windows the shim runs the package's alias through
# cmd, which reads `&` in an argument (`--tag "on:win32-x64&release"`) as a second command.
exe=''; [ "$RUNNER_OS" != Windows ] || exe='.exe'
own="${XLINGS_HOME:-$HOME/.xlings}/data/xpkgs/xim-x-mtest/$MTEST_VERSION/bin/mtest$exe"
if [ -n "$launcher" ] && [ -f "$own" ]; then launcher="$own"; fi
xlings config --mirror GLOBAL > /dev/null 2>&1 || true
if [ -z "$launcher" ]; then
echo "::warning::xlings could not install mtest $MTEST_VERSION; taking the release itself"
archive="mtest-$MTEST_VERSION-openkal-bundle-all.tar.gz"
temp="$RUNNER_TEMP"; python=python3
if [ "$RUNNER_OS" = Windows ]; then temp=$(cygpath -u "$RUNNER_TEMP"); python=python; fi
if ! curl -fsSL --retry 5 --retry-all-errors --retry-delay 5 -o "$temp/$archive" \
"https://github.com/mcpp-community/mtest/releases/download/v$MTEST_VERSION/$archive"; then
id=$(curl -fsSL --retry 3 --retry-all-errors -H "Authorization: Bearer $GH_TOKEN" \
"https://api.github.com/repos/mcpp-community/mtest/releases/tags/v$MTEST_VERSION" \
| "$python" -c 'import json,sys; print(next(str(a["id"]) for a in json.load(sys.stdin)["assets"] if a["name"] == sys.argv[1]))' "$archive")
curl -fsSL --retry 5 --retry-all-errors --retry-delay 5 -H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/octet-stream" -o "$temp/$archive" \
"https://api.github.com/repos/mcpp-community/mtest/releases/assets/$id"
fi
actual=$("$python" -c "import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],'rb').read()).hexdigest())" "$temp/$archive")
[ "$actual" = "$MTEST_SHA256" ] || { echo "::error::$archive: sha256 $actual, the workflow pins $MTEST_SHA256"; exit 1; }
mkdir -p "$temp/mtest" && tar xzf "$temp/$archive" -C "$temp/mtest"
launcher="$temp/mtest/mtest-$MTEST_VERSION-openkal-bundle-all/bin/mtest"
[ "$RUNNER_OS" = Windows ] && launcher="$launcher.exe"
fi
"$launcher" --version
"$launcher" --version | grep -qF "$MTEST_VERSION" || { echo "::error::the mtest at $launcher is not $MTEST_VERSION"; exit 1; }
echo "MTEST=$launcher" >> "$GITHUB_ENV"
47 changes: 47 additions & 0 deletions .github/actions/test-report/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: test-report
description: >
The runs `mcpp test` kept in the mtest store's form: taken into one store of
the job, written as one Markdown report of this workflow run's runs into the
job's summary, and kept as an artifact for the report over every job of the
workflow run (ci.yml `report`).
inputs:
name:
description: the artifact's name, unique in the workflow run
required: true
stores:
description: the stores `mcpp test` kept in this job, relative to the workspace, separated by spaces
required: false
default: tests/target/mtest
runs:
using: composite
steps:
- uses: ./.github/actions/mtest
- shell: bash
env:
STORES: ${{ inputs.stores }}
run: |
set -euo pipefail
# The POSIX spelling of the runner's directories for this shell; the
# artifact's path below is the runner's own.
temp="$(cygpath -u "$RUNNER_TEMP" 2> /dev/null || printf '%s' "$RUNNER_TEMP")"
workspace="$(cygpath -u "$GITHUB_WORKSPACE" 2> /dev/null || printf '%s' "$GITHUB_WORKSPACE")"
job="$temp/mtest-job"
mkdir -p "$job"
taken=0
for store in $STORES; do
[ -f "$workspace/$store/index.ndjson" ] || continue
(cd "$job" && "$MTEST" store import --from "$workspace/$store")
taken=1
done
if [ "$taken" = 0 ]; then echo "mcpp test kept no run here"; exit 0; fi
(cd "$job" && "$MTEST" report --format md --group "$GITHUB_RUN_ID") >> "$GITHUB_STEP_SUMMARY" \
|| echo "::warning::no run of this workflow run in the store"
echo "MTEST_JOB_STORE=$RUNNER_TEMP/mtest-job/.mtest" >> "$GITHUB_ENV"
- uses: actions/upload-artifact@v4
if: env.MTEST_JOB_STORE != ''
with:
name: ${{ inputs.name }}
path: ${{ env.MTEST_JOB_STORE }}
include-hidden-files: true
if-no-files-found: ignore
retention-days: 7
5 changes: 5 additions & 0 deletions .github/versions.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# The engines CI pins, read by the composite actions (.github/actions/mtest).
# mtest: an xlings package (xim:mtest) whose sha256 the index states; the release
# bundle's sha256 checks the fallback download.
MTEST_VERSION=0.5.2
MTEST_SHA256=be443f8c546b3f4628dcd3f1eb6f45b4d698a7f805232f966349faf8250863c6
75 changes: 73 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ env:
# Windows program built here links no Win32 library mimalloc's own layer names.
# The image matrix uses the corrected platform group selected by this engine.
# MCPP_SOURCE_REF supplies its candidate until the release is installable.
MCPP_VERSION: 2026.11.5.1
# 0.20.0: 2026.11.9.1, for the tests on the mtest library (a test file of
# mtest's objects has no `main' from 2026.11.8.1, and `mcpp test' keeps its
# runs in mtest's store from 2026.11.9.1).
MCPP_VERSION: 2026.11.9.1
XLINGS_VERSION: v2026.10.26.1
# okrun is built from openkal-image, whose openkal-run states its own floor.
OKRUN_MCPP_VERSION: 2026.11.9.1
XLINGS_NON_INTERACTIVE: '1'

jobs:
Expand Down Expand Up @@ -131,6 +136,23 @@ jobs:
cd examples/import-std && mcpp run 2>&1 | tee out.log
grep -q 'import std above openkal: 2 4 7' out.log

# THE RUNTIME'S TESTS, ON THE mtest LIBRARY (tests/): examples/cxx's
# observations as one case, a second name for a file through
# std::filesystem, and a program found by the system's conventions. A
# package beside the runtime, as the examples are; `mcpp test' keeps the
# run in mtest's store (tests/target/mtest).
- name: The runtime's tests
run: |
set -euo pipefail
cd tests && mcpp test 2>&1 | tee tests.log
grep -q 'test result ok' tests.log

# The runs `mcpp test` kept, reported and kept for the report job.
- uses: ./.github/actions/test-report
if: always()
with:
name: mtest-${{ github.job }}-${{ strategy.job-index }}

# WHAT A FRONT END DOES WITH THE RUNTIME, TIMED AGAINST THE SYSTEM'S OWN
# (0.17.0; the design's L2). bench/ built above this runtime, and with
# this machine's C++ library by the same compiler family, Clang: the
Expand Down Expand Up @@ -648,6 +670,51 @@ jobs:
grep -q 'unwound: true' out.log
grep -q 'import std over openkal: ok' out.log

# THE RUNTIME'S TESTS ON THIS HOST (tests/, on the mtest library). On
# Windows this is where a program named without a separator is looked
# for by that system's conventions: `hostname' through a semicolon
# PATH and PATHEXT (openkal-musl 0.29.0).
- name: The runtime's tests on this host
run: |
set -euo pipefail
cd tests && rm -rf target
mcpp test --target '${{ matrix.native }}' 2>&1 | tee tests.log
grep -q 'test result ok' tests.log

# The runs `mcpp test` kept, reported and kept for the report job.
- uses: ./.github/actions/test-report
if: always()
with:
name: mtest-${{ github.job }}-${{ strategy.job-index }}

# EVERY JOB'S RUNS AS ONE REPORT (`mtest ci report`, the workflow run's group).
report:
name: tests (report)
needs: [runtime, host-dimension]
if: always()
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/mtest
- uses: actions/download-artifact@v4
with:
pattern: mtest-*
path: ${{ runner.temp }}/stores
- name: Every job's runs, reported together
shell: bash
run: |
set -euo pipefail
found=0
for store in "$RUNNER_TEMP"/stores/*/; do
[ -f "$store/index.ndjson" ] || continue
"$MTEST" store import --from "$store"
found=1
done
if [ "$found" = 0 ]; then echo "no job kept a run" >> "$GITHUB_STEP_SUMMARY"; exit 0; fi
"$MTEST" ci report --group "$GITHUB_RUN_ID" --out "$RUNNER_TEMP/tests.md"
cat "$RUNNER_TEMP/tests.md" >> "$GITHUB_STEP_SUMMARY"

# ── AN OK IMAGE (`<arch>-openkal`, openkal SPEC clause 12) ─────────────────
#
# libc++, libc++abi, libunwind and the builtins inside an image, above
Expand Down Expand Up @@ -743,7 +810,11 @@ jobs:
"$env:USERPROFILE\.xlings\subos\current\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: okrun, built here
run: |
xlings install mcpp -y -g
# PINNED, AND TO THE FLOOR openkal-run STATES. Unpinned, this step
# took whatever the runner's index offered (2026.10.24.1), and
# openkal-run, which states mcpp >= 2026.11.9.1, refused it.
xlings update
xlings install "mcpp@$OKRUN_MCPP_VERSION" -y -g
mcpp self config --mirror GLOBAL
mcpp toolchain install llvm 23.1.3
mcpp toolchain default llvm@23.1.3
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ C library.

```toml
[dependencies]
openkal-llvm-runtime = "0.19.2"
openkal-llvm-runtime = "0.20.0"
```

> **Engine floor (mcpp 2026.11.2.1):** 0.17.0 is built over openkal-musl 0.26.0,
Expand Down Expand Up @@ -328,6 +328,16 @@ openkal-musl 0.27.3 selects openkal-linux 0.24.1 on Linux and openkal-ld 0.4.3
for an image. Linux confinement requires Landlock ABI 3 to enforce read-only
grants against raw file truncation. The runtime implementation is unchanged.

## OpenKal 0.25 dependency group

Runtime 0.20.0 is built over openkal-musl `^0.29.0` and the OpenKal 0.25
implementations beneath it (Linux 0.26, macOS 0.23, Windows 0.21, OpenSBI 0.9).
The C++ runtime surface and the allocator selection are unchanged. Through the C
library, `std::filesystem::create_hard_link` gives a file a second name
(`link`, over `kal_fs_hard_link`), and a program named without a separator is
looked for by the system's conventions: on Windows PATH is split on `;` and the
`PATHEXT` suffixes are tried.

## OpenKal 0.24 dependency group

Runtime 0.19.2 keeps the volume where a name is rebuilt part by part. `X:` is a
Expand Down
6 changes: 3 additions & 3 deletions mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
namespace = "mcpplibs"
name = "openkal-llvm-runtime"
version = "0.19.2"
version = "0.20.0"
description = "LLVM's C++ runtime libraries — libc++, libc++abi and libunwind — configured for openkal-musl rather than for a host C library."
license = "Apache-2.0"
authors = ["mcpplibs"]
Expand Down Expand Up @@ -230,10 +230,10 @@ cflags = ["-DDISABLE_AARCH64_FMV=1"]
# (measured on OpenSBI: every request for an arena refused, ENOMEM). A
# target's edge replaces a general one, so each states every feature.
[target.'cfg(not(os = "none"))'.dependencies]
openkal-musl = { version = "^0.28.0", default-features = false, features = ["posix", "malloc-mimalloc"] }
openkal-musl = { version = "^0.29.0", default-features = false, features = ["posix", "malloc-mimalloc"] }

[target.'cfg(os = "none")'.dependencies]
openkal-musl = { version = "^0.28.0", default-features = false, features = ["posix", "malloc-mallocng"] }
openkal-musl = { version = "^0.29.0", default-features = false, features = ["posix", "malloc-mallocng"] }

[build]

Expand Down
Loading
Loading