diff --git a/kernel/Makefile b/kernel/Makefile index 8464cf0..8fc6148 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,41 +1,6 @@ -ARCHES = x86_64 i386 - -ARCH ?= x86_64 - -CC = zig cc -target $(ARCH)-freestanding -LD = ld -m elf_$(ARCH) -LDSCRIPT = make/$(ARCH)/linker.ld - --include make/$(ARCH)/make.config - -CFLAGS ?= -Og -g -CFLAGS := $(CFLAGS) $(ARCH_CFLAGS) \ - -Wall -Wextra -pedantic -std=gnu11 -I../ext -Isrc -fPIE -mno-red-zone -LDFLAGS := $(LDFLAGS) -T $(LDSCRIPT) - - -TARGET := kernel - -CFILES := $(shell find src -path src/arch -prune -o -type f -name '*.c' -print) -ARCHFILES := $(ARCHFILES) $(shell find src/arch/$(ARCH) -type f -name '*.c' -print) -HFILES := $(shell find src -type f -name '*.h') -OBJ := $(patsubst src/%,obj/$(ARCH)/%.o,$(CFILES) $(ARCHFILES)) - -.PHONY: all clean obj $(ARCHES) - -default: bin/$(TARGET)-$(ARCH) -all: $(ARCHES) - -$(ARCHES): - @$(MAKE) ARCH=$@ - -bin/$(TARGET)-$(ARCH): $(OBJ) - @mkdir -p $(@D) - $(LD) $(LDFLAGS) $(OBJ) -o $@ - -obj/$(ARCH)/%.c.o: src/%.c $(HFILES) $(ARCHHEADERS) - @mkdir -p $(@D) - $(CC) $(CFLAGS) -c $< -o $@ +.PHONY: x86_64_stivale2 clean +x86_64_stivale2: + zig build -Dtarget="$@" clean: - rm -rf bin obj zig-cache + rm -rf bin zig-cache \ No newline at end of file diff --git a/kernel/build.zig b/kernel/build.zig new file mode 100644 index 0000000..c97cc7f --- /dev/null +++ b/kernel/build.zig @@ -0,0 +1,194 @@ +// imports +const std = @import("std"); +const Builder = std.build.Builder; + +// Alloc stuff +var GPAAlloc = std.heap.GeneralPurposeAllocator(.{}){}; +var alloc = &GPAAlloc.allocator; + +// Target enumeration stuff +const Target = struct { + parent: ?*const Target = null, + cpu_arch: ?std.Target.Cpu.Arch = null, + cpu_model: ?std.build.Target.CpuModel = null, + archdir: ?[]const u8 = null, + linkscript: ?[]const u8 = null, + name: []const u8, +}; + +const x86 = Target{ + .archdir = "x86", + .name = "x86-generic" +}; +const x86_64 = Target { + .parent = &x86, + .cpu_arch = std.Target.Cpu.Arch.x86_64, + .archdir = "x86_64", + .name = "x86_64-generic" +}; +const x86_64_stivale2 = Target { + .parent = &x86_64, + // .archdir = "x86_64/stivale2", + .linkscript = "make/x86_64/linker.ld", + .name = "x86_64-stivale2", +}; + +const Targets = enum { + x86_64, + x86_64_stivale2, + + pub fn getTarget(self: Targets) Target { + return switch(self) { + .x86_64 => x86_64_stivale2, + .x86_64_stivale2 => x86_64_stivale2, + }; + } + pub fn default() Targets { + return Targets.x86_64_stivale2; + } +}; + +fn getCpuArch(t: Target) std.Target.Cpu.Arch { + return t.cpu_arch orelse getCpuArch(t.parent.?.*); +} + +fn getCpuModel(t: Target) std.build.Target.CpuModel { + if(t.cpu_model) |m| { + return m; + } else if (t.parent) |p| { + return getCpuModel(t.parent.?.*); + } else { + return std.build.Target.CpuModel.baseline; + } +} + +fn getLinkerScript(t: Target) []const u8 { + return t.linkscript orelse getLinkerScript(t.parent.?.*); +} + +fn getTarget(t: Target) std.zig.CrossTarget { + return .{ + .cpu_arch = getCpuArch(t), + .cpu_model = getCpuModel(t), + .os_tag = std.Target.Os.Tag.freestanding, + }; +} + +// Directory traversal stuff +const Files = struct { + generic_c: [][]const u8, + archspecific_c: [][]const u8, + archspecific_s: [][]const u8, + nasm: [][]const u8, +}; +fn strPrefix(str: []const u8, prefix: []const u8) bool { + if (str.len < prefix.len) return false; + return std.mem.eql(u8, str[0..prefix.len], prefix); +} +fn fileExtEql(name: []const u8, ext: []const u8) bool { + std.debug.assert(ext[0] == '.'); + if(name.len <= ext.len) return false; + const file_ext = name[name.len - ext.len..]; + return std.mem.eql(u8, file_ext, ext); +} +fn findSources(dir: []const u8, ext: []const u8, prefix: ?[]const u8) ![][] const u8 { + var files = std.ArrayList([]const u8).init(alloc); + var walker = try std.fs.walkPath(alloc, dir); + while (try walker.next()) |entry| { + if(entry.kind != std.fs.Dir.Entry.Kind.File) continue; + + if(prefix != null and strPrefix(entry.path, prefix.?)) { + // std.debug.print("Ignoring {}\n", .{entry.path}); + } else { + if(fileExtEql(entry.basename, ext)) { + // std.debug.print("Adding file {}\n", .{entry.path}); + var p = std.ArrayList(u8).init(alloc); + try p.appendSlice(entry.path); + try files.append(p.toOwnedSlice()); + } else { + // std.debug.print("wrong file extension: {}\n", .{entry.basename}); + } + } + } + walker.deinit(); + return files.toOwnedSlice(); +} +fn findArch(t: Target, ext: []const u8) ![][] const u8 { + var arch_c = std.ArrayList([]const u8).init(alloc); + if (t.parent) |parent| { + const parentfiles = findArch(parent.*, ext) catch unreachable; + try arch_c.appendSlice( parentfiles ); + } + if (t.archdir) |archdir| { + const dir = try std.fmt.allocPrint(alloc, "src/arch/{}", .{archdir}); + const files = try findSources(dir, ext, null); + try arch_c.appendSlice(files); + } + return arch_c.items; +} +fn findFiles(t: Target) !Files { + const generic_c = try findSources("src", ".c", "src/arch/"); + const arch_c = try findArch(t, ".c"); + const arch_s = try findArch(t, ".s"); + const nasm = try findArch(t, ".nasm"); + + return Files { + .generic_c = generic_c, + .archspecific_c = arch_c, + .archspecific_s = arch_s, + .nasm = nasm + }; +} + +pub fn build(b: *Builder) !void { + const target_option = b.option(Targets, "target", "The kernel target") orelse Targets.default(); + const ktarget = target_option.getTarget(); + + // Standard release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + b.cache_root = "zig-cache"; + + const files = try findFiles(ktarget); + + const cflags = [_][]const u8{"-Wall", "-Wextra", "-pedantic", "-std=gnu11", "-I../ext", "-Isrc", "-fPIE", "-mno-red-zone"}; + + const exename = try std.fmt.allocPrint(alloc, "kernel-{}", .{ktarget.name}); + const exe = b.addExecutable(exename, "src/main.zig"); + var cfiles = std.ArrayList([]const u8).init(alloc); + try cfiles.appendSlice(files.generic_c); + try cfiles.appendSlice(files.archspecific_c); + for (cfiles.items) |c_file| { + // std.debug.print("CC: {}\n", .{c_file}); + exe.addCSourceFile(c_file, &cflags); + } + for(files.archspecific_s) |s_file| { + // std.debug.print("zig as: {}\n", .{s_file}); + exe.addAssemblyFile(s_file); + } + for(files.nasm) |nasm_file| { + // std.debug.print("nasm: {}\n", .{nasm_file}); + const output = try std.fmt.allocPrint(alloc, "zig-cache/nasm/{}.o", .{nasm_file}); + const output_folder = std.fs.cwd().makePath(std.fs.path.dirname(output).?); + const assX = b.addSystemCommand(&[_][]const u8{"nasm", "-Isrc", "-felf64", nasm_file, "-o", output}); + exe.step.dependOn(&assX.step); + exe.addObjectFile(output); + } + + exe.setTarget(getTarget(ktarget)); + exe.setBuildMode(mode); + exe.setLinkerScriptPath(getLinkerScript(ktarget)); + exe.setOutputDir("bin"); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + + // const run_step = b.step("run", "Run the app"); + // run_step.dependOn(&run_cmd.step); +} diff --git a/kernel/src/main.zig b/kernel/src/main.zig new file mode 100644 index 0000000..76005f3 --- /dev/null +++ b/kernel/src/main.zig @@ -0,0 +1,5 @@ +const std = @import("std"); + +pub fn zigmain() anyerror!void { + std.log.info("All your codebase are belong to us.", .{}); +}