Building & running
Building
cosmos build wraps the .NET build + NativeAOT compile + image packaging. The project is in Medli3/, so build it with -p Medli3 (or cd Medli3 first):
cosmos build -p Medli3 # host architecture (auto-detected)
cosmos build -p Medli3 -a x64 # x86-64
cosmos build -p Medli3 -a arm64 # ARM64
Output: Medli3/output-<arch>/Medli3.iso.
The kernel targets net10.0 and references the Cosmos gen3 packages (see Medli3/Medli3.csproj):
<Project Sdk="Cosmos.Sdk/3.0.58">
<PackageReference Include="Cosmos.Kernel" Version="3.0.58" />
<PackageReference Include="Cosmos.Kernel.System" Version="3.0.58" />
Build info
A GenerateBuildInfo MSBuild target writes obj/.../BuildInfo.g.cs each build with BuildYear, BuildNumber, and CosmosVersion (the Cosmos package version actually resolved, read from project.assets.json). These surface in the boot banner and the version command, and keep the copyright year current automatically.
Running
run.sh (recommended)
./run.sh [x64|arm64] # builds the arch then boots it in QEMU
Aliases: amd64/x86_64 → x64, aarch64 → arm64. Environment knobs:
| Var | Default | Effect |
|---|---|---|
MEM | 512 | guest RAM in MB |
HEADLESS | 0 | 1 = serial only, no display window |
DISPLAY_BACKEND | cocoa | QEMU display (cocoa/sdl) |
INPUT | mmio | ARM64 input transport: mmio or pci (see below) |
run.sh deliberately mirrors cosmos run’s QEMU invocation minus -no-shutdown, so when the kernel calls Power.Shutdown() (ACPI S5) QEMU actually exits and the window closes. cosmos run keeps -no-shutdown (it leaves the window open to preserve final serial output), so the window won’t close on shutdown.
x86-64
Boots on QEMU’s q35 machine with -vga std. A PS/2 keyboard is present by default, so input “just works”.
ARM64
Boots on QEMU’s virt machine with UEFI (edk2 AAVMF) and a ramfb framebuffer. Two ARM-specific gotchas, both handled by run.sh:
- No PS/2. Input must come from a virtio-input device, and Cosmos’ ARM64 HAL only probes the virtio-MMIO transport — so
run.shattaches-device virtio-keyboard-device/virtio-mouse-device(the MMIO variants). The PCIe variants (INPUT=pci) are detected byPciManagerbut never bound, so you’d getkeyboards=0. Input comes from the GUI window, not the serial terminal. - Resolution is firmware-locked at 800×600. The AAVMF
ramfbGOP only advertises that mode, so a Limineresolution:directive is ignored. See Known issues.
Building against a from-source Cosmos devkit
To test against your own build of the Cosmos gen3 framework (e.g. to try an upstream fix), build the framework and point Medli3 at it:
git clone --recurse-submodules https://github.com/valentinbreiz/nativeaot-patcher
cd nativeaot-patcher
./.devcontainer/postCreateCommand.sh # packs all Cosmos.* to artifacts/, installs tools
Local dev builds are versioned 3.0.58.<yyyyMMdd>, not plain 3.0.58. Because Medli3.csproj pins exact 3.0.58, it keeps using the released packages until you bump it. To consume the source build, set the SDK + package versions to the dated version (a global.json with msbuild-sdks.Cosmos.Sdk plus matching PackageReferences) — they must all move together or NuGet errors with NU1605. The version command / boot banner’s “Built against Cosmos v…” line tells you which packages a given image actually used.
Submodules matter: the native ACPI library LAI is a git submodule. If you clone without
--recurse-submodules(or forgetgit submodule update --init --recursive), the source build links withundefined symbol: lai_*.