authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-29 15:36:33-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:34-07:00
log0f3471eb6643140c67587c205aea6582f415dd06
tree0dafc23d26964fe7104a533ec2fa52ad0f9665d2
parent4e3d14f590160013e655f69e249997ff597f8e93

maker: finish porting over run step


12 files changed, 193 insertions(+), 112 deletions(-)

BRANCH_TODO+1
......@@ -16,6 +16,7 @@
1616* restore the generated_compiler_rt_dyn_lib hack?
1717* run args
1818* https://codeberg.org/ziglang/zig/pulls/30762
19* get the target from the parent process instead
1920
2021## Followup Issues
2122* reduce the size of Maker.Step.Extended (make Run smaller) probably by using an arena per make
lib/compiler/Maker/Graph.zig+5-4
......@@ -6,6 +6,7 @@ const Io = std.Io;
66const Allocator = std.mem.Allocator;
77const Configuration = std.Build.Configuration;
88const Path = std.Build.Cache.Path;
9const Directory = std.Build.Cache.Directory;
910
1011io: Io,
1112/// Process lifetime.
......@@ -13,10 +14,10 @@ arena: Allocator,
1314cache: std.Build.Cache,
1415zig_exe: []const u8,
1516environ_map: std.process.Environ.Map,
16global_cache_root: std.Build.Cache.Directory,
17local_cache_root: std.Build.Cache.Directory,
18zig_lib_directory: std.Build.Cache.Directory,
19build_root_directory: std.Build.Cache.Directory,
17global_cache_root: Directory,
18local_cache_root: Directory,
19zig_lib_directory: Directory,
20build_root_directory: Directory,
2021pkg_root: Path,
2122
2223debug_compiler_runtime_libs: ?std.builtin.OptimizeMode = null,
lib/compiler/Maker/Step/Compile.zig+5-1
......@@ -22,6 +22,8 @@ zig_process: ?*Step.ZigProcess = null,
2222zig_args: std.ArrayList([]const u8) = .empty,
2323/// Populated by InstallArtifact.
2424installed_path: ?Path = null,
25/// Populated by `make`, used by `Run`.
26is_linking_libc: bool = false,
2527
2628pub fn make(
2729 compile: *Compile,
......@@ -144,7 +146,7 @@ const ModuleListContext = struct {
144146};
145147
146148fn lowerZigArgs(
147 compile: *const Compile,
149 compile: *Compile,
148150 compile_index: Configuration.Step.Index,
149151 maker: *const Maker,
150152 zig_args: *std.ArrayList([]const u8),
......@@ -564,6 +566,8 @@ fn lowerZigArgs(
564566 try zig_args.ensureUnusedCapacity(gpa, 2);
565567 if (is_linking_libcpp) zig_args.appendAssumeCapacity("-lc++");
566568 if (is_linking_libc) zig_args.appendAssumeCapacity("-lc");
569
570 compile.is_linking_libc = is_linking_libc;
567571 }
568572
569573 if (conf_comp.win32_manifest.value) |manifest_file| {
lib/compiler/Maker/Step/Run.zig+116-81
......@@ -1717,7 +1717,7 @@ fn runCommand(
17171717 has_side_effects: bool,
17181718 output_dir_path: []const u8,
17191719 fuzz_context: ?FuzzContext,
1720) !void {
1720) Step.ExtendedMakeError!void {
17211721 const graph = maker.graph;
17221722 const arena = graph.arena; // TODO don't leak into process arena
17231723 const gpa = maker.gpa;
......@@ -1757,8 +1757,6 @@ fn runCommand(
17571757 }
17581758 try graph.handleVerbose(cwd, environ_map, argv);
17591759
1760 if (true) @panic("TODO");
1761
17621760 const opt_generic_result = spawnChildAndCollect(
17631761 run_index,
17641762 run,
......@@ -1777,22 +1775,33 @@ fn runCommand(
17771775 // relying on it being a Compile step. This will make this logic
17781776 // work even for the edge case that the binary was produced by a
17791777 // third party.
1780 const exe = switch (run.argv.items[0]) {
1781 .artifact => |exe| exe.artifact,
1782 else => break :interpret,
1783 };
1784 switch (exe.kind) {
1778 const arg0 = conf_run.args.slice[0].get(conf);
1779 const producer_index = arg0.producer.value orelse break :interpret;
1780 const producer_step = producer_index.ptr(conf);
1781 const producer = producer_step.extended.get(conf.extra).compile;
1782 switch (producer.flags3.kind) {
17851783 .exe, .@"test" => {},
17861784 else => break :interpret,
17871785 }
1786 const root_module = producer.root_module.get(conf);
1787 const root_module_target = root_module.resolved_target.get(conf).?.result.get(conf);
1788 const other_target_query = root_module_target.unwrap(conf);
1789 const root_target = std.zig.system.resolveTargetQuery(io, other_target_query) catch unreachable;
1790 const link_libc = maker.stepByIndex(producer_index).extended.compile.is_linking_libc;
1791
1792 // TODO get this from the parent process instead
1793 const host: std.Target = std.zig.system.resolveTargetQuery(io, .{}) catch |he| switch (he) {
1794 error.Canceled => |e| return e,
1795 else => builtin.target,
1796 };
17881797
1789 const root_target = exe.rootModuleTarget();
1790 const need_cross_libc = exe.is_linking_libc and
1791 (root_target.isGnuLibC() or (root_target.isMuslLibC() and exe.linkage == .dynamic));
1792 const other_target = exe.root_module.resolved_target.?.result;
1793 switch (std.zig.system.getExternalExecutor(io, &graph.host.result, &other_target, .{
1798 const need_cross_libc = link_libc and root_target.os.tag == .linux and
1799 producer.flags2.linkage == .dynamic;
1800 switch (std.zig.system.getExternalExecutor(io, &root_target, .{
1801 .host_cpu_arch = host.cpu.arch,
1802 .host_os_tag = host.os.tag,
17941803 .qemu_fixes_dl = need_cross_libc and graph.libc_runtimes_dir != null,
1795 .link_libc = exe.is_linking_libc,
1804 .link_libc = link_libc,
17961805 })) {
17971806 .native, .rosetta => {
17981807 if (allow_skip) return error.MakeSkipped;
......@@ -1800,8 +1809,9 @@ fn runCommand(
18001809 },
18011810 .wine => |bin_name| {
18021811 if (graph.enable_wine) {
1803 try interp_argv.append(bin_name);
1804 try interp_argv.appendSlice(argv);
1812 try interp_argv.ensureUnusedCapacity(arena, 1 + argv.len);
1813 interp_argv.appendAssumeCapacity(bin_name);
1814 interp_argv.appendSliceAssumeCapacity(argv);
18051815
18061816 // Wine's excessive stderr logging is only situationally helpful. Disable it by default, but
18071817 // allow the user to override it (e.g. with `WINEDEBUG=err+all`) if desired.
......@@ -1809,17 +1819,18 @@ fn runCommand(
18091819 try environ_map.put("WINEDEBUG", "-all");
18101820 }
18111821 } else {
1812 return failForeign(conf_run, maker, run_index, "-fwine", argv[0], exe);
1822 return failForeign(&conf_run, maker, run_index, "-fwine", argv[0], &root_target, &host);
18131823 }
18141824 },
18151825 .qemu => |bin_name| {
18161826 if (graph.enable_qemu) {
1817 try interp_argv.append(bin_name);
1827 try interp_argv.ensureUnusedCapacity(arena, 3 + argv.len);
1828 interp_argv.appendAssumeCapacity(bin_name);
18181829
18191830 if (need_cross_libc) {
18201831 if (graph.libc_runtimes_dir) |dir| {
1821 try interp_argv.append("-L");
1822 try interp_argv.append(try Dir.path.join(arena, &.{
1832 interp_argv.appendAssumeCapacity("-L");
1833 interp_argv.appendAssumeCapacity(try Dir.path.join(arena, &.{
18231834 dir,
18241835 try if (root_target.isGnuLibC()) std.zig.target.glibcRuntimeTriple(
18251836 arena,
......@@ -1832,37 +1843,38 @@ fn runCommand(
18321843 root_target.abi,
18331844 ) else unreachable,
18341845 }));
1835 } else return failForeign(conf_run, maker, run_index, "--libc-runtimes", argv[0], exe);
1846 } else return failForeign(&conf_run, maker, run_index, "--libc-runtimes", argv[0], &root_target, &host);
18361847 }
18371848
1838 try interp_argv.appendSlice(argv);
1839 } else return failForeign(conf_run, maker, run_index, "-fqemu", argv[0], exe);
1849 interp_argv.appendSliceAssumeCapacity(argv);
1850 } else return failForeign(&conf_run, maker, run_index, "-fqemu", argv[0], &root_target, &host);
18401851 },
18411852 .darling => |bin_name| {
18421853 if (graph.enable_darling) {
1843 try interp_argv.append(bin_name);
1844 try interp_argv.appendSlice(argv);
1854 try interp_argv.ensureUnusedCapacity(arena, 1 + argv.len);
1855 interp_argv.appendAssumeCapacity(bin_name);
1856 interp_argv.appendSliceAssumeCapacity(argv);
18451857 } else {
1846 return failForeign(conf_run, maker, run_index, "-fdarling", argv[0], exe);
1858 return failForeign(&conf_run, maker, run_index, "-fdarling", argv[0], &root_target, &host);
18471859 }
18481860 },
18491861 .wasmtime => |bin_name| {
18501862 if (graph.enable_wasmtime) {
1851 try interp_argv.append(bin_name);
1852 try interp_argv.append("--dir=.");
1863 try interp_argv.ensureUnusedCapacity(arena, 3 + argv.len);
1864 interp_argv.appendAssumeCapacity(bin_name);
1865 interp_argv.appendAssumeCapacity("--dir=.");
18531866 // Wasmtime doeesn't inherit environment variables from the parent process
18541867 // by default. '-S inherit-env' was added in Wasmtime version 20.
1855 try interp_argv.append("-Sinherit-env");
1856 try interp_argv.append(argv[0]);
1857 try interp_argv.appendSlice(argv[1..]);
1868 interp_argv.appendAssumeCapacity("-Sinherit-env");
1869 interp_argv.appendSliceAssumeCapacity(argv);
18581870 } else {
1859 return failForeign(conf_run, maker, run_index, "-fwasmtime", argv[0], exe);
1871 return failForeign(&conf_run, maker, run_index, "-fwasmtime", argv[0], &root_target, &host);
18601872 }
18611873 },
18621874 .bad_dl => |foreign_dl| {
18631875 if (allow_skip) return error.MakeSkipped;
18641876
1865 const host_dl = graph.host.result.dynamic_linker.get() orelse "(none)";
1877 const host_dl = host.dynamic_linker.get() orelse "(none)";
18661878
18671879 return step.fail(maker,
18681880 \\the host system is unable to execute binaries from the target
......@@ -1874,7 +1886,7 @@ fn runCommand(
18741886 .bad_os_or_cpu => {
18751887 if (allow_skip) return error.MakeSkipped;
18761888
1877 const host_name = try graph.host.result.zigTriple(arena);
1889 const host_name = try host.zigTriple(arena);
18781890 const foreign_name = try root_target.zigTriple(arena);
18791891
18801892 return step.fail(maker, "the host system ({s}) is unable to execute binaries from the target ({s})", .{
......@@ -1885,15 +1897,24 @@ fn runCommand(
18851897
18861898 if (root_target.os.tag == .windows) {
18871899 // On Windows we don't have rpaths so we have to add .dll search paths to PATH
1888 addPathForDynLibs(exe);
1900 addPathForDynLibs(producer_index);
18891901 }
18901902
18911903 gpa.free(step.result_failed_command.?);
18921904 step.result_failed_command = null;
1893 try graph.handleVerbose(cwd, run.environ_map, interp_argv.items);
1905 try graph.handleVerbose(cwd, environ_map, interp_argv.items);
18941906
1895 break :term spawnChildAndCollect(run_index, run, maker, progress_node, interp_argv.items, &environ_map, has_side_effects, fuzz_context) catch |e| {
1896 if (!run.failing_to_execute_foreign_is_an_error) return error.MakeSkipped;
1907 break :term spawnChildAndCollect(
1908 run_index,
1909 run,
1910 maker,
1911 progress_node,
1912 interp_argv.items,
1913 environ_map,
1914 has_side_effects,
1915 fuzz_context,
1916 ) catch |e| {
1917 if (!conf_run.flags.failing_to_execute_foreign_is_an_error) return error.MakeSkipped;
18971918 if (e == error.MakeFailed) return error.MakeFailed; // error already reported
18981919 return step.fail(maker, "unable to spawn interpreter {s}: {t}", .{ interp_argv.items[0], e });
18991920 };
......@@ -1919,47 +1940,51 @@ fn runCommand(
19191940 const Stream = struct {
19201941 captured: ?Configuration.Step.Run.CapturedStream,
19211942 bytes: ?[]const u8,
1943 trim_whitespace: Configuration.Step.Run.TrimWhitespace,
19221944 };
1923 for ([_]Stream{
1945 for (&[_]Stream{
19241946 .{
19251947 .captured = conf_run.captured_stdout.value,
19261948 .bytes = generic_result.stdout,
1949 .trim_whitespace = conf_run.flags.stdout_trim_whitespace,
19271950 },
19281951 .{
19291952 .captured = conf_run.captured_stderr.value,
19301953 .bytes = generic_result.stderr,
1954 .trim_whitespace = conf_run.flags.stderr_trim_whitespace,
19311955 },
1932 }) |stream| {
1956 }) |*stream| {
19331957 if (stream.captured) |captured| {
1934 const output_components = .{ output_dir_path, captured.output.basename };
1935 const output_path = try cache_root.join(arena, &output_components);
1936 captured.output.generated_file.path = output_path;
1937
1938 const sub_path = try Dir.path.join(arena, &output_components);
1939 const sub_path_dirname = Dir.path.dirname(sub_path).?;
1940 cache_root.handle.createDirPath(io, sub_path_dirname) catch |err| {
1941 return step.fail(maker, "unable to make path '{f}{s}': {t}", .{
1942 cache_root, sub_path_dirname, err,
1943 });
1958 const output_path: Path = .{
1959 .root_dir = cache_root,
1960 .sub_path = try Dir.path.join(arena, &.{
1961 output_dir_path, captured.basename.slice(conf),
1962 }),
19441963 };
1945 const data = switch (captured.trim_whitespace) {
1964 maker.generatedPath(captured.generated_file).* = output_path;
1965
1966 const sub_path_parent = output_path.dirname().?;
1967 sub_path_parent.root_dir.handle.createDirPath(io, sub_path_parent.sub_path) catch |err|
1968 return step.fail(maker, "unable to make path {f}: {t}", .{ sub_path_parent, err });
1969
1970 const data = switch (stream.trim_whitespace) {
19461971 .none => stream.bytes.?,
19471972 .all => mem.trim(u8, stream.bytes.?, &std.ascii.whitespace),
19481973 .leading => mem.trimStart(u8, stream.bytes.?, &std.ascii.whitespace),
19491974 .trailing => mem.trimEnd(u8, stream.bytes.?, &std.ascii.whitespace),
19501975 };
1951 cache_root.handle.writeFile(io, .{ .sub_path = sub_path, .data = data }) catch |err| {
1952 return step.fail(maker, "unable to write file '{f}{s}': {t}", .{
1953 cache_root, sub_path, err,
1954 });
1955 };
1976 output_path.root_dir.handle.writeFile(io, .{
1977 .sub_path = output_path.sub_path,
1978 .data = data,
1979 }) catch |err| return step.fail(maker, "unable to write file {f}: {t}", .{ output_path, err });
19561980 }
19571981 }
19581982
19591983 switch (conf_run.flags.stdio) {
19601984 .zig_test => unreachable,
1961 .check => |checks| for (checks.items) |check| switch (check) {
1962 .expect_stderr_exact => |expected_bytes| {
1985 .check => {
1986 if (conf_run.expect_stderr_exact.value) |bytes| {
1987 const expected_bytes = bytes.slice(conf);
19631988 if (!mem.eql(u8, expected_bytes, generic_result.stderr.?)) {
19641989 return step.fail(maker,
19651990 \\========= expected this stderr: =========
......@@ -1971,34 +1996,37 @@ fn runCommand(
19711996 generic_result.stderr.?,
19721997 });
19731998 }
1974 },
1975 .expect_stderr_match => |match| {
1976 if (mem.find(u8, generic_result.stderr.?, match) == null) {
1999 }
2000 if (conf_run.expect_stdout_exact.value) |bytes| {
2001 const expected_bytes = bytes.slice(conf);
2002 if (!mem.eql(u8, expected_bytes, generic_result.stdout.?)) {
19772003 return step.fail(maker,
1978 \\========= expected to find in stderr: =========
2004 \\========= expected this stdout: =========
19792005 \\{s}
1980 \\========= but stderr does not contain it: =====
2006 \\========= but found: ====================
19812007 \\{s}
19822008 , .{
1983 match,
1984 generic_result.stderr.?,
2009 expected_bytes,
2010 generic_result.stdout.?,
19852011 });
19862012 }
1987 },
1988 .expect_stdout_exact => |expected_bytes| {
1989 if (!mem.eql(u8, expected_bytes, generic_result.stdout.?)) {
2013 }
2014 for (conf_run.expect_stderr_match.slice) |bytes| {
2015 const match = bytes.slice(conf);
2016 if (mem.find(u8, generic_result.stderr.?, match) == null) {
19902017 return step.fail(maker,
1991 \\========= expected this stdout: =========
2018 \\========= expected to find in stderr: =========
19922019 \\{s}
1993 \\========= but found: ====================
2020 \\========= but stderr does not contain it: =====
19942021 \\{s}
19952022 , .{
1996 expected_bytes,
1997 generic_result.stdout.?,
2023 match,
2024 generic_result.stderr.?,
19982025 });
19992026 }
2000 },
2001 .expect_stdout_match => |match| {
2027 }
2028 for (conf_run.expect_stdout_match.slice) |bytes| {
2029 const match = bytes.slice(conf);
20022030 if (mem.find(u8, generic_result.stdout.?, match) == null) {
20032031 return step.fail(maker,
20042032 \\========= expected to find in stdout: =========
......@@ -2010,15 +2038,21 @@ fn runCommand(
20102038 generic_result.stdout.?,
20112039 });
20122040 }
2013 },
2014 .expect_term => |expected_term| {
2041 }
2042 if (conf_run.expect_term_value.value) |expected_term_value| {
2043 const expected_term: process.Child.Term = switch (conf_run.flags2.expect_term_status) {
2044 .exited => .{ .exited = @intCast(expected_term_value) },
2045 .signal => .{ .signal = @enumFromInt(expected_term_value) },
2046 .stopped => .{ .stopped = @enumFromInt(expected_term_value) },
2047 .unknown => .{ .unknown = expected_term_value },
2048 };
20152049 if (!termMatches(expected_term, generic_result.term)) {
20162050 return step.fail(maker, "process {f} (expected {f})", .{
20172051 fmtTerm(generic_result.term),
20182052 fmtTerm(expected_term),
20192053 });
20202054 }
2021 },
2055 }
20222056 },
20232057 else => {
20242058 // On failure, report captured stderr like normal standard error output.
......@@ -2032,7 +2066,7 @@ fn runCommand(
20322066 }
20332067 }
20342068
2035 try step.handleChildProcessTerm(generic_result.term);
2069 try step.handleChildProcessTerm(maker, generic_result.term);
20362070 },
20372071 }
20382072}
......@@ -2256,7 +2290,8 @@ fn failForeign(
22562290 step_index: Configuration.Step.Index,
22572291 suggested_flag: []const u8,
22582292 argv0: []const u8,
2259 exe: *Step.Compile,
2293 artifact_target: *const std.Target,
2294 host_target: *const std.Target,
22602295) Step.ExtendedMakeError {
22612296 const step = maker.stepByIndex(step_index);
22622297 switch (conf_run.flags.stdio) {
......@@ -2265,8 +2300,8 @@ fn failForeign(
22652300
22662301 const graph = maker.graph;
22672302 const process_arena = graph.arena; // TODO don't leak into process arena
2268 const host_name = try graph.host.result.zigTriple(process_arena);
2269 const foreign_name = try exe.rootModuleTarget().zigTriple(process_arena);
2303 const host_name = try host_target.zigTriple(process_arena);
2304 const foreign_name = try artifact_target.zigTriple(process_arena);
22702305
22712306 return step.fail(maker,
22722307 \\unable to spawn foreign binary '{s}' ({s}) on host system ({s})
lib/compiler/aro/aro/Driver.zig+4-3
......@@ -1041,9 +1041,10 @@ fn parseTarget(d: *Driver, arch_os_abi: []const u8, opt_cpu_features: ?[]const u
10411041 } else if (mem.eql(u8, cpu_name, "baseline")) {
10421042 query.cpu_model = .baseline;
10431043 } else {
1044 query.cpu_model = .{ .explicit = arch.parseCpuModel(cpu_name) catch |er| switch (er) {
1045 error.UnknownCpuModel => return d.fatal("unknown CPU model: '{s}'", .{cpu_name}),
1046 } };
1044 query.cpu_model = .{
1045 .explicit = arch.parseCpuModel(cpu_name) orelse
1046 return d.fatal("unknown CPU model: '{s}'", .{cpu_name}),
1047 };
10471048 }
10481049
10491050 if (opt_sub_arch) |sub_arch| {
lib/compiler/configurer.zig+1
......@@ -83,6 +83,7 @@ pub fn main(init: process.Init.Minimal) !void {
8383 .environ_map = try init.environ.createMap(arena),
8484 .global_cache_root = global_cache_directory,
8585 .zig_lib_directory = zig_lib_directory,
86 // TODO get this from parent process instead
8687 .host = .{
8788 .query = .{},
8889 .result = try std.zig.system.resolveTargetQuery(io, .{}),
lib/std/Build/Configuration.zig+36-1
......@@ -1797,7 +1797,7 @@ pub const TargetQuery = struct {
17971797 }
17981798
17991799 pub fn get(this: @This(), c: *const Configuration) ?TargetQuery {
1800 return (unwrap(this) orelse return null).get(c);
1800 return (this.unwrap() orelse return null).get(c);
18011801 }
18021802 };
18031803
......@@ -1831,6 +1831,15 @@ pub const TargetQuery = struct {
18311831 .windows => .windows,
18321832 };
18331833 }
1834
1835 pub fn unwrap(this: @This(), c: *const Configuration) ?std.Target.Query.OsVersion {
1836 return switch (this) {
1837 .none => .none,
1838 .semver => |sv| .{ .semver = std.SemanticVersion.parse(sv.slice(c)) catch unreachable },
1839 .windows => |wv| .{ .windows = wv },
1840 .default => null,
1841 };
1842 }
18341843 };
18351844 pub const Abi = enum(u5) {
18361845 none,
......@@ -2052,6 +2061,32 @@ pub const TargetQuery = struct {
20522061 android_api_level: bool,
20532062 dynamic_linker: bool,
20542063 };
2064
2065 pub fn unwrap(tq: *const TargetQuery, c: *const Configuration) std.Target.Query {
2066 const cpu_arch = tq.flags.cpu_arch.unwrap();
2067 return .{
2068 .cpu_arch = cpu_arch,
2069 .cpu_model = switch (tq.flags.cpu_model) {
2070 .native => .native,
2071 .baseline => .baseline,
2072 .determined_by_arch_os => .determined_by_arch_os,
2073 .explicit => .{ .explicit = cpu_arch.?.parseCpuModel(tq.cpu_name.value.?.slice(c)).? },
2074 },
2075 .cpu_features_add = tq.cpu_features_add.value orelse .empty,
2076 .cpu_features_sub = tq.cpu_features_sub.value orelse .empty,
2077 .os_tag = tq.flags.os_tag.unwrap(),
2078 .os_version_min = tq.os_version_min.u.unwrap(c),
2079 .os_version_max = tq.os_version_max.u.unwrap(c),
2080 .glibc_version = if (tq.glibc_version.value) |s|
2081 std.SemanticVersion.parse(s.slice(c)) catch unreachable
2082 else
2083 null,
2084 .android_api_level = tq.android_api_level.value,
2085 .abi = tq.flags.abi.unwrap(),
2086 .dynamic_linker = .init(if (tq.dynamic_linker.value) |s| s.slice(c) else null),
2087 .ofmt = tq.flags.object_format.unwrap(),
2088 };
2089 }
20552090};
20562091
20572092pub const Storage = enum {
lib/std/Target.zig+2-2
......@@ -1668,13 +1668,13 @@ pub const Cpu = struct {
16681668 };
16691669 }
16701670
1671 pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model {
1671 pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) ?*const Cpu.Model {
16721672 for (arch.allCpuModels()) |cpu| {
16731673 if (std.mem.eql(u8, cpu_name, cpu.name)) {
16741674 return cpu;
16751675 }
16761676 }
1677 return error.UnknownCpuModel;
1677 return null;
16781678 }
16791679
16801680 pub fn endian(arch: Arch) std.builtin.Endian {
lib/std/Target/Query.zig+1-1
......@@ -282,7 +282,7 @@ pub fn parse(args: ParseOptions) !Query {
282282 } else if (mem.eql(u8, cpu_name, "baseline")) {
283283 result.cpu_model = .baseline;
284284 } else {
285 result.cpu_model = .{ .explicit = try arch.parseCpuModel(cpu_name) };
285 result.cpu_model = .{ .explicit = arch.parseCpuModel(cpu_name) orelse return error.UnknownCpuModel };
286286 }
287287
288288 while (index < cpu_features.len) {
lib/std/zig.zig+1-1
......@@ -680,7 +680,7 @@ pub fn putAstErrorsIntoBundle(
680680
681681pub fn resolveTargetQueryOrFatal(io: Io, target_query: std.Target.Query) std.Target {
682682 return std.zig.system.resolveTargetQuery(io, target_query) catch |err|
683 std.process.fatal("unable to resolve target: {s}", .{@errorName(err)});
683 std.process.fatal("unable to resolve target: {t}", .{err});
684684}
685685
686686pub fn parseTargetQueryOrReportFatalError(
lib/std/zig/system.zig+16-17
......@@ -28,6 +28,8 @@ pub const Executor = union(enum) {
2828};
2929
3030pub const GetExternalExecutorOptions = struct {
31 host_cpu_arch: std.Target.Cpu.Arch,
32 host_os_tag: std.Target.Os.Tag,
3133 allow_darling: bool = true,
3234 allow_qemu: bool = true,
3335 allow_rosetta: bool = true,
......@@ -39,24 +41,21 @@ pub const GetExternalExecutorOptions = struct {
3941
4042/// Return whether or not the given host is capable of running executables of
4143/// the other target.
42pub fn getExternalExecutor(
43 io: Io,
44 host: *const std.Target,
45 candidate: *const std.Target,
46 options: GetExternalExecutorOptions,
47) Executor {
48 const os_match = host.os.tag == candidate.os.tag;
44pub fn getExternalExecutor(io: Io, candidate: *const std.Target, options: GetExternalExecutorOptions) Executor {
45 const host_os_tag = options.host_os_tag;
46 const host_cpu_arch = options.host_cpu_arch;
47 const os_match = host_os_tag == candidate.os.tag;
4948 const cpu_ok = cpu_ok: {
50 if (host.cpu.arch == candidate.cpu.arch)
49 if (host_cpu_arch == candidate.cpu.arch)
5150 break :cpu_ok true;
5251
53 if (host.cpu.arch == .x86_64 and candidate.cpu.arch == .x86)
52 if (host_cpu_arch == .x86_64 and candidate.cpu.arch == .x86)
5453 break :cpu_ok true;
5554
56 if (host.cpu.arch == .aarch64 and candidate.cpu.arch == .arm)
55 if (host_cpu_arch == .aarch64 and candidate.cpu.arch == .arm)
5756 break :cpu_ok true;
5857
59 if (host.cpu.arch == .aarch64_be and candidate.cpu.arch == .armeb)
58 if (host_cpu_arch == .aarch64_be and candidate.cpu.arch == .armeb)
6059 break :cpu_ok true;
6160
6261 // TODO additionally detect incompatible CPU features.
......@@ -83,7 +82,7 @@ pub fn getExternalExecutor(
8382 // If the OS match and OS is macOS and CPU is arm64, we can use Rosetta 2
8483 // to emulate the foreign architecture.
8584 if (options.allow_rosetta and os_match and
86 (host.os.tag == .maccatalyst or host.os.tag == .macos) and host.cpu.arch == .aarch64)
85 (host_os_tag == .maccatalyst or host_os_tag == .macos) and host_cpu_arch == .aarch64)
8786 {
8887 switch (candidate.cpu.arch) {
8988 .x86_64 => return .rosetta,
......@@ -173,13 +172,13 @@ pub fn getExternalExecutor(
173172 .windows => {
174173 if (options.allow_wine) {
175174 const wine_supported = switch (candidate.cpu.arch) {
176 .thumb => switch (host.cpu.arch) {
175 .thumb => switch (host_cpu_arch) {
177176 .arm, .thumb, .aarch64 => true,
178177 else => false,
179178 },
180 .aarch64 => host.cpu.arch == .aarch64,
181 .x86 => host.cpu.arch.isX86(),
182 .x86_64 => host.cpu.arch == .x86_64,
179 .aarch64 => host_cpu_arch == .aarch64,
180 .x86 => host_cpu_arch.isX86(),
181 .x86_64 => host_cpu_arch == .x86_64,
183182 else => false,
184183 };
185184 return if (wine_supported) .{ .wine = "wine" } else bad_result;
......@@ -191,7 +190,7 @@ pub fn getExternalExecutor(
191190 // This check can be loosened once darling adds a QEMU-based emulation
192191 // layer for non-host architectures:
193192 // https://github.com/darlinghq/darling/issues/863
194 if (candidate.cpu.arch != host.cpu.arch) {
193 if (candidate.cpu.arch != host_cpu_arch) {
195194 return bad_result;
196195 }
197196 return .{ .darling = "darling" };
src/main.zig+5-1
......@@ -6825,7 +6825,11 @@ fn warnAboutForeignBinaries(
68256825 const host_query: std.Target.Query = .{};
68266826 const host_target = std.zig.resolveTargetQueryOrFatal(io, host_query);
68276827
6828 switch (std.zig.system.getExternalExecutor(io, &host_target, target, .{ .link_libc = link_libc })) {
6828 switch (std.zig.system.getExternalExecutor(io, target, .{
6829 .host_cpu_arch = host_target.cpu.arch,
6830 .host_os_tag = host_target.os.tag,
6831 .link_libc = link_libc,
6832 })) {
68296833 .native => return,
68306834 .rosetta => {
68316835 const host_name = try host_target.zigTriple(arena);