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 arch_module = b.createModule(.{
49 .root_source_file = b.path(arch_root_path),
50 .target = target,
51 .optimize = optimize,
52 .code_model = code_model,
53 });
54
55 switch (arch) {
56 .amd64 => {
57 arch_module.addAssemblyFile(b.path("arch/amd64/asm/traps.S"));
58 },
59 else => {},
60 }
61
62 const limine_dep = b.dependency("limine", .{
63 .api_revision = 3,
64 });
65 const spinlock_dep = b.dependency("spinlock", .{});
66 const flanterm_dep = b.dependency("flanterm", .{});
67
68 const limine_mod = limine_dep.module("limine");
69 const spinlock_mod = spinlock_dep.module("spinlock");
70 const flanterm_mod = flanterm_dep.module("flanterm");
71
72 const common_mod = b.createModule(.{
73 .root_source_file = b.path("common/root.zig"),
74 });
75
76 arch_module.addImport("limine", limine_mod);
77 arch_module.addImport("flanterm", flanterm_mod);
78 arch_module.addImport("common", common_mod);
79
80 common_mod.addImport("arch", arch_module);
81 common_mod.addImport("spinlock", spinlock_mod);
82 common_mod.addImport("flanterm", flanterm_mod);
83 common_mod.addImport("limine", limine_mod);
84
85 const kernel = b.addExecutable(.{
86 .name = "ukernel",
87 .root_module = arch_module,
88 // TODO: remove when x86 backend is less broken with removing CPU features
89 .use_llvm = true,
90 });
91
92 kernel.pie = false;
93 kernel.want_lto = false;
94 kernel.setLinkerScript(b.path(linker_script_path));
95 b.installArtifact(kernel);
96}