mlugg 927f233ff8 compiler: allow emitting tests to an object file
This is fairly straightforward; the actual compiler changes are limited
to the CLI, since `Compilation` already supports this combination.

A new `std.Build` API is introduced to allow representing this. By
passing the `emit_object` option to `std.Build.addTest`, you get a
`Step.Compile` which emits an object file; you can then use that as you
would any other object, such as either installing it for external use,
or linking it into another step.

A standalone test is added to cover the build system API. It builds a
test into an object, and links it into a final executable, which it then
runs.

Using this build system mechanism prevents the build system from
noticing that you're running a `zig test`, so the build runner and test
runner do not communicate over stdio. However, that's okay, because the
real-world use cases for this feature don't want to do that anyway!

Resolves: #23374
2025-04-22 22:50:36 +01:00

33 lines
961 B
Zig

pub fn build(b: *std.Build) void {
// To avoid having to explicitly link required system libraries into the final test
// executable (e.g. ntdll on Windows), we'll just link everything with libc here.
const test_obj = b.addTest(.{
.emit_object = true,
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = b.graph.host,
.link_libc = true,
}),
});
const test_exe_mod = b.createModule(.{
.root_source_file = null,
.target = b.graph.host,
.link_libc = true,
});
test_exe_mod.addObject(test_obj);
const test_exe = b.addExecutable(.{
.name = "test",
.root_module = test_exe_mod,
});
const test_step = b.step("test", "Test the program");
b.default_step = test_step;
const test_run = b.addRunArtifact(test_exe);
test_step.dependOn(&test_run.step);
}
const std = @import("std");