const std = @import("std"); const manifest = @import("build.zig.zon"); pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); // What `parcel --version` says: the version a `release: X.Y.Z` commit // sets in build.zig.zon, unless the build names another. const options = b.addOptions(); options.addOption([]const u8, "version", b.option([]const u8, "version", "The version parcel reports") orelse manifest.version); // siv-static links libsiv.a into the program, so it runs from zig-out // with no libsiv.so beside it; libsiv.so also links with LLD, which bs // does not. siv-webview stays off until a view needs HTML mail. const siv = b.dependency("siv", .{ .target = target, .optimize = optimize, .webview = false }); const siv_mod = siv.module("siv-static"); // Local time for the dates mail shows, from the system's zone files. const zeit = b.dependency("zeit", .{ .target = target, .optimize = optimize }); const mod = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .imports = &.{ .{ .name = "siv", .module = siv_mod }, .{ .name = "zeit", .module = zeit.module("zeit") }, }, }); mod.addOptions("build_options", options); // HTTP, on siv's event loop (src/Http.zig). mod.linkSystemLibrary("curl", .{}); const exe = b.addExecutable(.{ .name = "parcel", .root_module = mod }); b.installArtifact(exe); // The desktop entry and its icon, named for the app_id the window // gives itself, so launchers and compositors match them to it. b.installFile("data/dev.rockorager.parcel.desktop", "share/applications/dev.rockorager.parcel.desktop"); b.installFile("data/dev.rockorager.parcel.svg", "share/icons/hicolor/scalable/apps/dev.rockorager.parcel.svg"); // The licences of what the binary compiles in, which it must carry: // libsiv's, then zeit's, parcel's one Zig dependency of its own. curl // is linked from the system. const rule: [78]u8 = @splat('='); const zeit_title = b.addWriteFiles().add("zeit-title", "\n" ++ rule ++ "\nzeit (MIT)\nhttps://github.com/rockorager/zeit\n" ++ rule ++ "\n\n"); const notices = b.addSystemCommand(&.{"cat"}); notices.addFileArg(siv.namedLazyPath("notices")); notices.addFileArg(zeit_title); notices.addFileArg(zeit.path("LICENSE")); b.getInstallStep().dependOn( &b.addInstallFileWithDir(notices.captureStdOut(.{}), .prefix, "share/doc/parcel/NOTICES").step, ); const run = b.addRunArtifact(exe); run.addPassthruArgs(); b.step("run", "Run parcel").dependOn(&run.step); // Mailbox-view prototypes (src/proto): `zig build proto -- NAME` runs // one, and `zig build proto-shots` renders them all headless to PNG. const proto_mod = b.createModule(.{ .root_source_file = b.path("src/proto/main.zig"), .target = target, .optimize = optimize, .imports = &.{.{ .name = "siv", .module = siv_mod }}, }); const proto = b.addExecutable(.{ .name = "parcel-proto", .root_module = proto_mod }); // Built with a development build of parcel, so it keeps compiling, but // not installed with it; a release build, which ships parcel alone, // leaves it out. if (optimize == .debug) b.getInstallStep().dependOn(&proto.step); const run_proto = b.addRunArtifact(proto); run_proto.addPassthruArgs(); b.step("proto", "Run a mailbox-view prototype (no NAME lists them)").dependOn(&run_proto.step); const image = b.dependency("image", .{ .target = target, .optimize = optimize }); const shots = b.addExecutable(.{ .name = "parcel-proto-shots", .root_module = b.createModule(.{ .root_source_file = b.path("src/proto/shots.zig"), .target = target, .optimize = optimize, .imports = &.{ .{ .name = "siv", .module = siv_mod }, .{ .name = "image", .module = image.module("image") }, }, }), }); const run_shots = b.addRunArtifact(shots); run_shots.addDirectoryArg(b.path("zig-out/shots")); run_shots.addPassthruArgs(); run_shots.has_side_effects = true; b.step("proto-shots", "Render the prototypes to zig-out/shots (NAME... picks some)").dependOn(&run_shots.step); // The tests run siv on its headless backend, so they need no display. const filters = b.option([]const []const u8, "test-filter", "Run only tests whose names contain it") orelse &.{}; const test_step = b.step("test", "Run the tests"); for ([_]*std.Build.Module{ mod, proto_mod }) |m| { const tests = b.addTest(.{ .root_module = m, .filters = filters }); test_step.dependOn(&b.addRunArtifact(tests).step); } }