commit 18e68acfdd9b4d9ca827c37836aa5363b9553e39
parent 1a7a430a51a5a35a44787646617187c859fa5ac9
Author: Sylvia Ivory <git@sivory.net>
Date: Tue, 13 Jan 2026 15:20:29 -0800
Add lab builder
Diffstat:
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;