From 99e8d09cf0a7e17ff04ba2958f0f3fd5aefb597e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=22xq=22=20Quei=C3=9Fner?= Date: Sat, 20 Jan 2024 12:23:41 +0100 Subject: [PATCH] Adds auto-discovery of BSPs. --- board-support/espressif-esp/build.zig | 5 +- board-support/gigadevice-gd32/build.zig | 9 +- board-support/microchip-atsam/build.zig | 5 +- board-support/microchip-avr/build.zig | 9 +- board-support/nordic-nrf5x/build.zig | 2 + board-support/nxp-lpc/build.zig | 2 + board-support/raspberrypi-rp2040/build.zig | 2 + board-support/stmicro-stm32/build.zig | 32 +- build/build.zig | 205 +++-- core/build.zig | 837 --------------------- examples/next-gen/build.zig | 5 - examples/next-gen/build.zig.zon | 8 +- tools/extract-bsp-info.zig | 29 +- 13 files changed, 193 insertions(+), 957 deletions(-) diff --git a/board-support/espressif-esp/build.zig b/board-support/espressif-esp/build.zig index d1b62cc..ebc95c7 100644 --- a/board-support/espressif-esp/build.zig +++ b/board-support/espressif-esp/build.zig @@ -1,4 +1,7 @@ const std = @import("std"); +const MicroZig = @import("microzig-build"); + +pub const microzig_board_support = MicroZig.registerBoardSupport(@This()); fn path(comptime suffix: []const u8) std.Build.LazyPath { return .{ @@ -26,7 +29,7 @@ const hal = .{ }; pub const chips = struct { - pub const esp32_c3 = .{ + pub const esp32_c3 = MicroZig.Target{ .preferred_format = .bin, // TODO: Exchange FLAT format with .esp format .chip = .{ .name = "ESP32-C3", diff --git a/board-support/gigadevice-gd32/build.zig b/board-support/gigadevice-gd32/build.zig index 61f41a4..7b13e1a 100644 --- a/board-support/gigadevice-gd32/build.zig +++ b/board-support/gigadevice-gd32/build.zig @@ -1,4 +1,7 @@ const std = @import("std"); +const MicroZig = @import("microzig-build"); + +pub const microzig_board_support = MicroZig.registerBoardSupport(@This()); fn path(comptime suffix: []const u8) std.Build.LazyPath { return .{ @@ -11,7 +14,7 @@ const hal = .{ }; pub const chips = struct { - pub const gd32vf103xb = .{ + pub const gd32vf103xb = MicroZig.Target{ .preferred_format = .elf, .chip = .{ .name = "GD32VF103", @@ -27,7 +30,7 @@ pub const chips = struct { .hal = hal, }; - pub const gd32vf103x8 = .{ + pub const gd32vf103x8 = MicroZig.Target{ .preferred_format = .elf, .chip = .{ .name = "GD32VF103", @@ -46,7 +49,7 @@ pub const chips = struct { pub const boards = struct { pub const sipeed = struct { - pub const longan_nano = .{ + pub const longan_nano = MicroZig.Target{ .preferred_format = .elf, .chip = chips.gd32vf103xb.chip, .hal = hal, diff --git a/board-support/microchip-atsam/build.zig b/board-support/microchip-atsam/build.zig index d9dbf95..77010ee 100644 --- a/board-support/microchip-atsam/build.zig +++ b/board-support/microchip-atsam/build.zig @@ -1,4 +1,7 @@ const std = @import("std"); +const MicroZig = @import("microzig-build"); + +pub const microzig_board_support = MicroZig.registerBoardSupport(@This()); pub fn build(b: *std.Build) void { _ = b; @@ -27,7 +30,7 @@ pub const chip_atsamd51j19 = .{ }; pub const chips = struct { - pub const atsamd51j19 = .{ + pub const atsamd51j19 = MicroZig.Target{ .preferred_format = .elf, .chip = chip_atsamd51j19, }; diff --git a/board-support/microchip-avr/build.zig b/board-support/microchip-avr/build.zig index 19ba076..650d54b 100644 --- a/board-support/microchip-avr/build.zig +++ b/board-support/microchip-avr/build.zig @@ -1,4 +1,7 @@ const std = @import("std"); +const MicroZig = @import("microzig-build"); + +pub const microzig_board_support = MicroZig.registerBoardSupport(@This()); fn path(comptime suffix: []const u8) std.Build.LazyPath { return .{ @@ -11,7 +14,7 @@ const hal = .{ }; pub const chips = struct { - pub const atmega328p = .{ + pub const atmega328p = MicroZig.Target{ .preferred_format = .hex, .chip = .{ .name = "ATmega328P", @@ -31,7 +34,7 @@ pub const chips = struct { pub const boards = struct { pub const arduino = struct { - pub const nano = .{ + pub const nano = MicroZig.Target{ .preferred_format = .hex, .chip = chips.atmega328p.chip, .hal = hal, @@ -42,7 +45,7 @@ pub const boards = struct { }, }; - pub const uno_rev3 = .{ + pub const uno_rev3 = MicroZig.Target{ .preferred_format = .hex, .chip = chips.atmega328p.chip, .hal = hal, diff --git a/board-support/nordic-nrf5x/build.zig b/board-support/nordic-nrf5x/build.zig index 9bc2b78..445bae7 100644 --- a/board-support/nordic-nrf5x/build.zig +++ b/board-support/nordic-nrf5x/build.zig @@ -1,6 +1,8 @@ const std = @import("std"); const MicroZig = @import("microzig-build"); +pub const microzig_board_support = MicroZig.registerBoardSupport(@This()); + fn path(comptime suffix: []const u8) std.Build.LazyPath { return .{ .cwd_relative = comptime ((std.fs.path.dirname(@src().file) orelse ".") ++ suffix), diff --git a/board-support/nxp-lpc/build.zig b/board-support/nxp-lpc/build.zig index 5f75d43..b17678e 100644 --- a/board-support/nxp-lpc/build.zig +++ b/board-support/nxp-lpc/build.zig @@ -1,6 +1,8 @@ const std = @import("std"); const MicroZig = @import("microzig-build"); +pub const microzig_board_support = MicroZig.registerBoardSupport(@This()); + fn path(comptime suffix: []const u8) std.Build.LazyPath { return .{ .cwd_relative = comptime ((std.fs.path.dirname(@src().file) orelse ".") ++ suffix), diff --git a/board-support/raspberrypi-rp2040/build.zig b/board-support/raspberrypi-rp2040/build.zig index 73453f3..3e0d534 100644 --- a/board-support/raspberrypi-rp2040/build.zig +++ b/board-support/raspberrypi-rp2040/build.zig @@ -1,6 +1,8 @@ const std = @import("std"); const microzig = @import("microzig-build"); +pub const microzig_board_support = microzig.registerBoardSupport(@This()); + fn root() []const u8 { return comptime (std.fs.path.dirname(@src().file) orelse "."); } diff --git a/board-support/stmicro-stm32/build.zig b/board-support/stmicro-stm32/build.zig index 4e0e0d5..b843537 100644 --- a/board-support/stmicro-stm32/build.zig +++ b/board-support/stmicro-stm32/build.zig @@ -1,5 +1,7 @@ const std = @import("std"); -const microzig = @import("microzig-build"); +const MicroZig = @import("microzig-build"); + +pub const microzig_board_support = MicroZig.registerBoardSupport(@This()); fn root() []const u8 { return comptime (std.fs.path.dirname(@src().file) orelse "."); @@ -18,7 +20,7 @@ pub fn build(b: *std.Build) !void { } pub const chips = struct { - pub const stm32f103x8 = .{ + pub const stm32f103x8 = MicroZig.Target{ .preferred_format = .elf, .chip = .{ .name = "STM32F103", @@ -36,7 +38,7 @@ pub const chips = struct { }, }; - pub const stm32f303vc = .{ + pub const stm32f303vc = MicroZig.Target{ .preferred_format = .elf, .chip = .{ .name = "STM32F303", @@ -51,7 +53,7 @@ pub const chips = struct { }, }; - pub const stm32f407vg = .{ + pub const stm32f407vg = MicroZig.Target{ .preferred_format = .elf, .chip = .{ .name = "STM32F407", @@ -67,7 +69,7 @@ pub const chips = struct { }, }; - pub const stm32f429zit6u = .{ + pub const stm32f429zit6u = MicroZig.Target{ .preferred_format = .elf, .chip = .{ .name = "STM32F429", @@ -85,8 +87,8 @@ pub const chips = struct { // All STM32L0x1 series MCUs differ only in memory size. So we create a comptime function // to generate all MCU variants as per https://www.st.com/en/microcontrollers-microprocessors/stm32l0x1.html - fn stm32l0x1(comptime rom_size: u64, comptime ram_size: u64) microzig.Target { - return microzig.Target{ + fn stm32l0x1(comptime rom_size: u64, comptime ram_size: u64) MicroZig.Target { + return MicroZig.Target{ .preferred_format = .elf, .chip = .{ .name = "STM32L0x1", @@ -123,8 +125,8 @@ pub const chips = struct { // All STM32L0x2 series MCUs differ only in memory size. So we create a comptime function // to generate all MCU variants as per https://www.st.com/en/microcontrollers-microprocessors/stm32l0x2.html - fn stm32l0x2(comptime rom_size: u64, comptime ram_size: u64) microzig.Target { - return microzig.Target{ + fn stm32l0x2(comptime rom_size: u64, comptime ram_size: u64) MicroZig.Target { + return MicroZig.Target{ .preferred_format = .elf, .chip = .{ .name = "STM32L0x2", @@ -154,8 +156,8 @@ pub const chips = struct { // All STM32L0x2 series MCUs differ only in memory size. So we create a comptime function // to generate all MCU variants as per https://www.st.com/en/microcontrollers-microprocessors/stm32l0x3.html - fn stm32l0x3(comptime rom_size: u64, comptime ram_size: u64) microzig.Target { - return microzig.Target{ + fn stm32l0x3(comptime rom_size: u64, comptime ram_size: u64) MicroZig.Target { + return MicroZig.Target{ .preferred_format = .elf, .chip = .{ .name = "STM32L0x3", @@ -187,7 +189,7 @@ pub const chips = struct { }; pub const boards = struct { - pub const stm32f3discovery = .{ + pub const stm32f3discovery = MicroZig.Target{ .preferred_format = .elf, .chip = chips.stm32f303vc.chip, .board = .{ @@ -196,7 +198,7 @@ pub const boards = struct { }, }; - pub const stm32f4discovery = .{ + pub const stm32f4discovery = MicroZig.Target{ .preferred_format = .elf, .chip = chips.stm32f407vg.chip, .board = .{ @@ -205,7 +207,7 @@ pub const boards = struct { }, }; - pub const stm3240geval = .{ + pub const stm3240geval = MicroZig.Target{ .preferred_format = .elf, .chip = chips.stm32f407vg.chip, .board = .{ @@ -214,7 +216,7 @@ pub const boards = struct { }, }; - pub const stm32f429idiscovery = .{ + pub const stm32f429idiscovery = MicroZig.Target{ .preferred_format = .elf, .chip = chips.stm32f429zit6u.chip, .board = .{ diff --git a/build/build.zig b/build/build.zig index 2c6df50..67c16e2 100644 --- a/build/build.zig +++ b/build/build.zig @@ -9,10 +9,131 @@ const uf2 = @import("uf2"); // MicroZig Gen 3 Interface // //////////////////////////////////////// -pub const EnvironmentInfo = struct { - /// include package names of your board support packages here: - board_support: []const []const u8, +pub const BoardSupportPackageDefinition = struct { + pub const TargetDefinition = struct { + id: []const u8, // full "uri" + target: Target, + }; + + bsp_root: type, + targets: []const TargetDefinition, + + fn init(comptime bsp_root: type) BoardSupportPackageDefinition { + var targets: []const TargetDefinition = &.{}; + + if (@hasDecl(bsp_root, "chips")) { + targets = targets ++ construct_target_database("chip:", bsp_root.chips); + } + + if (@hasDecl(bsp_root, "boards")) { + targets = targets ++ construct_target_database("board:", bsp_root.boards); + } + + if (targets.len == 0) { + @compileError("Board support package contains not a single target. Please add at least one target!"); + } + + return BoardSupportPackageDefinition{ + .bsp_root = bsp_root, + .targets = targets, + }; + } + + fn construct_target_database(comptime prefix: []const u8, comptime namespace: type) []const TargetDefinition { + var list: []const TargetDefinition = &.{}; + + inline for (@typeInfo(namespace).Struct.decls) |decl_info| { + const decl = @field(namespace, decl_info.name); + const T = @TypeOf(decl); + + const name = comptime prefix ++ decl_info.name; // board:vendor/name + + if (T == Target) { + const target: Target = decl; + + list = list ++ &[_]TargetDefinition{.{ + .id = name, + .target = target, + }}; + // be.targets.put(be.host_build.allocator, name, target) catch @panic("out of memory"); + } else { + if (T != type) { + @compileError(std.fmt.comptimePrint("Declaration {s} is neither a MicroZig.Target nor a namespace. Expected declaration to be a 'type', found {s}.", .{ + name, + @typeName(T), + })); + } + + const ti = @typeInfo(decl); + if (ti != .Struct) { + @compileError(std.fmt.comptimePrint("Declaration {s} is neither a MicroZig.Target nor a namespace. Expected declaration to be a 'struct', found {s}.", .{ + name, + @tagName(ti), + })); + } + + if (ti.Struct.fields.len > 0) { + @compileError(std.fmt.comptimePrint("Declaration {s} is neither a MicroZig.Target nor a namespace. Expected declaration to have no fields, but found {} fields.", .{ + name, + ti.Struct.fields.len, + })); + } + + const sublist = construct_target_database( + comptime name ++ "/", + decl, + ); + + list = list ++ sublist; + } + } + + return list; + } +}; + +/// Validates a board support package and returns a registration type that can be used +/// with MicroZig automatic BSP discovery. +/// +/// Store the return value into a public constant named "" at the root of your build script: +/// +/// pub const microzig_board_support = microzig.registerBoardSupport(@This()); +/// +pub fn registerBoardSupport(comptime bsp_root: type) BoardSupportPackageDefinition { + return BoardSupportPackageDefinition.init(bsp_root); +} + +const ImportedBSP = struct { + import_name: []const u8, + bsp: BoardSupportPackageDefinition, +}; + +fn get_declared_bsps() []const ImportedBSP { + + // Keep in sync with the logic from Build.zig:dependency + const build_runner = @import("root"); + const deps = build_runner.dependencies; + + var bsps: []const ImportedBSP = &.{}; + inline for (@typeInfo(deps.imports).Struct.decls) |decl| { + if (comptime std.mem.indexOfScalar(u8, decl.name, '.') == null) { + const maybe_bsp = @field(deps.imports, decl.name); + + if (@hasDecl(maybe_bsp, "microzig_board_support")) { + const bsp = @field(maybe_bsp, "microzig_board_support"); + if (@TypeOf(bsp) == BoardSupportPackageDefinition) { + bsps = bsps ++ [_]ImportedBSP{.{ + .import_name = decl.name, + .bsp = bsp, + }}; + } + } + } + } + return bsps; +} +pub const EnvironmentInfo = struct { /// package name of the build package (optional) self: []const u8 = "microzig", @@ -21,93 +142,37 @@ pub const EnvironmentInfo = struct { }; pub fn createBuildEnvironment(b: *std.Build, comptime info: EnvironmentInfo) *BuildEnvironment { + const available_bsps = comptime get_declared_bsps(); + const be = b.allocator.create(BuildEnvironment) catch @panic("out of memory"); be.* = BuildEnvironment{ .host_build = b, .self = undefined, .microzig_core = undefined, - .board_support_packages = b.allocator.alloc(BoardSupportPackage, info.board_support.len) catch @panic("out of memory"), + .board_support_packages = b.allocator.alloc(BoardSupportPackage, available_bsps.len) catch @panic("out of memory"), .targets = .{}, }; be.self = b.dependency(info.self, .{}); be.microzig_core = b.dependency(info.core, .{}); - for (be.board_support_packages, info.board_support) |*out, in| { - out.* = BoardSupportPackage{ - .name = in, - .dep = b.dependency(in, .{}), + inline for (be.board_support_packages, available_bsps) |*bsp, def| { + bsp.* = BoardSupportPackage{ + .name = def.import_name, + .dep = b.dependency(def.import_name, .{}), }; - } - // Fetch and collect all supported targets: - inline for (info.board_support) |bsp_name| { - // Keep in sync with the logic from Build.zig:dependency - const build_runner = @import("root"); - const deps = build_runner.dependencies; + for (def.bsp.targets) |tgt| { + const full_name = b.fmt("{s}#{s}", .{ tgt.id, def.import_name }); - const bsp_root = @field(deps.imports, bsp_name); - - if (@hasDecl(bsp_root, "chips")) { - fetch_microzig_targets("chip:", bsp_root.chips, bsp_name, be); - } - - if (@hasDecl(bsp_root, "boards")) { - fetch_microzig_targets("board:", bsp_root.boards, bsp_name, be); + be.targets.put(be.host_build.allocator, tgt.id, tgt.target) catch @panic("out of memory"); + be.targets.put(be.host_build.allocator, full_name, tgt.target) catch @panic("out of memory"); } } return be; } -fn fetch_microzig_targets(comptime prefix: []const u8, comptime namespace: type, comptime bsp_name: []const u8, be: *BuildEnvironment) void { - inline for (@typeInfo(namespace).Struct.decls) |decl_info| { - const decl = @field(namespace, decl_info.name); - const T = @TypeOf(decl); - - const name = comptime prefix ++ decl_info.name; // board:vendor/name - const full_name = comptime name ++ "#" ++ bsp_name; // board:vendor/name#bsp-package-name - - if (T == Target) { - const target: Target = decl; - - be.targets.put(be.host_build.allocator, name, target) catch @panic("out of memory"); - be.targets.put(be.host_build.allocator, full_name, target) catch @panic("out of memory"); - } else { - const ok = blk: { - if (comptime T != type) { - // @compileLog(full_name, "check 1:", T, decl); - break :blk false; - } - - const ti = @typeInfo(decl); - if (comptime ti != .Struct) { - // @compileLog(full_name, "check 2:", ti); - break :blk false; - } - - if (comptime ti.Struct.fields.len > 0) { - // @compileLog(full_name, "check 3:", ti.Struct); - // @compileLog(full_name, "check 3:", ti.Struct.fields); - break :blk false; - } - - fetch_microzig_targets( - comptime name ++ "/", - decl, - bsp_name, - be, - ); - - break :blk true; - }; - if (!ok) { - std.debug.print("Bad BSP: {s} is neither namespace nor a microzig.Target\n", .{ prefix, full_name }); - } - } - } -} - pub const BoardSupportPackage = struct { dep: *std.Build.Dependency, name: []const u8, diff --git a/core/build.zig b/core/build.zig index 1768f51..0337090 100644 --- a/core/build.zig +++ b/core/build.zig @@ -4,35 +4,12 @@ const std = @import("std"); const microbuild = @import("microzig-build"); -// const uf2 = @import("uf2"); - -//////////////////////////////////////// -// MicroZig Gen 2 Interface // -//////////////////////////////////////// fn root() []const u8 { return comptime (std.fs.path.dirname(@src().file) orelse "."); } const build_root = root(); -// const MicroZig = @This(); - -// b: *std.Build, -// self: *std.Build.Dependency, - -// /// Creates a new instance of the MicroZig build support. -// /// -// /// This is necessary as we need to keep track of some internal state to prevent -// /// duplicated work per firmware built. -// pub fn init(b: *std.Build, dependency_name: []const u8) *MicroZig { -// const mz = b.allocator.create(MicroZig) catch @panic("out of memory"); -// mz.* = MicroZig{ -// .b = b, -// .self = b.dependency(dependency_name, .{}), -// }; -// return mz; -// } - /// This build script validates usage patterns we expect from MicroZig pub fn build(b: *std.Build) !void { _ = b; @@ -98,684 +75,6 @@ pub fn build(b: *std.Build) !void { // test_step.dependOn(&b.addRunArtifact(core_tests).step); } -// /// The resulting binary format for the firmware file. -// /// A lot of embedded systems don't use plain ELF files, thus we provide means -// /// to convert the resulting ELF into other common formats. -// pub const BinaryFormat = union(enum) { -// /// [Executable and Linkable Format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format), the standard output from the compiler. -// elf, - -// /// A flat binary, contains only the loaded portions of the firmware with an unspecified base offset. -// bin, - -// /// The [Intel HEX](https://en.wikipedia.org/wiki/Intel_HEX) format, contains -// /// an ASCII description of what memory to load where. -// hex, - -// /// A [Device Firmware Upgrade](https://www.usb.org/sites/default/files/DFU_1.1.pdf) file. -// dfu, - -// /// The [USB Flashing Format (UF2)](https://github.com/microsoft/uf2) designed by Microsoft. -// uf2: uf2.FamilyId, - -// /// The [firmware format](https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/firmware-image-format.html) used by the [esptool](https://github.com/espressif/esptool) bootloader. -// esp, - -// /// Custom option for non-standard formats. -// custom: *Custom, - -// /// Returns the standard extension for the resulting binary file. -// pub fn getExtension(format: BinaryFormat) []const u8 { -// return switch (format) { -// .elf => ".elf", -// .bin => ".bin", -// .hex => ".hex", -// .dfu => ".dfu", -// .uf2 => ".uf2", -// .esp => ".bin", - -// .custom => |c| c.extension, -// }; -// } - -// pub const Custom = struct { -// /// The standard extension of the format. -// extension: []const u8, - -// /// A function that will convert a given `elf` file into the custom output format. -// /// -// /// The `*Custom` format is passed so contextual information can be obtained by using -// /// `@fieldParentPtr` to provide access to tooling. -// convert: *const fn (*Custom, elf: std.Build.LazyPath) std.Build.LazyPath, -// }; - -// const Enum = std.meta.Tag(BinaryFormat); - -// const Context = struct { -// pub fn hash(self: @This(), fmt: BinaryFormat) u32 { -// _ = self; - -// var hasher = std.hash.XxHash32.init(0x1337_42_21); - -// hasher.update(@tagName(fmt)); - -// switch (fmt) { -// .elf, .bin, .hex, .dfu, .esp => |val| { -// if (@TypeOf(val) != void) @compileError("Missing update: Context.hash now requires special care!"); -// }, - -// .uf2 => |family_id| hasher.update(@tagName(family_id)), -// .custom => |custom| hasher.update(std.mem.asBytes(custom)), -// } - -// return hasher.final(); -// } - -// pub fn eql(self: @This(), fmt_a: BinaryFormat, fmt_b: BinaryFormat, index: usize) bool { -// _ = self; -// _ = index; -// if (@as(BinaryFormat.Enum, fmt_a) != @as(BinaryFormat.Enum, fmt_b)) -// return false; - -// return switch (fmt_a) { -// .elf, .bin, .hex, .dfu, .esp => |val| { -// if (@TypeOf(val) != void) @compileError("Missing update: Context.eql now requires special care!"); -// return true; -// }, - -// .uf2 => |a| (a == fmt_b.uf2), -// .custom => |a| (a == fmt_b.custom), -// }; -// } -// }; -// }; - -// /// The CPU model a target uses. -// /// -// /// The CPUs usually require special care on how to do interrupts, and getting an entry point. -// /// -// /// MicroZig officially only supports the CPUs listed here, but other CPUs might be provided -// /// via the `custom` field. -// pub const CpuModel = union(enum) { -// avr5, -// cortex_m0, -// cortex_m0plus, -// cortex_m3, -// cortex_m4, -// riscv32_imac, - -// custom: *const Cpu, - -// pub fn getDescriptor(model: CpuModel) *const Cpu { -// return switch (@as(std.meta.Tag(CpuModel), model)) { -// inline else => |tag| &@field(cpus, @tagName(tag)), -// .custom => model.custom, -// }; -// } -// }; - -// /// A cpu descriptor. -// pub const Cpu = struct { -// /// Display name of the CPU. -// name: []const u8, - -// /// Source file providing startup code and memory initialization routines. -// source_file: std.build.LazyPath, - -// /// The compiler target we use to compile all the code. -// target: std.zig.CrossTarget, -// }; - -// /// A descriptor for memory regions in a microcontroller. -// pub const MemoryRegion = struct { -// /// The type of the memory region for generating a proper linker script. -// kind: Kind, -// offset: u64, -// length: u64, - -// pub const Kind = union(enum) { -// /// This is a (normally) immutable memory region where the code is stored. -// flash, - -// /// This is a mutable memory region for data storage. -// ram, - -// /// This is a memory region that maps MMIO devices. -// io, - -// /// This is a memory region that exists, but is reserved and must not be used. -// reserved, - -// /// This is a memory region used for internal linking tasks required by the board support package. -// private: PrivateRegion, -// }; - -// pub const PrivateRegion = struct { -// /// The name of the memory region. Will not have an automatic numeric counter and must be unique. -// name: []const u8, - -// /// Is the memory region executable? -// executable: bool, - -// /// Is the memory region readable? -// readable: bool, - -// /// Is the memory region writable? -// writeable: bool, -// }; -// }; - -// /// Defines a custom microcontroller. -// pub const Chip = struct { -// /// The display name of the controller. -// name: []const u8, - -// /// (optional) link to the documentation/vendor page of the controller. -// url: ?[]const u8 = null, - -// /// The cpu model this controller uses. -// cpu: CpuModel, - -// /// The provider for register definitions. -// register_definition: union(enum) { -// /// Use `regz` to create a zig file from a JSON schema. -// json: std.Build.LazyPath, - -// /// Use `regz` to create a json file from a SVD schema. -// svd: std.Build.LazyPath, - -// /// Use `regz` to create a zig file from an ATDF schema. -// atdf: std.Build.LazyPath, - -// /// Use the provided file directly as the chip file. -// zig: std.Build.LazyPath, -// }, - -// /// The memory regions that are present in this chip. -// memory_regions: []const MemoryRegion, -// }; - -// /// Defines a hardware abstraction layer. -// pub const HardwareAbstractionLayer = struct { -// /// Root source file for this HAL. -// source_file: std.Build.LazyPath, -// }; - -// /// Provides a description of a board. -// /// -// /// Boards provide additional information to a chip and HAL package. -// /// For example, they can list attached peripherials, external crystal frequencies, -// /// flash sizes, ... -// pub const BoardDefinition = struct { -// /// Display name of the board -// name: []const u8, - -// /// (optional) link to the documentation/vendor page of the board. -// url: ?[]const u8 = null, - -// /// Provides the root file for the board definition. -// source_file: std.Build.LazyPath, -// }; - -// /// The linker script used to link the firmware. -// pub const LinkerScript = union(enum) { -// /// Auto-generated linker script derived from the memory regions of the chip. -// generated, - -// /// Externally defined linker script. -// source_file: std.build.LazyPath, -// }; - -// /// A compilation target for MicroZig. Provides information about the chip, -// /// hal, board and so on. -// /// -// /// This is used instead of `std.zig.CrossTarget` to define a MicroZig Firmware. -// pub const Target = struct { -// /// The preferred binary format of this MicroZig target. If `null`, the user must -// /// explicitly give the `.format` field during a call to `getEmittedBin()` or installation steps. -// preferred_format: ?BinaryFormat, - -// /// The chip this target uses, -// chip: Chip, - -// /// Usually, embedded projects are single-threaded and single-core applications. Platforms that -// /// support multiple CPUs should set this to `false`. -// single_threaded: bool = true, - -// /// Determines whether the compiler_rt package is bundled with the application or not. -// /// This should always be true except for platforms where compiler_rt cannot be built right now. -// bundle_compiler_rt: bool = true, - -// /// (optional) Provides a default hardware abstraction layer that is used. -// /// If `null`, no `microzig.hal` will be available. -// hal: ?HardwareAbstractionLayer = null, - -// /// (optional) Provides description of external hardware and connected devices -// /// like oscillators and such. -// /// -// /// This structure isn't used by MicroZig itself, but can be utilized from the HAL -// /// if present. -// board: ?BoardDefinition = null, - -// /// (optional) Provide a custom linker script for the hardware or define a custom generation. -// linker_script: LinkerScript = .generated, - -// /// (optional) Further configures the created firmware depending on the chip and/or board settings. -// /// This can be used to set/change additional properties on the created `*Firmware` object. -// configure: ?*const fn (host_build: *std.Build, *Firmware) void = null, - -// /// (optional) Post processing step that will patch up and modify the elf file if necessary. -// binary_post_process: ?*const fn (host_build: *std.Build, std.Build.LazyPath) std.Build.LazyPath = null, -// }; - -// /// Options to the `addFirmware` function. -// pub const FirmwareOptions = struct { -// /// The name of the firmware file. -// name: []const u8, - -// /// The MicroZig target that the firmware is built for. Either a board or a chip. -// target: Target, - -// /// The optimization level that should be used. Usually `ReleaseSmall` or `Debug` is a good choice. -// /// Also using `std.Build.standardOptimizeOption` is a good idea. -// optimize: std.builtin.OptimizeMode, - -// /// The root source file for the application. This is your `src/main.zig` file. -// source_file: std.Build.LazyPath, - -// // Overrides: - -// /// If set, overrides the `single_threaded` property of the target. -// single_threaded: ?bool = null, - -// /// If set, overrides the `bundle_compiler_rt` property of the target. -// bundle_compiler_rt: ?bool = null, - -// /// If set, overrides the `hal` property of the target. -// hal: ?HardwareAbstractionLayer = null, - -// /// If set, overrides the `board` property of the target. -// board: ?BoardDefinition = null, - -// /// If set, overrides the `linker_script` property of the target. -// linker_script: ?LinkerScript = null, -// }; - -// /// Declares a new MicroZig firmware file. -// pub fn addFirmware( -// /// The MicroZig instance that should be used to create the firmware. -// mz: *MicroZig, -// /// The instance of the `build.zig` that is calling this function. -// host_build: *std.Build, -// /// Options that define how the firmware is built. -// options: FirmwareOptions, -// ) *Firmware { -// const micro_build = mz.self.builder; - -// const chip = &options.target.chip; -// const cpu = chip.cpu.getDescriptor(); -// const maybe_hal = options.hal orelse options.target.hal; -// const maybe_board = options.board orelse options.target.board; - -// const linker_script = options.linker_script orelse options.target.linker_script; - -// // TODO: let the user override which ram section to use the stack on, -// // for now just using the first ram section in the memory region list -// const first_ram = blk: { -// for (chip.memory_regions) |region| { -// if (region.kind == .ram) -// break :blk region; -// } else @panic("no ram memory region found for setting the end-of-stack address"); -// }; - -// // On demand, generate chip definitions via regz: -// const chip_source = switch (chip.register_definition) { -// .json, .atdf, .svd => |file| blk: { -// const regz_exe = mz.dependency("regz", .{ .optimize = .ReleaseSafe }).artifact("regz"); - -// const regz_gen = host_build.addRunArtifact(regz_exe); - -// regz_gen.addArg("--schema"); // Explicitly set schema type, one of: svd, atdf, json -// regz_gen.addArg(@tagName(chip.register_definition)); - -// regz_gen.addArg("--output_path"); // Write to a file -// const zig_file = regz_gen.addOutputFileArg("chip.zig"); - -// regz_gen.addFileArg(file); - -// break :blk zig_file; -// }, - -// .zig => |src| src, -// }; - -// const config = host_build.addOptions(); -// config.addOption(bool, "has_hal", (maybe_hal != null)); -// config.addOption(bool, "has_board", (maybe_board != null)); - -// config.addOption(?[]const u8, "board_name", if (maybe_board) |brd| brd.name else null); - -// config.addOption([]const u8, "chip_name", chip.name); -// config.addOption([]const u8, "cpu_name", chip.name); -// config.addOption(usize, "end_of_stack", first_ram.offset + first_ram.length); - -// const fw: *Firmware = host_build.allocator.create(Firmware) catch @panic("out of memory"); -// fw.* = Firmware{ -// .mz = mz, -// .host_build = host_build, -// .artifact = host_build.addExecutable(.{ -// .name = options.name, -// .optimize = options.optimize, -// .target = cpu.target, -// .linkage = .static, -// .root_source_file = .{ .cwd_relative = mz.self.builder.pathFromRoot("src/start.zig") }, -// }), -// .target = options.target, -// .output_files = Firmware.OutputFileMap.init(host_build.allocator), - -// .config = config, - -// .modules = .{ -// .microzig = micro_build.createModule(.{ -// .source_file = .{ .cwd_relative = micro_build.pathFromRoot("src/microzig.zig") }, -// .dependencies = &.{ -// .{ -// .name = "config", -// .module = micro_build.createModule(.{ .source_file = config.getSource() }), -// }, -// }, -// }), - -// .cpu = undefined, -// .chip = undefined, - -// .board = null, -// .hal = null, - -// .app = undefined, -// }, -// }; -// errdefer fw.output_files.deinit(); - -// fw.modules.chip = micro_build.createModule(.{ -// .source_file = chip_source, -// .dependencies = &.{ -// .{ .name = "microzig", .module = fw.modules.microzig }, -// }, -// }); -// fw.modules.microzig.dependencies.put("chip", fw.modules.chip) catch @panic("out of memory"); - -// fw.modules.cpu = micro_build.createModule(.{ -// .source_file = cpu.source_file, -// .dependencies = &.{ -// .{ .name = "microzig", .module = fw.modules.microzig }, -// }, -// }); -// fw.modules.microzig.dependencies.put("cpu", fw.modules.cpu) catch @panic("out of memory"); - -// if (maybe_hal) |hal| { -// fw.modules.hal = micro_build.createModule(.{ -// .source_file = hal.source_file, -// .dependencies = &.{ -// .{ .name = "microzig", .module = fw.modules.microzig }, -// }, -// }); -// fw.modules.microzig.dependencies.put("hal", fw.modules.hal.?) catch @panic("out of memory"); -// } - -// if (maybe_board) |brd| { -// fw.modules.board = micro_build.createModule(.{ -// .source_file = brd.source_file, -// .dependencies = &.{ -// .{ .name = "microzig", .module = fw.modules.microzig }, -// }, -// }); -// fw.modules.microzig.dependencies.put("board", fw.modules.board.?) catch @panic("out of memory"); -// } - -// fw.modules.app = host_build.createModule(.{ -// .source_file = options.source_file, -// .dependencies = &.{ -// .{ .name = "microzig", .module = fw.modules.microzig }, -// }, -// }); - -// const umm = mz.dependency("umm-zig", .{}).module("umm"); -// fw.modules.microzig.dependencies.put("umm", umm) catch @panic("out of memory"); - -// fw.artifact.addModule("app", fw.modules.app); -// fw.artifact.addModule("microzig", fw.modules.microzig); - -// fw.artifact.strip = false; // we always want debug symbols, stripping brings us no benefit on embedded -// fw.artifact.single_threaded = options.single_threaded orelse fw.target.single_threaded; -// fw.artifact.bundle_compiler_rt = options.bundle_compiler_rt orelse fw.target.bundle_compiler_rt; - -// switch (linker_script) { -// .generated => { -// fw.artifact.setLinkerScript( -// generateLinkerScript(host_build, chip.*) catch @panic("out of memory"), -// ); -// }, - -// .source_file => |source| { -// fw.artifact.setLinkerScriptPath(source); -// }, -// } - -// if (options.target.configure) |configure| { -// configure(host_build, fw); -// } - -// return fw; -// } - -// /// Configuration options for firmware installation. -// pub const InstallFirmwareOptions = struct { -// /// Overrides the output format for the binary. If not set, the standard preferred file format for the firmware target is used. -// format: ?BinaryFormat = null, -// }; - -// /// Adds a new dependency to the `install` step that will install the `firmware` into the folder `$prefix/firmware`. -// pub fn installFirmware( -// /// The MicroZig instance that was used to create the firmware. -// mz: *MicroZig, -// /// The instance of the `build.zig` that should perform installation. -// b: *std.Build, -// /// The firmware that should be installed. Please make sure that this was created with the same `MicroZig` instance as `mz`. -// firmware: *Firmware, -// /// Optional configuration of the installation process. Pass `.{}` if you're not sure what to do here. -// options: InstallFirmwareOptions, -// ) void { -// std.debug.assert(mz == firmware.mz); -// const install_step = addInstallFirmware(mz, b, firmware, options); -// b.getInstallStep().dependOn(&install_step.step); -// } - -// /// Creates a new `std.Build.Step.InstallFile` instance that will install the given firmware to `$prefix/firmware`. -// /// -// /// **NOTE:** This does not actually install the firmware yet. You have to add the returned step as a dependency to another step. -// /// If you want to just install the firmware, use `installFirmware` instead! -// pub fn addInstallFirmware( -// /// The MicroZig instance that was used to create the firmware. -// mz: *MicroZig, -// /// The instance of the `build.zig` that should perform installation. -// b: *std.Build, -// /// The firmware that should be installed. Please make sure that this was created with the same `MicroZig` instance as `mz`. -// firmware: *Firmware, -// /// Optional configuration of the installation process. Pass `.{}` if you're not sure what to do here. -// options: InstallFirmwareOptions, -// ) *std.Build.Step.InstallFile { -// const format = firmware.resolveFormat(options.format); - -// const basename = b.fmt("{s}{s}", .{ -// firmware.artifact.name, -// format.getExtension(), -// }); - -// _ = mz; - -// return b.addInstallFileWithDir(firmware.getEmittedBin(format), .{ .custom = "firmware" }, basename); -// } - -// /// Declaration of a firmware build. -// pub const Firmware = struct { -// const OutputFileMap = std.ArrayHashMap(BinaryFormat, std.Build.LazyPath, BinaryFormat.Context, false); - -// const Modules = struct { -// app: *std.Build.Module, -// cpu: *std.Build.Module, -// chip: *std.Build.Module, -// board: ?*std.Build.Module, -// hal: ?*std.Build.Module, -// microzig: *std.Build.Module, -// }; - -// // privates: -// mz: *MicroZig, -// host_build: *std.Build, -// target: Target, -// output_files: OutputFileMap, - -// // publics: - -// /// The artifact that is built by Zig. -// artifact: *std.Build.Step.Compile, - -// /// The options step that provides `microzig.config`. If you need custom configuration, you can add this here. -// config: *std.Build.Step.Options, - -// /// Declaration of the MicroZig modules used by this firmware. -// modules: Modules, - -// /// Path to the emitted elf file, if any. -// emitted_elf: ?std.Build.LazyPath = null, - -// /// Returns the emitted ELF file for this firmware. This is useful if you need debug information -// /// or want to use a debugger like Segger, ST-Link or similar. -// /// -// /// **NOTE:** This is similar, but not equivalent to `std.Build.Step.Compile.getEmittedBin`. The call on the compile step does -// /// not include post processing of the ELF files necessary by certain targets. -// pub fn getEmittedElf(firmware: *Firmware) std.Build.LazyPath { -// if (firmware.emitted_elf == null) { -// const raw_elf = firmware.artifact.getEmittedBin(); -// firmware.emitted_elf = if (firmware.target.binary_post_process) |binary_post_process| -// binary_post_process(firmware.host_build, raw_elf) -// else -// raw_elf; -// } -// return firmware.emitted_elf.?; -// } - -// /// Returns the emitted binary for this firmware. The file is either in the preferred file format for -// /// the target or in `format` if not null. -// /// -// /// **NOTE:** The file returned here is the same file that will be installed. -// pub fn getEmittedBin(firmware: *Firmware, format: ?BinaryFormat) std.Build.LazyPath { -// const actual_format = firmware.resolveFormat(format); - -// const gop = firmware.output_files.getOrPut(actual_format) catch @panic("out of memory"); -// if (!gop.found_existing) { -// const elf_file = firmware.getEmittedElf(); - -// const basename = firmware.host_build.fmt("{s}{s}", .{ -// firmware.artifact.name, -// actual_format.getExtension(), -// }); - -// gop.value_ptr.* = switch (actual_format) { -// .elf => elf_file, - -// .bin => blk: { -// const objcopy = firmware.host_build.addObjCopy(elf_file, .{ -// .basename = basename, -// .format = .bin, -// }); - -// break :blk objcopy.getOutput(); -// }, - -// .hex => blk: { -// const objcopy = firmware.host_build.addObjCopy(elf_file, .{ -// .basename = basename, -// .format = .hex, -// }); - -// break :blk objcopy.getOutput(); -// }, - -// .uf2 => |family_id| blk: { -// const uf2_exe = firmware.mz.dependency("uf2", .{ .optimize = .ReleaseSafe }).artifact("elf2uf2"); - -// const convert = firmware.host_build.addRunArtifact(uf2_exe); - -// convert.addArg("--family-id"); -// convert.addArg(firmware.host_build.fmt("0x{X:0>4}", .{@intFromEnum(family_id)})); - -// convert.addArg("--elf-path"); -// convert.addFileArg(elf_file); - -// convert.addArg("--output-path"); -// break :blk convert.addOutputFileArg(basename); -// }, - -// .dfu => buildConfigError(firmware.host_build, "DFU is not implemented yet. See https://github.com/ZigEmbeddedGroup/microzig/issues/145 for more details!", .{}), -// .esp => buildConfigError(firmware.host_build, "ESP firmware image is not implemented yet. See https://github.com/ZigEmbeddedGroup/microzig/issues/146 for more details!", .{}), - -// .custom => |generator| generator.convert(generator, elf_file), -// }; -// } -// return gop.value_ptr.*; -// } - -// pub const AppDependencyOptions = struct { -// depend_on_microzig: bool = false, -// }; - -// /// Adds a regular dependency to your application. -// pub fn addAppDependency(fw: *Firmware, name: []const u8, module: *std.Build.Module, options: AppDependencyOptions) void { -// if (options.depend_on_microzig) { -// module.dependencies.put("microzig", fw.modules.microzig) catch @panic("OOM"); -// } -// fw.modules.app.dependencies.put(name, module) catch @panic("OOM"); -// } - -// pub fn addIncludePath(fw: *Firmware, path: std.Build.LazyPath) void { -// fw.artifact.addIncludePath(path); -// } - -// pub fn addSystemIncludePath(fw: *Firmware, path: std.Build.LazyPath) void { -// fw.artifact.addSystemIncludePath(path); -// } - -// pub fn addCSourceFile(fw: *Firmware, source: std.Build.Step.Compile.CSourceFile) void { -// fw.artifact.addCSourceFile(source); -// } - -// pub fn addOptions(fw: *Firmware, module_name: []const u8, options: *std.Build.OptionsStep) void { -// fw.artifact.addOptions(module_name, options); -// fw.modules.app.dependencies.put( -// module_name, -// fw.host_build.createModule(.{ -// .source_file = options.getOutput(), -// }), -// ) catch @panic("OOM"); -// } - -// pub fn addObjectFile(fw: *Firmware, source: std.Build.LazyPath) void { -// fw.artifact.addObjectFile(source); -// } - -// fn resolveFormat(firmware: *Firmware, format: ?BinaryFormat) BinaryFormat { -// if (format) |fmt| return fmt; - -// if (firmware.target.preferred_format) |fmt| return fmt; - -// buildConfigError(firmware.host_build, "{s} has no preferred output format, please provide one in the `format` option.", .{ -// firmware.target.chip.name, -// }); -// } -// }; - pub const cpus = struct { pub const avr5 = microbuild.Cpu{ .name = "AVR5", @@ -843,139 +142,3 @@ pub const cpus = struct { }, }; }; - -// fn buildConfigError(b: *std.Build, comptime fmt: []const u8, args: anytype) noreturn { -// const msg = b.fmt(fmt, args); -// @panic(msg); -// } - -// fn dependency(mz: *MicroZig, name: []const u8, args: anytype) *std.Build.Dependency { -// return mz.self.builder.dependency(name, args); -// } - -// fn generateLinkerScript(b: *std.Build, chip: Chip) !std.Build.LazyPath { -// const cpu = chip.cpu.getDescriptor(); - -// var contents = std.ArrayList(u8).init(b.allocator); -// const writer = contents.writer(); -// try writer.print( -// \\/* -// \\ * This file was auto-generated by microzig -// \\ * -// \\ * Target CPU: {[cpu]s} -// \\ * Target Chip: {[chip]s} -// \\ */ -// \\ -// // This is not the "true" entry point, but there's no such thing on embedded platforms -// // anyways. This is the logical entrypoint that should be invoked when -// // stack, .data and .bss are set up and the CPU is ready to be used. -// \\ENTRY(microzig_main); -// \\ -// \\ -// , .{ -// .cpu = cpu.name, -// .chip = chip.name, -// }); - -// try writer.writeAll("MEMORY\n{\n"); -// { -// var counters = [4]usize{ 0, 0, 0, 0 }; -// for (chip.memory_regions) |region| { -// // flash (rx!w) : ORIGIN = 0x00000000, LENGTH = 512k - -// switch (region.kind) { -// .flash => { -// try writer.print(" flash{d} (rx!w)", .{counters[0]}); -// counters[0] += 1; -// }, - -// .ram => { -// try writer.print(" ram{d} (rw!x)", .{counters[1]}); -// counters[1] += 1; -// }, - -// .io => { -// try writer.print(" io{d} (rw!x)", .{counters[2]}); -// counters[2] += 1; -// }, - -// .reserved => { -// try writer.print(" reserved{d} (rw!x)", .{counters[3]}); -// counters[3] += 1; -// }, - -// .private => |custom| { -// try writer.print(" {s} (", .{custom.name}); -// if (custom.readable) try writer.writeAll("r"); -// if (custom.writeable) try writer.writeAll("w"); -// if (custom.executable) try writer.writeAll("x"); - -// if (!custom.readable or !custom.writeable or !custom.executable) { -// try writer.writeAll("!"); -// if (!custom.readable) try writer.writeAll("r"); -// if (!custom.writeable) try writer.writeAll("w"); -// if (!custom.executable) try writer.writeAll("x"); -// } -// try writer.writeAll(")"); -// }, -// } -// try writer.print(" : ORIGIN = 0x{X:0>8}, LENGTH = 0x{X:0>8}\n", .{ region.offset, region.length }); -// } -// } - -// try writer.writeAll("}\n\nSECTIONS\n{\n"); -// { -// try writer.writeAll( -// \\ .text : -// \\ { -// \\ KEEP(*(microzig_flash_start)) -// \\ *(.text*) -// \\ } > flash0 -// \\ -// \\ -// ); - -// switch (cpu.target.getCpuArch()) { -// .arm, .thumb => try writer.writeAll( -// \\ .ARM.exidx : { -// \\ *(.ARM.exidx* .gnu.linkonce.armexidx.*) -// \\ } >flash0 -// \\ -// \\ -// ), -// else => {}, -// } - -// try writer.writeAll( -// \\ .data : -// \\ { -// \\ microzig_data_start = .; -// \\ *(.rodata*) -// \\ *(.data*) -// \\ microzig_data_end = .; -// \\ } > ram0 AT> flash0 -// \\ -// \\ .bss (NOLOAD) : -// \\ { -// \\ microzig_bss_start = .; -// \\ *(.bss*) -// \\ microzig_bss_end = .; -// \\ } > ram0 -// \\ -// \\ microzig_data_load_start = LOADADDR(.data); -// \\ -// ); -// } -// try writer.writeAll("}\n"); - -// // TODO: Assert that the flash can actually hold all data! -// // try writer.writeAll( -// // \\ -// // \\ ASSERT( (SIZEOF(.text) + SIZEOF(.data) > LENGTH(flash0)), "Error: .text + .data is too large for flash!" ); -// // \\ -// // ); - -// const write = b.addWriteFiles(); - -// return write.add("linker.ld", contents.items); -// } diff --git a/examples/next-gen/build.zig b/examples/next-gen/build.zig index 37628be..0c3579e 100644 --- a/examples/next-gen/build.zig +++ b/examples/next-gen/build.zig @@ -5,11 +5,6 @@ pub fn build(b: *std.Build) void { const microzig = MicroZig.createBuildEnvironment(b, .{ .self = "microzig", // package name of the build package (optional) .core = "microzig-core", // package name of the core package (optional) - .board_support = &.{ - // package names for BSP packages: - "microzig-bsp-nxp", - "microzig-bsp-rp2040", - }, }); const optimize = b.standardOptimizeOption(.{}); diff --git a/examples/next-gen/build.zig.zon b/examples/next-gen/build.zig.zon index f9d6f77..9053967 100644 --- a/examples/next-gen/build.zig.zon +++ b/examples/next-gen/build.zig.zon @@ -4,19 +4,19 @@ .dependencies = .{ .microzig = .{ .url = "https://public.devspace.random-projects.net/microzig-build.tar.gz", - .hash = "122068db50e2a071cac3fc5b42d5cd2213ccb563986af60b941cb7af29b83df65b02", + .hash = "1220c87cc608598bdb4ae5ed6436c6fa3e126c57d3d1bbfaf01625c3af0c15da44e4", }, .@"microzig-core" = .{ .url = "https://public.devspace.random-projects.net/microzig-core.tar.gz", - .hash = "12202df033d2b967108b25b8e66d8c8abcf690348a24baa35474a28086170ff31e54", + .hash = "1220a37d914f0585bbaeba2bc4d4d15586bef310a6af340af87f0e13fde0b4ddfb1a", }, .@"microzig-bsp-nxp" = .{ .url = "https://public.devspace.random-projects.net/board-support/nxp/lpc.tar.gz", - .hash = "12201efd8d8b992caef770c87d78e6bd00bd73051bd1559bc342703f2e83650ef2f9", + .hash = "122040dc9467f6dac90a1376fff25350b2a5abd291904db7bea48a78db4f6e6dff13", }, .@"microzig-bsp-rp2040" = .{ .url = "https://public.devspace.random-projects.net/board-support/raspberrypi/rp2040.tar.gz", - .hash = "1220154cd3634d0f3286cd2fb727cce9af3f3ab166772065e3efe4f9577128f4c559", + .hash = "1220142a13e590252deb7667569bdd3f6147c5b461f6b0343a825079a7dd3a24dea9", }, }, } \ No newline at end of file diff --git a/tools/extract-bsp-info.zig b/tools/extract-bsp-info.zig index b0f5627..4c2b260 100644 --- a/tools/extract-bsp-info.zig +++ b/tools/extract-bsp-info.zig @@ -70,33 +70,26 @@ fn renderMicroZigTarget(stream: anytype, key: []const u8, target: microzig.Targe try std.json.stringify(jtarget, .{}, stream); } -fn renderTargetArray(stream: anytype, comptime array: type) !void { - inline for (comptime std.meta.declarations(array), 0..) |fld, i| { +fn renderTargetArray(stream: anytype, targets: []const microzig.BoardSupportPackageDefinition.TargetDefinition) !void { + for (targets, 0..) |target_def, i| { if (i > 0) try stream.writeAll(","); - const target = comptime @field(array, fld.name); - - if (@TypeOf(target) == type) { - // recurse - try renderTargetArray(stream, target); - } else { - try renderMicroZigTarget( - stream, - fld.name, - target, - ); - } + try renderMicroZigTarget( + stream, + target_def.id, + target_def.target, + ); } } pub fn main() !void { + const info = bsp.microzig_board_support; + var stdout = std.io.getStdOut().writer(); try stdout.writeAll("{ \"board-support\": {"); - try stdout.writeAll("\"chips\":["); - try renderTargetArray(stdout, bsp.chips); - try stdout.writeAll("],\"boards\":["); - try renderTargetArray(stdout, bsp.boards); + try stdout.writeAll("\"targets\":["); + try renderTargetArray(stdout, info.targets); try stdout.writeAll("]}}"); }