authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-07 00:09:33-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-12-07 00:09:33-08:00
log0812b5746622c4263ad0fcf23bea847a547b0c4d
treeea5f3cdd1e26c7345010f274e631f8804d807e95
parent274555be21ea756d8480a586f771274a79a58d80
parent592499404527b49e9d09a8fa358a8d702e61f614
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10288 from SpexGuy/test-build

Add test executable builds to build.zig

2 files changed, 113 insertions(+), 90 deletions(-)

lib/std/build.zig+112-89
...@@ -320,6 +320,14 @@ pub const Builder = struct {...@@ -320,6 +320,14 @@ pub const Builder = struct {
320 return LibExeObjStep.createTest(self, "test", root_src.dupe(self));320 return LibExeObjStep.createTest(self, "test", root_src.dupe(self));
321 }321 }
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
323 pub fn addAssemble(self: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {331 pub fn addAssemble(self: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {
324 return addAssembleSource(self, name, .{ .path = src });332 return addAssembleSource(self, name, .{ .path = src });
325 }333 }
...@@ -1569,6 +1577,7 @@ pub const LibExeObjStep = struct {...@@ -1569,6 +1577,7 @@ pub const LibExeObjStep = struct {
1569 lib,1577 lib,
1570 obj,1578 obj,
1571 @"test",1579 @"test",
1580 test_exe,
1572 };1581 };
15731582
1574 pub const SharedLibKind = union(enum) {1583 pub const SharedLibKind = union(enum) {
...@@ -1617,6 +1626,10 @@ pub const LibExeObjStep = struct {...@@ -1617,6 +1626,10 @@ pub const LibExeObjStep = struct {
1617 return initExtraArgs(builder, name, root_src, .@"test", null, null);1626 return initExtraArgs(builder, name, root_src, .@"test", null, null);
1618 }1627 }
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
1620 fn initExtraArgs(1633 fn initExtraArgs(
1621 builder: *Builder,1634 builder: *Builder,
1622 name_raw: []const u8,1635 name_raw: []const u8,
...@@ -1698,7 +1711,7 @@ pub const LibExeObjStep = struct {...@@ -1698,7 +1711,7 @@ pub const LibExeObjStep = struct {
1698 .output_mode = switch (self.kind) {1711 .output_mode = switch (self.kind) {
1699 .lib => .Lib,1712 .lib => .Lib,
1700 .obj => .Obj,1713 .obj => .Obj,
1701 .exe, .@"test" => .Exe,1714 .exe, .@"test", .test_exe => .Exe,
1702 },1715 },
1703 .link_mode = if (self.linkage) |some| @as(std.builtin.LinkMode, switch (some) {1716 .link_mode = if (self.linkage) |some| @as(std.builtin.LinkMode, switch (some) {
1704 .dynamic => .Dynamic,1717 .dynamic => .Dynamic,
...@@ -1762,7 +1775,7 @@ pub const LibExeObjStep = struct {...@@ -1762,7 +1775,7 @@ pub const LibExeObjStep = struct {
1762 /// Creates a `RunStep` with an executable built with `addExecutable`.1775 /// Creates a `RunStep` with an executable built with `addExecutable`.
1763 /// Add command line arguments with `addArg`.1776 /// Add command line arguments with `addArg`.
1764 pub fn run(exe: *LibExeObjStep) *RunStep {1777 pub fn run(exe: *LibExeObjStep) *RunStep {
1765 assert(exe.kind == .exe);1778 assert(exe.kind == .exe or exe.kind == .test_exe);
17661779
1767 // It doesn't have to be native. We catch that if you actually try to run it.1780 // It doesn't have to be native. We catch that if you actually try to run it.
1768 // Consider that this is declarative; the run step may not be run unless a user1781 // Consider that this is declarative; the run step may not be run unless a user
...@@ -1770,6 +1783,10 @@ pub const LibExeObjStep = struct {...@@ -1770,6 +1783,10 @@ pub const LibExeObjStep = struct {
1770 const run_step = RunStep.create(exe.builder, exe.builder.fmt("run {s}", .{exe.step.name}));1783 const run_step = RunStep.create(exe.builder, exe.builder.fmt("run {s}", .{exe.step.name}));
1771 run_step.addArtifactArg(exe);1784 run_step.addArtifactArg(exe);
17721785
1786 if (exe.kind == .test_exe) {
1787 run_step.addArg(exe.builder.zig_exe);
1788 }
1789
1773 if (exe.vcpkg_bin_path) |path| {1790 if (exe.vcpkg_bin_path) |path| {
1774 run_step.addPathDir(path);1791 run_step.addPathDir(path);
1775 }1792 }
...@@ -1816,7 +1833,7 @@ pub const LibExeObjStep = struct {...@@ -1816,7 +1833,7 @@ pub const LibExeObjStep = struct {
1816 pub fn producesPdbFile(self: *LibExeObjStep) bool {1833 pub fn producesPdbFile(self: *LibExeObjStep) bool {
1817 if (!self.target.isWindows() and !self.target.isUefi()) return false;1834 if (!self.target.isWindows() and !self.target.isUefi()) return false;
1818 if (self.strip) return false;1835 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;
1820 }1837 }
18211838
1822 pub fn linkLibC(self: *LibExeObjStep) void {1839 pub fn linkLibC(self: *LibExeObjStep) void {
...@@ -1976,12 +1993,12 @@ pub const LibExeObjStep = struct {...@@ -1976,12 +1993,12 @@ pub const LibExeObjStep = struct {
1976 }1993 }
19771994
1978 pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void {1995 pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void {
1979 assert(self.kind == .@"test");1996 assert(self.kind == .@"test" or self.kind == .test_exe);
1980 self.name_prefix = self.builder.dupe(text);1997 self.name_prefix = self.builder.dupe(text);
1981 }1998 }
19821999
1983 pub fn setFilter(self: *LibExeObjStep, text: ?[]const u8) void {2000 pub fn setFilter(self: *LibExeObjStep, text: ?[]const u8) void {
1984 assert(self.kind == .@"test");2001 assert(self.kind == .@"test" or self.kind == .test_exe);
1985 self.filter = if (text) |t| self.builder.dupe(t) else null;2002 self.filter = if (text) |t| self.builder.dupe(t) else null;
1986 }2003 }
19872004
...@@ -2052,7 +2069,7 @@ pub const LibExeObjStep = struct {...@@ -2052,7 +2069,7 @@ pub const LibExeObjStep = struct {
2052 /// Returns the generated header file.2069 /// Returns the generated header file.
2053 /// This function can only be called for libraries or object files which have `emit_h` set.2070 /// This function can only be called for libraries or object files which have `emit_h` set.
2054 pub fn getOutputHSource(self: *LibExeObjStep) FileSource {2071 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");
2056 assert(self.emit_h);2073 assert(self.emit_h);
2057 return FileSource{ .generated = &self.output_h_path_source };2074 return FileSource{ .generated = &self.output_h_path_source };
2058 }2075 }
...@@ -2222,6 +2239,7 @@ pub const LibExeObjStep = struct {...@@ -2222,6 +2239,7 @@ pub const LibExeObjStep = struct {
2222 .exe => "build-exe",2239 .exe => "build-exe",
2223 .obj => "build-obj",2240 .obj => "build-obj",
2224 .@"test" => "test",2241 .@"test" => "test",
2242 .test_exe => "test",
2225 };2243 };
2226 zig_args.append(cmd) catch unreachable;2244 zig_args.append(cmd) catch unreachable;
22272245
...@@ -2268,8 +2286,9 @@ pub const LibExeObjStep = struct {...@@ -2268,8 +2286,9 @@ pub const LibExeObjStep = struct {
2268 .static_path => |static_path| try zig_args.append(static_path.getPath(builder)),2286 .static_path => |static_path| try zig_args.append(static_path.getPath(builder)),
22692287
2270 .other_step => |other| switch (other.kind) {2288 .other_step => |other| switch (other.kind) {
2271 .exe => unreachable,2289 .exe => @panic("Cannot link with an executable build artifact"),
2272 .@"test" => unreachable,2290 .test_exe => @panic("Cannot link with an executable build artifact"),
2291 .@"test" => @panic("Cannot link with a test"),
2273 .obj => {2292 .obj => {
2274 try zig_args.append(other.getOutputSource().getPath(builder));2293 try zig_args.append(other.getOutputSource().getPath(builder));
2275 },2294 },
...@@ -2542,89 +2561,93 @@ pub const LibExeObjStep = struct {...@@ -2542,89 +2561,93 @@ pub const LibExeObjStep = struct {
2542 try zig_args.append(builder.pathFromRoot(version_script));2561 try zig_args.append(builder.pathFromRoot(version_script));
2543 }2562 }
25442563
2545 if (self.exec_cmd_args) |exec_cmd_args| {2564 if (self.kind == .@"test") {
2546 for (exec_cmd_args) |cmd_arg| {2565 if (self.exec_cmd_args) |exec_cmd_args| {
2547 if (cmd_arg) |arg| {2566 for (exec_cmd_args) |cmd_arg| {
2548 try zig_args.append("--test-cmd");2567 if (cmd_arg) |arg| {
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;
2576 try zig_args.append("--test-cmd");2568 try zig_args.append("--test-cmd");
2577 try zig_args.append(bin_name);2569 try zig_args.append(arg);
2578 if (glibc_dir_arg) |dir| {2570 } else {
2579 // TODO look into making this a call to `linuxTriple`. This2571 try zig_args.append("--test-cmd-bin");
2580 // needs the directory to be called "i686" rather than2572 }
2581 // "i386" which is why we do it manually here.2573 }
2582 const fmt_str = "{s}" ++ fs.path.sep_str ++ "{s}-{s}-{s}";2574 } else {
2583 const cpu_arch = self.target.getCpuArch();2575 const need_cross_glibc = self.target.isGnuLibC() and self.is_linking_libc;
2584 const os_tag = self.target.getOsTag();2576
2585 const abi = self.target.getAbi();2577 switch (self.builder.host.getExternalExecutor(self.target_info, .{
2586 const cpu_arch_name: []const u8 = if (cpu_arch == .i386)2578 .qemu_fixes_dl = need_cross_glibc and builder.glibc_runtimes_dir != null,
2587 "i686"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
2588 else2594 else
2589 @tagName(cpu_arch);2595 null;
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");
2596 try zig_args.append("--test-cmd");2596 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;
2598 }2621 }
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);
2599 try zig_args.append("--test-cmd-bin");2627 try zig_args.append("--test-cmd-bin");
2600 break :ok;2628 } else {
2601 }2629 try zig_args.append("--test-no-exec");
2602 try zig_args.append("--test-no-exec");2630 },
2603 },2631 .wasmtime => |bin_name| if (builder.enable_wasmtime) {
2604 .wine => |bin_name| if (builder.enable_wine) {2632 try zig_args.append("--test-cmd");
2605 try zig_args.append("--test-cmd");2633 try zig_args.append(bin_name);
2606 try zig_args.append(bin_name);2634 try zig_args.append("--test-cmd");
2607 try zig_args.append("--test-cmd-bin");2635 try zig_args.append("--dir=.");
2608 } else {2636 try zig_args.append("--test-cmd-bin");
2609 try zig_args.append("--test-no-exec");2637 } else {
2610 },2638 try zig_args.append("--test-no-exec");
2611 .wasmtime => |bin_name| if (builder.enable_wasmtime) {2639 },
2612 try zig_args.append("--test-cmd");2640 .darling => |bin_name| if (builder.enable_darling) {
2613 try zig_args.append(bin_name);2641 try zig_args.append("--test-cmd");
2614 try zig_args.append("--test-cmd");2642 try zig_args.append(bin_name);
2615 try zig_args.append("--dir=.");2643 try zig_args.append("--test-cmd-bin");
2616 try zig_args.append("--test-cmd-bin");2644 } else {
2617 } else {2645 try zig_args.append("--test-no-exec");
2618 try zig_args.append("--test-no-exec");2646 },
2619 },2647 }
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 },
2627 }2648 }
2649 } else if (self.kind == .test_exe) {
2650 try zig_args.append("--test-no-exec");
2628 }2651 }
26292652
2630 for (self.packages.items) |pkg| {2653 for (self.packages.items) |pkg| {
...@@ -2877,13 +2900,13 @@ pub const InstallArtifactStep = struct {...@@ -2877,13 +2900,13 @@ pub const InstallArtifactStep = struct {
2877 .step = Step.init(.install_artifact, builder.fmt("install {s}", .{artifact.step.name}), builder.allocator, make),2900 .step = Step.init(.install_artifact, builder.fmt("install {s}", .{artifact.step.name}), builder.allocator, make),
2878 .artifact = artifact,2901 .artifact = artifact,
2879 .dest_dir = artifact.override_dest_dir orelse switch (artifact.kind) {2902 .dest_dir = artifact.override_dest_dir orelse switch (artifact.kind) {
2880 .obj => unreachable,2903 .obj => @panic("Cannot install a .obj build artifact."),
2881 .@"test" => unreachable,2904 .@"test" => @panic("Cannot install a test build artifact, use addTestExe instead."),
2882 .exe => InstallDir{ .bin = {} },2905 .exe, .test_exe => InstallDir{ .bin = {} },
2883 .lib => InstallDir{ .lib = {} },2906 .lib => InstallDir{ .lib = {} },
2884 },2907 },
2885 .pdb_dir = if (artifact.producesPdbFile()) blk: {2908 .pdb_dir = if (artifact.producesPdbFile()) blk: {
2886 if (artifact.kind == .exe) {2909 if (artifact.kind == .exe or artifact.kind == .test_exe) {
2887 break :blk InstallDir{ .bin = {} };2910 break :blk InstallDir{ .bin = {} };
2888 } else {2911 } else {
2889 break :blk InstallDir{ .lib = {} };2912 break :blk InstallDir{ .lib = {} };
lib/std/build/InstallRawStep.zig+1-1
...@@ -451,7 +451,7 @@ pub fn create(builder: *Builder, artifact: *LibExeObjStep, dest_filename: []cons...@@ -451,7 +451,7 @@ pub fn create(builder: *Builder, artifact: *LibExeObjStep, dest_filename: []cons
451 .dest_dir = if (options.dest_dir) |d| d else switch (artifact.kind) {451 .dest_dir = if (options.dest_dir) |d| d else switch (artifact.kind) {
452 .obj => unreachable,452 .obj => unreachable,
453 .@"test" => unreachable,453 .@"test" => unreachable,
454 .exe => .bin,454 .exe, .test_exe => .bin,
455 .lib => unreachable,455 .lib => unreachable,
456 },456 },
457 .dest_filename = dest_filename,457 .dest_filename = dest_filename,