Commit 030742f1f7

Andrew Kelley <andrew@ziglang.org>
2023-03-08 08:16:16
re-enable standalone tests based on build.zig
1 parent 15c4fae
Changed files (42)
test
standalone
brace_expansion
c_compiler
dep_diamond
dep_mutually_recursive
dep_recursive
dep_shared_builtin
dep_triangle
embed_generated_file
emit_asm_and_bin
empty_env
global_linkage
install_raw_hex
issue_11595
issue_12588
issue_12706
issue_13030
issue_13970
issue_339
issue_5825
issue_7030
issue_794
issue_8550
issue_9812
load_dynamic_library
main_pkg_path
mix_c_files
mix_o_files
pie
pkg_import
shared_library
sigpipe
static_c_lib
test_runner_path
use_alias
windows_spawn
test/standalone/brace_expansion/build.zig
@@ -1,11 +0,0 @@
-const std = @import("std");
-
-pub fn build(b: *std.Build) void {
-    const main = b.addTest(.{
-        .root_source_file = .{ .path = "main.zig" },
-        .optimize = b.standardOptimizeOption(.{}),
-    });
-
-    const test_step = b.step("test", "Test it");
-    test_step.dependOn(&main.step);
-}
test/standalone/c_compiler/build.zig
@@ -1,27 +1,24 @@
 const std = @import("std");
 const builtin = @import("builtin");
-const CrossTarget = std.zig.CrossTarget;
 
-// TODO integrate this with the std.Build executor API
-fn isRunnableTarget(t: CrossTarget) bool {
-    if (t.isNative()) return true;
+pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
 
-    return (t.getOsTag() == builtin.os.tag and
-        t.getCpuArch() == builtin.cpu.arch);
+    add(b, test_step, .Debug);
+    add(b, test_step, .ReleaseFast);
+    add(b, test_step, .ReleaseSmall);
+    add(b, test_step, .ReleaseSafe);
 }
 
-pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
-    const target = b.standardTargetOptions(.{});
-
-    const test_step = b.step("test", "Test the program");
+fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
+    const target: std.zig.CrossTarget = .{};
 
     const exe_c = b.addExecutable(.{
         .name = "test_c",
         .optimize = optimize,
         .target = target,
     });
-    b.default_step.dependOn(&exe_c.step);
     exe_c.addCSourceFile("test.c", &[0][]const u8{});
     exe_c.linkLibC();
 
@@ -47,13 +44,13 @@ pub fn build(b: *std.Build) void {
         else => {},
     }
 
-    if (isRunnableTarget(target)) {
-        const run_c_cmd = exe_c.run();
-        test_step.dependOn(&run_c_cmd.step);
-        const run_cpp_cmd = exe_cpp.run();
-        test_step.dependOn(&run_cpp_cmd.step);
-    } else {
-        test_step.dependOn(&exe_c.step);
-        test_step.dependOn(&exe_cpp.step);
-    }
+    const run_c_cmd = b.addRunArtifact(exe_c);
+    run_c_cmd.expectExitCode(0);
+    run_c_cmd.skip_foreign_checks = true;
+    test_step.dependOn(&run_c_cmd.step);
+
+    const run_cpp_cmd = b.addRunArtifact(exe_cpp);
+    run_cpp_cmd.expectExitCode(0);
+    run_cpp_cmd.skip_foreign_checks = true;
+    test_step.dependOn(&run_cpp_cmd.step);
 }
test/standalone/dep_diamond/build.zig
@@ -1,7 +1,10 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
 
     const shared = b.createModule(.{
         .source_file = .{ .path = "shared.zig" },
@@ -23,6 +26,5 @@ pub fn build(b: *std.Build) void {
 
     const run = exe.run();
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&run.step);
 }
test/standalone/dep_mutually_recursive/build.zig
@@ -1,7 +1,10 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
 
     const foo = b.createModule(.{
         .source_file = .{ .path = "foo.zig" },
@@ -21,6 +24,5 @@ pub fn build(b: *std.Build) void {
 
     const run = exe.run();
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&run.step);
 }
test/standalone/dep_recursive/build.zig
@@ -1,7 +1,10 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
 
     const foo = b.createModule(.{
         .source_file = .{ .path = "foo.zig" },
@@ -17,6 +20,5 @@ pub fn build(b: *std.Build) void {
 
     const run = exe.run();
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&run.step);
 }
test/standalone/dep_shared_builtin/build.zig
@@ -1,7 +1,10 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
 
     const exe = b.addExecutable(.{
         .name = "test",
@@ -14,6 +17,5 @@ pub fn build(b: *std.Build) void {
 
     const run = exe.run();
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&run.step);
 }
test/standalone/dep_triangle/build.zig
@@ -1,7 +1,10 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
 
     const shared = b.createModule(.{
         .source_file = .{ .path = "shared.zig" },
@@ -20,6 +23,5 @@ pub fn build(b: *std.Build) void {
 
     const run = exe.run();
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&run.step);
 }
test/standalone/embed_generated_file/build.zig
@@ -1,8 +1,8 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const target = b.standardTargetOptions(.{});
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
 
     const bootloader = b.addExecutable(.{
         .name = "bootloader",
@@ -16,13 +16,11 @@ pub fn build(b: *std.Build) void {
 
     const exe = b.addTest(.{
         .root_source_file = .{ .path = "main.zig" },
-        .target = target,
-        .optimize = optimize,
+        .optimize = .Debug,
     });
     exe.addAnonymousModule("bootloader.elf", .{
         .source_file = bootloader.getOutputSource(),
     });
 
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&exe.step);
 }
test/standalone/emit_asm_and_bin/build.zig
@@ -1,6 +1,9 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
     const main = b.addTest(.{
         .root_source_file = .{ .path = "main.zig" },
         .optimize = b.standardOptimizeOption(.{}),
@@ -8,6 +11,5 @@ pub fn build(b: *std.Build) void {
     main.emit_asm = .{ .emit_to = b.pathFromRoot("main.s") };
     main.emit_bin = .{ .emit_to = b.pathFromRoot("main") };
 
-    const test_step = b.step("test", "Run test");
     test_step.dependOn(&main.step);
 }
test/standalone/empty_env/build.zig
@@ -1,15 +1,25 @@
 const std = @import("std");
+const builtin = @import("builtin");
 
 pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+
+    if (builtin.os.tag == .windows and builtin.cpu.arch == .aarch64) {
+        // https://github.com/ziglang/zig/issues/13685
+        return;
+    }
+
     const main = b.addExecutable(.{
         .name = "main",
         .root_source_file = .{ .path = "main.zig" },
-        .optimize = b.standardOptimizeOption(.{}),
+        .optimize = optimize,
     });
 
-    const run = main.run();
+    const run = b.addRunArtifact(main);
     run.clearEnvironment();
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&run.step);
 }
test/standalone/global_linkage/build.zig
@@ -1,20 +1,24 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test the program");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+    const target: std.zig.CrossTarget = .{};
 
     const obj1 = b.addStaticLibrary(.{
         .name = "obj1",
         .root_source_file = .{ .path = "obj1.zig" },
         .optimize = optimize,
-        .target = .{},
+        .target = target,
     });
 
     const obj2 = b.addStaticLibrary(.{
         .name = "obj2",
         .root_source_file = .{ .path = "obj2.zig" },
         .optimize = optimize,
-        .target = .{},
+        .target = target,
     });
 
     const main = b.addTest(.{
@@ -24,6 +28,5 @@ pub fn build(b: *std.Build) void {
     main.linkLibrary(obj1);
     main.linkLibrary(obj2);
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&main.step);
 }
test/standalone/install_raw_hex/build.zig
@@ -3,8 +3,8 @@ const std = @import("std");
 const CheckFileStep = std.Build.CheckFileStep;
 
 pub fn build(b: *std.Build) void {
-    const test_step = b.step("test", "Test the program");
-    b.default_step.dependOn(test_step);
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
 
     const target = .{
         .cpu_arch = .thumb,
@@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void {
         .abi = .gnueabihf,
     };
 
-    const optimize = b.standardOptimizeOption(.{});
+    const optimize: std.builtin.OptimizeMode = .Debug;
 
     const elf = b.addExecutable(.{
         .name = "zig-nrf52-blink.elf",
test/standalone/issue_11595/build.zig
@@ -1,18 +1,17 @@
 const std = @import("std");
 const builtin = @import("builtin");
-const CrossTarget = std.zig.CrossTarget;
 
-// TODO integrate this with the std.Build executor API
-fn isRunnableTarget(t: CrossTarget) bool {
-    if (t.isNative()) return true;
+pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
 
-    return (t.getOsTag() == builtin.os.tag and
-        t.getCpuArch() == builtin.cpu.arch);
-}
+    const optimize: std.builtin.OptimizeMode = .Debug;
+    const target: std.zig.CrossTarget = .{};
 
-pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
-    const target = b.standardTargetOptions(.{});
+    if (builtin.os.tag == .windows) {
+        // https://github.com/ziglang/zig/issues/12419
+        return;
+    }
 
     const exe = b.addExecutable(.{
         .name = "zigtest",
@@ -44,11 +43,9 @@ pub fn build(b: *std.Build) void {
 
     b.default_step.dependOn(&exe.step);
 
-    const test_step = b.step("test", "Test the program");
-    if (isRunnableTarget(target)) {
-        const run_cmd = exe.run();
-        test_step.dependOn(&run_cmd.step);
-    } else {
-        test_step.dependOn(&exe.step);
-    }
+    const run_cmd = b.addRunArtifact(exe);
+    run_cmd.skip_foreign_checks = true;
+    run_cmd.expectExitCode(0);
+
+    test_step.dependOn(&run_cmd.step);
 }
test/standalone/issue_12588/build.zig
@@ -1,8 +1,11 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
-    const target = b.standardTargetOptions(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+    const target: std.zig.CrossTarget = .{};
 
     const obj = b.addObject(.{
         .name = "main",
@@ -15,6 +18,5 @@ pub fn build(b: *std.Build) void {
     obj.emit_bin = .no_emit;
     b.default_step.dependOn(&obj.step);
 
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&obj.step);
 }
test/standalone/issue_12706/build.zig
@@ -2,17 +2,12 @@ const std = @import("std");
 const builtin = @import("builtin");
 const CrossTarget = std.zig.CrossTarget;
 
-// TODO integrate this with the std.Build executor API
-fn isRunnableTarget(t: CrossTarget) bool {
-    if (t.isNative()) return true;
-
-    return (t.getOsTag() == builtin.os.tag and
-        t.getCpuArch() == builtin.cpu.arch);
-}
-
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
-    const target = b.standardTargetOptions(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+    const target: std.zig.CrossTarget = .{};
 
     const exe = b.addExecutable(.{
         .name = "main",
@@ -20,22 +15,15 @@ pub fn build(b: *std.Build) void {
         .optimize = optimize,
         .target = target,
     });
-    exe.install();
 
     const c_sources = [_][]const u8{
         "test.c",
     };
-
     exe.addCSourceFiles(&c_sources, &.{});
     exe.linkLibC();
 
-    b.default_step.dependOn(&exe.step);
-
-    const test_step = b.step("test", "Test the program");
-    if (isRunnableTarget(target)) {
-        const run_cmd = exe.run();
-        test_step.dependOn(&run_cmd.step);
-    } else {
-        test_step.dependOn(&exe.step);
-    }
+    const run_cmd = b.addRunArtifact(exe);
+    run_cmd.expectExitCode(0);
+    run_cmd.skip_foreign_checks = true;
+    test_step.dependOn(&run_cmd.step);
 }
test/standalone/issue_13030/build.zig
@@ -3,17 +3,22 @@ const builtin = @import("builtin");
 const CrossTarget = std.zig.CrossTarget;
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
-    const target = b.standardTargetOptions(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
 
+    add(b, test_step, .Debug);
+    add(b, test_step, .ReleaseFast);
+    add(b, test_step, .ReleaseSmall);
+    add(b, test_step, .ReleaseSafe);
+}
+
+fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
     const obj = b.addObject(.{
         .name = "main",
         .root_source_file = .{ .path = "main.zig" },
         .optimize = optimize,
-        .target = target,
+        .target = .{},
     });
-    b.default_step.dependOn(&obj.step);
 
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&obj.step);
 }
test/standalone/issue_13970/build.zig
@@ -1,6 +1,9 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
     const test1 = b.addTest(.{
         .root_source_file = .{ .path = "test_root/empty.zig" },
     });
@@ -14,7 +17,6 @@ pub fn build(b: *std.Build) void {
     test2.setTestRunner("src/main.zig");
     test3.setTestRunner("src/main.zig");
 
-    const test_step = b.step("test", "Test package path resolution of custom test runner");
     test_step.dependOn(&test1.step);
     test_step.dependOn(&test2.step);
     test_step.dependOn(&test3.step);
test/standalone/issue_339/build.zig
@@ -1,13 +1,18 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+    const target: std.zig.CrossTarget = .{};
+
     const obj = b.addObject(.{
         .name = "test",
         .root_source_file = .{ .path = "test.zig" },
-        .target = b.standardTargetOptions(.{}),
-        .optimize = b.standardOptimizeOption(.{}),
+        .target = target,
+        .optimize = optimize,
     });
 
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&obj.step);
 }
test/standalone/issue_5825/build.zig
@@ -1,12 +1,15 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
     const target = .{
         .cpu_arch = .x86_64,
         .os_tag = .windows,
         .abi = .msvc,
     };
-    const optimize = b.standardOptimizeOption(.{});
+    const optimize: std.builtin.OptimizeMode = .Debug;
     const obj = b.addObject(.{
         .name = "issue_5825",
         .root_source_file = .{ .path = "main.zig" },
@@ -24,6 +27,5 @@ pub fn build(b: *std.Build) void {
     exe.linkSystemLibrary("ntdll");
     exe.addObject(obj);
 
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&exe.step);
 }
test/standalone/issue_7030/build.zig
@@ -1,17 +0,0 @@
-const std = @import("std");
-
-pub fn build(b: *std.Build) void {
-    const exe = b.addExecutable(.{
-        .name = "issue_7030",
-        .root_source_file = .{ .path = "main.zig" },
-        .target = .{
-            .cpu_arch = .wasm32,
-            .os_tag = .freestanding,
-        },
-    });
-    exe.install();
-    b.default_step.dependOn(&exe.step);
-
-    const test_step = b.step("test", "Test the program");
-    test_step.dependOn(&exe.step);
-}
test/standalone/issue_794/build.zig
@@ -1,13 +1,13 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
     const test_artifact = b.addTest(.{
         .root_source_file = .{ .path = "main.zig" },
     });
     test_artifact.addIncludePath("a_directory");
 
-    b.default_step.dependOn(&test_artifact.step);
-
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&test_artifact.step);
 }
test/standalone/issue_8550/build.zig
@@ -1,6 +1,10 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) !void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
     const target = std.zig.CrossTarget{
         .os_tag = .freestanding,
         .cpu_arch = .arm,
@@ -8,7 +12,7 @@ pub fn build(b: *std.Build) !void {
             .explicit = &std.Target.arm.cpu.arm1176jz_s,
         },
     };
-    const optimize = b.standardOptimizeOption(.{});
+
     const kernel = b.addExecutable(.{
         .name = "kernel",
         .root_source_file = .{ .path = "./main.zig" },
@@ -19,6 +23,5 @@ pub fn build(b: *std.Build) !void {
     kernel.setLinkerScriptPath(.{ .path = "./linker.ld" });
     kernel.install();
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&kernel.step);
 }
test/standalone/issue_9812/build.zig
@@ -1,7 +1,11 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) !void {
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+
     const zip_add = b.addTest(.{
         .root_source_file = .{ .path = "main.zig" },
         .optimize = optimize,
@@ -13,6 +17,5 @@ pub fn build(b: *std.Build) !void {
     zip_add.addIncludePath("vendor/kuba-zip");
     zip_add.linkLibC();
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&zip_add.step);
 }
test/standalone/load_dynamic_library/build.zig
@@ -1,8 +1,19 @@
 const std = @import("std");
+const builtin = @import("builtin");
 
 pub fn build(b: *std.Build) void {
-    const target = b.standardTargetOptions(.{});
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+    const target: std.zig.CrossTarget = .{};
+
+    const ok = (builtin.os.tag != .wasi and
+        // https://github.com/ziglang/zig/issues/13550
+        (builtin.os.tag != .macos or builtin.cpu.arch != .aarch64) and
+        // https://github.com/ziglang/zig/issues/13686
+        (builtin.os.tag != .windows or builtin.cpu.arch != .aarch64));
+    if (!ok) return;
 
     const lib = b.addSharedLibrary(.{
         .name = "add",
@@ -19,9 +30,10 @@ pub fn build(b: *std.Build) void {
         .target = target,
     });
 
-    const run = main.run();
+    const run = b.addRunArtifact(main);
     run.addArtifactArg(lib);
+    run.skip_foreign_checks = true;
+    run.expectExitCode(0);
 
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&run.step);
 }
test/standalone/load_dynamic_library/main.zig
@@ -11,11 +11,7 @@ pub fn main() !void {
     var lib = try std.DynLib.open(dynlib_name);
     defer lib.close();
 
-    const Add = switch (@import("builtin").zig_backend) {
-        .stage1 => fn (i32, i32) callconv(.C) i32,
-        else => *const fn (i32, i32) callconv(.C) i32,
-    };
-
+    const Add = *const fn (i32, i32) callconv(.C) i32;
     const addFn = lib.lookup(Add, "add") orelse return error.SymbolNotFound;
 
     const result = addFn(12, 34);
test/standalone/main_pkg_path/build.zig
@@ -1,11 +1,13 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
     const test_exe = b.addTest(.{
         .root_source_file = .{ .path = "a/test.zig" },
     });
     test_exe.setMainPkgPath(".");
 
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&test_exe.step);
 }
test/standalone/mix_c_files/build.zig
@@ -1,34 +1,28 @@
 const std = @import("std");
-const builtin = @import("builtin");
-const CrossTarget = std.zig.CrossTarget;
 
-// TODO integrate this with the std.Build executor API
-fn isRunnableTarget(t: CrossTarget) bool {
-    if (t.isNative()) return true;
+pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
 
-    return (t.getOsTag() == builtin.os.tag and
-        t.getCpuArch() == builtin.cpu.arch);
+    add(b, test_step, .Debug);
+    add(b, test_step, .ReleaseFast);
+    add(b, test_step, .ReleaseSmall);
+    add(b, test_step, .ReleaseSafe);
 }
 
-pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
-    const target = b.standardTargetOptions(.{});
-
+fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
     const exe = b.addExecutable(.{
         .name = "test",
         .root_source_file = .{ .path = "main.zig" },
         .optimize = optimize,
-        .target = target,
     });
     exe.addCSourceFile("test.c", &[_][]const u8{"-std=c11"});
     exe.linkLibC();
     b.default_step.dependOn(&exe.step);
 
-    const test_step = b.step("test", "Test the program");
-    if (isRunnableTarget(target)) {
-        const run_cmd = exe.run();
-        test_step.dependOn(&run_cmd.step);
-    } else {
-        test_step.dependOn(&exe.step);
-    }
+    const run_cmd = b.addRunArtifact(exe);
+    run_cmd.skip_foreign_checks = true;
+    run_cmd.expectExitCode(0);
+
+    test_step.dependOn(&run_cmd.step);
 }
test/standalone/mix_o_files/build.zig
@@ -1,18 +1,23 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+    const target: std.zig.CrossTarget = .{};
 
     const obj = b.addObject(.{
         .name = "base64",
         .root_source_file = .{ .path = "base64.zig" },
         .optimize = optimize,
-        .target = .{},
+        .target = target,
     });
 
     const exe = b.addExecutable(.{
         .name = "test",
         .optimize = optimize,
+        .target = target,
     });
     exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});
     exe.addObject(obj);
@@ -22,6 +27,5 @@ pub fn build(b: *std.Build) void {
 
     const run_cmd = exe.run();
 
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&run_cmd.step);
 }
test/standalone/pie/build.zig
@@ -1,14 +1,21 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+    const target: std.zig.CrossTarget = .{
+        .os_tag = .linux,
+        .cpu_arch = .x86_64,
+    };
+
     const main = b.addTest(.{
         .root_source_file = .{ .path = "main.zig" },
-        .optimize = b.standardOptimizeOption(.{}),
+        .optimize = optimize,
+        .target = target,
     });
     main.pie = true;
 
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&main.step);
-
-    b.default_step.dependOn(test_step);
 }
test/standalone/pkg_import/build.zig
@@ -1,7 +1,10 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
 
     const exe = b.addExecutable(.{
         .name = "test",
@@ -12,6 +15,5 @@ pub fn build(b: *std.Build) void {
 
     const run = exe.run();
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&run.step);
 }
test/standalone/shared_library/build.zig
@@ -1,8 +1,11 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
-    const target = b.standardTargetOptions(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+    const target: std.zig.CrossTarget = .{};
     const lib = b.addSharedLibrary(.{
         .name = "mathtest",
         .root_source_file = .{ .path = "mathtest.zig" },
@@ -20,10 +23,7 @@ pub fn build(b: *std.Build) void {
     exe.linkLibrary(lib);
     exe.linkSystemLibrary("c");
 
-    b.default_step.dependOn(&exe.step);
-
     const run_cmd = exe.run();
 
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&run_cmd.step);
 }
test/standalone/sigpipe/build.zig
@@ -2,7 +2,16 @@ const std = @import("std");
 const os = std.os;
 
 pub fn build(b: *std.build.Builder) !void {
-    const test_step = b.step("test", "Run the tests");
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    // TODO signal handling code has no business being in a build script.
+    // this logic needs to move to a file called parent.zig which is
+    // added as an executable.
+
+    //if (!std.os.have_sigpipe_support) {
+    //    return;
+    //}
 
     // This test runs "breakpipe" as a child process and that process
     // depends on inheriting a SIGPIPE disposition of "default".
test/standalone/static_c_lib/build.zig
@@ -1,7 +1,10 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
 
     const foo = b.addStaticLibrary(.{
         .name = "foo",
@@ -18,6 +21,5 @@ pub fn build(b: *std.Build) void {
     test_exe.linkLibrary(foo);
     test_exe.addIncludePath(".");
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&test_exe.step);
 }
test/standalone/test_runner_path/build.zig
@@ -1,6 +1,11 @@
 const std = @import("std");
 
+pub const requires_stage2 = true;
+
 pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test the program");
+    b.default_step = test_step;
+
     const test_exe = b.addTest(.{
         .root_source_file = .{ .path = "test.zig" },
         .kind = .test_exe,
@@ -9,6 +14,5 @@ pub fn build(b: *std.Build) void {
 
     const test_run = test_exe.run();
 
-    const test_step = b.step("test", "Test the program");
     test_step.dependOn(&test_run.step);
 }
test/standalone/test_runner_path/test_runner.zig
@@ -1,51 +1,19 @@
 const std = @import("std");
-const io = std.io;
 const builtin = @import("builtin");
 
-pub const io_mode: io.Mode = builtin.test_io_mode;
-
 pub fn main() void {
-    const test_fn_list = builtin.test_functions;
     var ok_count: usize = 0;
     var skip_count: usize = 0;
     var fail_count: usize = 0;
 
-    var async_frame_buffer: []align(std.Target.stack_align) u8 = undefined;
-    // TODO this is on the next line (using `undefined` above) because otherwise zig incorrectly
-    // ignores the alignment of the slice.
-    async_frame_buffer = &[_]u8{};
-
-    for (test_fn_list) |test_fn| {
-        const result = if (test_fn.async_frame_size) |size| switch (io_mode) {
-            .evented => blk: {
-                if (async_frame_buffer.len < size) {
-                    std.heap.page_allocator.free(async_frame_buffer);
-                    async_frame_buffer = std.heap.page_allocator.alignedAlloc(u8, std.Target.stack_align, size) catch @panic("out of memory");
-                }
-                const casted_fn = @ptrCast(fn () callconv(.Async) anyerror!void, test_fn.func);
-                break :blk await @asyncCall(async_frame_buffer, {}, casted_fn, .{});
-            },
-            .blocking => {
-                skip_count += 1;
-                continue;
-            },
-        } else test_fn.func();
-        if (result) |_| {
+    for (builtin.test_functions) |test_fn| {
+        if (test_fn.func()) |_| {
             ok_count += 1;
         } else |err| switch (err) {
-            error.SkipZigTest => {
-                skip_count += 1;
-            },
-            else => {
-                fail_count += 1;
-            },
+            error.SkipZigTest => skip_count += 1,
+            else => fail_count += 1,
         }
     }
-    if (ok_count == test_fn_list.len) {
-        std.debug.print("All {d} tests passed.\n", .{ok_count});
-    } else {
-        std.debug.print("{d} passed; {d} skipped; {d} failed.\n", .{ ok_count, skip_count, fail_count });
-    }
     if (ok_count != 1 or skip_count != 1 or fail_count != 1) {
         std.process.exit(1);
     }
test/standalone/use_alias/build.zig
@@ -1,12 +1,16 @@
 const std = @import("std");
 
 pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+
     const main = b.addTest(.{
         .root_source_file = .{ .path = "main.zig" },
-        .optimize = b.standardOptimizeOption(.{}),
+        .optimize = optimize,
     });
     main.addIncludePath(".");
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&main.step);
 }
test/standalone/windows_spawn/build.zig
@@ -1,23 +1,34 @@
 const std = @import("std");
+const builtin = @import("builtin");
 
 pub fn build(b: *std.Build) void {
-    const optimize = b.standardOptimizeOption(.{});
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+    const target: std.zig.CrossTarget = .{
+        .os_tag = .windows,
+        .cpu_arch = .x86_64,
+    };
 
     const hello = b.addExecutable(.{
         .name = "hello",
         .root_source_file = .{ .path = "hello.zig" },
         .optimize = optimize,
+        .target = target,
     });
 
     const main = b.addExecutable(.{
         .name = "main",
         .root_source_file = .{ .path = "main.zig" },
         .optimize = optimize,
+        .target = target,
     });
 
-    const run = main.run();
+    const run = b.addRunArtifact(main);
     run.addArtifactArg(hello);
+    run.expectExitCode(0);
+    run.skip_foreign_checks = true;
 
-    const test_step = b.step("test", "Test it");
     test_step.dependOn(&run.step);
 }
test/standalone/brace_expansion/main.zig → test/standalone/brace_expansion.zig
@@ -234,8 +234,8 @@ pub fn main() !void {
     var result_buf = ArrayList(u8).init(global_allocator);
     defer result_buf.deinit();
 
-    try expandString(stdin.items, &result_buf);
-    try stdout_file.write(result_buf.items);
+    try expandString(stdin, &result_buf);
+    try stdout_file.writeAll(result_buf.items);
 }
 
 test "invalid inputs" {
test/standalone/issue_7030/main.zig → test/standalone/issue_7030.zig
File renamed without changes
test/standalone.zig
@@ -3,6 +3,8 @@ pub const SimpleCase = struct {
     link_libc: bool = false,
     all_modes: bool = false,
     target: std.zig.CrossTarget = .{},
+    is_test: bool = false,
+    is_exe: bool = true,
 };
 
 pub const BuildCase = struct {
@@ -27,6 +29,17 @@ pub const simple_cases = [_]SimpleCase{
     //.{
     //    .src_path = "test/standalone/issue_9693/main.zig",
     //},
+    .{
+        .src_path = "test/standalone/brace_expansion.zig",
+        .is_test = true,
+    },
+    .{
+        .src_path = "test/standalone/issue_7030.zig",
+        .target = .{
+            .cpu_arch = .wasm32,
+            .os_tag = .freestanding,
+        },
+    },
 
     .{ .src_path = "test/standalone/issue_12471/main.zig" },
     .{ .src_path = "test/standalone/guess_number/main.zig" },
@@ -57,88 +70,143 @@ pub const simple_cases = [_]SimpleCase{
     .{ .src_path = "tools/update_spirv_features.zig" },
 };
 
-pub const build_cases = [_]BuildCase{};
-
-//pub fn addCases(cases: *tests.StandaloneContext) void {
-//    cases.addBuildFile("test/standalone/options/build.zig", .{
-//        .extra_argv = &.{
-//            "-Dbool_true",
-//            "-Dbool_false=false",
-//            "-Dint=1234",
-//            "-De=two",
-//            "-Dstring=hello",
-//        },
-//    });
-//
-//    cases.addBuildFile("test/standalone/test_runner_path/build.zig", .{ .requires_stage2 = true });
-//    cases.addBuildFile("test/standalone/issue_13970/build.zig", .{});
-//    cases.addBuildFile("test/standalone/main_pkg_path/build.zig", .{});
-//    cases.addBuildFile("test/standalone/shared_library/build.zig", .{});
-//    cases.addBuildFile("test/standalone/mix_o_files/build.zig", .{});
-//    cases.addBuildFile("test/standalone/mix_c_files/build.zig", .{
-//        .build_modes = true,
-//        .cross_targets = true,
-//    });
-//    cases.addBuildFile("test/standalone/global_linkage/build.zig", .{});
-//    cases.addBuildFile("test/standalone/static_c_lib/build.zig", .{});
-//    cases.addBuildFile("test/standalone/issue_339/build.zig", .{});
-//    cases.addBuildFile("test/standalone/issue_8550/build.zig", .{});
-//    cases.addBuildFile("test/standalone/issue_794/build.zig", .{});
-//    cases.addBuildFile("test/standalone/issue_5825/build.zig", .{});
-//    cases.addBuildFile("test/standalone/pkg_import/build.zig", .{});
-//    cases.addBuildFile("test/standalone/use_alias/build.zig", .{});
-//    cases.addBuildFile("test/standalone/brace_expansion/build.zig", .{});
-//    if (builtin.os.tag != .windows or builtin.cpu.arch != .aarch64) {
-//        // https://github.com/ziglang/zig/issues/13685
-//        cases.addBuildFile("test/standalone/empty_env/build.zig", .{});
-//    }
-//    cases.addBuildFile("test/standalone/issue_7030/build.zig", .{});
-//    cases.addBuildFile("test/standalone/install_raw_hex/build.zig", .{});
-//    if (builtin.zig_backend == .stage1) { // https://github.com/ziglang/zig/issues/12194
-//        cases.addBuildFile("test/standalone/issue_9812/build.zig", .{});
-//    }
-//    if (builtin.os.tag != .windows) {
-//        // https://github.com/ziglang/zig/issues/12419
-//        cases.addBuildFile("test/standalone/issue_11595/build.zig", .{});
-//    }
-//
-//    if (builtin.os.tag != .wasi and
-//        // https://github.com/ziglang/zig/issues/13550
-//        (builtin.os.tag != .macos or builtin.cpu.arch != .aarch64) and
-//        // https://github.com/ziglang/zig/issues/13686
-//        (builtin.os.tag != .windows or builtin.cpu.arch != .aarch64))
-//    {
-//        cases.addBuildFile("test/standalone/load_dynamic_library/build.zig", .{});
-//    }
-//
-//    if (builtin.os.tag == .windows) {
-//        cases.addBuildFile("test/standalone/windows_spawn/build.zig", .{});
-//    }
-//
-//    cases.addBuildFile("test/standalone/c_compiler/build.zig", .{
-//        .build_modes = true,
-//        .cross_targets = true,
-//    });
-//
-//    // Try to build and run a PIE executable.
-//    if (builtin.os.tag == .linux) {
-//        cases.addBuildFile("test/standalone/pie/build.zig", .{});
-//    }
-//    cases.addBuildFile("test/standalone/issue_12706/build.zig", .{});
-//    if (std.os.have_sigpipe_support) {
-//        cases.addBuildFile("test/standalone/sigpipe/build.zig", .{});
-//    }
-//
-//    cases.addBuildFile("test/standalone/issue_13030/build.zig", .{ .build_modes = true });
-//    cases.addBuildFile("test/standalone/emit_asm_and_bin/build.zig", .{});
-//    cases.addBuildFile("test/standalone/issue_12588/build.zig", .{});
-//    cases.addBuildFile("test/standalone/embed_generated_file/build.zig", .{});
-//
-//    cases.addBuildFile("test/standalone/dep_diamond/build.zig", .{});
-//    cases.addBuildFile("test/standalone/dep_triangle/build.zig", .{});
-//    cases.addBuildFile("test/standalone/dep_recursive/build.zig", .{});
-//    cases.addBuildFile("test/standalone/dep_mutually_recursive/build.zig", .{});
-//    cases.addBuildFile("test/standalone/dep_shared_builtin/build.zig", .{});
-//}
+pub const build_cases = [_]BuildCase{
+    .{
+        .build_root = "test/standalone/test_runner_path",
+        .import = @import("standalone/test_runner_path/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/issue_13970",
+        .import = @import("standalone/issue_13970/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/main_pkg_path",
+        .import = @import("standalone/main_pkg_path/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/shared_library",
+        .import = @import("standalone/shared_library/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/mix_o_files",
+        .import = @import("standalone/mix_o_files/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/mix_c_files",
+        .import = @import("standalone/mix_c_files/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/global_linkage",
+        .import = @import("standalone/global_linkage/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/static_c_lib",
+        .import = @import("standalone/static_c_lib/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/issue_339",
+        .import = @import("standalone/issue_339/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/issue_8550",
+        .import = @import("standalone/issue_8550/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/issue_794",
+        .import = @import("standalone/issue_794/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/issue_5825",
+        .import = @import("standalone/issue_5825/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/pkg_import",
+        .import = @import("standalone/pkg_import/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/use_alias",
+        .import = @import("standalone/use_alias/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/install_raw_hex",
+        .import = @import("standalone/install_raw_hex/build.zig"),
+    },
+    // TODO take away EmitOption.emit_to option and make it give a FileSource
+    //.{
+    //    .build_root = "test/standalone/emit_asm_and_bin",
+    //    .import = @import("standalone/emit_asm_and_bin/build.zig"),
+    //},
+    // TODO take away EmitOption.emit_to option and make it give a FileSource
+    //.{
+    //    .build_root = "test/standalone/issue_12588",
+    //    .import = @import("standalone/issue_12588/build.zig"),
+    //},
+    .{
+        .build_root = "test/standalone/embed_generated_file",
+        .import = @import("standalone/embed_generated_file/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/dep_diamond",
+        .import = @import("standalone/dep_diamond/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/dep_triangle",
+        .import = @import("standalone/dep_triangle/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/dep_recursive",
+        .import = @import("standalone/dep_recursive/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/dep_mutually_recursive",
+        .import = @import("standalone/dep_mutually_recursive/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/dep_shared_builtin",
+        .import = @import("standalone/dep_shared_builtin/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/empty_env",
+        .import = @import("standalone/empty_env/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/issue_9812",
+        .import = @import("standalone/issue_9812/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/issue_11595",
+        .import = @import("standalone/issue_11595/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/load_dynamic_library",
+        .import = @import("standalone/load_dynamic_library/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/windows_spawn",
+        .import = @import("standalone/windows_spawn/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/c_compiler",
+        .import = @import("standalone/c_compiler/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/pie",
+        .import = @import("standalone/pie/build.zig"),
+    },
+    .{
+        .build_root = "test/standalone/issue_12706",
+        .import = @import("standalone/issue_12706/build.zig"),
+    },
+    // TODO This test is disabled for doing naughty things in the build script.
+    // The logic needs to get moved to a child process instead of build.zig.
+    //.{
+    //    .build_root = "test/standalone/sigpipe",
+    //    .import = @import("standalone/sigpipe/build.zig"),
+    //},
+    .{
+        .build_root = "test/standalone/issue_13030",
+        .import = @import("standalone/issue_13030/build.zig"),
+    },
+};
 
 const std = @import("std");
test/tests.zig
@@ -560,34 +560,62 @@ pub fn addStackTraceTests(
 
 pub fn addStandaloneTests(
     b: *std.Build,
-    test_filter: ?[]const u8,
     optimize_modes: []const OptimizeMode,
-    skip_non_native: bool,
     enable_macos_sdk: bool,
     omit_stage2: bool,
     enable_symlinks_windows: bool,
 ) *Step {
     const step = b.step("test-standalone", "Run the standalone tests");
-
-    _ = test_filter;
-    _ = skip_non_native;
-    _ = enable_macos_sdk;
-    _ = omit_stage2;
-    _ = enable_symlinks_windows;
+    const omit_symlinks = builtin.os.tag == .windows and !enable_symlinks_windows;
 
     for (standalone.simple_cases) |case| {
         for (optimize_modes) |optimize| {
             if (!case.all_modes and optimize != .Debug) continue;
 
-            const exe = b.addExecutable(.{
-                .name = std.fs.path.stem(case.src_path),
-                .root_source_file = .{ .path = case.src_path },
-                .optimize = optimize,
-                .target = case.target,
-            });
-            if (case.link_libc) exe.linkLibC();
+            if (case.is_exe) {
+                const exe = b.addExecutable(.{
+                    .name = std.fs.path.stem(case.src_path),
+                    .root_source_file = .{ .path = case.src_path },
+                    .optimize = optimize,
+                    .target = case.target,
+                });
+                if (case.link_libc) exe.linkLibC();
+
+                step.dependOn(&exe.step);
+            }
 
-            step.dependOn(&exe.step);
+            if (case.is_test) {
+                const exe = b.addTest(.{
+                    .name = std.fs.path.stem(case.src_path),
+                    .root_source_file = .{ .path = case.src_path },
+                    .optimize = optimize,
+                    .target = case.target,
+                });
+                if (case.link_libc) exe.linkLibC();
+
+                step.dependOn(&exe.step);
+            }
+        }
+    }
+
+    inline for (standalone.build_cases) |case| {
+        const requires_stage2 = @hasDecl(case.import, "requires_stage2") and
+            case.import.requires_stage2;
+        const requires_symlinks = @hasDecl(case.import, "requires_symlinks") and
+            case.import.requires_symlinks;
+        const requires_macos_sdk = @hasDecl(case.import, "requires_macos_sdk") and
+            case.import.requires_macos_sdk;
+        const bad =
+            (requires_stage2 and omit_stage2) or
+            (requires_symlinks and omit_symlinks) or
+            (requires_macos_sdk and !enable_macos_sdk);
+        if (!bad) {
+            const dep = b.anonymousDependency(case.build_root, case.import, .{});
+            const dep_step = dep.builder.default_step;
+            assert(mem.startsWith(u8, dep.builder.dep_prefix, "test."));
+            const dep_prefix_adjusted = dep.builder.dep_prefix["test.".len..];
+            dep_step.name = b.fmt("{s}{s}", .{ dep_prefix_adjusted, dep_step.name });
+            step.dependOn(dep_step);
         }
     }
 
@@ -603,19 +631,19 @@ pub fn addLinkTests(
     const step = b.step("test-link", "Run the linker tests");
     const omit_symlinks = builtin.os.tag == .windows and !enable_symlinks_windows;
 
-    inline for (link.cases) |link_test| {
-        const requires_stage2 = @hasDecl(link_test.import, "requires_stage2") and
-            link_test.import.requires_stage2;
-        const requires_symlinks = @hasDecl(link_test.import, "requires_symlinks") and
-            link_test.import.requires_symlinks;
-        const requires_macos_sdk = @hasDecl(link_test.import, "requires_macos_sdk") and
-            link_test.import.requires_macos_sdk;
+    inline for (link.cases) |case| {
+        const requires_stage2 = @hasDecl(case.import, "requires_stage2") and
+            case.import.requires_stage2;
+        const requires_symlinks = @hasDecl(case.import, "requires_symlinks") and
+            case.import.requires_symlinks;
+        const requires_macos_sdk = @hasDecl(case.import, "requires_macos_sdk") and
+            case.import.requires_macos_sdk;
         const bad =
             (requires_stage2 and omit_stage2) or
             (requires_symlinks and omit_symlinks) or
             (requires_macos_sdk and !enable_macos_sdk);
         if (!bad) {
-            const dep = b.anonymousDependency(link_test.build_root, link_test.import, .{});
+            const dep = b.anonymousDependency(case.build_root, case.import, .{});
             const dep_step = dep.builder.default_step;
             assert(mem.startsWith(u8, dep.builder.dep_prefix, "test."));
             const dep_prefix_adjusted = dep.builder.dep_prefix["test.".len..];
@@ -627,9 +655,7 @@ pub fn addLinkTests(
     return step;
 }
 
-pub fn addCliTests(b: *std.Build, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode) *Step {
-    _ = test_filter;
-    _ = optimize_modes;
+pub fn addCliTests(b: *std.Build) *Step {
     const step = b.step("test-cli", "Test the command line interface");
 
     {
@@ -815,6 +841,19 @@ pub fn addCliTests(b: *std.Build, test_filter: ?[]const u8, optimize_modes: []co
         step.dependOn(&cleanup.step);
     }
 
+    {
+        // TODO this should move to become a CLI test rather than standalone
+        //    cases.addBuildFile("test/standalone/options/build.zig", .{
+        //        .extra_argv = &.{
+        //            "-Dbool_true",
+        //            "-Dbool_false=false",
+        //            "-Dint=1234",
+        //            "-De=two",
+        //            "-Dstring=hello",
+        //        },
+        //    });
+    }
+
     return step;
 }
 
build.zig
@@ -445,9 +445,7 @@ pub fn build(b: *std.Build) !void {
     test_step.dependOn(tests.addCompareOutputTests(b, test_filter, optimization_modes));
     test_step.dependOn(tests.addStandaloneTests(
         b,
-        test_filter,
         optimization_modes,
-        skip_non_native,
         enable_macos_sdk,
         skip_stage2_tests,
         enable_symlinks_windows,
@@ -455,7 +453,7 @@ pub fn build(b: *std.Build) !void {
     test_step.dependOn(tests.addCAbiTests(b, skip_non_native, skip_release));
     test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, skip_stage2_tests, enable_symlinks_windows));
     test_step.dependOn(tests.addStackTraceTests(b, test_filter, optimization_modes));
-    test_step.dependOn(tests.addCliTests(b, test_filter, optimization_modes));
+    test_step.dependOn(tests.addCliTests(b));
     test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, optimization_modes));
     test_step.dependOn(tests.addTranslateCTests(b, test_filter));
     if (!skip_run_translated_c) {