const std = @import("std"); const Arch = enum { x86_64, aarch64, pub fn stdlib(self: Arch) std.Target.Cpu.Arch { return switch (self) { .x86_64 => .x86_64, .aarch64 => .aarch64, }; } pub fn efiName(self: Arch, b: *std.Build) []const u8 { const suffix = switch (self) { .x86_64 => "X64", .aarch64 => "AA64", }; return b.fmt("BOOT{s}", .{suffix}); } }; pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const cpu_arch = b.option(Arch, "arch", "cpu architecture") orelse .x86_64; const efi_name = cpu_arch.efiName(b); const lumine_exe = b.addExecutable(.{ .name = efi_name, .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = b.resolveTargetQuery(.{ .os_tag = .uefi, .cpu_arch = cpu_arch.stdlib(), }), .optimize = optimize, }), }); const install_step = b.getInstallStep(); const lumine_install = b.addInstallArtifact(lumine_exe, .{}); install_step.dependOn(&lumine_install.step); const qemu_exe = b.option([]const u8, "qemu", "path to qemu binary") orelse b.fmt("qemu-system-{t}", .{cpu_arch}); const qemu_cmd = b.addSystemCommand(&.{ qemu_exe, "-m", "512M", "-serial", "mon:stdio", "-nographic", "-no-reboot", "-no-shutdown" }); { const ovmf_dep = b.dependency("ovmf", .{}); const ovmf_code = ovmf_dep.path(b.fmt("ovmf-code-{t}.fd", .{cpu_arch})); switch (cpu_arch) { .aarch64 => { qemu_cmd.addArgs(&.{ "-M", "virt", "-cpu", "max" }); }, .x86_64 => {}, } qemu_cmd.addArg("-bios"); qemu_cmd.addFileArg(ovmf_code); } { const boot_dir = b.addTempFiles(); _ = boot_dir.addCopyFile(lumine_exe.getEmittedBin(), b.fmt("EFI/BOOT/{s}.EFI", .{efi_name})); qemu_cmd.addArg("-drive"); qemu_cmd.addPrefixedDirectoryArg("format=raw,file=fat:rw:", boot_dir.getDirectory()); } const run_step = b.step("run", "run in qemu"); run_step.dependOn(&qemu_cmd.step); }