diff --git a/build.zig b/build.zig index 5e48566..57a2ae3 100644 --- a/build.zig +++ b/build.zig @@ -30,8 +30,18 @@ pub const Backing = union(enum) { pub const EmbeddedExecutable = struct { inner: *LibExeObjStep, - pub fn addModule(exe: *EmbeddedExecutable, name: []const u8, module: *Module) void { - exe.inner.addModule(name, module); + pub const AppDependencyOptions = struct { + depend_on_microzig: bool = false, + }; + + pub fn addAppDependency(exe: *EmbeddedExecutable, name: []const u8, module: *Module, options: AppDependencyOptions) void { + if (options.depend_on_microzig) { + const microzig_module = exe.inner.modules.get("microzig").?; + module.dependencies.put("microzig", microzig_module) catch @panic("OOM"); + } + + const app_module = exe.inner.modules.get("app").?; + app_module.dependencies.put(name, module) catch @panic("OOM"); } pub fn install(exe: *EmbeddedExecutable) void { @@ -190,6 +200,13 @@ pub fn addEmbeddedExecutable( else => {}, } + const app_module = builder.createModule(.{ + .source_file = opts.source_file, + .dependencies = &.{ + .{ .name = "microzig", .module = microzig_module }, + }, + }); + const exe = builder.allocator.create(EmbeddedExecutable) catch unreachable; exe.* = EmbeddedExecutable{ .inner = builder.addExecutable(.{ @@ -199,6 +216,8 @@ pub fn addEmbeddedExecutable( .optimize = opts.optimize, }), }; + exe.inner.addModule("app", app_module); + exe.inner.addModule("microzig", microzig_module); exe.inner.strip = false; // we always want debug symbols, stripping brings us no benefit on embedded @@ -218,13 +237,6 @@ pub fn addEmbeddedExecutable( // - This requires building another tool that runs on the host that compiles those files and emits the linker script. // - src/tools/linkerscript-gen.zig is the source file for this exe.inner.bundle_compiler_rt = (exe.inner.target.getCpuArch() != .avr); // don't bundle compiler_rt for AVR as it doesn't compile right now - exe.addModule("microzig", microzig_module); - exe.addModule("app", builder.createModule(.{ - .source_file = opts.source_file, - .dependencies = &.{ - .{ .name = "microzig", .module = microzig_module }, - }, - })); return exe; } diff --git a/src/modules/LinkerScriptStep.zig b/src/modules/LinkerScriptStep.zig index 8a25bfe..fb92277 100644 --- a/src/modules/LinkerScriptStep.zig +++ b/src/modules/LinkerScriptStep.zig @@ -2,65 +2,41 @@ const std = @import("std"); const MemoryRegion = @import("MemoryRegion.zig"); const Chip = @import("Chip.zig"); const Step = std.build.Step; -const Builder = std.build.Builder; +const Build = std.Build; const GeneratedFile = std.build.GeneratedFile; const LinkerscriptStep = @This(); step: Step, generated_file: std.build.GeneratedFile, -builder: *Builder, chip: Chip, -pub fn create(builder: *Builder, chip: Chip) !*LinkerscriptStep { - var hasher = std.hash.SipHash128(1, 2).init("abcdefhijklmnopq"); - - hasher.update(chip.name); - hasher.update(chip.source.getPath(builder)); - hasher.update(chip.cpu.name); - hasher.update(chip.cpu.source.getPath(builder)); - - var mac: [16]u8 = undefined; - hasher.final(&mac); - - const filename = try std.fmt.allocPrint(builder.allocator, "{}{s}", .{ - std.fmt.fmtSliceHexLower(&mac), - ".ld", - }); - - const path = try std.fs.path.join(builder.allocator, &.{ - "zig-cache", - "microzig", - filename, - }); - try std.fs.cwd().makePath(std.fs.path.dirname(path).?); - - var ret = try builder.allocator.create(LinkerscriptStep); - ret.* = LinkerscriptStep{ +pub fn create(owner: *Build, chip: Chip) !*LinkerscriptStep { + var linkerscript = try owner.allocator.create(LinkerscriptStep); + linkerscript.* = LinkerscriptStep{ .step = Step.init(.{ .id = .custom, .name = "linkerscript", - .owner = builder, + .owner = owner, .makeFn = make, }), .generated_file = .{ - .step = &ret.step, - .path = path, + .step = &linkerscript.step, }, - .builder = builder, .chip = chip, }; - return ret; + + return linkerscript; } -fn make(step: *Step, progress: *std.Progress.Node) !void { - _ = progress; +fn make(step: *Step, _: *std.Progress.Node) anyerror!void { const linkerscript = @fieldParentPtr(LinkerscriptStep, "step", step); - const file = try std.fs.cwd().createFile(linkerscript.generated_file.path.?, .{}); - defer file.close(); + const owner = linkerscript.step.owner; const target = linkerscript.chip.cpu.target; - const writer = file.writer(); + + var contents = std.ArrayList(u8).init(owner.allocator); + const writer = contents.writer(); try writer.print( \\/* \\ * This file was auto-generated by microzig @@ -162,4 +138,35 @@ fn make(step: *Step, progress: *std.Progress.Node) !void { // \\ ASSERT( (SIZEOF(.text) + SIZEOF(.data) > LENGTH(flash0)), "Error: .text + .data is too large for flash!" ); // \\ // ); + + const filename = try std.fmt.allocPrint(owner.allocator, "{s}_{s}.ld", .{ + linkerscript.chip.name, + linkerscript.chip.cpu.name, + }); + + var hash = owner.cache.hash; + hash.addBytes(linkerscript.chip.name); + hash.addBytes(linkerscript.chip.cpu.name); + + // TODO: hash more information to reduce chance of collision + for (linkerscript.chip.memory_regions) |memory_region| { + hash.add(memory_region.offset); + hash.add(memory_region.length); + } + + const digest = hash.final(); + const dir_path = try owner.cache_root.join(owner.allocator, &.{ + "microzig", + &digest, + }); + + var dir = try owner.cache_root.handle.makeOpenPath(dir_path, .{}); + defer dir.close(); + + const file = try dir.createFile(filename, .{}); + defer file.close(); + + try file.writeAll(contents.items); + const full_path = owner.pathJoin(&.{ dir_path, filename }); + linkerscript.generated_file.path = full_path; } diff --git a/src/modules/cpus/cortex-m.zig b/src/modules/cpus/cortex-m.zig index 3338ff3..f69151b 100644 --- a/src/modules/cpus/cortex-m.zig +++ b/src/modules/cpus/cortex-m.zig @@ -135,7 +135,7 @@ fn create_interrupt_vector( .C = struct { fn wrapper() callconv(.C) void { if (calling_convention == .Unspecified) // TODO: workaround for some weird stage1 bug - @call(.{ .modifier = .always_inline }, function, .{}); + @call(.always_inline, function, .{}); } }.wrapper, },