Skip to content

deps: follow openkal 0.7.0 #14

deps: follow openkal 0.7.0

deps: follow openkal 0.7.0 #14

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
jobs:
build:
name: boots under OVMF as BOOTX64.EFI
runs-on: ubuntu-24.04
timeout-minutes: 40
env:
MCPP_VERSION: 2026.8.20.2
XLINGS_VERSION: v2026.8.17.2
XLINGS_NON_INTERACTIVE: '1'
steps:
- uses: actions/checkout@v4
- name: Install xlings
run: |
curl -fsSL 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: Install mcpp
run: |
# ⚠️ A LOOP, BECAUSE ONE `xlings update` CAN RETURN A STALE INDEX
# WITHOUT SAYING SO.
#
# The index is published as an artifact behind a pointer, and that
# pointer propagates asynchronously after a version bump is merged.
# Measured on release day: an update run four minutes after the merge
# printed `index updated`, and the install then failed with
#
# package 'mcpp@<ver>' not found in the synced index
# (xim@artifact:<an older sha>, ...), synced 0 seconds ago
#
# Nothing had gone wrong. The update fetched the PREVIOUS artifact,
# and "synced 0 seconds ago" describes when it was fetched rather than
# what it contains — which is why the message reads as freshness.
#
# So this is not a retry around flakiness; it is the wait that a
# single update does not perform. A pin naming a version that was
# never published still fails, after the last attempt, and says which
# of the two situations it is.
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
if [ "$attempt" = 6 ]; then
echo "::error::mcpp@$MCPP_VERSION never appeared in the index (6 attempts over 5 minutes). If it was just released, the pointer has not propagated; if the pin names a version that was never published, it never will."
exit 1
fi
echo "the index has not caught up yet (attempt $attempt of 6); waiting 60s"
sleep 60
done
mcpp --version
mcpp self config --mirror GLOBAL
- name: Install OVMF and qemu
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends ovmf qemu-system-x86
- name: The example is a real EFI application
run: |
set -euo pipefail
cd examples/hello
mcpp build
EXE=$(find target -name "hello.exe" | head -1)
# ⚠️ THE TOOLCHAIN THAT BUILT THE IMAGE, NOT LLVM.
#
# This target resolves to mingw-cross-gcc, so on a machine that has
# never built anything else there is no LLVM to borrow `llvm-readobj`
# from — the previous version of this step globbed for one and died on
# `ls: cannot access .../xim-x-llvm/*/bin/llvm-readobj`, AFTER the
# build had succeeded. The verification tool has to come from the same
# place as the compiler, or the check is only available on machines
# that happen to have another one.
OD=$(ls -d "$HOME"/.mcpp/registry/data/xpkgs/xim-x-mingw-cross-gcc/*/bin/x86_64-w64-mingw32-objdump | head -1)
test -x "$OD"
# ⚠️ Subsystem 10 is what makes firmware load it. A Windows console
# subsystem would build, link, and never be executed by UEFI.
# Measured spelling from this objdump: `Subsystem 0000000a (EFI application)`.
"$OD" -p "$EXE" | grep -qE 'Subsystem[[:space:]]+0000000a'
# And no import table: a DLL dependency cannot be satisfied by firmware.
if "$OD" -p "$EXE" | grep -qi "DLL Name"; then
"$OD" -p "$EXE" | grep -i -A2 "DLL Name"; echo "unexpected DLL import"; exit 1
fi
- name: It boots under OVMF and prints
run: |
set -euo pipefail
cd examples/hello
EXE=$(find target -name "hello.exe" | head -1)
mkdir -p esp/EFI/BOOT && cp "$EXE" esp/EFI/BOOT/BOOTX64.EFI
cp /usr/share/OVMF/OVMF_VARS_4M.fd vars.fd
timeout 90 qemu-system-x86_64 -machine q35 -m 256 -display none \
-serial file:uefi.log \
-drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \
-drive if=pflash,format=raw,file=vars.fd \
-drive format=raw,file=fat:rw:esp -net none || true
cat uefi.log | tr -d "\\000" | head -40
grep -q "hello from openkal over UEFI" uefi.log
grep -q "pool ok" uefi.log
# ---------------------------------------------------------------------------
# The cross-compilation is performed FROM three systems, not only from Linux.
#
# Every target in this repository is a cross target, which makes the host a
# separate axis from the target: the compiler, the target C library and the
# emulator are payloads mcpp resolves for whichever system it is running on.
# A package that has only ever been built from Linux is a package whose
# consumers must use Linux, and nothing in these sources says so.
#
# ⚠️ A TOOLCHAIN AXIS IS ABSENT HERE, AND THAT IS MEASURED RATHER THAN
# ASSUMED. The row for a bare-metal triple names its compiler, and the
# command-line override does not displace it: `--toolchain gcc@16.1.0` on a
# `riscv64-none-elf` build resolves llvm@22.1.8 regardless. A matrix over
# compiler families would therefore run the same compiler on every row and
# report coverage it does not have. The toolchain axis belongs where the
# choice is real — openkal, whose declarations are compiled by three families
# on three systems.
#
# ⚠️ BUILD ONLY, AND DELIBERATELY. Behaviour is asserted once, above, under an
# emulator. Booting the same image from three systems would be a statement
# about the emulator rather than about this package, and "the image does what
# the README says" does not become more true for having been observed from
# macOS.
portability:
name: cross-builds from ${{ matrix.os }}
runs-on: ${{ matrix.os }}
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
os: [macos-14, windows-2022]
defaults:
run:
shell: bash
env:
MCPP_VERSION: 2026.8.20.2
XLINGS_VERSION: v2026.8.17.2
XLINGS_NON_INTERACTIVE: '1'
steps:
- uses: actions/checkout@v4
- name: Install xlings (Unix)
if: runner.os != 'Windows'
run: |
curl -fsSL 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: Install xlings (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
irm https://d2learn.org/xlings-install.ps1.txt | iex
# The installer amends the user's environment; no later step in this
# job reads it back, so the directory is named here.
"$env:USERPROFILE\.xlings\subos\current\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Install mcpp
run: |
# ⚠️ A LOOP, BECAUSE ONE `xlings update` CAN RETURN A STALE INDEX
# WITHOUT SAYING SO.
#
# The index is published as an artifact behind a pointer, and that
# pointer propagates asynchronously after a version bump is merged.
# Measured on release day: an update run four minutes after the merge
# printed `index updated`, and the install then failed with
#
# package 'mcpp@<ver>' not found in the synced index
# (xim@artifact:<an older sha>, ...), synced 0 seconds ago
#
# Nothing had gone wrong. The update fetched the PREVIOUS artifact,
# and "synced 0 seconds ago" describes when it was fetched rather than
# what it contains — which is why the message reads as freshness.
#
# So this is not a retry around flakiness; it is the wait that a
# single update does not perform. A pin naming a version that was
# never published still fails, after the last attempt, and says which
# of the two situations it is.
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
if [ "$attempt" = 6 ]; then
echo "::error::mcpp@$MCPP_VERSION never appeared in the index (6 attempts over 5 minutes). If it was just released, the pointer has not propagated; if the pin names a version that was never published, it never will."
exit 1
fi
echo "the index has not caught up yet (attempt $attempt of 6); waiting 60s"
sleep 60
done
mcpp --version
mcpp self config --mirror GLOBAL
- name: The EFI application cross-builds
run: |
# ⚠️ TWICE, AND THE FIRST IS ALLOWED TO FAIL — every row of this
# matrix is a machine that has never targeted this triple, which is
# precisely where mcpp's lazy install of the target C library shows.
# The first build compiles sources needing its headers before they
# exist; the second has them. A single build here reported a
# portability failure that was really a cold-machine one.
mcpp build || true
mcpp build