Microkernel thing OS experiment (Zig ⚡)
1const std = @import("std");
2const build_helpers = @import("build_helpers");
3
4pub fn build(b: *std.Build) void {
5 const arch = b.option(build_helpers.Architecture, "arch", "The target ukernel architecture") orelse .amd64;
6
7 // set CPU features based on the architecture
8 var target_query: std.Target.Query = .{
9 .cpu_arch = arch.get(),
10 .os_tag = .freestanding,
11 .abi = .none,
12 };
13 const arch_root_path, const linker_script_path, const code_model: std.builtin.CodeModel = blk: {
14 switch (arch) {
15 .amd64 => {
16 const Feature = std.Target.x86.Feature;
17
18 target_query.cpu_features_add.addFeature(@intFromEnum(Feature.soft_float));
19 target_query.cpu_features_sub.addFeature(@intFromEnum(Feature.mmx));
20 target_query.cpu_features_sub.addFeature(@intFromEnum(Feature.sse));
21 target_query.cpu_features_sub.addFeature(@intFromEnum(Feature.sse2));
22 target_query.cpu_features_sub.addFeature(@intFromEnum(Feature.avx));
23 target_query.cpu_features_sub.addFeature(@intFromEnum(Feature.avx2));
24
25 break :blk .{ "arch/amd64/root.zig", "arch/amd64/linker.ld", .kernel };
26 },
27 .aarch64 => {
28 const Feature = std.Target.aarch64.Feature;
29
30 target_query.cpu_features_sub.addFeature(@intFromEnum(Feature.fp_armv8));
31 target_query.cpu_features_sub.addFeature(@intFromEnum(Feature.crypto));
32 target_query.cpu_features_sub.addFeature(@intFromEnum(Feature.neon));
33
34 break :blk .{ "arch/aarch64/root.zig", "arch/aarch64/linker.ld", .default };
35 },
36 .riscv64 => {
37 const Feature = std.Target.riscv.Feature;
38 target_query.cpu_features_sub.addFeature(@intFromEnum(Feature.d));
39
40 break :blk .{ "arch/riscv64/root.zig", "arch/riscv64/linker.ld", .default };
41 },
42 }
43 };
44
45 const target = b.resolveTargetQuery(target_query);
46 const optimize = b.standardOptimizeOption(.{ .preferred_optimize_mode = .ReleaseSafe });
47
48 const common_mod = b.createModule(.{
49 .root_source_file = b.path("common/root.zig"),
50 .target = target,
51 .optimize = optimize,
52 .code_model = code_model,
53 });
54
55 const arch_module = b.createModule(.{
56 .root_source_file = b.path(arch_root_path),
57 });
58 switch (arch) {
59 .amd64 => {
60 arch_module.addAssemblyFile(b.path("arch/amd64/asm/traps.S"));
61 },
62 else => {},
63 }
64
65 const spinlock_mod = b.dependency("spinlock", .{}).module("spinlock");
66 const limine_mod = b.dependency("limine", .{ .api_revision = 3 }).module("limine");
67 const console_mod = b.dependency("console", .{}).module("console");
68 const queue_mod = b.dependency("Queue", .{}).module("Queue");
69
70 arch_module.addImport("limine", limine_mod);
71 arch_module.addImport("console", console_mod);
72 arch_module.addImport("common", common_mod);
73 arch_module.addImport("Queue", queue_mod);
74
75 common_mod.addImport("arch", arch_module);
76 common_mod.addImport("spinlock", spinlock_mod);
77 common_mod.addImport("console", console_mod);
78 common_mod.addImport("Queue", queue_mod);
79
80 const kernel = b.addExecutable(.{
81 .name = "ukernel",
82 .root_module = common_mod,
83 // TODO: remove when x86 backend is less broken with removing CPU features
84 .use_llvm = true,
85 });
86
87 kernel.pie = false;
88 kernel.want_lto = false;
89 kernel.setLinkerScript(b.path(linker_script_path));
90 b.installArtifact(kernel);
91}