authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-01 15:44:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-02 20:43:01-07:00
log105db13536b4dc2affe130cb8d2eee6c97c89bcd
tree07d5a285d7ff1ea5262118e94ea61a018f1d775a
parentbd1d2b0ae25ead6cd27c0bfeb65490ee92f06bad

std.Build: implement --host-target, --host-cpu, --host-dynamic-linker

This also makes a long-overdue change of extracting common state from Build into a shared Graph object. Getting the semantics right for these flags turned out to be quite tricky. In the end it works like this: * The override only happens when the target is fully native, with no additional query parameters, such as versions or CPU features added. * The override affects the resolved Target but leaves the original Query unmodified. * The "is native?" detection logic operates on the original, unmodified query. This makes it possible to provide invalid host target information, causing confusing errors to occur. Don't do that. There are some minor breaking changes to std.Build API such as the fact that `b.zig_exe` is now moved to `b.graph.zig_exe`, as well as a handful of other similar flags.

15 files changed, 230 insertions(+), 216 deletions(-)

build.zig+8-8
......@@ -45,7 +45,7 @@ pub fn build(b: *std.Build) !void {
4545 });
4646
4747 const docgen_cmd = b.addRunArtifact(docgen_exe);
48 docgen_cmd.addArgs(&.{ "--zig", b.zig_exe });
48 docgen_cmd.addArgs(&.{ "--zig", b.graph.zig_exe });
4949 if (b.zig_lib_dir) |p| {
5050 docgen_cmd.addArg("--zig-lib-dir");
5151 docgen_cmd.addDirectoryArg(p);
......@@ -410,14 +410,14 @@ pub fn build(b: *std.Build) !void {
410410 test_cases_options.addOption(bool, "only_c", only_c);
411411 test_cases_options.addOption(bool, "only_core_functionality", true);
412412 test_cases_options.addOption(bool, "only_reduce", false);
413 test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu);
414 test_cases_options.addOption(bool, "enable_wine", b.enable_wine);
415 test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime);
416 test_cases_options.addOption(bool, "enable_rosetta", b.enable_rosetta);
417 test_cases_options.addOption(bool, "enable_darling", b.enable_darling);
413 test_cases_options.addOption(bool, "enable_qemu", b.graph.enable_qemu);
414 test_cases_options.addOption(bool, "enable_wine", b.graph.enable_wine);
415 test_cases_options.addOption(bool, "enable_wasmtime", b.graph.enable_wasmtime);
416 test_cases_options.addOption(bool, "enable_rosetta", b.graph.enable_rosetta);
417 test_cases_options.addOption(bool, "enable_darling", b.graph.enable_darling);
418418 test_cases_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2);
419419 test_cases_options.addOption(bool, "value_tracing", value_tracing);
420 test_cases_options.addOption(?[]const u8, "glibc_runtimes_dir", b.glibc_runtimes_dir);
420 test_cases_options.addOption(?[]const u8, "glibc_runtimes_dir", b.graph.glibc_runtimes_dir);
421421 test_cases_options.addOption([:0]const u8, "version", version);
422422 test_cases_options.addOption(std.SemanticVersion, "semver", semver);
423423 test_cases_options.addOption(?[]const u8, "test_filter", test_filter);
......@@ -884,7 +884,7 @@ fn findConfigH(b: *std.Build, config_h_path_option: ?[]const u8) ?[]const u8 {
884884 }
885885 }
886886
887 var check_dir = fs.path.dirname(b.zig_exe).?;
887 var check_dir = fs.path.dirname(b.graph.zig_exe).?;
888888 while (true) {
889889 var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable;
890890 defer dir.close();
deps/aro/build/GenerateDef.zig+1-1
......@@ -53,7 +53,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
5353 const self = @fieldParentPtr(GenerateDef, "step", step);
5454 const arena = b.allocator;
5555
56 var man = b.cache.obtain();
56 var man = b.graph.cache.obtain();
5757 defer man.deinit();
5858
5959 // Random bytes to make GenerateDef unique. Refresh this with new
lib/build_runner.zig+50-40
......@@ -46,11 +46,6 @@ pub fn main() !void {
4646 return error.InvalidArgs;
4747 };
4848
49 const host: std.Build.ResolvedTarget = .{
50 .query = .{},
51 .result = try std.zig.system.resolveTargetQuery(.{}),
52 };
53
5449 const build_root_directory: std.Build.Cache.Directory = .{
5550 .path = build_root,
5651 .handle = try std.fs.cwd().openDir(build_root, .{}),
......@@ -66,28 +61,28 @@ pub fn main() !void {
6661 .handle = try std.fs.cwd().makeOpenPath(global_cache_root, .{}),
6762 };
6863
69 var cache: std.Build.Cache = .{
70 .gpa = arena,
71 .manifest_dir = try local_cache_directory.handle.makeOpenPath("h", .{}),
64 var graph: std.Build.Graph = .{
65 .arena = arena,
66 .cache = .{
67 .gpa = arena,
68 .manifest_dir = try local_cache_directory.handle.makeOpenPath("h", .{}),
69 },
70 .zig_exe = zig_exe,
71 .env_map = try process.getEnvMap(arena),
72 .global_cache_root = global_cache_directory,
7273 };
73 cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });
74 cache.addPrefix(build_root_directory);
75 cache.addPrefix(local_cache_directory);
76 cache.addPrefix(global_cache_directory);
77 cache.hash.addBytes(builtin.zig_version_string);
7874
79 var system_library_options: std.StringArrayHashMapUnmanaged(std.Build.SystemLibraryMode) = .{};
75 graph.cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });
76 graph.cache.addPrefix(build_root_directory);
77 graph.cache.addPrefix(local_cache_directory);
78 graph.cache.addPrefix(global_cache_directory);
79 graph.cache.hash.addBytes(builtin.zig_version_string);
8080
8181 const builder = try std.Build.create(
82 arena,
83 zig_exe,
82 &graph,
8483 build_root_directory,
8584 local_cache_directory,
86 global_cache_directory,
87 host,
88 &cache,
8985 dependencies.root_deps,
90 &system_library_options,
9186 );
9287
9388 var targets = ArrayList([]const u8).init(arena);
......@@ -132,10 +127,16 @@ pub fn main() !void {
132127 steps_menu = true;
133128 } else if (mem.eql(u8, arg, "--system-lib")) {
134129 const name = nextArgOrFatal(args, &arg_idx);
135 builder.system_library_options.put(arena, name, .user_enabled) catch @panic("OOM");
130 graph.system_library_options.put(arena, name, .user_enabled) catch @panic("OOM");
136131 } else if (mem.eql(u8, arg, "--no-system-lib")) {
137132 const name = nextArgOrFatal(args, &arg_idx);
138 builder.system_library_options.put(arena, name, .user_disabled) catch @panic("OOM");
133 graph.system_library_options.put(arena, name, .user_disabled) catch @panic("OOM");
134 } else if (mem.eql(u8, arg, "--host-target")) {
135 graph.host_query_options.arch_os_abi = nextArgOrFatal(args, &arg_idx);
136 } else if (mem.eql(u8, arg, "--host-cpu")) {
137 graph.host_query_options.cpu_features = nextArgOrFatal(args, &arg_idx);
138 } else if (mem.eql(u8, arg, "--host-dynamic-linker")) {
139 graph.host_query_options.dynamic_linker = nextArgOrFatal(args, &arg_idx);
139140 } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {
140141 dir_list.lib_dir = nextArgOrFatal(args, &arg_idx);
141142 } else if (mem.eql(u8, arg, "--prefix-exe-dir")) {
......@@ -193,7 +194,7 @@ pub fn main() !void {
193194 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
194195 builder.debug_compile_errors = true;
195196 } else if (mem.eql(u8, arg, "--glibc-runtimes")) {
196 builder.glibc_runtimes_dir = nextArgOrFatal(args, &arg_idx);
197 graph.glibc_runtimes_dir = nextArgOrFatal(args, &arg_idx);
197198 } else if (mem.eql(u8, arg, "--verbose-link")) {
198199 builder.verbose_link = true;
199200 } else if (mem.eql(u8, arg, "--verbose-air")) {
......@@ -213,25 +214,25 @@ pub fn main() !void {
213214 } else if (mem.eql(u8, arg, "--prominent-compile-errors")) {
214215 prominent_compile_errors = true;
215216 } else if (mem.eql(u8, arg, "-fwine")) {
216 builder.enable_wine = true;
217 graph.enable_wine = true;
217218 } else if (mem.eql(u8, arg, "-fno-wine")) {
218 builder.enable_wine = false;
219 graph.enable_wine = false;
219220 } else if (mem.eql(u8, arg, "-fqemu")) {
220 builder.enable_qemu = true;
221 graph.enable_qemu = true;
221222 } else if (mem.eql(u8, arg, "-fno-qemu")) {
222 builder.enable_qemu = false;
223 graph.enable_qemu = false;
223224 } else if (mem.eql(u8, arg, "-fwasmtime")) {
224 builder.enable_wasmtime = true;
225 graph.enable_wasmtime = true;
225226 } else if (mem.eql(u8, arg, "-fno-wasmtime")) {
226 builder.enable_wasmtime = false;
227 graph.enable_wasmtime = false;
227228 } else if (mem.eql(u8, arg, "-frosetta")) {
228 builder.enable_rosetta = true;
229 graph.enable_rosetta = true;
229230 } else if (mem.eql(u8, arg, "-fno-rosetta")) {
230 builder.enable_rosetta = false;
231 graph.enable_rosetta = false;
231232 } else if (mem.eql(u8, arg, "-fdarling")) {
232 builder.enable_darling = true;
233 graph.enable_darling = true;
233234 } else if (mem.eql(u8, arg, "-fno-darling")) {
234 builder.enable_darling = false;
235 graph.enable_darling = false;
235236 } else if (mem.eql(u8, arg, "-freference-trace")) {
236237 builder.reference_trace = 256;
237238 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
......@@ -266,11 +267,19 @@ pub fn main() !void {
266267 }
267268 }
268269
270 const host_query = std.Build.parseTargetQuery(graph.host_query_options) catch |err| switch (err) {
271 error.ParseFailed => process.exit(1),
272 };
273 builder.host = .{
274 .query = .{},
275 .result = try std.zig.system.resolveTargetQuery(host_query),
276 };
277
269278 const stderr = std.io.getStdErr();
270279 const ttyconf = get_tty_conf(color, stderr);
271280 switch (ttyconf) {
272 .no_color => try builder.env_map.put("NO_COLOR", "1"),
273 .escape_codes => try builder.env_map.put("YES_COLOR", "1"),
281 .no_color => try graph.env_map.put("NO_COLOR", "1"),
282 .escape_codes => try graph.env_map.put("YES_COLOR", "1"),
274283 .windows_api => {},
275284 }
276285
......@@ -1029,7 +1038,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
10291038 \\
10301039 \\Steps:
10311040 \\
1032 , .{b.zig_exe});
1041 , .{b.graph.zig_exe});
10331042 try steps(b, out_stream);
10341043
10351044 try out_stream.writeAll(
......@@ -1104,22 +1113,23 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
11041113 \\ --system [dir] System Package Mode. Disable fetching; prefer system libs
11051114 \\ --host-target [triple] Use the provided target as the host
11061115 \\ --host-cpu [cpu] Use the provided CPU as the host
1116 \\ --host-dynamic-linker [path] Use the provided dynamic linker as the host
11071117 \\ --system-lib [name] Use the system-provided library
11081118 \\ --no-system-lib [name] Do not use the system-provided library
11091119 \\
11101120 \\ Available System Library Integrations: Enabled:
11111121 \\
11121122 );
1113 if (b.system_library_options.entries.len == 0) {
1123 if (b.graph.system_library_options.entries.len == 0) {
11141124 try out_stream.writeAll(" (none) -\n");
11151125 } else {
1116 for (b.system_library_options.keys(), b.system_library_options.values()) |name, v| {
1126 for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| {
11171127 const status = switch (v) {
11181128 .declared_enabled => "yes",
11191129 .declared_disabled => "no",
11201130 .user_enabled, .user_disabled => unreachable, // already emitted error
11211131 };
1122 try out_stream.print(" {s:<43} {s}\n", .{ name, status });
1132 try out_stream.print(" {s:<43} {s}\n", .{ k, status });
11231133 }
11241134 }
11251135
......@@ -1203,7 +1213,7 @@ fn fatal(comptime f: []const u8, args: anytype) noreturn {
12031213
12041214fn validateSystemLibraryOptions(b: *std.Build) void {
12051215 var bad = false;
1206 for (b.system_library_options.keys(), b.system_library_options.values()) |k, v| {
1216 for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| {
12071217 switch (v) {
12081218 .user_disabled, .user_enabled => {
12091219 // The user tried to enable or disable a system library integration, but
lib/std/Build.zig+115-122
......@@ -22,15 +22,14 @@ pub const Cache = @import("Build/Cache.zig");
2222pub const Step = @import("Build/Step.zig");
2323pub const Module = @import("Build/Module.zig");
2424
25/// Shared state among all Build instances.
26graph: *Graph,
2527install_tls: TopLevelStep,
2628uninstall_tls: TopLevelStep,
2729allocator: Allocator,
2830user_input_options: UserInputOptionsMap,
2931available_options_map: AvailableOptionsMap,
3032available_options_list: ArrayList(AvailableOption),
31/// All Build instances share this hash map.
32system_library_options: *std.StringArrayHashMapUnmanaged(SystemLibraryMode),
33system_package_mode: bool,
3433verbose: bool,
3534verbose_link: bool,
3635verbose_cc: bool,
......@@ -41,9 +40,7 @@ verbose_cimport: bool,
4140verbose_llvm_cpu_features: bool,
4241reference_trace: ?u32 = null,
4342invalid_user_input: bool,
44zig_exe: [:0]const u8,
4543default_step: *Step,
46env_map: *EnvMap,
4744top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep),
4845install_prefix: []const u8,
4946dest_dir: ?[]const u8,
......@@ -52,14 +49,12 @@ exe_dir: []const u8,
5249h_dir: []const u8,
5350install_path: []const u8,
5451sysroot: ?[]const u8 = null,
55search_prefixes: ArrayList([]const u8),
52search_prefixes: std.ArrayListUnmanaged([]const u8),
5653libc_file: ?[]const u8 = null,
5754installed_files: ArrayList(InstalledFile),
5855/// Path to the directory containing build.zig.
5956build_root: Cache.Directory,
6057cache_root: Cache.Directory,
61global_cache_root: Cache.Directory,
62cache: *Cache,
6358zig_lib_dir: ?LazyPath,
6459pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null,
6560args: ?[][]const u8 = null,
......@@ -71,22 +66,6 @@ debug_pkg_config: bool = false,
7166/// Set to 0 to disable stack collection.
7267debug_stack_frames_count: u8 = 8,
7368
74/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
75enable_darling: bool = false,
76/// Use system QEMU installation to run cross compiled foreign architecture build artifacts.
77enable_qemu: bool = false,
78/// Darwin. Use Rosetta to run x86_64 macOS build artifacts on arm64 macOS.
79enable_rosetta: bool = false,
80/// Use system Wasmtime installation to run cross compiled wasm/wasi build artifacts.
81enable_wasmtime: bool = false,
82/// Use system Wine installation to run cross compiled Windows build artifacts.
83enable_wine: bool = false,
84/// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc,
85/// this will be the directory $glibc-build-dir/install/glibcs
86/// Given the example of the aarch64 target, this is the directory
87/// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
88glibc_runtimes_dir: ?[]const u8 = null,
89
9069/// Information about the native target. Computed before build() is invoked.
9170host: ResolvedTarget,
9271
......@@ -101,9 +80,38 @@ initialized_deps: *InitializedDepMap,
10180/// A mapping from dependency names to package hashes.
10281available_deps: AvailableDeps,
10382
83/// Shared state among all Build instances.
84/// Settings that are here rather than in Build are not configurable per-package.
85pub const Graph = struct {
86 arena: Allocator,
87 system_library_options: std.StringArrayHashMapUnmanaged(SystemLibraryMode) = .{},
88 system_package_mode: bool = false,
89 cache: Cache,
90 zig_exe: [:0]const u8,
91 env_map: EnvMap,
92 global_cache_root: Cache.Directory,
93 host_query_options: std.Target.Query.ParseOptions = .{},
94
95 /// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
96 enable_darling: bool = false,
97 /// Use system QEMU installation to run cross compiled foreign architecture build artifacts.
98 enable_qemu: bool = false,
99 /// Darwin. Use Rosetta to run x86_64 macOS build artifacts on arm64 macOS.
100 enable_rosetta: bool = false,
101 /// Use system Wasmtime installation to run cross compiled wasm/wasi build artifacts.
102 enable_wasmtime: bool = false,
103 /// Use system Wine installation to run cross compiled Windows build artifacts.
104 enable_wine: bool = false,
105 /// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc,
106 /// this will be the directory $glibc-build-dir/install/glibcs
107 /// Given the example of the aarch64 target, this is the directory
108 /// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
109 glibc_runtimes_dir: ?[]const u8 = null,
110};
111
104112const AvailableDeps = []const struct { []const u8, []const u8 };
105113
106pub const SystemLibraryMode = enum {
114const SystemLibraryMode = enum {
107115 /// User asked for the library to be disabled.
108116 /// The build runner has not confirmed whether the setting is recognized yet.
109117 user_disabled,
......@@ -226,29 +234,20 @@ pub const DirList = struct {
226234};
227235
228236pub fn create(
229 allocator: Allocator,
230 zig_exe: [:0]const u8,
237 graph: *Graph,
231238 build_root: Cache.Directory,
232239 cache_root: Cache.Directory,
233 global_cache_root: Cache.Directory,
234 host: ResolvedTarget,
235 cache: *Cache,
236240 available_deps: AvailableDeps,
237 system_library_options: *std.StringArrayHashMapUnmanaged(SystemLibraryMode),
238241) !*Build {
239 const env_map = try allocator.create(EnvMap);
240 env_map.* = try process.getEnvMap(allocator);
242 const arena = graph.arena;
243 const initialized_deps = try arena.create(InitializedDepMap);
244 initialized_deps.* = InitializedDepMap.initContext(arena, .{ .allocator = arena });
241245
242 const initialized_deps = try allocator.create(InitializedDepMap);
243 initialized_deps.* = InitializedDepMap.initContext(allocator, .{ .allocator = allocator });
244
245 const self = try allocator.create(Build);
246 const self = try arena.create(Build);
246247 self.* = .{
247 .zig_exe = zig_exe,
248 .graph = graph,
248249 .build_root = build_root,
249250 .cache_root = cache_root,
250 .global_cache_root = global_cache_root,
251 .cache = cache,
252251 .verbose = false,
253252 .verbose_link = false,
254253 .verbose_cc = false,
......@@ -258,20 +257,19 @@ pub fn create(
258257 .verbose_cimport = false,
259258 .verbose_llvm_cpu_features = false,
260259 .invalid_user_input = false,
261 .allocator = allocator,
262 .user_input_options = UserInputOptionsMap.init(allocator),
263 .available_options_map = AvailableOptionsMap.init(allocator),
264 .available_options_list = ArrayList(AvailableOption).init(allocator),
260 .allocator = arena,
261 .user_input_options = UserInputOptionsMap.init(arena),
262 .available_options_map = AvailableOptionsMap.init(arena),
263 .available_options_list = ArrayList(AvailableOption).init(arena),
265264 .top_level_steps = .{},
266265 .default_step = undefined,
267 .env_map = env_map,
268 .search_prefixes = ArrayList([]const u8).init(allocator),
266 .search_prefixes = .{},
269267 .install_prefix = undefined,
270268 .lib_dir = undefined,
271269 .exe_dir = undefined,
272270 .h_dir = undefined,
273 .dest_dir = env_map.get("DESTDIR"),
274 .installed_files = ArrayList(InstalledFile).init(allocator),
271 .dest_dir = graph.env_map.get("DESTDIR"),
272 .installed_files = ArrayList(InstalledFile).init(arena),
275273 .install_tls = .{
276274 .step = Step.init(.{
277275 .id = .top_level,
......@@ -292,16 +290,14 @@ pub fn create(
292290 .zig_lib_dir = null,
293291 .install_path = undefined,
294292 .args = null,
295 .host = host,
296 .modules = std.StringArrayHashMap(*Module).init(allocator),
297 .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator),
293 .host = undefined,
294 .modules = std.StringArrayHashMap(*Module).init(arena),
295 .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(arena),
298296 .initialized_deps = initialized_deps,
299297 .available_deps = available_deps,
300 .system_library_options = system_library_options,
301 .system_package_mode = false,
302298 };
303 try self.top_level_steps.put(allocator, self.install_tls.step.name, &self.install_tls);
304 try self.top_level_steps.put(allocator, self.uninstall_tls.step.name, &self.uninstall_tls);
299 try self.top_level_steps.put(arena, self.install_tls.step.name, &self.install_tls);
300 try self.top_level_steps.put(arena, self.uninstall_tls.step.name, &self.uninstall_tls);
305301 self.default_step = &self.install_tls.step;
306302 return self;
307303}
......@@ -328,6 +324,7 @@ fn createChildOnly(
328324 const allocator = parent.allocator;
329325 const child = try allocator.create(Build);
330326 child.* = .{
327 .graph = parent.graph,
331328 .allocator = allocator,
332329 .install_tls = .{
333330 .step = Step.init(.{
......@@ -359,9 +356,7 @@ fn createChildOnly(
359356 .verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features,
360357 .reference_trace = parent.reference_trace,
361358 .invalid_user_input = false,
362 .zig_exe = parent.zig_exe,
363359 .default_step = undefined,
364 .env_map = parent.env_map,
365360 .top_level_steps = .{},
366361 .install_prefix = undefined,
367362 .dest_dir = parent.dest_dir,
......@@ -375,26 +370,16 @@ fn createChildOnly(
375370 .installed_files = ArrayList(InstalledFile).init(allocator),
376371 .build_root = build_root,
377372 .cache_root = parent.cache_root,
378 .global_cache_root = parent.global_cache_root,
379 .cache = parent.cache,
380373 .zig_lib_dir = parent.zig_lib_dir,
381374 .debug_log_scopes = parent.debug_log_scopes,
382375 .debug_compile_errors = parent.debug_compile_errors,
383376 .debug_pkg_config = parent.debug_pkg_config,
384 .enable_darling = parent.enable_darling,
385 .enable_qemu = parent.enable_qemu,
386 .enable_rosetta = parent.enable_rosetta,
387 .enable_wasmtime = parent.enable_wasmtime,
388 .enable_wine = parent.enable_wine,
389 .glibc_runtimes_dir = parent.glibc_runtimes_dir,
390377 .host = parent.host,
391378 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
392379 .modules = std.StringArrayHashMap(*Module).init(allocator),
393380 .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator),
394381 .initialized_deps = parent.initialized_deps,
395382 .available_deps = pkg_deps,
396 .system_library_options = parent.system_library_options,
397 .system_package_mode = parent.system_package_mode,
398383 };
399384 try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls);
400385 try child.top_level_steps.put(allocator, child.uninstall_tls.step.name, &child.uninstall_tls);
......@@ -572,7 +557,7 @@ fn hashUserInputOptionsMap(allocator: Allocator, user_input_options: UserInputOp
572557fn determineAndApplyInstallPrefix(b: *Build) !void {
573558 // Create an installation directory local to this package. This will be used when
574559 // dependant packages require a standard prefix, such as include directories for C headers.
575 var hash = b.cache.hash;
560 var hash = b.graph.cache.hash;
576561 // Random bytes to make unique. Refresh this with new random bytes when
577562 // implementation is modified in a non-backwards-compatible way.
578563 hash.add(@as(u32, 0xd8cb0055));
......@@ -587,12 +572,6 @@ fn determineAndApplyInstallPrefix(b: *Build) !void {
587572 b.resolveInstallPrefix(install_prefix, .{});
588573}
589574
590pub fn destroy(b: *Build) void {
591 b.env_map.deinit();
592 b.top_level_steps.deinit(b.allocator);
593 b.allocator.destroy(b);
594}
595
596575/// This function is intended to be called by lib/build_runner.zig, not a build.zig file.
597576pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: DirList) void {
598577 if (self.dest_dir) |dest_dir| {
......@@ -1273,67 +1252,83 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve
12731252 return b.resolveTargetQuery(query);
12741253}
12751254
1276/// Exposes standard `zig build` options for choosing a target.
1277pub fn standardTargetOptionsQueryOnly(b: *Build, args: StandardTargetOptionsArgs) Target.Query {
1278 const maybe_triple = b.option(
1279 []const u8,
1280 "target",
1281 "The CPU architecture, OS, and ABI to build for",
1282 );
1283 const mcpu = b.option([]const u8, "cpu", "Target CPU features to add or subtract");
1284
1285 if (maybe_triple == null and mcpu == null) {
1286 return args.default_target;
1287 }
1288
1289 const triple = maybe_triple orelse "native";
1290
1255pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFailed}!std.Target.Query {
12911256 var diags: Target.Query.ParseOptions.Diagnostics = .{};
1292 const selected_target = Target.Query.parse(.{
1293 .arch_os_abi = triple,
1294 .cpu_features = mcpu,
1295 .diagnostics = &diags,
1296 }) catch |err| switch (err) {
1257 var opts_copy = options;
1258 opts_copy.diagnostics = &diags;
1259 return std.Target.Query.parse(options) catch |err| switch (err) {
12971260 error.UnknownCpuModel => {
1298 log.err("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':", .{
1299 diags.cpu_name.?,
1300 @tagName(diags.arch.?),
1261 std.debug.print("unknown CPU: '{s}'\navailable CPUs for architecture '{s}':\n", .{
1262 diags.cpu_name.?, @tagName(diags.arch.?),
13011263 });
13021264 for (diags.arch.?.allCpuModels()) |cpu| {
1303 log.err(" {s}", .{cpu.name});
1265 std.debug.print(" {s}\n", .{cpu.name});
13041266 }
1305 b.markInvalidUserInput();
1306 return args.default_target;
1267 return error.ParseFailed;
13071268 },
13081269 error.UnknownCpuFeature => {
1309 log.err(
1310 \\Unknown CPU feature: '{s}'
1311 \\Available CPU features for architecture '{s}':
1270 std.debug.print(
1271 \\unknown CPU feature: '{s}'
1272 \\available CPU features for architecture '{s}':
13121273 \\
13131274 , .{
13141275 diags.unknown_feature_name.?,
13151276 @tagName(diags.arch.?),
13161277 });
13171278 for (diags.arch.?.allFeaturesList()) |feature| {
1318 log.err(" {s}: {s}", .{ feature.name, feature.description });
1279 std.debug.print(" {s}: {s}\n", .{ feature.name, feature.description });
13191280 }
1320 b.markInvalidUserInput();
1321 return args.default_target;
1281 return error.ParseFailed;
13221282 },
13231283 error.UnknownOperatingSystem => {
1324 log.err(
1325 \\Unknown OS: '{s}'
1326 \\Available operating systems:
1284 std.debug.print(
1285 \\unknown OS: '{s}'
1286 \\available operating systems:
13271287 \\
13281288 , .{diags.os_name.?});
13291289 inline for (std.meta.fields(Target.Os.Tag)) |field| {
1330 log.err(" {s}", .{field.name});
1290 std.debug.print(" {s}\n", .{field.name});
13311291 }
1332 b.markInvalidUserInput();
1333 return args.default_target;
1292 return error.ParseFailed;
13341293 },
13351294 else => |e| {
1336 log.err("Unable to parse target '{s}': {s}\n", .{ triple, @errorName(e) });
1295 std.debug.print("unable to parse target '{s}': {s}\n", .{
1296 options.arch_os_abi, @errorName(e),
1297 });
1298 return error.ParseFailed;
1299 },
1300 };
1301}
1302
1303/// Exposes standard `zig build` options for choosing a target.
1304pub fn standardTargetOptionsQueryOnly(b: *Build, args: StandardTargetOptionsArgs) Target.Query {
1305 const maybe_triple = b.option(
1306 []const u8,
1307 "target",
1308 "The CPU architecture, OS, and ABI to build for",
1309 );
1310 const mcpu = b.option(
1311 []const u8,
1312 "cpu",
1313 "Target CPU features to add or subtract",
1314 );
1315 const dynamic_linker = b.option(
1316 []const u8,
1317 "dynamic-linker",
1318 "Path to interpreter on the target system",
1319 );
1320
1321 if (maybe_triple == null and mcpu == null and dynamic_linker == null)
1322 return args.default_target;
1323
1324 const triple = maybe_triple orelse "native";
1325
1326 const selected_target = parseTargetQuery(.{
1327 .arch_os_abi = triple,
1328 .cpu_features = mcpu,
1329 .dynamic_linker = dynamic_linker,
1330 }) catch |err| switch (err) {
1331 error.ParseFailed => {
13371332 b.markInvalidUserInput();
13381333 return args.default_target;
13391334 },
......@@ -1622,7 +1617,7 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con
16221617 return fs.realpathAlloc(self.allocator, full_path) catch continue;
16231618 }
16241619 }
1625 if (self.env_map.get("PATH")) |PATH| {
1620 if (self.graph.env_map.get("PATH")) |PATH| {
16261621 for (names) |name| {
16271622 if (fs.path.isAbsolute(name)) {
16281623 return name;
......@@ -1668,7 +1663,7 @@ pub fn runAllowFail(
16681663 child.stdin_behavior = .Ignore;
16691664 child.stdout_behavior = .Pipe;
16701665 child.stderr_behavior = stderr_behavior;
1671 child.env_map = self.env_map;
1666 child.env_map = &self.graph.env_map;
16721667
16731668 try child.spawn();
16741669
......@@ -1714,8 +1709,8 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 {
17141709 };
17151710}
17161711
1717pub fn addSearchPrefix(self: *Build, search_prefix: []const u8) void {
1718 self.search_prefixes.append(self.dupePath(search_prefix)) catch @panic("OOM");
1712pub fn addSearchPrefix(b: *Build, search_prefix: []const u8) void {
1713 b.search_prefixes.append(b.allocator, b.dupePath(search_prefix)) catch @panic("OOM");
17191714}
17201715
17211716pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 {
......@@ -2310,9 +2305,7 @@ pub const ResolvedTarget = struct {
23102305/// Converts a target query into a fully resolved target that can be passed to
23112306/// various parts of the API.
23122307pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget {
2313 // This context will likely be required in the future when the target is
2314 // resolved via a WASI API or via the build protocol.
2315 _ = b;
2308 if (query.isNative()) return b.host;
23162309
23172310 return .{
23182311 .query = query,
......@@ -2326,7 +2319,7 @@ pub fn wantSharedLibSymLinks(target: Target) bool {
23262319}
23272320
23282321pub fn systemLibraryOption(b: *Build, name: []const u8) bool {
2329 const gop = b.system_library_options.getOrPut(b.allocator, name) catch @panic("OOM");
2322 const gop = b.graph.system_library_options.getOrPut(b.allocator, name) catch @panic("OOM");
23302323 if (gop.found_existing) switch (gop.value_ptr.*) {
23312324 .user_disabled => {
23322325 gop.value_ptr.* = .declared_disabled;
......@@ -2340,7 +2333,7 @@ pub fn systemLibraryOption(b: *Build, name: []const u8) bool {
23402333 .declared_enabled => return true,
23412334 } else {
23422335 gop.key_ptr.* = b.dupe(name);
2343 if (b.system_package_mode) {
2336 if (b.graph.system_package_mode) {
23442337 gop.value_ptr.* = .declared_enabled;
23452338 return true;
23462339 } else {
lib/std/Build/Step.zig+1-1
......@@ -314,7 +314,7 @@ pub fn evalZigProcess(
314314 try handleVerbose(s.owner, null, argv);
315315
316316 var child = std.ChildProcess.init(argv, arena);
317 child.env_map = b.env_map;
317 child.env_map = &b.graph.env_map;
318318 child.stdin_behavior = .Pipe;
319319 child.stdout_behavior = .Pipe;
320320 child.stderr_behavior = .Pipe;
lib/std/Build/Step/Compile.zig+12-2
......@@ -923,7 +923,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
923923 var zig_args = ArrayList([]const u8).init(arena);
924924 defer zig_args.deinit();
925925
926 try zig_args.append(b.zig_exe);
926 try zig_args.append(b.graph.zig_exe);
927927
928928 const cmd = switch (self.kind) {
929929 .lib => "build-lib",
......@@ -933,6 +933,16 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
933933 };
934934 try zig_args.append(cmd);
935935
936 if (!mem.eql(u8, b.graph.host_query_options.arch_os_abi, "native")) {
937 try zig_args.appendSlice(&.{ "--host-target", b.graph.host_query_options.arch_os_abi });
938 }
939 if (b.graph.host_query_options.cpu_features) |cpu| {
940 try zig_args.appendSlice(&.{ "--host-cpu", cpu });
941 }
942 if (b.graph.host_query_options.dynamic_linker) |dl| {
943 try zig_args.appendSlice(&.{ "--host-dynamic-linker", dl });
944 }
945
936946 if (b.reference_trace) |some| {
937947 try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some}));
938948 }
......@@ -1393,7 +1403,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
13931403 try zig_args.append(b.cache_root.path orelse ".");
13941404
13951405 try zig_args.append("--global-cache-dir");
1396 try zig_args.append(b.global_cache_root.path orelse ".");
1406 try zig_args.append(b.graph.global_cache_root.path orelse ".");
13971407
13981408 try zig_args.append("--name");
13991409 try zig_args.append(self.name);
lib/std/Build/Step/ConfigHeader.zig+1-1
......@@ -171,7 +171,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
171171 const gpa = b.allocator;
172172 const arena = b.allocator;
173173
174 var man = b.cache.obtain();
174 var man = b.graph.cache.obtain();
175175 defer man.deinit();
176176
177177 // Random bytes to make ConfigHeader unique. Refresh this with new
lib/std/Build/Step/Fmt.zig+1-1
......@@ -52,7 +52,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
5252 var argv: std.ArrayListUnmanaged([]const u8) = .{};
5353 try argv.ensureUnusedCapacity(arena, 2 + 1 + self.paths.len + 2 * self.exclude_paths.len);
5454
55 argv.appendAssumeCapacity(b.zig_exe);
55 argv.appendAssumeCapacity(b.graph.zig_exe);
5656 argv.appendAssumeCapacity("fmt");
5757
5858 if (self.check) {
lib/std/Build/Step/ObjCopy.zig+2-2
......@@ -94,7 +94,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
9494 const b = step.owner;
9595 const self = @fieldParentPtr(ObjCopy, "step", step);
9696
97 var man = b.cache.obtain();
97 var man = b.graph.cache.obtain();
9898 defer man.deinit();
9999
100100 // Random bytes to make ObjCopy unique. Refresh this with new random
......@@ -133,7 +133,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
133133 };
134134
135135 var argv = std.ArrayList([]const u8).init(b.allocator);
136 try argv.appendSlice(&.{ b.zig_exe, "objcopy" });
136 try argv.appendSlice(&.{ b.graph.zig_exe, "objcopy" });
137137
138138 if (self.only_section) |only_section| {
139139 try argv.appendSlice(&.{ "-j", only_section });
lib/std/Build/Step/Options.zig+16-15
......@@ -222,7 +222,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
222222 const basename = "options.zig";
223223
224224 // Hash contents to file name.
225 var hash = b.cache.hash;
225 var hash = b.graph.cache.hash;
226226 // Random bytes to make unique. Refresh this with new random bytes when
227227 // implementation is modified in a non-backwards-compatible way.
228228 hash.add(@as(u32, 0xad95e922));
......@@ -301,27 +301,28 @@ test Options {
301301 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
302302 defer arena.deinit();
303303
304 const host: std.Build.ResolvedTarget = .{
305 .query = .{},
306 .result = try std.zig.system.resolveTargetQuery(.{}),
307 };
308
309 var cache: std.Build.Cache = .{
310 .gpa = arena.allocator(),
311 .manifest_dir = std.fs.cwd(),
304 var graph: std.Build.Graph = .{
305 .arena = arena.allocator(),
306 .cache = .{
307 .gpa = arena.allocator(),
308 .manifest_dir = std.fs.cwd(),
309 },
310 .zig_exe = "test",
311 .env_map = std.process.EnvMap.init(arena.allocator()),
312 .global_cache_root = .{ .path = "test", .handle = std.fs.cwd() },
312313 };
313314
314315 var builder = try std.Build.create(
315 arena.allocator(),
316 "test",
316 &graph,
317317 .{ .path = "test", .handle = std.fs.cwd() },
318318 .{ .path = "test", .handle = std.fs.cwd() },
319 .{ .path = "test", .handle = std.fs.cwd() },
320 host,
321 &cache,
322319 &.{},
323320 );
324 defer builder.destroy();
321
322 builder.host = .{
323 .query = .{},
324 .result = try std.zig.system.resolveTargetQuery(.{}),
325 };
325326
326327 const options = builder.addOptions();
327328
lib/std/Build/Step/Run.zig+8-8
......@@ -463,7 +463,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
463463 var argv_list = ArrayList([]const u8).init(arena);
464464 var output_placeholders = ArrayList(IndexedOutput).init(arena);
465465
466 var man = b.cache.obtain();
466 var man = b.graph.cache.obtain();
467467 defer man.deinit();
468468
469469 for (self.argv.items) |arg| {
......@@ -747,7 +747,7 @@ fn runCommand(
747747 exe.is_linking_libc;
748748 const other_target = exe.root_module.resolved_target.?.result;
749749 switch (std.zig.system.getExternalExecutor(b.host.result, &other_target, .{
750 .qemu_fixes_dl = need_cross_glibc and b.glibc_runtimes_dir != null,
750 .qemu_fixes_dl = need_cross_glibc and b.graph.glibc_runtimes_dir != null,
751751 .link_libc = exe.is_linking_libc,
752752 })) {
753753 .native, .rosetta => {
......@@ -755,7 +755,7 @@ fn runCommand(
755755 break :interpret;
756756 },
757757 .wine => |bin_name| {
758 if (b.enable_wine) {
758 if (b.graph.enable_wine) {
759759 try interp_argv.append(bin_name);
760760 try interp_argv.appendSlice(argv);
761761 } else {
......@@ -763,9 +763,9 @@ fn runCommand(
763763 }
764764 },
765765 .qemu => |bin_name| {
766 if (b.enable_qemu) {
766 if (b.graph.enable_qemu) {
767767 const glibc_dir_arg = if (need_cross_glibc)
768 b.glibc_runtimes_dir orelse
768 b.graph.glibc_runtimes_dir orelse
769769 return failForeign(self, "--glibc-runtimes", argv[0], exe)
770770 else
771771 null;
......@@ -798,7 +798,7 @@ fn runCommand(
798798 }
799799 },
800800 .darling => |bin_name| {
801 if (b.enable_darling) {
801 if (b.graph.enable_darling) {
802802 try interp_argv.append(bin_name);
803803 try interp_argv.appendSlice(argv);
804804 } else {
......@@ -806,7 +806,7 @@ fn runCommand(
806806 }
807807 },
808808 .wasmtime => |bin_name| {
809 if (b.enable_wasmtime) {
809 if (b.graph.enable_wasmtime) {
810810 try interp_argv.append(bin_name);
811811 try interp_argv.append("--dir=.");
812812 try interp_argv.append(argv[0]);
......@@ -1036,7 +1036,7 @@ fn spawnChildAndCollect(
10361036 child.cwd = b.build_root.path;
10371037 child.cwd_dir = b.build_root.handle;
10381038 }
1039 child.env_map = self.env_map orelse b.env_map;
1039 child.env_map = self.env_map orelse &b.graph.env_map;
10401040 child.request_resource_usage_statistics = true;
10411041
10421042 child.stdin_behavior = switch (self.stdio) {
lib/std/Build/Step/TranslateC.zig+1-1
......@@ -121,7 +121,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
121121 const self = @fieldParentPtr(TranslateC, "step", step);
122122
123123 var argv_list = std.ArrayList([]const u8).init(b.allocator);
124 try argv_list.append(b.zig_exe);
124 try argv_list.append(b.graph.zig_exe);
125125 try argv_list.append("translate-c");
126126 if (self.link_libc) {
127127 try argv_list.append("-lc");
lib/std/Build/Step/WriteFile.zig+1-1
......@@ -190,7 +190,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
190190 // If, for example, a hard-coded path was used as the location to put WriteFile
191191 // files, then two WriteFiles executing in parallel might clobber each other.
192192
193 var man = b.cache.obtain();
193 var man = b.graph.cache.obtain();
194194 defer man.deinit();
195195
196196 // Random bytes to make WriteFile unique. Refresh this with
test/src/Cases.zig+2-2
......@@ -562,7 +562,7 @@ pub fn lowerToBuildSteps(
562562 run.setName(incr_case.base_path);
563563 run.addArgs(&.{
564564 case_base_path_with_dir,
565 b.zig_exe,
565 b.graph.zig_exe,
566566 });
567567 run.expectStdOutEqual("");
568568 parent_step.dependOn(&run.step);
......@@ -653,7 +653,7 @@ pub fn lowerToBuildSteps(
653653 break :no_exec;
654654 }
655655 const run_c = b.addSystemCommand(&.{
656 b.zig_exe,
656 b.graph.zig_exe,
657657 "run",
658658 "-cflags",
659659 "-Ilib",
test/tests.zig+11-11
......@@ -796,7 +796,7 @@ pub fn addCliTests(b: *std.Build) *Step {
796796 {
797797 // Test `zig init`.
798798 const tmp_path = b.makeTempPath();
799 const init_exe = b.addSystemCommand(&.{ b.zig_exe, "init" });
799 const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init" });
800800 init_exe.setCwd(.{ .cwd_relative = tmp_path });
801801 init_exe.setName("zig init");
802802 init_exe.expectStdOutEqual("");
......@@ -810,20 +810,20 @@ pub fn addCliTests(b: *std.Build) *Step {
810810 const bad_out_arg = "-femit-bin=does" ++ s ++ "not" ++ s ++ "exist" ++ s ++ "foo.exe";
811811 const ok_src_arg = "src" ++ s ++ "main.zig";
812812 const expected = "error: unable to open output directory 'does" ++ s ++ "not" ++ s ++ "exist': FileNotFound\n";
813 const run_bad = b.addSystemCommand(&.{ b.zig_exe, "build-exe", ok_src_arg, bad_out_arg });
813 const run_bad = b.addSystemCommand(&.{ b.graph.zig_exe, "build-exe", ok_src_arg, bad_out_arg });
814814 run_bad.setName("zig build-exe error message for bad -femit-bin arg");
815815 run_bad.expectExitCode(1);
816816 run_bad.expectStdErrEqual(expected);
817817 run_bad.expectStdOutEqual("");
818818 run_bad.step.dependOn(&init_exe.step);
819819
820 const run_test = b.addSystemCommand(&.{ b.zig_exe, "build", "test" });
820 const run_test = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "test" });
821821 run_test.setCwd(.{ .cwd_relative = tmp_path });
822822 run_test.setName("zig build test");
823823 run_test.expectStdOutEqual("");
824824 run_test.step.dependOn(&init_exe.step);
825825
826 const run_run = b.addSystemCommand(&.{ b.zig_exe, "build", "run" });
826 const run_run = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "run" });
827827 run_run.setCwd(.{ .cwd_relative = tmp_path });
828828 run_run.setName("zig build run");
829829 run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n");
......@@ -857,7 +857,7 @@ pub fn addCliTests(b: *std.Build) *Step {
857857
858858 // This is intended to be the exact CLI usage used by godbolt.org.
859859 const run = b.addSystemCommand(&.{
860 b.zig_exe, "build-obj",
860 b.graph.zig_exe, "build-obj",
861861 "--cache-dir", tmp_path,
862862 "--name", "example",
863863 "-fno-emit-bin", "-fno-emit-h",
......@@ -900,7 +900,7 @@ pub fn addCliTests(b: *std.Build) *Step {
900900 subdir.writeFile("fmt3.zig", unformatted_code) catch @panic("unhandled");
901901
902902 // Test zig fmt affecting only the appropriate files.
903 const run1 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "fmt1.zig" });
903 const run1 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "fmt1.zig" });
904904 run1.setName("run zig fmt one file");
905905 run1.setCwd(.{ .cwd_relative = tmp_path });
906906 run1.has_side_effects = true;
......@@ -908,7 +908,7 @@ pub fn addCliTests(b: *std.Build) *Step {
908908 run1.expectStdOutEqual("fmt1.zig\n");
909909
910910 // Test excluding files and directories from a run
911 const run2 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." });
911 const run2 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." });
912912 run2.setName("run zig fmt on directory with exclusions");
913913 run2.setCwd(.{ .cwd_relative = tmp_path });
914914 run2.has_side_effects = true;
......@@ -916,7 +916,7 @@ pub fn addCliTests(b: *std.Build) *Step {
916916 run2.step.dependOn(&run1.step);
917917
918918 // Test excluding non-existent file
919 const run3 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." });
919 const run3 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." });
920920 run3.setName("run zig fmt on directory with non-existent exclusion");
921921 run3.setCwd(.{ .cwd_relative = tmp_path });
922922 run3.has_side_effects = true;
......@@ -924,7 +924,7 @@ pub fn addCliTests(b: *std.Build) *Step {
924924 run3.step.dependOn(&run2.step);
925925
926926 // running it on the dir, only the new file should be changed
927 const run4 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." });
927 const run4 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
928928 run4.setName("run zig fmt the directory");
929929 run4.setCwd(.{ .cwd_relative = tmp_path });
930930 run4.has_side_effects = true;
......@@ -932,7 +932,7 @@ pub fn addCliTests(b: *std.Build) *Step {
932932 run4.step.dependOn(&run3.step);
933933
934934 // both files have been formatted, nothing should change now
935 const run5 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." });
935 const run5 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
936936 run5.setName("run zig fmt with nothing to do");
937937 run5.setCwd(.{ .cwd_relative = tmp_path });
938938 run5.has_side_effects = true;
......@@ -946,7 +946,7 @@ pub fn addCliTests(b: *std.Build) *Step {
946946 write6.step.dependOn(&run5.step);
947947
948948 // Test `zig fmt` handling UTF-16 decoding.
949 const run6 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." });
949 const run6 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
950950 run6.setName("run zig fmt convert UTF-16 to UTF-8");
951951 run6.setCwd(.{ .cwd_relative = tmp_path });
952952 run6.has_side_effects = true;