sylveos

Toy Operating System
Log | Files | Refs

commit 18e68acfdd9b4d9ca827c37836aa5363b9553e39
parent 1a7a430a51a5a35a44787646617187c859fa5ac9
Author: Sylvia Ivory <git@sivory.net>
Date:   Tue, 13 Jan 2026 15:20:29 -0800

Add lab builder

Diffstat:
M.gitignore | 1+
MJustfile | 3+++
Mbuild.zig | 72+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/labs/lab1.zig | 6+++---
4 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,2 +1,3 @@ /.zig-cache /zig-out +/src/lab-runner.zig diff --git a/Justfile b/Justfile @@ -1,5 +1,8 @@ build: zig build +lab name: + zig build -Dlab={{ name }} + list: build arm-none-eabi-objdump -D zig-out/bin/SylveOS diff --git a/build.zig b/build.zig @@ -12,22 +12,84 @@ const target: std.Target.Query = .{ .os_tag = .freestanding, }; -pub fn build(b: *std.Build) !void { +fn add_exe(exe_name: []const u8, path: std.Build.LazyPath, b: *std.Build) !*std.Build.Step.Compile { const exe = b.addExecutable(.{ - .name = @tagName(config.name), + .name = exe_name, + .linkage = .static, .root_module = b.createModule(.{ - .root_source_file = b.path("src/root.zig"), + .root_source_file = path, .target = b.resolveTargetQuery(target), .optimize = .ReleaseSafe, .unwind_tables = .none, .single_threaded = true, }), - .linkage = .static, }); exe.setLinkerScript(b.path("linker.ld")); - const install_asm = b.addInstallBinFile(exe.getEmittedAsm(), @tagName(config.name) ++ ".s"); + const asm_name = try std.fmt.allocPrint(b.allocator, "{s}.s", .{exe_name}); + defer b.allocator.free(asm_name); + + const install_asm = b.addInstallBinFile(exe.getEmittedAsm(), asm_name); b.getInstallStep().dependOn(&install_asm.step); b.installArtifact(exe); + + return exe; +} + +fn lab(name: []const u8, units: []const []const u8, b: *std.Build) !void { + for (units) |unit| { + const exe_name = try std.fmt.allocPrint(b.allocator, "{s}_{s}", .{ name, unit }); + defer b.allocator.free(exe_name); + + const src_name = try std.fmt.allocPrint(b.allocator, "{s}.zig", .{exe_name}); + defer b.allocator.free(src_name); + + const lab_path = try std.fmt.allocPrint(b.allocator, "labs/{s}.zig", .{name}); + defer b.allocator.free(lab_path); + + const template = + \\ const lab = @import("{s}"); + \\ export fn main() void {{ lab.{s}(); }} + \\ export fn abort() void {{ while(true) {{}} }} + \\ export fn _start() callconv(.naked) noreturn {{ + \\ asm volatile ( + \\ \\ mov sp, 0x800000 + \\ \\ bl main + \\ \\ bl abort + \\ ); + \\ }} + ; + + const root_src = try std.fmt.allocPrint(b.allocator, template, .{ lab_path, unit }); + defer b.allocator.free(root_src); + + // Ensure correct imports + const relative_path = b.path("src/lab-runner.zig"); + const path = try relative_path.getPath3(b, null).toString(b.allocator); + defer b.allocator.free(path); + + const file = try std.fs.createFileAbsolute(path, .{}); + _ = try file.write(root_src); + file.close(); + + _ = try add_exe(exe_name, relative_path, b); + } +} + +fn handle_lab(name: []const u8, b: *std.Build) !void { + if (std.mem.eql(u8, name, "lab1")) { + try lab("lab1", &.{ "blink_1", "blink_2", "loopback" }, b); + } else { + @panic("invalid lab name"); + } +} + +pub fn build(b: *std.Build) !void { + const lab_opt = b.option([]const u8, "lab", "compile specific lab"); + if (lab_opt) |lab_name| { + try handle_lab(lab_name, b); + } + + _ = try add_exe("SylveOS", b.path("src/root.zig"), b); } diff --git a/src/labs/lab1.zig b/src/labs/lab1.zig @@ -1,5 +1,5 @@ -const gpio = @import("gpio.zig"); -const util = @import("util.zig"); +const gpio = @import("../gpio.zig"); +const util = @import("../util.zig"); const led0 = 20; const led1 = 21; @@ -35,7 +35,7 @@ pub fn loopback() void { gpio.set_output(led0); gpio.set_input(input); - gpio.set_ouput(led1); + gpio.set_output(led1); gpio.set_output(output); var v = false;