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
124 changes: 110 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ name: CI
#
# tests every module behaves as stated, on every system and with every
# compiler family a consumer builds it with (the native rows)
# hosted the same tests, the program's C library and C++ run-time being
# openkal-musl and openkal-llvm-runtime on the system's own triple
# (checks/hosted; mcpp docs/24)
# platform a platform module used outside `if constexpr' for its platform
# fails to LINK, and the same use in a discarded branch links (R5)
#
# The library is built with the released mcpp, 2026.10.26.2 or later: the
# first that compiles a unit with a module map importing another package's
# module through a third under GCC (`mcpplibs.os.terminal' through
# `mcpplibs.os.error', mcpp part 2 design §10.2) and builds the ok images.
# The library is built with the released mcpp, 2026.10.27.1 or later: the
# first that selects a platform (SPEC-013), which the ok images and
# checks/hosted take their C library and C++ run-time from (openkal-platform
# 0.17.3), after 2026.10.26.2 compiled a unit with a module map importing
# another package's module through a third under GCC.
# A dispatch may name a branch of mcpp instead (`mcpp_ref'), which is then
# built and used.

Expand All @@ -27,7 +31,7 @@ on:

env:
MCPP_SOURCE_REF: ${{ github.event.inputs.mcpp_ref || vars.MCPP_SOURCE_REF || '' }}
MCPP_VERSION: 2026.10.26.2
MCPP_VERSION: 2026.10.27.1
XLINGS_VERSION: v2026.10.26.1
XLINGS_NON_INTERACTIVE: '1'

Expand Down Expand Up @@ -119,6 +123,88 @@ jobs:
grep -Eiq "undefined|unresolved" misuse.log || { cat misuse.log; echo "::error::the misuse failed for another reason than an undefined name"; exit 1; }
echo " ok the misuse fails at the link, naming what is undefined"

# ── THE TESTS OVER A C LIBRARY ON OPENKAL ──────────────────────────────────
#
# The C library presents POSIX and openkal rather than the system: its headers
# are not the SDK's, on Windows its data model is LP64 and its `wchar_t' 32
# bits, and its descriptors and signals are its own. The units beside openkal
# reach each system through the system's own interface, and these rows are
# where that is asserted.
hosted:
name: hosted ${{ matrix.os }} ${{ matrix.profile }}
runs-on: ${{ matrix.os }}
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
# The system's own triple; on macOS and Windows named, as a program in
# this arrangement names it: a Windows host defaults to the MSVC target,
# and openkal's Windows implementation is reached through the GNU one.
include:
- { os: ubuntu-24.04, target: '', profile: dev }
- { os: ubuntu-24.04, target: '', profile: release }
- { os: ubuntu-24.04-arm, target: '', profile: dev }
- { os: macos-15, target: '--target aarch64-macos', profile: dev }
- { os: windows-2022, target: '--target x86_64-windows-gnu', profile: dev }
- { os: windows-2022, target: '--target x86_64-windows-gnu', profile: release }
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4

- name: Install xlings and mcpp (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 and mcpp (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
irm https://d2learn.org/xlings-install.ps1.txt | iex
"$env:USERPROFILE\.xlings\subos\current\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- name: The mcpp under cross-validation
run: |
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
if [ -n "${MCPP_SOURCE_REF:-}" ]; then
src="$RUNNER_TEMP/mcpp-src"
git clone --quiet --depth 1 --branch "$MCPP_SOURCE_REF" https://github.com/mcpp-community/mcpp.git "$src"
rm -f "$src/.xlings.json"
( cd "$src" && mcpp build --release )
built=$(find "$src/target" -type f \( -name mcpp -o -name mcpp.exe \) | head -1)
[ -n "$built" ] || { echo "::error::mcpp did not build from $MCPP_SOURCE_REF"; exit 1; }
echo "$(cd "$(dirname "$built")" && pwd)" >> "$GITHUB_PATH"
echo "under review: $("$built" --version) (from $MCPP_SOURCE_REF)"
fi
mcpp toolchain install llvm 23.1.3

- name: Every test of the package has its counterpart here
run: |
for t in tests/*_test.cpp; do
n=$(basename "$t")
[ -f "checks/hosted/tests/$n" ] || { echo "::error::checks/hosted/tests has no $n"; exit 1; }
done

- name: Tests
working-directory: checks/hosted
run: |
profile='${{ matrix.profile }}'
mcpp test --profile "$profile" ${{ matrix.target }} 2>&1 | tee tests.log
for name in platform_test fs_test process_test ipc_test dirs_terminal_test linux_test library_test; do
grep -q "^$name \.\.\. ok" tests.log || { echo "::error::$name did not run or did not pass"; exit 1; }
done

# ── THE TESTS AS OK IMAGES (`<arch>-openkal`, openkal SPEC clause 12) ──────
#
# The same five suites, built once on Linux for both architectures and run
Expand Down Expand Up @@ -206,15 +292,25 @@ jobs:
run: |
xlings install "mcpp@$MCPP_VERSION" -y -g
mcpp self config --mirror GLOBAL
mcpp toolchain install llvm 23.1.3
mcpp toolchain default [email protected]
# The okrun of the openkal-tools version this package's manifest names.
tools=$(sed -n 's/^openkal-tools = { version = "\([^"]*\)".*/\1/p' mcpp.toml)
[ -n "$tools" ] || { echo "::error::mcpp.toml names no openkal-tools version"; exit 1; }
git clone --quiet --depth 1 --branch "$tools" https://github.com/mcpplibs/openkal-image.git "$RUNNER_TEMP/oi"
( cd "$RUNNER_TEMP/oi/tools" && mcpp build --release )
okrun=$(find "$RUNNER_TEMP/oi/target" -path '*bin*' \( -name okrun -o -name okrun.exe \) -type f | head -1)
[ -n "$okrun" ] || { echo "::error::okrun did not build"; exit 1; }
if [ -n "${MCPP_SOURCE_REF:-}" ]; then
src="$RUNNER_TEMP/mcpp-src"
git clone --quiet --depth 1 --branch "$MCPP_SOURCE_REF" https://github.com/mcpp-community/mcpp.git "$src"
rm -f "$src/.xlings.json"
( cd "$src" && mcpp build --release )
built=$(find "$src/target" -type f \( -name mcpp -o -name mcpp.exe \) -path '*/bin/*' | head -1)
[ -n "$built" ] || { echo "::error::mcpp did not build"; exit 1; }
PATH="$(cd "$(dirname "$built")" && pwd):$PATH"
echo "$(cd "$(dirname "$built")" && pwd)" >> "$GITHUB_PATH"
fi
# The platform's runner, as this machine's configuration of the
# target names it: the platform's toolchain installed, its tools
# built (mcpp SPEC-013 §13).
t='${{ matrix.arch }}-openkal'
cd "$RUNNER_TEMP" # outside the sparse checkout: the configuration of no project
mcpp toolchain install --target "$t"
py=python3; command -v python3 > /dev/null 2>&1 && python3 -c '' 2>/dev/null || py=python
okrun=$(mcpp self env --target "$t" --format json | $py -c 'import json,sys; print(json.load(sys.stdin)["data"]["runner"]["program"] or "")')
[ -n "$okrun" ] || { echo "::error::the platform's runner was not located"; exit 1; }
echo "OKRUN=$okrun" >> "$GITHUB_ENV"
- name: The same bytes, every suite
run: |
Expand Down
96 changes: 96 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Changelog

## 0.2.1

- **The ok-image targets take their C library, C++ run-time and loader from
their platform.** `[target.'cfg(os = "openkal")']` no longer declares
openkal-llvm-runtime or openkal-tools: mcpp 2026.10.27.1 selects
openkal-platform for `<arch>-openkal` (mcpp SPEC-013). CI finds the runner
through `mcpp toolchain install --target` and `mcpp self env --target`.

The package builds and its tests pass in every arrangement of the program's C
library on Linux, macOS and Windows: the system's own (glibc, libSystem, the
Microsoft C runtime), and a C library that sits on openkal (openkal-musl with
openkal-llvm-runtime, mcpp docs/24) on the system's own triple. Under the
second, a C library presents POSIX and openkal, not the system: its headers are
not the SDK's, on Windows its data model is LP64 and its `wchar_t` 32 bits, and
its descriptors, signals, `uname`, `sysinfo` and `syscall` are its own.

- **The units beside openkal reach each system through that system's stable
interface, not through the C library.**
- **Linux:** the kernel's calls, one trap per architecture
(`src/linux/kernel.h`, `src/linux/arch/`). These cover the machine's name
and memory, a volume's kind and an exchange of two entries. In the second
arrangement the C library had answered `openkal` for the machine, had no
`sysinfo`, and turned `renameat2(RENAME_EXCHANGE)` into a plain rename that
replaced the second entry.
- **macOS:** the kernel's calls for a volume's kind and an exchange
(`src/macos/kernel.h`, as openkal-macos itself does), and the libSystem
names no C library defines for sysctl and the host's statistics
(`src/macos/darwin.h`). These are declared rather than included from the
SDK. A link whose libSystem is openkal-macos's stub binds them when the
program is loaded (`-U`).
- **Windows:** `src/windows/win32.h` declares DWORD as 32 bits and WCHAR as
UTF-16 (`char16_t`) under every C environment. Names reach the system as
UTF-8 converted to UTF-16, never through `path::c_str()` (R7). The
kernel32 names that openkal-windows does not itself call are found when
first called, so a toolchain without the system's import libraries links
the package.
- **The process's output and its ending for a closed reader are changed where
the process keeps them.**
- On Linux and macOS, the diversion of the standard output (`output_to_error`),
the reset of SIGPIPE before `exec` and `end_as_output_closed` use the
kernel's descriptors and dispositions (`src/posix/kernel.h`): what openkal's
standard output, the C library's and a started program all use.
- On Windows the diversion moves the Microsoft C runtime's descriptor, as
before (`src/windows/crt/stdio.cpp`). For a C library on openkal it moves
that library's descriptor and the process's standard handle, each apart
(`src/windows/posix/stdio.cpp`). The manifest selects the form by
`cfg(c-abi = "musl")`.
- **`checks/hosted`** builds the package's tests over openkal-musl and
openkal-llvm-runtime. CI runs them on Linux, macOS and Windows, beside the
native rows and the ok images. Locally, the native and hosted suites pass on
Linux x86_64 (gcc 16.1.0 and llvm 23.1.3, dev and release) and on aarch64
under qemu. The Windows and macOS builds are cross-linked from Linux.
- **What mcpp-language-server's operating-system layer carried** (its
`modules/os` and `modules/platform`, removed in its 0.0.18):
- `process::run(options, bounds, input)`: a run with a hard bound, a grace
and a drain, and limits on what each output keeps. It reports a timeout,
an output a descendant held open, and an output it cut.
- `process::threads(id)`: the threads of a program and the processor time of
each (Linux; none elsewhere).
- `env::assignments(entries)`: `NAME=value` entries as the overrides of a
started program's environment.
- `fs::read(file, at_most)`: a bounded read, `errc::too_large` past the
bound (new error condition).
- `fs::canonical(name)`: the name a node is known by, with links followed
and, on Windows, short (8.3) components replaced by their long names.
- Tests: `platform_test` asserts that Linux names the machine as the processor
the program runs on. `fs_test` asserts that a volume's kind is named.
`process_test` makes a file executable with `os::fs::set_executable` rather
than with `std::filesystem::permissions`, which a C library on openkal
refuses. `process_test` covers the bounded run (a cut output, a hard bound,
an output held open), the threads of this program and environment entries;
`fs_test` covers the bounded read and the canonical name.

## 0.2.0

What mcpp's operating-system layer carried: `exec`; both outputs on one pipe;
appending and durability; measured volumes; place and exchange; owners,
processors and available memory; a bounded read of input; output sent to the
error stream; raw mode that keeps the interrupt; Windows facts. Over openkal
0.17.1 (openkal-linux 0.18.2, openkal-macos 0.15.1, openkal-windows 0.13.3); ok
images over openkal-llvm-runtime 0.16.3 and openkal-tools 0.1.1 (#3).

## 0.1.2

Shared libraries at run time (`mcpplibs.os.library`) (#5).

## 0.1.1

Names reach the system as UTF-8 and come back as UTF-8 on every host, never
through the process's code page (R7) (#4).

## 0.1.0

A C++ operating-system library over openkal 0.17 (#1, #2).
42 changes: 34 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ with compile-time platform constants and a few platform modules.

```toml
[dependencies]
os = { namespace = "mcpplibs", version = "0.2.0" }
os = { namespace = "mcpplibs", version = "0.2.1" }
```

```cpp
Expand Down Expand Up @@ -34,15 +34,37 @@ what is not a kernel question: the machine beneath the system (`machine`), the d
loader (`library`: the C library's on Linux and macOS, kernel32's on Windows), and the
platform modules.

## The program's C library

A program over this package chooses its C library. It can be the system's own (glibc,
libSystem, the Microsoft C runtime), or one that sits on openkal on the system's own
triple: openkal-musl with openkal-llvm-runtime (mcpp `docs/24`). The package behaves the
same under either.

Native code beside openkal reaches each system through that system's stable interface,
never through the C library, because a C library on openkal presents POSIX and openkal
rather than the system:

| System | How native code reaches it |
|---|---|
| Linux | the kernel's calls, one trap per architecture (`src/linux/kernel.h`) |
| macOS | the kernel's calls (`src/macos/kernel.h`), and the libSystem names no C library defines (`src/macos/darwin.h`) |
| Windows | kernel32 and advapi32, with DWORD as 32 bits and WCHAR as UTF-16 under every C environment (`src/windows/win32.h`) |

The standard output's diversion and the ending for a closed reader act on the process
itself: the kernel's descriptors and dispositions, or on Windows the process's standard
handles. `checks/hosted` runs the tests under openkal-musl and openkal-llvm-runtime on
every system in CI.

## Modules

| Module | Contents |
|---|---|
| `mcpplibs.os.platform` | `PLATFORM`, `ARCH`, `is_linux` / `is_macos` / `is_windows` / `is_posix`, `exe_suffix`, `path_list_separator`; `host()`, a constant expression on a native target |
| `mcpplibs.os.error` | `errc` (openkal's closed set of conditions), `error`, `result<T>` |
| `mcpplibs.os.env` | variables (names without case on Windows), arguments, the program's own image, lists of directories in the host's separator (`split_list`, `join_list`), PATH search with PATHEXT |
| `mcpplibs.os.fs` | `write_atomic`, `publish` (no replace), `append`, `sync`, `caps`, `lock`, links, `set_executable`, `stamp_of`, `identity_of`, `owner_of`, `writable`, `locate`, `absolute`, `names_a_place`; what a volume does, measured (`measure`, `volume_type`), and the operations that follow it (`place`, `exchange`); names in the host's rules without the file system: `generic`, `native`, `extended`, `is_absolute`, `same`, `within` |
| `mcpplibs.os.process` | `spawn`, `run`, `exec`, a command line joined as it is for the command interpreter (`one_string`), pipes, both outputs on one pipe, output onto this program's error output, units and `end_unit`, bound lifetime, bounded waits and reads; `self`, `describe`, `alive` |
| `mcpplibs.os.env` | variables (names without case on Windows), `NAME=value` entries as overrides (`assignments`), arguments, the program's own image, lists of directories in the host's separator (`split_list`, `join_list`), PATH search with PATHEXT |
| `mcpplibs.os.fs` | `write_atomic`, `publish` (no replace), `append`, `sync`, `caps`, `lock`, links, `set_executable`, `stamp_of`, `identity_of`, `owner_of`, `writable`, `locate`, `absolute`, `names_a_place`, `canonical`, a bounded `read`; what a volume does, measured (`measure`, `volume_type`), and the operations that follow it (`place`, `exchange`); names in the host's rules without the file system: `generic`, `native`, `extended`, `is_absolute`, `same`, `within` |
| `mcpplibs.os.process` | `spawn`, `run` (and with bounds: a hard bound, a grace, a drain, output limits), `exec`, a command line joined as it is for the command interpreter (`one_string`), pipes, both outputs on one pipe, output onto this program's error output, units and `end_unit`, bound lifetime, bounded waits and reads; `self`, `describe`, `alive`, `threads` |
| `mcpplibs.os.interrupt` | `requested`, `wait`, `end_as_requested`, `end_as_output_closed` |
| `mcpplibs.os.stdio` | the three streams as bytes; a bounded read of input; the output sent to the error stream for a while (`output_to_error`) |
| `mcpplibs.os.terminal` | `interactive`, `size`, `sequences`, `color`, `raw_mode` (with or without the interrupting keystroke), `foreground` |
Expand Down Expand Up @@ -77,8 +99,10 @@ platform modules.
nothing else. The tests write, read and rename names in four scripts.

Interface units import `std` and contain no system header and no macro. Implementation units
on openkal import only `openkal.*`. The Windows units declare the functions they call
themselves (`src/windows/win32.h`).
on openkal import only `openkal.*`. The Windows and macOS units declare the functions they
call themselves (`src/windows/win32.h`, `src/macos/darwin.h`). Linux's and macOS's kernel
calls are in `src/linux/arch/` and `src/macos/arch/`, which the manifest selects by
architecture.

## As an ok image

Expand All @@ -95,8 +119,10 @@ name's spelling is the host's as well: `os::fs::absolute()` and
`os::fs::names_a_place()` read `C:\x` and `bin\x` as Windows does when the
image runs there, where the standard library inside an image reads names as
POSIX does. The
image carries its C library and C++ run-time (`openkal-llvm-runtime`); the
tests are built as images in CI and run through okrun on four systems, and
image carries its C library and C++ run-time, which with the loader are the
image's platform's (openkal-platform, selected by mcpp 2026.10.27.1 and later
for `<arch>-openkal`; this package declares none of them); the tests are built
as images in CI and run through okrun on four systems, and
`checks/constants` holds the compile-time facts of a native target.

## License
Expand Down
Loading
Loading