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 {...@@ -45,7 +45,7 @@ pub fn build(b: *std.Build) !void {
45 });45 });
4646
47 const docgen_cmd = b.addRunArtifact(docgen_exe);47 const docgen_cmd = b.addRunArtifact(docgen_exe);
48 docgen_cmd.addArgs(&.{ "--zig", b.zig_exe });48 docgen_cmd.addArgs(&.{ "--zig", b.graph.zig_exe });
49 if (b.zig_lib_dir) |p| {49 if (b.zig_lib_dir) |p| {
50 docgen_cmd.addArg("--zig-lib-dir");50 docgen_cmd.addArg("--zig-lib-dir");
51 docgen_cmd.addDirectoryArg(p);51 docgen_cmd.addDirectoryArg(p);
...@@ -410,14 +410,14 @@ pub fn build(b: *std.Build) !void {...@@ -410,14 +410,14 @@ pub fn build(b: *std.Build) !void {
410 test_cases_options.addOption(bool, "only_c", only_c);410 test_cases_options.addOption(bool, "only_c", only_c);
411 test_cases_options.addOption(bool, "only_core_functionality", true);411 test_cases_options.addOption(bool, "only_core_functionality", true);
412 test_cases_options.addOption(bool, "only_reduce", false);412 test_cases_options.addOption(bool, "only_reduce", false);
413 test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu);413 test_cases_options.addOption(bool, "enable_qemu", b.graph.enable_qemu);
414 test_cases_options.addOption(bool, "enable_wine", b.enable_wine);414 test_cases_options.addOption(bool, "enable_wine", b.graph.enable_wine);
415 test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime);415 test_cases_options.addOption(bool, "enable_wasmtime", b.graph.enable_wasmtime);
416 test_cases_options.addOption(bool, "enable_rosetta", b.enable_rosetta);416 test_cases_options.addOption(bool, "enable_rosetta", b.graph.enable_rosetta);
417 test_cases_options.addOption(bool, "enable_darling", b.enable_darling);417 test_cases_options.addOption(bool, "enable_darling", b.graph.enable_darling);
418 test_cases_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2);418 test_cases_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2);
419 test_cases_options.addOption(bool, "value_tracing", value_tracing);419 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);
421 test_cases_options.addOption([:0]const u8, "version", version);421 test_cases_options.addOption([:0]const u8, "version", version);
422 test_cases_options.addOption(std.SemanticVersion, "semver", semver);422 test_cases_options.addOption(std.SemanticVersion, "semver", semver);
423 test_cases_options.addOption(?[]const u8, "test_filter", test_filter);423 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 {...@@ -884,7 +884,7 @@ fn findConfigH(b: *std.Build, config_h_path_option: ?[]const u8) ?[]const u8 {
884 }884 }
885 }885 }
886886
887 var check_dir = fs.path.dirname(b.zig_exe).?;887 var check_dir = fs.path.dirname(b.graph.zig_exe).?;
888 while (true) {888 while (true) {
889 var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable;889 var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable;
890 defer dir.close();890 defer dir.close();
deps/aro/build/GenerateDef.zig+1-1
...@@ -53,7 +53,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -53,7 +53,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
53 const self = @fieldParentPtr(GenerateDef, "step", step);53 const self = @fieldParentPtr(GenerateDef, "step", step);
54 const arena = b.allocator;54 const arena = b.allocator;
5555
56 var man = b.cache.obtain();56 var man = b.graph.cache.obtain();
57 defer man.deinit();57 defer man.deinit();
5858
59 // Random bytes to make GenerateDef unique. Refresh this with new59 // Random bytes to make GenerateDef unique. Refresh this with new
lib/build_runner.zig+50-40
...@@ -46,11 +46,6 @@ pub fn main() !void {...@@ -46,11 +46,6 @@ pub fn main() !void {
46 return error.InvalidArgs;46 return error.InvalidArgs;
47 };47 };
4848
49 const host: std.Build.ResolvedTarget = .{
50 .query = .{},
51 .result = try std.zig.system.resolveTargetQuery(.{}),
52 };
53
54 const build_root_directory: std.Build.Cache.Directory = .{49 const build_root_directory: std.Build.Cache.Directory = .{
55 .path = build_root,50 .path = build_root,
56 .handle = try std.fs.cwd().openDir(build_root, .{}),51 .handle = try std.fs.cwd().openDir(build_root, .{}),
...@@ -66,28 +61,28 @@ pub fn main() !void {...@@ -66,28 +61,28 @@ pub fn main() !void {
66 .handle = try std.fs.cwd().makeOpenPath(global_cache_root, .{}),61 .handle = try std.fs.cwd().makeOpenPath(global_cache_root, .{}),
67 };62 };
6863
69 var cache: std.Build.Cache = .{64 var graph: std.Build.Graph = .{
70 .gpa = arena,65 .arena = arena,
71 .manifest_dir = try local_cache_directory.handle.makeOpenPath("h", .{}),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,
72 };73 };
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
81 const builder = try std.Build.create(81 const builder = try std.Build.create(
82 arena,82 &graph,
83 zig_exe,
84 build_root_directory,83 build_root_directory,
85 local_cache_directory,84 local_cache_directory,
86 global_cache_directory,
87 host,
88 &cache,
89 dependencies.root_deps,85 dependencies.root_deps,
90 &system_library_options,
91 );86 );
9287
93 var targets = ArrayList([]const u8).init(arena);88 var targets = ArrayList([]const u8).init(arena);
...@@ -132,10 +127,16 @@ pub fn main() !void {...@@ -132,10 +127,16 @@ pub fn main() !void {
132 steps_menu = true;127 steps_menu = true;
133 } else if (mem.eql(u8, arg, "--system-lib")) {128 } else if (mem.eql(u8, arg, "--system-lib")) {
134 const name = nextArgOrFatal(args, &arg_idx);129 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");
136 } else if (mem.eql(u8, arg, "--no-system-lib")) {131 } else if (mem.eql(u8, arg, "--no-system-lib")) {
137 const name = nextArgOrFatal(args, &arg_idx);132 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);
139 } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {140 } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {
140 dir_list.lib_dir = nextArgOrFatal(args, &arg_idx);141 dir_list.lib_dir = nextArgOrFatal(args, &arg_idx);
141 } else if (mem.eql(u8, arg, "--prefix-exe-dir")) {142 } else if (mem.eql(u8, arg, "--prefix-exe-dir")) {
...@@ -193,7 +194,7 @@ pub fn main() !void {...@@ -193,7 +194,7 @@ pub fn main() !void {
193 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {194 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
194 builder.debug_compile_errors = true;195 builder.debug_compile_errors = true;
195 } else if (mem.eql(u8, arg, "--glibc-runtimes")) {196 } 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);
197 } else if (mem.eql(u8, arg, "--verbose-link")) {198 } else if (mem.eql(u8, arg, "--verbose-link")) {
198 builder.verbose_link = true;199 builder.verbose_link = true;
199 } else if (mem.eql(u8, arg, "--verbose-air")) {200 } else if (mem.eql(u8, arg, "--verbose-air")) {
...@@ -213,25 +214,25 @@ pub fn main() !void {...@@ -213,25 +214,25 @@ pub fn main() !void {
213 } else if (mem.eql(u8, arg, "--prominent-compile-errors")) {214 } else if (mem.eql(u8, arg, "--prominent-compile-errors")) {
214 prominent_compile_errors = true;215 prominent_compile_errors = true;
215 } else if (mem.eql(u8, arg, "-fwine")) {216 } else if (mem.eql(u8, arg, "-fwine")) {
216 builder.enable_wine = true;217 graph.enable_wine = true;
217 } else if (mem.eql(u8, arg, "-fno-wine")) {218 } else if (mem.eql(u8, arg, "-fno-wine")) {
218 builder.enable_wine = false;219 graph.enable_wine = false;
219 } else if (mem.eql(u8, arg, "-fqemu")) {220 } else if (mem.eql(u8, arg, "-fqemu")) {
220 builder.enable_qemu = true;221 graph.enable_qemu = true;
221 } else if (mem.eql(u8, arg, "-fno-qemu")) {222 } else if (mem.eql(u8, arg, "-fno-qemu")) {
222 builder.enable_qemu = false;223 graph.enable_qemu = false;
223 } else if (mem.eql(u8, arg, "-fwasmtime")) {224 } else if (mem.eql(u8, arg, "-fwasmtime")) {
224 builder.enable_wasmtime = true;225 graph.enable_wasmtime = true;
225 } else if (mem.eql(u8, arg, "-fno-wasmtime")) {226 } else if (mem.eql(u8, arg, "-fno-wasmtime")) {
226 builder.enable_wasmtime = false;227 graph.enable_wasmtime = false;
227 } else if (mem.eql(u8, arg, "-frosetta")) {228 } else if (mem.eql(u8, arg, "-frosetta")) {
228 builder.enable_rosetta = true;229 graph.enable_rosetta = true;
229 } else if (mem.eql(u8, arg, "-fno-rosetta")) {230 } else if (mem.eql(u8, arg, "-fno-rosetta")) {
230 builder.enable_rosetta = false;231 graph.enable_rosetta = false;
231 } else if (mem.eql(u8, arg, "-fdarling")) {232 } else if (mem.eql(u8, arg, "-fdarling")) {
232 builder.enable_darling = true;233 graph.enable_darling = true;
233 } else if (mem.eql(u8, arg, "-fno-darling")) {234 } else if (mem.eql(u8, arg, "-fno-darling")) {
234 builder.enable_darling = false;235 graph.enable_darling = false;
235 } else if (mem.eql(u8, arg, "-freference-trace")) {236 } else if (mem.eql(u8, arg, "-freference-trace")) {
236 builder.reference_trace = 256;237 builder.reference_trace = 256;
237 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {238 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
...@@ -266,11 +267,19 @@ pub fn main() !void {...@@ -266,11 +267,19 @@ pub fn main() !void {
266 }267 }
267 }268 }
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
269 const stderr = std.io.getStdErr();278 const stderr = std.io.getStdErr();
270 const ttyconf = get_tty_conf(color, stderr);279 const ttyconf = get_tty_conf(color, stderr);
271 switch (ttyconf) {280 switch (ttyconf) {
272 .no_color => try builder.env_map.put("NO_COLOR", "1"),281 .no_color => try graph.env_map.put("NO_COLOR", "1"),
273 .escape_codes => try builder.env_map.put("YES_COLOR", "1"),282 .escape_codes => try graph.env_map.put("YES_COLOR", "1"),
274 .windows_api => {},283 .windows_api => {},
275 }284 }
276285
...@@ -1029,7 +1038,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void {...@@ -1029,7 +1038,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
1029 \\1038 \\
1030 \\Steps:1039 \\Steps:
1031 \\1040 \\
1032 , .{b.zig_exe});1041 , .{b.graph.zig_exe});
1033 try steps(b, out_stream);1042 try steps(b, out_stream);
10341043
1035 try out_stream.writeAll(1044 try out_stream.writeAll(
...@@ -1104,22 +1113,23 @@ fn usage(b: *std.Build, out_stream: anytype) !void {...@@ -1104,22 +1113,23 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
1104 \\ --system [dir] System Package Mode. Disable fetching; prefer system libs1113 \\ --system [dir] System Package Mode. Disable fetching; prefer system libs
1105 \\ --host-target [triple] Use the provided target as the host1114 \\ --host-target [triple] Use the provided target as the host
1106 \\ --host-cpu [cpu] Use the provided CPU as the host1115 \\ --host-cpu [cpu] Use the provided CPU as the host
1116 \\ --host-dynamic-linker [path] Use the provided dynamic linker as the host
1107 \\ --system-lib [name] Use the system-provided library1117 \\ --system-lib [name] Use the system-provided library
1108 \\ --no-system-lib [name] Do not use the system-provided library1118 \\ --no-system-lib [name] Do not use the system-provided library
1109 \\1119 \\
1110 \\ Available System Library Integrations: Enabled:1120 \\ Available System Library Integrations: Enabled:
1111 \\1121 \\
1112 );1122 );
1113 if (b.system_library_options.entries.len == 0) {1123 if (b.graph.system_library_options.entries.len == 0) {
1114 try out_stream.writeAll(" (none) -\n");1124 try out_stream.writeAll(" (none) -\n");
1115 } else {1125 } 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| {
1117 const status = switch (v) {1127 const status = switch (v) {
1118 .declared_enabled => "yes",1128 .declared_enabled => "yes",
1119 .declared_disabled => "no",1129 .declared_disabled => "no",
1120 .user_enabled, .user_disabled => unreachable, // already emitted error1130 .user_enabled, .user_disabled => unreachable, // already emitted error
1121 };1131 };
1122 try out_stream.print(" {s:<43} {s}\n", .{ name, status });1132 try out_stream.print(" {s:<43} {s}\n", .{ k, status });
1123 }1133 }
1124 }1134 }
11251135
...@@ -1203,7 +1213,7 @@ fn fatal(comptime f: []const u8, args: anytype) noreturn {...@@ -1203,7 +1213,7 @@ fn fatal(comptime f: []const u8, args: anytype) noreturn {
12031213
1204fn validateSystemLibraryOptions(b: *std.Build) void {1214fn validateSystemLibraryOptions(b: *std.Build) void {
1205 var bad = false;1215 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| {
1207 switch (v) {1217 switch (v) {
1208 .user_disabled, .user_enabled => {1218 .user_disabled, .user_enabled => {
1209 // The user tried to enable or disable a system library integration, but1219 // 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");...@@ -22,15 +22,14 @@ pub const Cache = @import("Build/Cache.zig");
22pub const Step = @import("Build/Step.zig");22pub const Step = @import("Build/Step.zig");
23pub const Module = @import("Build/Module.zig");23pub const Module = @import("Build/Module.zig");
2424
25/// Shared state among all Build instances.
26graph: *Graph,
25install_tls: TopLevelStep,27install_tls: TopLevelStep,
26uninstall_tls: TopLevelStep,28uninstall_tls: TopLevelStep,
27allocator: Allocator,29allocator: Allocator,
28user_input_options: UserInputOptionsMap,30user_input_options: UserInputOptionsMap,
29available_options_map: AvailableOptionsMap,31available_options_map: AvailableOptionsMap,
30available_options_list: ArrayList(AvailableOption),32available_options_list: ArrayList(AvailableOption),
31/// All Build instances share this hash map.
32system_library_options: *std.StringArrayHashMapUnmanaged(SystemLibraryMode),
33system_package_mode: bool,
34verbose: bool,33verbose: bool,
35verbose_link: bool,34verbose_link: bool,
36verbose_cc: bool,35verbose_cc: bool,
...@@ -41,9 +40,7 @@ verbose_cimport: bool,...@@ -41,9 +40,7 @@ verbose_cimport: bool,
41verbose_llvm_cpu_features: bool,40verbose_llvm_cpu_features: bool,
42reference_trace: ?u32 = null,41reference_trace: ?u32 = null,
43invalid_user_input: bool,42invalid_user_input: bool,
44zig_exe: [:0]const u8,
45default_step: *Step,43default_step: *Step,
46env_map: *EnvMap,
47top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep),44top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep),
48install_prefix: []const u8,45install_prefix: []const u8,
49dest_dir: ?[]const u8,46dest_dir: ?[]const u8,
...@@ -52,14 +49,12 @@ exe_dir: []const u8,...@@ -52,14 +49,12 @@ exe_dir: []const u8,
52h_dir: []const u8,49h_dir: []const u8,
53install_path: []const u8,50install_path: []const u8,
54sysroot: ?[]const u8 = null,51sysroot: ?[]const u8 = null,
55search_prefixes: ArrayList([]const u8),52search_prefixes: std.ArrayListUnmanaged([]const u8),
56libc_file: ?[]const u8 = null,53libc_file: ?[]const u8 = null,
57installed_files: ArrayList(InstalledFile),54installed_files: ArrayList(InstalledFile),
58/// Path to the directory containing build.zig.55/// Path to the directory containing build.zig.
59build_root: Cache.Directory,56build_root: Cache.Directory,
60cache_root: Cache.Directory,57cache_root: Cache.Directory,
61global_cache_root: Cache.Directory,
62cache: *Cache,
63zig_lib_dir: ?LazyPath,58zig_lib_dir: ?LazyPath,
64pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null,59pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null,
65args: ?[][]const u8 = null,60args: ?[][]const u8 = null,
...@@ -71,22 +66,6 @@ debug_pkg_config: bool = false,...@@ -71,22 +66,6 @@ debug_pkg_config: bool = false,
71/// Set to 0 to disable stack collection.66/// Set to 0 to disable stack collection.
72debug_stack_frames_count: u8 = 8,67debug_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
90/// Information about the native target. Computed before build() is invoked.69/// Information about the native target. Computed before build() is invoked.
91host: ResolvedTarget,70host: ResolvedTarget,
9271
...@@ -101,9 +80,38 @@ initialized_deps: *InitializedDepMap,...@@ -101,9 +80,38 @@ initialized_deps: *InitializedDepMap,
101/// A mapping from dependency names to package hashes.80/// A mapping from dependency names to package hashes.
102available_deps: AvailableDeps,81available_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
104const AvailableDeps = []const struct { []const u8, []const u8 };112const AvailableDeps = []const struct { []const u8, []const u8 };
105113
106pub const SystemLibraryMode = enum {114const SystemLibraryMode = enum {
107 /// User asked for the library to be disabled.115 /// User asked for the library to be disabled.
108 /// The build runner has not confirmed whether the setting is recognized yet.116 /// The build runner has not confirmed whether the setting is recognized yet.
109 user_disabled,117 user_disabled,
...@@ -226,29 +234,20 @@ pub const DirList = struct {...@@ -226,29 +234,20 @@ pub const DirList = struct {
226};234};
227235
228pub fn create(236pub fn create(
229 allocator: Allocator,237 graph: *Graph,
230 zig_exe: [:0]const u8,
231 build_root: Cache.Directory,238 build_root: Cache.Directory,
232 cache_root: Cache.Directory,239 cache_root: Cache.Directory,
233 global_cache_root: Cache.Directory,
234 host: ResolvedTarget,
235 cache: *Cache,
236 available_deps: AvailableDeps,240 available_deps: AvailableDeps,
237 system_library_options: *std.StringArrayHashMapUnmanaged(SystemLibraryMode),
238) !*Build {241) !*Build {
239 const env_map = try allocator.create(EnvMap);242 const arena = graph.arena;
240 env_map.* = try process.getEnvMap(allocator);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);246 const self = try arena.create(Build);
243 initialized_deps.* = InitializedDepMap.initContext(allocator, .{ .allocator = allocator });
244
245 const self = try allocator.create(Build);
246 self.* = .{247 self.* = .{
247 .zig_exe = zig_exe,248 .graph = graph,
248 .build_root = build_root,249 .build_root = build_root,
249 .cache_root = cache_root,250 .cache_root = cache_root,
250 .global_cache_root = global_cache_root,
251 .cache = cache,
252 .verbose = false,251 .verbose = false,
253 .verbose_link = false,252 .verbose_link = false,
254 .verbose_cc = false,253 .verbose_cc = false,
...@@ -258,20 +257,19 @@ pub fn create(...@@ -258,20 +257,19 @@ pub fn create(
258 .verbose_cimport = false,257 .verbose_cimport = false,
259 .verbose_llvm_cpu_features = false,258 .verbose_llvm_cpu_features = false,
260 .invalid_user_input = false,259 .invalid_user_input = false,
261 .allocator = allocator,260 .allocator = arena,
262 .user_input_options = UserInputOptionsMap.init(allocator),261 .user_input_options = UserInputOptionsMap.init(arena),
263 .available_options_map = AvailableOptionsMap.init(allocator),262 .available_options_map = AvailableOptionsMap.init(arena),
264 .available_options_list = ArrayList(AvailableOption).init(allocator),263 .available_options_list = ArrayList(AvailableOption).init(arena),
265 .top_level_steps = .{},264 .top_level_steps = .{},
266 .default_step = undefined,265 .default_step = undefined,
267 .env_map = env_map,266 .search_prefixes = .{},
268 .search_prefixes = ArrayList([]const u8).init(allocator),
269 .install_prefix = undefined,267 .install_prefix = undefined,
270 .lib_dir = undefined,268 .lib_dir = undefined,
271 .exe_dir = undefined,269 .exe_dir = undefined,
272 .h_dir = undefined,270 .h_dir = undefined,
273 .dest_dir = env_map.get("DESTDIR"),271 .dest_dir = graph.env_map.get("DESTDIR"),
274 .installed_files = ArrayList(InstalledFile).init(allocator),272 .installed_files = ArrayList(InstalledFile).init(arena),
275 .install_tls = .{273 .install_tls = .{
276 .step = Step.init(.{274 .step = Step.init(.{
277 .id = .top_level,275 .id = .top_level,
...@@ -292,16 +290,14 @@ pub fn create(...@@ -292,16 +290,14 @@ pub fn create(
292 .zig_lib_dir = null,290 .zig_lib_dir = null,
293 .install_path = undefined,291 .install_path = undefined,
294 .args = null,292 .args = null,
295 .host = host,293 .host = undefined,
296 .modules = std.StringArrayHashMap(*Module).init(allocator),294 .modules = std.StringArrayHashMap(*Module).init(arena),
297 .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator),295 .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(arena),
298 .initialized_deps = initialized_deps,296 .initialized_deps = initialized_deps,
299 .available_deps = available_deps,297 .available_deps = available_deps,
300 .system_library_options = system_library_options,
301 .system_package_mode = false,
302 };298 };
303 try self.top_level_steps.put(allocator, self.install_tls.step.name, &self.install_tls);299 try self.top_level_steps.put(arena, self.install_tls.step.name, &self.install_tls);
304 try self.top_level_steps.put(allocator, self.uninstall_tls.step.name, &self.uninstall_tls);300 try self.top_level_steps.put(arena, self.uninstall_tls.step.name, &self.uninstall_tls);
305 self.default_step = &self.install_tls.step;301 self.default_step = &self.install_tls.step;
306 return self;302 return self;
307}303}
...@@ -328,6 +324,7 @@ fn createChildOnly(...@@ -328,6 +324,7 @@ fn createChildOnly(
328 const allocator = parent.allocator;324 const allocator = parent.allocator;
329 const child = try allocator.create(Build);325 const child = try allocator.create(Build);
330 child.* = .{326 child.* = .{
327 .graph = parent.graph,
331 .allocator = allocator,328 .allocator = allocator,
332 .install_tls = .{329 .install_tls = .{
333 .step = Step.init(.{330 .step = Step.init(.{
...@@ -359,9 +356,7 @@ fn createChildOnly(...@@ -359,9 +356,7 @@ fn createChildOnly(
359 .verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features,356 .verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features,
360 .reference_trace = parent.reference_trace,357 .reference_trace = parent.reference_trace,
361 .invalid_user_input = false,358 .invalid_user_input = false,
362 .zig_exe = parent.zig_exe,
363 .default_step = undefined,359 .default_step = undefined,
364 .env_map = parent.env_map,
365 .top_level_steps = .{},360 .top_level_steps = .{},
366 .install_prefix = undefined,361 .install_prefix = undefined,
367 .dest_dir = parent.dest_dir,362 .dest_dir = parent.dest_dir,
...@@ -375,26 +370,16 @@ fn createChildOnly(...@@ -375,26 +370,16 @@ fn createChildOnly(
375 .installed_files = ArrayList(InstalledFile).init(allocator),370 .installed_files = ArrayList(InstalledFile).init(allocator),
376 .build_root = build_root,371 .build_root = build_root,
377 .cache_root = parent.cache_root,372 .cache_root = parent.cache_root,
378 .global_cache_root = parent.global_cache_root,
379 .cache = parent.cache,
380 .zig_lib_dir = parent.zig_lib_dir,373 .zig_lib_dir = parent.zig_lib_dir,
381 .debug_log_scopes = parent.debug_log_scopes,374 .debug_log_scopes = parent.debug_log_scopes,
382 .debug_compile_errors = parent.debug_compile_errors,375 .debug_compile_errors = parent.debug_compile_errors,
383 .debug_pkg_config = parent.debug_pkg_config,376 .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,
390 .host = parent.host,377 .host = parent.host,
391 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),378 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
392 .modules = std.StringArrayHashMap(*Module).init(allocator),379 .modules = std.StringArrayHashMap(*Module).init(allocator),
393 .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator),380 .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator),
394 .initialized_deps = parent.initialized_deps,381 .initialized_deps = parent.initialized_deps,
395 .available_deps = pkg_deps,382 .available_deps = pkg_deps,
396 .system_library_options = parent.system_library_options,
397 .system_package_mode = parent.system_package_mode,
398 };383 };
399 try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls);384 try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls);
400 try child.top_level_steps.put(allocator, child.uninstall_tls.step.name, &child.uninstall_tls);385 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...@@ -572,7 +557,7 @@ fn hashUserInputOptionsMap(allocator: Allocator, user_input_options: UserInputOp
572fn determineAndApplyInstallPrefix(b: *Build) !void {557fn determineAndApplyInstallPrefix(b: *Build) !void {
573 // Create an installation directory local to this package. This will be used when558 // Create an installation directory local to this package. This will be used when
574 // dependant packages require a standard prefix, such as include directories for C headers.559 // 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;
576 // Random bytes to make unique. Refresh this with new random bytes when561 // Random bytes to make unique. Refresh this with new random bytes when
577 // implementation is modified in a non-backwards-compatible way.562 // implementation is modified in a non-backwards-compatible way.
578 hash.add(@as(u32, 0xd8cb0055));563 hash.add(@as(u32, 0xd8cb0055));
...@@ -587,12 +572,6 @@ fn determineAndApplyInstallPrefix(b: *Build) !void {...@@ -587,12 +572,6 @@ fn determineAndApplyInstallPrefix(b: *Build) !void {
587 b.resolveInstallPrefix(install_prefix, .{});572 b.resolveInstallPrefix(install_prefix, .{});
588}573}
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
596/// This function is intended to be called by lib/build_runner.zig, not a build.zig file.575/// This function is intended to be called by lib/build_runner.zig, not a build.zig file.
597pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: DirList) void {576pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: DirList) void {
598 if (self.dest_dir) |dest_dir| {577 if (self.dest_dir) |dest_dir| {
...@@ -1273,67 +1252,83 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve...@@ -1273,67 +1252,83 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve
1273 return b.resolveTargetQuery(query);1252 return b.resolveTargetQuery(query);
1274}1253}
12751254
1276/// Exposes standard `zig build` options for choosing a target.1255pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFailed}!std.Target.Query {
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
1291 var diags: Target.Query.ParseOptions.Diagnostics = .{};1256 var diags: Target.Query.ParseOptions.Diagnostics = .{};
1292 const selected_target = Target.Query.parse(.{1257 var opts_copy = options;
1293 .arch_os_abi = triple,1258 opts_copy.diagnostics = &diags;
1294 .cpu_features = mcpu,1259 return std.Target.Query.parse(options) catch |err| switch (err) {
1295 .diagnostics = &diags,
1296 }) catch |err| switch (err) {
1297 error.UnknownCpuModel => {1260 error.UnknownCpuModel => {
1298 log.err("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':", .{1261 std.debug.print("unknown CPU: '{s}'\navailable CPUs for architecture '{s}':\n", .{
1299 diags.cpu_name.?,1262 diags.cpu_name.?, @tagName(diags.arch.?),
1300 @tagName(diags.arch.?),
1301 });1263 });
1302 for (diags.arch.?.allCpuModels()) |cpu| {1264 for (diags.arch.?.allCpuModels()) |cpu| {
1303 log.err(" {s}", .{cpu.name});1265 std.debug.print(" {s}\n", .{cpu.name});
1304 }1266 }
1305 b.markInvalidUserInput();1267 return error.ParseFailed;
1306 return args.default_target;
1307 },1268 },
1308 error.UnknownCpuFeature => {1269 error.UnknownCpuFeature => {
1309 log.err(1270 std.debug.print(
1310 \\Unknown CPU feature: '{s}'1271 \\unknown CPU feature: '{s}'
1311 \\Available CPU features for architecture '{s}':1272 \\available CPU features for architecture '{s}':
1312 \\1273 \\
1313 , .{1274 , .{
1314 diags.unknown_feature_name.?,1275 diags.unknown_feature_name.?,
1315 @tagName(diags.arch.?),1276 @tagName(diags.arch.?),
1316 });1277 });
1317 for (diags.arch.?.allFeaturesList()) |feature| {1278 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 });
1319 }1280 }
1320 b.markInvalidUserInput();1281 return error.ParseFailed;
1321 return args.default_target;
1322 },1282 },
1323 error.UnknownOperatingSystem => {1283 error.UnknownOperatingSystem => {
1324 log.err(1284 std.debug.print(
1325 \\Unknown OS: '{s}'1285 \\unknown OS: '{s}'
1326 \\Available operating systems:1286 \\available operating systems:
1327 \\1287 \\
1328 , .{diags.os_name.?});1288 , .{diags.os_name.?});
1329 inline for (std.meta.fields(Target.Os.Tag)) |field| {1289 inline for (std.meta.fields(Target.Os.Tag)) |field| {
1330 log.err(" {s}", .{field.name});1290 std.debug.print(" {s}\n", .{field.name});
1331 }1291 }
1332 b.markInvalidUserInput();1292 return error.ParseFailed;
1333 return args.default_target;
1334 },1293 },
1335 else => |e| {1294 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 => {
1337 b.markInvalidUserInput();1332 b.markInvalidUserInput();
1338 return args.default_target;1333 return args.default_target;
1339 },1334 },
...@@ -1622,7 +1617,7 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con...@@ -1622,7 +1617,7 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con
1622 return fs.realpathAlloc(self.allocator, full_path) catch continue;1617 return fs.realpathAlloc(self.allocator, full_path) catch continue;
1623 }1618 }
1624 }1619 }
1625 if (self.env_map.get("PATH")) |PATH| {1620 if (self.graph.env_map.get("PATH")) |PATH| {
1626 for (names) |name| {1621 for (names) |name| {
1627 if (fs.path.isAbsolute(name)) {1622 if (fs.path.isAbsolute(name)) {
1628 return name;1623 return name;
...@@ -1668,7 +1663,7 @@ pub fn runAllowFail(...@@ -1668,7 +1663,7 @@ pub fn runAllowFail(
1668 child.stdin_behavior = .Ignore;1663 child.stdin_behavior = .Ignore;
1669 child.stdout_behavior = .Pipe;1664 child.stdout_behavior = .Pipe;
1670 child.stderr_behavior = stderr_behavior;1665 child.stderr_behavior = stderr_behavior;
1671 child.env_map = self.env_map;1666 child.env_map = &self.graph.env_map;
16721667
1673 try child.spawn();1668 try child.spawn();
16741669
...@@ -1714,8 +1709,8 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 {...@@ -1714,8 +1709,8 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 {
1714 };1709 };
1715}1710}
17161711
1717pub fn addSearchPrefix(self: *Build, search_prefix: []const u8) void {1712pub fn addSearchPrefix(b: *Build, search_prefix: []const u8) void {
1718 self.search_prefixes.append(self.dupePath(search_prefix)) catch @panic("OOM");1713 b.search_prefixes.append(b.allocator, b.dupePath(search_prefix)) catch @panic("OOM");
1719}1714}
17201715
1721pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 {1716pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 {
...@@ -2310,9 +2305,7 @@ pub const ResolvedTarget = struct {...@@ -2310,9 +2305,7 @@ pub const ResolvedTarget = struct {
2310/// Converts a target query into a fully resolved target that can be passed to2305/// Converts a target query into a fully resolved target that can be passed to
2311/// various parts of the API.2306/// various parts of the API.
2312pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget {2307pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget {
2313 // This context will likely be required in the future when the target is2308 if (query.isNative()) return b.host;
2314 // resolved via a WASI API or via the build protocol.
2315 _ = b;
23162309
2317 return .{2310 return .{
2318 .query = query,2311 .query = query,
...@@ -2326,7 +2319,7 @@ pub fn wantSharedLibSymLinks(target: Target) bool {...@@ -2326,7 +2319,7 @@ pub fn wantSharedLibSymLinks(target: Target) bool {
2326}2319}
23272320
2328pub fn systemLibraryOption(b: *Build, name: []const u8) bool {2321pub 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");
2330 if (gop.found_existing) switch (gop.value_ptr.*) {2323 if (gop.found_existing) switch (gop.value_ptr.*) {
2331 .user_disabled => {2324 .user_disabled => {
2332 gop.value_ptr.* = .declared_disabled;2325 gop.value_ptr.* = .declared_disabled;
...@@ -2340,7 +2333,7 @@ pub fn systemLibraryOption(b: *Build, name: []const u8) bool {...@@ -2340,7 +2333,7 @@ pub fn systemLibraryOption(b: *Build, name: []const u8) bool {
2340 .declared_enabled => return true,2333 .declared_enabled => return true,
2341 } else {2334 } else {
2342 gop.key_ptr.* = b.dupe(name);2335 gop.key_ptr.* = b.dupe(name);
2343 if (b.system_package_mode) {2336 if (b.graph.system_package_mode) {
2344 gop.value_ptr.* = .declared_enabled;2337 gop.value_ptr.* = .declared_enabled;
2345 return true;2338 return true;
2346 } else {2339 } else {
lib/std/Build/Step.zig+1-1
...@@ -314,7 +314,7 @@ pub fn evalZigProcess(...@@ -314,7 +314,7 @@ pub fn evalZigProcess(
314 try handleVerbose(s.owner, null, argv);314 try handleVerbose(s.owner, null, argv);
315315
316 var child = std.ChildProcess.init(argv, arena);316 var child = std.ChildProcess.init(argv, arena);
317 child.env_map = b.env_map;317 child.env_map = &b.graph.env_map;
318 child.stdin_behavior = .Pipe;318 child.stdin_behavior = .Pipe;
319 child.stdout_behavior = .Pipe;319 child.stdout_behavior = .Pipe;
320 child.stderr_behavior = .Pipe;320 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 {...@@ -923,7 +923,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
923 var zig_args = ArrayList([]const u8).init(arena);923 var zig_args = ArrayList([]const u8).init(arena);
924 defer zig_args.deinit();924 defer zig_args.deinit();
925925
926 try zig_args.append(b.zig_exe);926 try zig_args.append(b.graph.zig_exe);
927927
928 const cmd = switch (self.kind) {928 const cmd = switch (self.kind) {
929 .lib => "build-lib",929 .lib => "build-lib",
...@@ -933,6 +933,16 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -933,6 +933,16 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
933 };933 };
934 try zig_args.append(cmd);934 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
936 if (b.reference_trace) |some| {946 if (b.reference_trace) |some| {
937 try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some}));947 try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some}));
938 }948 }
...@@ -1393,7 +1403,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1393,7 +1403,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1393 try zig_args.append(b.cache_root.path orelse ".");1403 try zig_args.append(b.cache_root.path orelse ".");
13941404
1395 try zig_args.append("--global-cache-dir");1405 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
1398 try zig_args.append("--name");1408 try zig_args.append("--name");
1399 try zig_args.append(self.name);1409 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 {...@@ -171,7 +171,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
171 const gpa = b.allocator;171 const gpa = b.allocator;
172 const arena = b.allocator;172 const arena = b.allocator;
173173
174 var man = b.cache.obtain();174 var man = b.graph.cache.obtain();
175 defer man.deinit();175 defer man.deinit();
176176
177 // Random bytes to make ConfigHeader unique. Refresh this with new177 // 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 {...@@ -52,7 +52,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
52 var argv: std.ArrayListUnmanaged([]const u8) = .{};52 var argv: std.ArrayListUnmanaged([]const u8) = .{};
53 try argv.ensureUnusedCapacity(arena, 2 + 1 + self.paths.len + 2 * self.exclude_paths.len);53 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);
56 argv.appendAssumeCapacity("fmt");56 argv.appendAssumeCapacity("fmt");
5757
58 if (self.check) {58 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 {...@@ -94,7 +94,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
94 const b = step.owner;94 const b = step.owner;
95 const self = @fieldParentPtr(ObjCopy, "step", step);95 const self = @fieldParentPtr(ObjCopy, "step", step);
9696
97 var man = b.cache.obtain();97 var man = b.graph.cache.obtain();
98 defer man.deinit();98 defer man.deinit();
9999
100 // Random bytes to make ObjCopy unique. Refresh this with new random100 // 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 {...@@ -133,7 +133,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
133 };133 };
134134
135 var argv = std.ArrayList([]const u8).init(b.allocator);135 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
138 if (self.only_section) |only_section| {138 if (self.only_section) |only_section| {
139 try argv.appendSlice(&.{ "-j", only_section });139 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 {...@@ -222,7 +222,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
222 const basename = "options.zig";222 const basename = "options.zig";
223223
224 // Hash contents to file name.224 // Hash contents to file name.
225 var hash = b.cache.hash;225 var hash = b.graph.cache.hash;
226 // Random bytes to make unique. Refresh this with new random bytes when226 // Random bytes to make unique. Refresh this with new random bytes when
227 // implementation is modified in a non-backwards-compatible way.227 // implementation is modified in a non-backwards-compatible way.
228 hash.add(@as(u32, 0xad95e922));228 hash.add(@as(u32, 0xad95e922));
...@@ -301,27 +301,28 @@ test Options {...@@ -301,27 +301,28 @@ test Options {
301 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);301 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
302 defer arena.deinit();302 defer arena.deinit();
303303
304 const host: std.Build.ResolvedTarget = .{304 var graph: std.Build.Graph = .{
305 .query = .{},305 .arena = arena.allocator(),
306 .result = try std.zig.system.resolveTargetQuery(.{}),306 .cache = .{
307 };307 .gpa = arena.allocator(),
308308 .manifest_dir = std.fs.cwd(),
309 var cache: std.Build.Cache = .{309 },
310 .gpa = arena.allocator(),310 .zig_exe = "test",
311 .manifest_dir = std.fs.cwd(),311 .env_map = std.process.EnvMap.init(arena.allocator()),
312 .global_cache_root = .{ .path = "test", .handle = std.fs.cwd() },
312 };313 };
313314
314 var builder = try std.Build.create(315 var builder = try std.Build.create(
315 arena.allocator(),316 &graph,
316 "test",
317 .{ .path = "test", .handle = std.fs.cwd() },317 .{ .path = "test", .handle = std.fs.cwd() },
318 .{ .path = "test", .handle = std.fs.cwd() },318 .{ .path = "test", .handle = std.fs.cwd() },
319 .{ .path = "test", .handle = std.fs.cwd() },
320 host,
321 &cache,
322 &.{},319 &.{},
323 );320 );
324 defer builder.destroy();321
322 builder.host = .{
323 .query = .{},
324 .result = try std.zig.system.resolveTargetQuery(.{}),
325 };
325326
326 const options = builder.addOptions();327 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 {...@@ -463,7 +463,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
463 var argv_list = ArrayList([]const u8).init(arena);463 var argv_list = ArrayList([]const u8).init(arena);
464 var output_placeholders = ArrayList(IndexedOutput).init(arena);464 var output_placeholders = ArrayList(IndexedOutput).init(arena);
465465
466 var man = b.cache.obtain();466 var man = b.graph.cache.obtain();
467 defer man.deinit();467 defer man.deinit();
468468
469 for (self.argv.items) |arg| {469 for (self.argv.items) |arg| {
...@@ -747,7 +747,7 @@ fn runCommand(...@@ -747,7 +747,7 @@ fn runCommand(
747 exe.is_linking_libc;747 exe.is_linking_libc;
748 const other_target = exe.root_module.resolved_target.?.result;748 const other_target = exe.root_module.resolved_target.?.result;
749 switch (std.zig.system.getExternalExecutor(b.host.result, &other_target, .{749 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,
751 .link_libc = exe.is_linking_libc,751 .link_libc = exe.is_linking_libc,
752 })) {752 })) {
753 .native, .rosetta => {753 .native, .rosetta => {
...@@ -755,7 +755,7 @@ fn runCommand(...@@ -755,7 +755,7 @@ fn runCommand(
755 break :interpret;755 break :interpret;
756 },756 },
757 .wine => |bin_name| {757 .wine => |bin_name| {
758 if (b.enable_wine) {758 if (b.graph.enable_wine) {
759 try interp_argv.append(bin_name);759 try interp_argv.append(bin_name);
760 try interp_argv.appendSlice(argv);760 try interp_argv.appendSlice(argv);
761 } else {761 } else {
...@@ -763,9 +763,9 @@ fn runCommand(...@@ -763,9 +763,9 @@ fn runCommand(
763 }763 }
764 },764 },
765 .qemu => |bin_name| {765 .qemu => |bin_name| {
766 if (b.enable_qemu) {766 if (b.graph.enable_qemu) {
767 const glibc_dir_arg = if (need_cross_glibc)767 const glibc_dir_arg = if (need_cross_glibc)
768 b.glibc_runtimes_dir orelse768 b.graph.glibc_runtimes_dir orelse
769 return failForeign(self, "--glibc-runtimes", argv[0], exe)769 return failForeign(self, "--glibc-runtimes", argv[0], exe)
770 else770 else
771 null;771 null;
...@@ -798,7 +798,7 @@ fn runCommand(...@@ -798,7 +798,7 @@ fn runCommand(
798 }798 }
799 },799 },
800 .darling => |bin_name| {800 .darling => |bin_name| {
801 if (b.enable_darling) {801 if (b.graph.enable_darling) {
802 try interp_argv.append(bin_name);802 try interp_argv.append(bin_name);
803 try interp_argv.appendSlice(argv);803 try interp_argv.appendSlice(argv);
804 } else {804 } else {
...@@ -806,7 +806,7 @@ fn runCommand(...@@ -806,7 +806,7 @@ fn runCommand(
806 }806 }
807 },807 },
808 .wasmtime => |bin_name| {808 .wasmtime => |bin_name| {
809 if (b.enable_wasmtime) {809 if (b.graph.enable_wasmtime) {
810 try interp_argv.append(bin_name);810 try interp_argv.append(bin_name);
811 try interp_argv.append("--dir=.");811 try interp_argv.append("--dir=.");
812 try interp_argv.append(argv[0]);812 try interp_argv.append(argv[0]);
...@@ -1036,7 +1036,7 @@ fn spawnChildAndCollect(...@@ -1036,7 +1036,7 @@ fn spawnChildAndCollect(
1036 child.cwd = b.build_root.path;1036 child.cwd = b.build_root.path;
1037 child.cwd_dir = b.build_root.handle;1037 child.cwd_dir = b.build_root.handle;
1038 }1038 }
1039 child.env_map = self.env_map orelse b.env_map;1039 child.env_map = self.env_map orelse &b.graph.env_map;
1040 child.request_resource_usage_statistics = true;1040 child.request_resource_usage_statistics = true;
10411041
1042 child.stdin_behavior = switch (self.stdio) {1042 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 {...@@ -121,7 +121,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
121 const self = @fieldParentPtr(TranslateC, "step", step);121 const self = @fieldParentPtr(TranslateC, "step", step);
122122
123 var argv_list = std.ArrayList([]const u8).init(b.allocator);123 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);
125 try argv_list.append("translate-c");125 try argv_list.append("translate-c");
126 if (self.link_libc) {126 if (self.link_libc) {
127 try argv_list.append("-lc");127 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 {...@@ -190,7 +190,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
190 // If, for example, a hard-coded path was used as the location to put WriteFile190 // If, for example, a hard-coded path was used as the location to put WriteFile
191 // files, then two WriteFiles executing in parallel might clobber each other.191 // 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();
194 defer man.deinit();194 defer man.deinit();
195195
196 // Random bytes to make WriteFile unique. Refresh this with196 // Random bytes to make WriteFile unique. Refresh this with
test/src/Cases.zig+2-2
...@@ -562,7 +562,7 @@ pub fn lowerToBuildSteps(...@@ -562,7 +562,7 @@ pub fn lowerToBuildSteps(
562 run.setName(incr_case.base_path);562 run.setName(incr_case.base_path);
563 run.addArgs(&.{563 run.addArgs(&.{
564 case_base_path_with_dir,564 case_base_path_with_dir,
565 b.zig_exe,565 b.graph.zig_exe,
566 });566 });
567 run.expectStdOutEqual("");567 run.expectStdOutEqual("");
568 parent_step.dependOn(&run.step);568 parent_step.dependOn(&run.step);
...@@ -653,7 +653,7 @@ pub fn lowerToBuildSteps(...@@ -653,7 +653,7 @@ pub fn lowerToBuildSteps(
653 break :no_exec;653 break :no_exec;
654 }654 }
655 const run_c = b.addSystemCommand(&.{655 const run_c = b.addSystemCommand(&.{
656 b.zig_exe,656 b.graph.zig_exe,
657 "run",657 "run",
658 "-cflags",658 "-cflags",
659 "-Ilib",659 "-Ilib",
test/tests.zig+11-11
...@@ -796,7 +796,7 @@ pub fn addCliTests(b: *std.Build) *Step {...@@ -796,7 +796,7 @@ pub fn addCliTests(b: *std.Build) *Step {
796 {796 {
797 // Test `zig init`.797 // Test `zig init`.
798 const tmp_path = b.makeTempPath();798 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" });
800 init_exe.setCwd(.{ .cwd_relative = tmp_path });800 init_exe.setCwd(.{ .cwd_relative = tmp_path });
801 init_exe.setName("zig init");801 init_exe.setName("zig init");
802 init_exe.expectStdOutEqual("");802 init_exe.expectStdOutEqual("");
...@@ -810,20 +810,20 @@ pub fn addCliTests(b: *std.Build) *Step {...@@ -810,20 +810,20 @@ pub fn addCliTests(b: *std.Build) *Step {
810 const bad_out_arg = "-femit-bin=does" ++ s ++ "not" ++ s ++ "exist" ++ s ++ "foo.exe";810 const bad_out_arg = "-femit-bin=does" ++ s ++ "not" ++ s ++ "exist" ++ s ++ "foo.exe";
811 const ok_src_arg = "src" ++ s ++ "main.zig";811 const ok_src_arg = "src" ++ s ++ "main.zig";
812 const expected = "error: unable to open output directory 'does" ++ s ++ "not" ++ s ++ "exist': FileNotFound\n";812 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 });
814 run_bad.setName("zig build-exe error message for bad -femit-bin arg");814 run_bad.setName("zig build-exe error message for bad -femit-bin arg");
815 run_bad.expectExitCode(1);815 run_bad.expectExitCode(1);
816 run_bad.expectStdErrEqual(expected);816 run_bad.expectStdErrEqual(expected);
817 run_bad.expectStdOutEqual("");817 run_bad.expectStdOutEqual("");
818 run_bad.step.dependOn(&init_exe.step);818 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" });
821 run_test.setCwd(.{ .cwd_relative = tmp_path });821 run_test.setCwd(.{ .cwd_relative = tmp_path });
822 run_test.setName("zig build test");822 run_test.setName("zig build test");
823 run_test.expectStdOutEqual("");823 run_test.expectStdOutEqual("");
824 run_test.step.dependOn(&init_exe.step);824 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" });
827 run_run.setCwd(.{ .cwd_relative = tmp_path });827 run_run.setCwd(.{ .cwd_relative = tmp_path });
828 run_run.setName("zig build run");828 run_run.setName("zig build run");
829 run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n");829 run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n");
...@@ -857,7 +857,7 @@ pub fn addCliTests(b: *std.Build) *Step {...@@ -857,7 +857,7 @@ pub fn addCliTests(b: *std.Build) *Step {
857857
858 // This is intended to be the exact CLI usage used by godbolt.org.858 // This is intended to be the exact CLI usage used by godbolt.org.
859 const run = b.addSystemCommand(&.{859 const run = b.addSystemCommand(&.{
860 b.zig_exe, "build-obj",860 b.graph.zig_exe, "build-obj",
861 "--cache-dir", tmp_path,861 "--cache-dir", tmp_path,
862 "--name", "example",862 "--name", "example",
863 "-fno-emit-bin", "-fno-emit-h",863 "-fno-emit-bin", "-fno-emit-h",
...@@ -900,7 +900,7 @@ pub fn addCliTests(b: *std.Build) *Step {...@@ -900,7 +900,7 @@ pub fn addCliTests(b: *std.Build) *Step {
900 subdir.writeFile("fmt3.zig", unformatted_code) catch @panic("unhandled");900 subdir.writeFile("fmt3.zig", unformatted_code) catch @panic("unhandled");
901901
902 // Test zig fmt affecting only the appropriate files.902 // 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" });
904 run1.setName("run zig fmt one file");904 run1.setName("run zig fmt one file");
905 run1.setCwd(.{ .cwd_relative = tmp_path });905 run1.setCwd(.{ .cwd_relative = tmp_path });
906 run1.has_side_effects = true;906 run1.has_side_effects = true;
...@@ -908,7 +908,7 @@ pub fn addCliTests(b: *std.Build) *Step {...@@ -908,7 +908,7 @@ pub fn addCliTests(b: *std.Build) *Step {
908 run1.expectStdOutEqual("fmt1.zig\n");908 run1.expectStdOutEqual("fmt1.zig\n");
909909
910 // Test excluding files and directories from a run910 // 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", "." });
912 run2.setName("run zig fmt on directory with exclusions");912 run2.setName("run zig fmt on directory with exclusions");
913 run2.setCwd(.{ .cwd_relative = tmp_path });913 run2.setCwd(.{ .cwd_relative = tmp_path });
914 run2.has_side_effects = true;914 run2.has_side_effects = true;
...@@ -916,7 +916,7 @@ pub fn addCliTests(b: *std.Build) *Step {...@@ -916,7 +916,7 @@ pub fn addCliTests(b: *std.Build) *Step {
916 run2.step.dependOn(&run1.step);916 run2.step.dependOn(&run1.step);
917917
918 // Test excluding non-existent file918 // 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", "." });
920 run3.setName("run zig fmt on directory with non-existent exclusion");920 run3.setName("run zig fmt on directory with non-existent exclusion");
921 run3.setCwd(.{ .cwd_relative = tmp_path });921 run3.setCwd(.{ .cwd_relative = tmp_path });
922 run3.has_side_effects = true;922 run3.has_side_effects = true;
...@@ -924,7 +924,7 @@ pub fn addCliTests(b: *std.Build) *Step {...@@ -924,7 +924,7 @@ pub fn addCliTests(b: *std.Build) *Step {
924 run3.step.dependOn(&run2.step);924 run3.step.dependOn(&run2.step);
925925
926 // running it on the dir, only the new file should be changed926 // 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", "." });
928 run4.setName("run zig fmt the directory");928 run4.setName("run zig fmt the directory");
929 run4.setCwd(.{ .cwd_relative = tmp_path });929 run4.setCwd(.{ .cwd_relative = tmp_path });
930 run4.has_side_effects = true;930 run4.has_side_effects = true;
...@@ -932,7 +932,7 @@ pub fn addCliTests(b: *std.Build) *Step {...@@ -932,7 +932,7 @@ pub fn addCliTests(b: *std.Build) *Step {
932 run4.step.dependOn(&run3.step);932 run4.step.dependOn(&run3.step);
933933
934 // both files have been formatted, nothing should change now934 // 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", "." });
936 run5.setName("run zig fmt with nothing to do");936 run5.setName("run zig fmt with nothing to do");
937 run5.setCwd(.{ .cwd_relative = tmp_path });937 run5.setCwd(.{ .cwd_relative = tmp_path });
938 run5.has_side_effects = true;938 run5.has_side_effects = true;
...@@ -946,7 +946,7 @@ pub fn addCliTests(b: *std.Build) *Step {...@@ -946,7 +946,7 @@ pub fn addCliTests(b: *std.Build) *Step {
946 write6.step.dependOn(&run5.step);946 write6.step.dependOn(&run5.step);
947947
948 // Test `zig fmt` handling UTF-16 decoding.948 // 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", "." });
950 run6.setName("run zig fmt convert UTF-16 to UTF-8");950 run6.setName("run zig fmt convert UTF-16 to UTF-8");
951 run6.setCwd(.{ .cwd_relative = tmp_path });951 run6.setCwd(.{ .cwd_relative = tmp_path });
952 run6.has_side_effects = true;952 run6.has_side_effects = true;