Skip to content

build: add Windows build support via zig cc and GNU objcopy - #6

Open
coff33ninja wants to merge 2 commits into
robiot:mainfrom
coff33ninja:main
Open

build: add Windows build support via zig cc and GNU objcopy#6
coff33ninja wants to merge 2 commits into
robiot:mainfrom
coff33ninja:main

Conversation

@coff33ninja

@coff33ninja coff33ninja commented Aug 3, 2026

Copy link
Copy Markdown

What

Adds a Windows build path alongside the macOS Makefile. These three scripts make the tree build on a stock Windows box with Zig's bundled clang (zig cc), NASM, QEMU and GNU binutils from MSYS2:

  • scripts/ensure-toolchain.ps1 - provisions zig, nasm, qemu, python and the MSYS2 mingw-w64-x86_64-binutils package; records resolved paths in a gitignored scripts/.toolchain.json.
  • scripts/build.ps1 - compiles the same 211 objects as the Makefile with the same flags (minus the GCC-only ones), links with lld, then re-labels the ELF64 image as an ELF32 container with objcopy -O elf32-i386 - the exact command the Makefile's $(OBJCOPY) step runs. Verified end-to-end: kernel.bin boots, formats disk.img FAT32, and persists across reboots.
  • scripts/run.ps1 - boots kernel.bin in QEMU with the same netdev/e1000/IDE/fw_cfg flags and the same .env API-key rules as the Makefile.

README: new "On Windows" section, plus a footer crediting NO_OS - the ELF-reframing ADR there is where the objcopy trick came from.

Follow-up: the QEMU boot-assertion suite also runs on Windows

  • scripts/test-qemu.ps1 - entry point mirroring the Makefile's test-qemu recipe: tests/qemu/lint_printf.py (the lib/kfmt.c formatter-grammar check), then all six boot-assertion cases.
  • tests/qemu/harness.py - ported to Windows Python: signal registration and process reaping (no SIGKILL or process groups), and the interactive REPL case speaks to the VM over a loopback TCP serial port where POSIX uses an AF_UNIX socket. The per-case build hook (FABLEOS_TEST_MAKE) points at build.ps1 so the build-cflags: AC'97 bring-up case works with no make on the box.
  • scripts/build.ps1 - objects are now linked in the Makefile's source order, not directory order, because the self-registering driver table initializes in link order and the boot cases pin that order.

Verified on Windows: lint_printf CLEAN, all 6 cases pass (the AC'97 variant build restores the tree afterwards; kernel.bin is byte-identical).

Notes for the maintainer

  • QEMU's multiboot loader only accepts ELF32; zig's bundled llvm-objcopy can only emit flat binary, so the one missing piece was a real GNU objcopy. The reframing follows coff33ninja/NO_OS (linked in the README).
  • -fno-sanitize=undefined is required because zig's compiler_rt pulls in __ubsan_handle_* on freestanding builds.
  • The README footer names the fork location - happy to trim it from the PR if you'd rather not carry it upstream.

Three scripts port \make\ to Windows: ensure-toolchain.ps1 provisions zig,
nasm, qemu and MSYS2 binutils; build.ps1 compiles with zig cc (clang) and
re-labels the ELF64 kernel as an ELF32 container with \objcopy -O elf32-i386\,
matching the Makefile; run.ps1 boots it in QEMU headless or with graphics.
README gains the On Windows section and a fork/NO_OS attribution.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant