build: add @import("mach").addExecutable helper

This adds a helper that can be used people's `build.zig` code, called `@import("mach").addExecutable`,
a direct replacement for `b.addExecutable`.

The benefits of using this method are:

1. Your `build.zig` code does not need to be aware of platform-specifics that may be required to build an executable,
   for example setting a Windows manifest to ensure your app is DPI-aware.
2. You do not need to write `main.zig` entrypoint code, which although simple today is expected to become more complex
   over time as we add support for more platforms. For example, WASM and other platforms require different entrypoints
   and this can account for that without your `build.zig` containing that logic.

Steps to use:

1. Delete your `main.zig` file.
2. Define your `Modules` as a public const in your `App.zig` file, e.g.:

```zig
// The set of Mach modules our application may use.
pub const Modules = mach.Modules(.{
    mach.Core,
    App,
});
```

3. Update your `build.zig` code to use `@import("mach").addExecutable` like so:

```zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const app_mod = b.createModule(.{
        .root_source_file = b.path("src/App.zig"),
        .optimize = optimize,
        .target = target,
    });

    // Add Mach to our library and executable
    const mach_dep = b.dependency("mach", .{
        .target = target,
        .optimize = optimize,
    });
    app_mod.addImport("mach", mach_dep.module("mach"));

    // Use the Mach entrypoint to write main for us
    const exe = @import("mach").addExecutable(mach_dep.builder, .{
        .name = "hello-world",
        .app = app_mod,
        .target = target,
        .optimize = optimize,
    });
    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);
    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);

    const app_unit_tests = b.addTest(.{
        .root_module = app_mod,
    });
    const run_app_unit_tests = b.addRunArtifact(app_unit_tests);
    const test_step = b.step("test", "Run unit tests");
    test_step.dependOn(&run_app_unit_tests.step);
}
```

Signed-off-by: Emi <emi@hexops.com>
This commit is contained in:
Emi 2025-02-17 20:51:42 -07:00
parent 2410814e91
commit b14f8e69ee
19 changed files with 101 additions and 201 deletions

View file

@ -16,6 +16,13 @@ const Mat4x4 = math.Mat4x4;
const App = @This();
// The set of Mach modules our application may use.
pub const Modules = mach.Modules(.{
mach.Core,
mach.gfx.Sprite,
App,
});
pub const mach_module = .app;
pub const mach_systems = .{ .main, .init, .deinit, .tick };