const std = @import("std"); pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const hex = b.dependency("hex", .{}); const zli = hex.module("zli"); const matte = hex.module("matte"); const mod = b.addModule("mplabx", .{ .root_source_file = b.path("src/root.zig"), .target = target, .imports = &.{ .{ .name = "cli", .module = zli }, .{ .name = "blush", .module = matte }, }, }); const exe = b.addExecutable(.{ .name = "mplabx", .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .imports = &.{ .{ .name = "mplabx", .module = mod }, .{ .name = "cli", .module = zli }, .{ .name = "blush", .module = matte }, }, }), }); b.installArtifact(exe); const run_step = b.step("run", "Run the app"); const run_cmd = b.addRunArtifact(exe); run_step.dependOn(&run_cmd.step); run_cmd.step.dependOn(b.getInstallStep()); if (b.args) |args| { run_cmd.addArgs(args); } const mod_tests = b.addTest(.{ .root_module = mod, }); const run_mod_tests = b.addRunArtifact(mod_tests); const exe_tests = b.addTest(.{ .root_module = exe.root_module, }); const run_exe_tests = b.addRunArtifact(exe_tests); const test_step = b.step("test", "Run tests"); test_step.dependOn(&run_mod_tests.step); test_step.dependOn(&run_exe_tests.step); buildJava(b); } /// Build the Java programming engine (java_src/). /// /// Steps: /// zig build java-lib - refresh java_src/lib from the MPLAB X install /// zig build java - compile owned sources into engine.jar /// zig build smoke - exercise the launcher end to end /// /// Environment: /// JAVAC / JAR tool overrides (default: resolved via PATH) fn buildJava(b: *std.Build) void { const java_lib_step = b.step("java-lib", "Refresh bundled engine jars from the MPLAB X install"); const assemble = b.addSystemCommand(&.{"./assemble-lib.sh"}); assemble.setCwd(b.path("java_src")); java_lib_step.dependOn(&assemble.step); const java_step = b.step("java", "Compile the Java engine and pack engine.jar"); const javac = envOrDefault(b, "JAVAC", "javac"); const jar_tool = envOrDefault(b, "JAR", "jar"); const cp = collectLibClasspath(b) catch |err| switch (err) { error.FileNotFound => { std.log.err( \\missing java_src/lib - run `zig build java-lib` first \\with the MPLAB X install available. , .{}); return; }, else => |e| { std.log.err("scanning java_src/lib failed: {s}", .{@errorName(e)}); return; }, }; const classes_dir = "build/classes"; const compile = b.addSystemCommand(&.{ javac, "--release", "8", "-encoding", "UTF-8", "-nowarn", "-cp", cp, "-d", classes_dir, }); compile.setCwd(b.path("java_src")); compile.addArgs(collectJavaSources(b)); java_step.dependOn(&compile.step); const jar_pack = b.addSystemCommand(&.{ jar_tool, "--create", "--file", "build/engine.jar", "-C", classes_dir, ".", "-C", "resources", ".", }); jar_pack.setCwd(b.path("java_src")); jar_pack.step.dependOn(&compile.step); java_step.dependOn(&jar_pack.step); // Smoke: launcher help path exercises classpath assembly end to end. const smoke_step = b.step("smoke", "Run progcli --list-tools through the launcher"); const smoke = b.addSystemCommand(&.{ "./bin/mplabx-program", "--list-tools" }); smoke.setCwd(b.path("java_src")); smoke.step.dependOn(java_step); smoke_step.dependOn(&smoke.step); } fn envOrDefault(b: *std.Build, name: []const u8, default: []const u8) []const u8 { return b.graph.environ_map.get(name) orelse default; } fn collectJavaSources(b: *std.Build) []const []const u8 { var list: std.ArrayList([]const u8) = .empty; const io = b.graph.io; var dir = std.Io.Dir.cwd().openDir(io, "java_src/src", .{ .iterate = true }) catch { std.log.err("cannot open java_src/src", .{}); std.process.exit(1); }; defer dir.close(io); var walker = dir.walk(b.allocator) catch @panic("OOM"); defer walker.deinit(); while (walker.next(io) catch |err| { std.log.err("walking java_src/src failed: {s}", .{@errorName(err)}); std.process.exit(1); }) |entry| { if (entry.kind != .file) continue; if (!std.mem.endsWith(u8, entry.basename, ".java")) continue; const rel = std.fmt.allocPrint(b.allocator, "src/{s}", .{entry.path}) catch @panic("OOM"); list.append(b.allocator, rel) catch @panic("OOM"); } return list.toOwnedSlice(b.allocator) catch @panic("OOM"); } fn collectLibClasspath(b: *std.Build) ![]const u8 { var out: std.ArrayList(u8) = .empty; const io = b.graph.io; var dir = try std.Io.Dir.cwd().openDir(io, "java_src/lib", .{ .iterate = true }); defer dir.close(io); var walker = try dir.walk(b.allocator); defer walker.deinit(); while (try walker.next(io)) |entry| { if (entry.kind != .file) continue; if (!std.mem.endsWith(u8, entry.basename, ".jar")) continue; if (out.items.len != 0) try out.append(b.allocator, ':'); try out.print(b.allocator, "lib/{s}", .{entry.path}); } return out.toOwnedSlice(b.allocator); }