| ... | @@ -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 | } |
| 322 | | 322 | |
| | 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 | }; |
| 1573 | | 1582 | |
| 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 | } |
| 1619 | | 1628 | |
| | 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); |
| 1766 | | 1779 | |
| 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 user | 1781 | // 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); |
| 1772 | | 1785 | |
| | 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 | } |
| 1821 | | 1838 | |
| 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 | } |
| 1977 | | 1994 | |
| 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 | } |
| 1982 | | 1999 | |
| 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 | } |
| 1987 | | 2004 | |
| ... | @@ -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; |
| 2227 | | 2245 | |
| ... | @@ -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)), |
| 2269 | | 2287 | |
| 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 | } |
| 2544 | | 2563 | |
| 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`. This | 2571 | try zig_args.append("--test-cmd-bin"); |
| 2580 | // needs the directory to be called "i686" rather than | 2572 | } |
| 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 | else | 2594 | 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 | } |
| 2629 | | 2652 | |
| 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 = {} }; |