Skip to content

Commit 0812b57

Browse files
authored
Merge pull request #10288 from SpexGuy/test-build
Add test executable builds to build.zig
2 parents 274555b + 5924994 commit 0812b57

File tree

2 files changed

+113
-90
lines changed

2 files changed

+113
-90
lines changed

lib/std/build.zig

Lines changed: 112 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,14 @@ pub const Builder = struct {
320320
return LibExeObjStep.createTest(self, "test", root_src.dupe(self));
321321
}
322322

323+
pub fn addTestExe(self: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {
324+
return LibExeObjStep.createTestExe(self, name, .{ .path = root_src });
325+
}
326+
327+
pub fn addTestExeSource(self: *Builder, name: []const u8, root_src: FileSource) *LibExeObjStep {
328+
return LibExeObjStep.createTestExe(self, name, root_src.dupe(self));
329+
}
330+
323331
pub fn addAssemble(self: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {
324332
return addAssembleSource(self, name, .{ .path = src });
325333
}
@@ -1569,6 +1577,7 @@ pub const LibExeObjStep = struct {
15691577
lib,
15701578
obj,
15711579
@"test",
1580+
test_exe,
15721581
};
15731582

15741583
pub const SharedLibKind = union(enum) {
@@ -1617,6 +1626,10 @@ pub const LibExeObjStep = struct {
16171626
return initExtraArgs(builder, name, root_src, .@"test", null, null);
16181627
}
16191628

1629+
pub fn createTestExe(builder: *Builder, name: []const u8, root_src: FileSource) *LibExeObjStep {
1630+
return initExtraArgs(builder, name, root_src, .test_exe, null, null);
1631+
}
1632+
16201633
fn initExtraArgs(
16211634
builder: *Builder,
16221635
name_raw: []const u8,
@@ -1698,7 +1711,7 @@ pub const LibExeObjStep = struct {
16981711
.output_mode = switch (self.kind) {
16991712
.lib => .Lib,
17001713
.obj => .Obj,
1701-
.exe, .@"test" => .Exe,
1714+
.exe, .@"test", .test_exe => .Exe,
17021715
},
17031716
.link_mode = if (self.linkage) |some| @as(std.builtin.LinkMode, switch (some) {
17041717
.dynamic => .Dynamic,
@@ -1762,14 +1775,18 @@ pub const LibExeObjStep = struct {
17621775
/// Creates a `RunStep` with an executable built with `addExecutable`.
17631776
/// Add command line arguments with `addArg`.
17641777
pub fn run(exe: *LibExeObjStep) *RunStep {
1765-
assert(exe.kind == .exe);
1778+
assert(exe.kind == .exe or exe.kind == .test_exe);
17661779

17671780
// It doesn't have to be native. We catch that if you actually try to run it.
17681781
// Consider that this is declarative; the run step may not be run unless a user
17691782
// option is supplied.
17701783
const run_step = RunStep.create(exe.builder, exe.builder.fmt("run {s}", .{exe.step.name}));
17711784
run_step.addArtifactArg(exe);
17721785

1786+
if (exe.kind == .test_exe) {
1787+
run_step.addArg(exe.builder.zig_exe);
1788+
}
1789+
17731790
if (exe.vcpkg_bin_path) |path| {
17741791
run_step.addPathDir(path);
17751792
}
@@ -1816,7 +1833,7 @@ pub const LibExeObjStep = struct {
18161833
pub fn producesPdbFile(self: *LibExeObjStep) bool {
18171834
if (!self.target.isWindows() and !self.target.isUefi()) return false;
18181835
if (self.strip) return false;
1819-
return self.isDynamicLibrary() or self.kind == .exe;
1836+
return self.isDynamicLibrary() or self.kind == .exe or self.kind == .test_exe;
18201837
}
18211838

18221839
pub fn linkLibC(self: *LibExeObjStep) void {
@@ -1976,12 +1993,12 @@ pub const LibExeObjStep = struct {
19761993
}
19771994

19781995
pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void {
1979-
assert(self.kind == .@"test");
1996+
assert(self.kind == .@"test" or self.kind == .test_exe);
19801997
self.name_prefix = self.builder.dupe(text);
19811998
}
19821999

19832000
pub fn setFilter(self: *LibExeObjStep, text: ?[]const u8) void {
1984-
assert(self.kind == .@"test");
2001+
assert(self.kind == .@"test" or self.kind == .test_exe);
19852002
self.filter = if (text) |t| self.builder.dupe(t) else null;
19862003
}
19872004

@@ -2052,7 +2069,7 @@ pub const LibExeObjStep = struct {
20522069
/// Returns the generated header file.
20532070
/// This function can only be called for libraries or object files which have `emit_h` set.
20542071
pub fn getOutputHSource(self: *LibExeObjStep) FileSource {
2055-
assert(self.kind != .exe);
2072+
assert(self.kind != .exe and self.kind != .test_exe and self.kind != .@"test");
20562073
assert(self.emit_h);
20572074
return FileSource{ .generated = &self.output_h_path_source };
20582075
}
@@ -2222,6 +2239,7 @@ pub const LibExeObjStep = struct {
22222239
.exe => "build-exe",
22232240
.obj => "build-obj",
22242241
.@"test" => "test",
2242+
.test_exe => "test",
22252243
};
22262244
zig_args.append(cmd) catch unreachable;
22272245

@@ -2268,8 +2286,9 @@ pub const LibExeObjStep = struct {
22682286
.static_path => |static_path| try zig_args.append(static_path.getPath(builder)),
22692287

22702288
.other_step => |other| switch (other.kind) {
2271-
.exe => unreachable,
2272-
.@"test" => unreachable,
2289+
.exe => @panic("Cannot link with an executable build artifact"),
2290+
.test_exe => @panic("Cannot link with an executable build artifact"),
2291+
.@"test" => @panic("Cannot link with a test"),
22732292
.obj => {
22742293
try zig_args.append(other.getOutputSource().getPath(builder));
22752294
},
@@ -2542,89 +2561,93 @@ pub const LibExeObjStep = struct {
25422561
try zig_args.append(builder.pathFromRoot(version_script));
25432562
}
25442563

2545-
if (self.exec_cmd_args) |exec_cmd_args| {
2546-
for (exec_cmd_args) |cmd_arg| {
2547-
if (cmd_arg) |arg| {
2548-
try zig_args.append("--test-cmd");
2549-
try zig_args.append(arg);
2550-
} else {
2551-
try zig_args.append("--test-cmd-bin");
2552-
}
2553-
}
2554-
} else {
2555-
const need_cross_glibc = self.target.isGnuLibC() and self.is_linking_libc;
2556-
2557-
switch (self.builder.host.getExternalExecutor(self.target_info, .{
2558-
.qemu_fixes_dl = need_cross_glibc and builder.glibc_runtimes_dir != null,
2559-
.link_libc = self.is_linking_libc,
2560-
})) {
2561-
.native => {},
2562-
.bad_dl, .bad_os_or_cpu => {
2563-
try zig_args.append("--test-no-exec");
2564-
},
2565-
.rosetta => if (builder.enable_rosetta) {
2566-
try zig_args.append("--test-cmd-bin");
2567-
} else {
2568-
try zig_args.append("--test-no-exec");
2569-
},
2570-
.qemu => |bin_name| ok: {
2571-
if (builder.enable_qemu) qemu: {
2572-
const glibc_dir_arg = if (need_cross_glibc)
2573-
builder.glibc_runtimes_dir orelse break :qemu
2574-
else
2575-
null;
2564+
if (self.kind == .@"test") {
2565+
if (self.exec_cmd_args) |exec_cmd_args| {
2566+
for (exec_cmd_args) |cmd_arg| {
2567+
if (cmd_arg) |arg| {
25762568
try zig_args.append("--test-cmd");
2577-
try zig_args.append(bin_name);
2578-
if (glibc_dir_arg) |dir| {
2579-
// TODO look into making this a call to `linuxTriple`. This
2580-
// needs the directory to be called "i686" rather than
2581-
// "i386" which is why we do it manually here.
2582-
const fmt_str = "{s}" ++ fs.path.sep_str ++ "{s}-{s}-{s}";
2583-
const cpu_arch = self.target.getCpuArch();
2584-
const os_tag = self.target.getOsTag();
2585-
const abi = self.target.getAbi();
2586-
const cpu_arch_name: []const u8 = if (cpu_arch == .i386)
2587-
"i686"
2569+
try zig_args.append(arg);
2570+
} else {
2571+
try zig_args.append("--test-cmd-bin");
2572+
}
2573+
}
2574+
} else {
2575+
const need_cross_glibc = self.target.isGnuLibC() and self.is_linking_libc;
2576+
2577+
switch (self.builder.host.getExternalExecutor(self.target_info, .{
2578+
.qemu_fixes_dl = need_cross_glibc and builder.glibc_runtimes_dir != null,
2579+
.link_libc = self.is_linking_libc,
2580+
})) {
2581+
.native => {},
2582+
.bad_dl, .bad_os_or_cpu => {
2583+
try zig_args.append("--test-no-exec");
2584+
},
2585+
.rosetta => if (builder.enable_rosetta) {
2586+
try zig_args.append("--test-cmd-bin");
2587+
} else {
2588+
try zig_args.append("--test-no-exec");
2589+
},
2590+
.qemu => |bin_name| ok: {
2591+
if (builder.enable_qemu) qemu: {
2592+
const glibc_dir_arg = if (need_cross_glibc)
2593+
builder.glibc_runtimes_dir orelse break :qemu
25882594
else
2589-
@tagName(cpu_arch);
2590-
const full_dir = try std.fmt.allocPrint(builder.allocator, fmt_str, .{
2591-
dir, cpu_arch_name, @tagName(os_tag), @tagName(abi),
2592-
});
2593-
2594-
try zig_args.append("--test-cmd");
2595-
try zig_args.append("-L");
2595+
null;
25962596
try zig_args.append("--test-cmd");
2597-
try zig_args.append(full_dir);
2597+
try zig_args.append(bin_name);
2598+
if (glibc_dir_arg) |dir| {
2599+
// TODO look into making this a call to `linuxTriple`. This
2600+
// needs the directory to be called "i686" rather than
2601+
// "i386" which is why we do it manually here.
2602+
const fmt_str = "{s}" ++ fs.path.sep_str ++ "{s}-{s}-{s}";
2603+
const cpu_arch = self.target.getCpuArch();
2604+
const os_tag = self.target.getOsTag();
2605+
const abi = self.target.getAbi();
2606+
const cpu_arch_name: []const u8 = if (cpu_arch == .i386)
2607+
"i686"
2608+
else
2609+
@tagName(cpu_arch);
2610+
const full_dir = try std.fmt.allocPrint(builder.allocator, fmt_str, .{
2611+
dir, cpu_arch_name, @tagName(os_tag), @tagName(abi),
2612+
});
2613+
2614+
try zig_args.append("--test-cmd");
2615+
try zig_args.append("-L");
2616+
try zig_args.append("--test-cmd");
2617+
try zig_args.append(full_dir);
2618+
}
2619+
try zig_args.append("--test-cmd-bin");
2620+
break :ok;
25982621
}
2622+
try zig_args.append("--test-no-exec");
2623+
},
2624+
.wine => |bin_name| if (builder.enable_wine) {
2625+
try zig_args.append("--test-cmd");
2626+
try zig_args.append(bin_name);
25992627
try zig_args.append("--test-cmd-bin");
2600-
break :ok;
2601-
}
2602-
try zig_args.append("--test-no-exec");
2603-
},
2604-
.wine => |bin_name| if (builder.enable_wine) {
2605-
try zig_args.append("--test-cmd");
2606-
try zig_args.append(bin_name);
2607-
try zig_args.append("--test-cmd-bin");
2608-
} else {
2609-
try zig_args.append("--test-no-exec");
2610-
},
2611-
.wasmtime => |bin_name| if (builder.enable_wasmtime) {
2612-
try zig_args.append("--test-cmd");
2613-
try zig_args.append(bin_name);
2614-
try zig_args.append("--test-cmd");
2615-
try zig_args.append("--dir=.");
2616-
try zig_args.append("--test-cmd-bin");
2617-
} else {
2618-
try zig_args.append("--test-no-exec");
2619-
},
2620-
.darling => |bin_name| if (builder.enable_darling) {
2621-
try zig_args.append("--test-cmd");
2622-
try zig_args.append(bin_name);
2623-
try zig_args.append("--test-cmd-bin");
2624-
} else {
2625-
try zig_args.append("--test-no-exec");
2626-
},
2628+
} else {
2629+
try zig_args.append("--test-no-exec");
2630+
},
2631+
.wasmtime => |bin_name| if (builder.enable_wasmtime) {
2632+
try zig_args.append("--test-cmd");
2633+
try zig_args.append(bin_name);
2634+
try zig_args.append("--test-cmd");
2635+
try zig_args.append("--dir=.");
2636+
try zig_args.append("--test-cmd-bin");
2637+
} else {
2638+
try zig_args.append("--test-no-exec");
2639+
},
2640+
.darling => |bin_name| if (builder.enable_darling) {
2641+
try zig_args.append("--test-cmd");
2642+
try zig_args.append(bin_name);
2643+
try zig_args.append("--test-cmd-bin");
2644+
} else {
2645+
try zig_args.append("--test-no-exec");
2646+
},
2647+
}
26272648
}
2649+
} else if (self.kind == .test_exe) {
2650+
try zig_args.append("--test-no-exec");
26282651
}
26292652

26302653
for (self.packages.items) |pkg| {
@@ -2877,13 +2900,13 @@ pub const InstallArtifactStep = struct {
28772900
.step = Step.init(.install_artifact, builder.fmt("install {s}", .{artifact.step.name}), builder.allocator, make),
28782901
.artifact = artifact,
28792902
.dest_dir = artifact.override_dest_dir orelse switch (artifact.kind) {
2880-
.obj => unreachable,
2881-
.@"test" => unreachable,
2882-
.exe => InstallDir{ .bin = {} },
2903+
.obj => @panic("Cannot install a .obj build artifact."),
2904+
.@"test" => @panic("Cannot install a test build artifact, use addTestExe instead."),
2905+
.exe, .test_exe => InstallDir{ .bin = {} },
28832906
.lib => InstallDir{ .lib = {} },
28842907
},
28852908
.pdb_dir = if (artifact.producesPdbFile()) blk: {
2886-
if (artifact.kind == .exe) {
2909+
if (artifact.kind == .exe or artifact.kind == .test_exe) {
28872910
break :blk InstallDir{ .bin = {} };
28882911
} else {
28892912
break :blk InstallDir{ .lib = {} };

lib/std/build/InstallRawStep.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ pub fn create(builder: *Builder, artifact: *LibExeObjStep, dest_filename: []cons
451451
.dest_dir = if (options.dest_dir) |d| d else switch (artifact.kind) {
452452
.obj => unreachable,
453453
.@"test" => unreachable,
454-
.exe => .bin,
454+
.exe, .test_exe => .bin,
455455
.lib => unreachable,
456456
},
457457
.dest_filename = dest_filename,

0 commit comments

Comments
 (0)