authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-17 17:08:55-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:33-07:00
log0505318efe0d2757a344dded9ae1607f948f7511
tree80feb60a23f512c1110aec4d477cfece57d79cef
parent2b11859a1049910a2bd8031e53c24beea305ae10

make runner gets compiled and run

and --print-configuration prints some deserialized stuff

11 files changed, 593 insertions(+), 477 deletions(-)

lib/compiler/configure_runner.zig+48-17
...@@ -1,18 +1,19 @@...@@ -1,18 +1,19 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
22
3const std = @import("std");3const std = @import("std");
4const Allocator = std.mem.Allocator;
5const Color = std.zig.Color;
6const Configuration = std.Build.Configuration;
7const File = std.Io.File;
4const Io = std.Io;8const Io = std.Io;
9const Step = std.Build.Step;
10const Writer = std.Io.Writer;
5const assert = std.debug.assert;11const assert = std.debug.assert;
12const fatal = std.process.fatal;
6const fmt = std.fmt;13const fmt = std.fmt;
14const log = std.log;
7const mem = std.mem;15const mem = std.mem;
8const process = std.process;16const process = std.process;
9const File = std.Io.File;
10const Step = std.Build.Step;
11const Allocator = std.mem.Allocator;
12const fatal = std.process.fatal;
13const Writer = std.Io.Writer;
14const Color = std.zig.Color;
15const Configuration = std.Build.Configuration;
1617
17pub const root = @import("@build");18pub const root = @import("@build");
18pub const dependencies = @import("@dependencies");19pub const dependencies = @import("@dependencies");
...@@ -95,7 +96,6 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -95,7 +96,6 @@ pub fn main(init: process.Init.Minimal) !void {
95 .query = .{},96 .query = .{},
96 .result = try std.zig.system.resolveTargetQuery(io, .{}),97 .result = try std.zig.system.resolveTargetQuery(io, .{}),
97 },98 },
98 .time_report = false,
99 };99 };
100100
101 graph.cache.addPrefix(.{ .path = null, .handle = cwd });101 graph.cache.addPrefix(.{ .path = null, .handle = cwd });
...@@ -141,9 +141,9 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -141,9 +141,9 @@ pub fn main(init: process.Init.Minimal) !void {
141 fatal(" access the help menu with 'zig build -h'", .{});141 fatal(" access the help menu with 'zig build -h'", .{});
142 }142 }
143 } else if (mem.cutPrefix(u8, arg, "-fsys=")) |name| {143 } else if (mem.cutPrefix(u8, arg, "-fsys=")) |name| {
144 graph.system_library_options.put(arena, name, .user_enabled) catch @panic("OOM");144 try graph.system_integration_options.put(arena, name, .user_enabled);
145 } else if (mem.cutPrefix(u8, arg, "-fno-sys=")) |name| {145 } else if (mem.cutPrefix(u8, arg, "-fno-sys=")) |name| {
146 graph.system_library_options.put(arena, name, .user_disabled) catch @panic("OOM");146 try graph.system_integration_options.put(arena, name, .user_disabled);
147 } else if (mem.eql(u8, arg, "--release")) {147 } else if (mem.eql(u8, arg, "--release")) {
148 graph.release_mode = .any;148 graph.release_mode = .any;
149 } else if (mem.cutPrefix(u8, arg, "--release=")) |text| {149 } else if (mem.cutPrefix(u8, arg, "--release=")) |text| {
...@@ -177,8 +177,6 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -177,8 +177,6 @@ pub fn main(init: process.Init.Minimal) !void {
177 } else if (mem.cutPrefix(u8, arg, "--build-id=")) |style| {177 } else if (mem.cutPrefix(u8, arg, "--build-id=")) |style| {
178 builder.build_id = std.zig.BuildId.parse(style) catch |err|178 builder.build_id = std.zig.BuildId.parse(style) catch |err|
179 fatal("unable to parse --build-id style '{s}': {t}", .{ style, err });179 fatal("unable to parse --build-id style '{s}': {t}", .{ style, err });
180 } else if (mem.eql(u8, arg, "--debug-rt")) {
181 graph.debug_compiler_runtime_libs = true;
182 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {180 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
183 builder.debug_compile_errors = true;181 builder.debug_compile_errors = true;
184 } else if (mem.eql(u8, arg, "--debug-incremental")) {182 } else if (mem.eql(u8, arg, "--debug-incremental")) {
...@@ -204,10 +202,16 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -204,10 +202,16 @@ pub fn main(init: process.Init.Minimal) !void {
204202
205 try builder.runBuild(root);203 try builder.runBuild(root);
206204
205 if (builder.validateUserInputDidItFail()) {
206 fatal(" access the help menu with 'zig build -h'", .{});
207 }
208
207 var wc: Configuration.Wip = .init(gpa);209 var wc: Configuration.Wip = .init(gpa);
208 defer wc.deinit();210 defer wc.deinit();
209 assert(try wc.addString("") == .empty);211 assert(try wc.addString("") == .empty);
210212
213 try serializeSystemIntegrationOptions(&graph, &wc);
214
211 var stdout_buffer: [1024]u8 = undefined;215 var stdout_buffer: [1024]u8 = undefined;
212 var file_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer);216 var file_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer);
213 serialize(builder, &wc, &file_writer.interface) catch |err| switch (err) {217 serialize(builder, &wc, &file_writer.interface) catch |err| switch (err) {
...@@ -367,7 +371,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {...@@ -367,7 +371,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
367 .root_name = try wc.addString(c.name),371 .root_name = try wc.addString(c.name),
368 }));372 }));
369373
370 std.log.err("TODO serialize the trailing Compile step data", .{});374 log.err("TODO serialize the trailing Compile step data", .{});
371375
372 break :e extra_index;376 break :e extra_index;
373 },377 },
...@@ -441,7 +445,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {...@@ -441,7 +445,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
441 .captured_stderr = captured_stderr,445 .captured_stderr = captured_stderr,
442 }));446 }));
443447
444 std.log.err("TODO serialize the trailing Run step data", .{});448 log.err("TODO serialize the trailing Run step data", .{});
445449
446 break :e extra_index;450 break :e extra_index;
447 },451 },
...@@ -489,7 +493,7 @@ fn addModule(...@@ -489,7 +493,7 @@ fn addModule(
489 m.import_table.values(),493 m.import_table.values(),
490 @intFromEnum(import_table) + 1 + m.import_table.entries.len..,494 @intFromEnum(import_table) + 1 + m.import_table.entries.len..,
491 ) |dep, extra_index| {495 ) |dep, extra_index| {
492 // TODO module dependencies can be cyclic496 log.err("TODO module dependencies can be cyclic", .{});
493 wc.extra.items[extra_index] = @intFromEnum(try addModule(wc, module_map, dep));497 wc.extra.items[extra_index] = @intFromEnum(try addModule(wc, module_map, dep));
494 }498 }
495499
...@@ -530,7 +534,7 @@ fn addModule(...@@ -530,7 +534,7 @@ fn addModule(
530 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),534 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),
531 })));535 })));
532536
533 std.log.err("TODO serialize the trailing Module data", .{});537 log.err("TODO serialize the trailing Module data", .{});
534538
535 try module_map.putNoClobber(gpa, m, module_index);539 try module_map.putNoClobber(gpa, m, module_index);
536540
...@@ -542,7 +546,7 @@ fn addOptionalResolvedTarget(...@@ -542,7 +546,7 @@ fn addOptionalResolvedTarget(
542 optional_resolved_target: ?std.Build.ResolvedTarget,546 optional_resolved_target: ?std.Build.ResolvedTarget,
543) !Configuration.ResolvedTarget.OptionalIndex {547) !Configuration.ResolvedTarget.OptionalIndex {
544 const resolved_target = optional_resolved_target orelse return .none;548 const resolved_target = optional_resolved_target orelse return .none;
545 // TODO dedupe549 log.debug("TODO deduplicate resolved targets", .{});
546 return @enumFromInt(try wc.addExtra(@as(Configuration.ResolvedTarget, .{550 return @enumFromInt(try wc.addExtra(@as(Configuration.ResolvedTarget, .{
547 .query = try wc.addTargetQuery(resolved_target.query),551 .query = try wc.addTargetQuery(resolved_target.query),
548 .result = try wc.addTarget(resolved_target.result),552 .result = try wc.addTarget(resolved_target.result),
...@@ -698,3 +702,30 @@ const Summary = enum { all, new, failures, line, none };...@@ -698,3 +702,30 @@ const Summary = enum { all, new, failures, line, none };
698fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn {702fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn {
699 fatal(f ++ "\n access the help menu with \"zig build -h\"", args);703 fatal(f ++ "\n access the help menu with \"zig build -h\"", args);
700}704}
705
706fn serializeSystemIntegrationOptions(graph: *std.Build.Graph, wc: *Configuration.Wip) Allocator.Error!void {
707 const gpa = wc.gpa;
708
709 var bad = false;
710 try wc.system_integrations.ensureTotalCapacityPrecise(gpa, graph.system_integration_options.entries.len);
711 for (graph.system_integration_options.keys(), graph.system_integration_options.values()) |k, v| {
712 wc.system_integrations.appendAssumeCapacity(.{
713 .name = try wc.addString(k),
714 .status = switch (v) {
715 .user_disabled, .user_enabled => x: {
716 // The user tried to enable or disable a system library integration, but
717 // the configure script did not recognize that option.
718 log.err("system integration name not recognized by configure script: {s}", .{k});
719 bad = true;
720 break :x .disabled;
721 },
722 .declared_disabled => .disabled,
723 .declared_enabled => .enabled,
724 },
725 });
726 }
727 if (bad) {
728 log.info("access the help menu with \"zig build -h\"", .{});
729 process.exit(1);
730 }
731}
lib/compiler/maker.zig+345-299
...@@ -1,21 +1,23 @@...@@ -1,21 +1,23 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
22
3const std = @import("std");3const std = @import("std");
4const Allocator = std.mem.Allocator;
5const Cache = std.Build.Cache;
6const Configuration = std.Build.Configuration;
7const File = std.Io.File;
4const Io = std.Io;8const Io = std.Io;
9const Path = std.Build.Cache.Path;
10const Writer = std.Io.Writer;
5const assert = std.debug.assert;11const assert = std.debug.assert;
12const fatal = std.process.fatal;
6const fmt = std.fmt;13const fmt = std.fmt;
14const log = std.log;
7const mem = std.mem;15const mem = std.mem;
8const process = std.process;16const process = std.process;
9const File = std.Io.File;
10const Allocator = std.mem.Allocator;
11const fatal = std.process.fatal;
12const Writer = std.Io.Writer;
13const Cache = std.Build.Cache;
14const Configuration = std.Build.Configuration;
1517
16const Fuzz = @import("maker/Fuzz.zig");18const Fuzz = @import("maker/Fuzz.zig");
17const Graph = @import("maker/Graph.zig");19const Graph = @import("maker/Graph.zig");
18const Step = @import("maker/Step.zig");20const Step = void; // @import("maker/Step.zig");
19const Watch = @import("maker/Watch.zig");21const Watch = @import("maker/Watch.zig");
20const WebServer = @import("maker/WebServer.zig");22const WebServer = @import("maker/WebServer.zig");
2123
...@@ -48,12 +50,12 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -48,12 +50,12 @@ pub fn main(init: process.Init.Minimal) !void {
48 // skip my own exe name50 // skip my own exe name
49 var arg_idx: usize = 1;51 var arg_idx: usize = 1;
5052
51 const zig_exe = cutArgPrefixOrFatal(args, &arg_idx, "--zig=");53 const zig_exe = expectArgOrFatal(args, &arg_idx, "--zig");
52 const zig_lib_dir = cutArgPrefixOrFatal(args, &arg_idx, "--lib=");54 const zig_lib_dir = expectArgOrFatal(args, &arg_idx, "--zig-lib-dir");
53 const build_root = cutArgPrefixOrFatal(args, &arg_idx, "--build-root=");55 const build_root = expectArgOrFatal(args, &arg_idx, "--build-root");
54 const local_cache_root = cutArgPrefixOrFatal(args, &arg_idx, "--local-cache=");56 const local_cache_root = expectArgOrFatal(args, &arg_idx, "--local-cache");
55 const global_cache_root = cutArgPrefixOrFatal(args, &arg_idx, "--global-cache=");57 const global_cache_root = expectArgOrFatal(args, &arg_idx, "--global-cache");
56 const configure_path = cutArgPrefixOrFatal(args, &arg_idx, "--configure=");58 const configure_path = expectArgOrFatal(args, &arg_idx, "--configuration");
5759
58 const cwd: Io.Dir = .cwd();60 const cwd: Io.Dir = .cwd();
5961
...@@ -90,11 +92,6 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -90,11 +92,6 @@ pub fn main(init: process.Init.Minimal) !void {
90 .environ_map = try init.environ.createMap(arena),92 .environ_map = try init.environ.createMap(arena),
91 .global_cache_root = global_cache_directory,93 .global_cache_root = global_cache_directory,
92 .zig_lib_directory = zig_lib_directory,94 .zig_lib_directory = zig_lib_directory,
93 .host = .{
94 .query = .{},
95 .result = try std.zig.system.resolveTargetQuery(io, .{}),
96 },
97 .time_report = false,
98 };95 };
9996
100 graph.cache.addPrefix(.{ .path = null, .handle = cwd });97 graph.cache.addPrefix(.{ .path = null, .handle = cwd });
...@@ -105,9 +102,13 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -105,9 +102,13 @@ pub fn main(init: process.Init.Minimal) !void {
105102
106 var targets = std.array_list.Managed([]const u8).init(arena);103 var targets = std.array_list.Managed([]const u8).init(arena);
107 var debug_log_scopes = std.array_list.Managed([]const u8).init(arena);104 var debug_log_scopes = std.array_list.Managed([]const u8).init(arena);
108105 var help_menu = false;
109 var install_prefix: ?[]const u8 = null;106 var steps_menu = false;
110 var dir_list: std.Build.DirList = .{};107 var print_configuration = false;
108 var override_install_prefix: ?[]const u8 = null;
109 var override_lib_dir: ?[]const u8 = null;
110 var override_bin_dir: ?[]const u8 = null;
111 var override_include_dir: ?[]const u8 = null;
111 var error_style: ErrorStyle = .verbose;112 var error_style: ErrorStyle = .verbose;
112 var multiline_errors: MultilineErrors = .indent;113 var multiline_errors: MultilineErrors = .indent;
113 var summary: ?Summary = null;114 var summary: ?Summary = null;
...@@ -115,8 +116,6 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -115,8 +116,6 @@ pub fn main(init: process.Init.Minimal) !void {
115 var skip_oom_steps = false;116 var skip_oom_steps = false;
116 var test_timeout_ns: ?u64 = null;117 var test_timeout_ns: ?u64 = null;
117 var color: Color = .auto;118 var color: Color = .auto;
118 var help_menu = false;
119 var steps_menu = false;
120 var watch = false;119 var watch = false;
121 var fuzz: ?Fuzz.Mode = null;120 var fuzz: ?Fuzz.Mode = null;
122 var debounce_interval_ms: u16 = 50;121 var debounce_interval_ms: u16 = 50;
...@@ -152,51 +151,53 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -152,51 +151,53 @@ pub fn main(init: process.Init.Minimal) !void {
152 }151 }
153 }152 }
154153
155 var configuration: Configuration = undefined;154 const scanned_config: ScannedConfig = sc: {
156 {155 const configuration = c: {
157 var file = cwd.openFile(io, configure_path, .{}) catch |err|156 var file = cwd.openFile(io, configure_path, .{}) catch |err|
158 fatal("failed to open configuration file {f}: {t}", .{ configure_path, err });157 fatal("failed to open configuration file {s}: {t}", .{ configure_path, err });
159 defer file.close(io);158 defer file.close(io);
160 configuration = Configuration.load(arena, io, file) catch |err|159 break :c Configuration.loadFile(arena, io, file) catch |err|
161 fatal("failed to load configuration file {f}: {t}", .{ configure_path, err });160 fatal("failed to load configuration file {s}: {t}", .{ configure_path, err });
162 }161 };
163 graph.configuration = &configuration;162 var top_level_steps: std.ArrayList(Configuration.Step.Index) = .empty;
164 graph.scanConfiguration();163 for (configuration.steps, 0..) |*conf_step, step_index| {
164 const flags: Configuration.Step.Flags = @bitCast(configuration.extra[conf_step.extra_index]);
165 if (flags.tag == .top_level) {
166 try top_level_steps.append(arena, @enumFromInt(step_index));
167 }
168 }
169 break :sc .{
170 .configuration = configuration,
171 .top_level_steps = top_level_steps.items,
172 };
173 };
165174
166 std.log.err("TODO handle user -D options", .{});175 log.err("TODO handle user -D options", .{});
167176
168 while (nextArg(args, &arg_idx)) |arg| {177 while (nextArg(args, &arg_idx)) |arg| {
169 if (mem.startsWith(u8, arg, "-")) {178 if (mem.startsWith(u8, arg, "-")) {
170 if (mem.eql(u8, arg, "--verbose")) {179 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
171 verbose = true;
172 } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
173 help_menu = true;180 help_menu = true;
174 } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) {
175 install_prefix = nextArgOrFatal(args, &arg_idx);
176 } else if (mem.eql(u8, arg, "-l") or mem.eql(u8, arg, "--list-steps")) {181 } else if (mem.eql(u8, arg, "-l") or mem.eql(u8, arg, "--list-steps")) {
177 steps_menu = true;182 steps_menu = true;
178 } else if (mem.startsWith(u8, arg, "-fsys=")) {183 } else if (mem.eql(u8, arg, "--print-configuration")) {
179 const name = arg["-fsys=".len..];184 print_configuration = true;
180 graph.system_library_options.put(arena, name, .user_enabled) catch @panic("OOM");185 } else if (mem.eql(u8, arg, "--verbose")) {
181 } else if (mem.startsWith(u8, arg, "-fno-sys=")) {186 verbose = true;
182 const name = arg["-fno-sys=".len..];187 } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) {
183 graph.system_library_options.put(arena, name, .user_disabled) catch @panic("OOM");188 override_install_prefix = nextArgOrFatal(args, &arg_idx);
184 } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {189 } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {
185 dir_list.lib_dir = nextArgOrFatal(args, &arg_idx);190 override_lib_dir = nextArgOrFatal(args, &arg_idx);
186 } else if (mem.eql(u8, arg, "--prefix-exe-dir")) {191 } else if (mem.eql(u8, arg, "--prefix-exe-dir")) {
187 dir_list.exe_dir = nextArgOrFatal(args, &arg_idx);192 override_bin_dir = nextArgOrFatal(args, &arg_idx);
188 } else if (mem.eql(u8, arg, "--prefix-include-dir")) {193 } else if (mem.eql(u8, arg, "--prefix-include-dir")) {
189 dir_list.include_dir = nextArgOrFatal(args, &arg_idx);194 override_include_dir = nextArgOrFatal(args, &arg_idx);
190 } else if (mem.eql(u8, arg, "--sysroot")) {195 } else if (mem.eql(u8, arg, "--sysroot")) {
191 sysroot = nextArgOrFatal(args, &arg_idx);196 sysroot = nextArgOrFatal(args, &arg_idx);
192 } else if (mem.eql(u8, arg, "--maxrss")) {197 } else if (mem.eql(u8, arg, "--maxrss")) {
193 const max_rss_text = nextArgOrFatal(args, &arg_idx);198 const max_rss_text = nextArgOrFatal(args, &arg_idx);
194 max_rss = std.fmt.parseIntSizeSuffix(max_rss_text, 10) catch |err| {199 max_rss = std.fmt.parseIntSizeSuffix(max_rss_text, 10) catch |err|
195 std.debug.print("invalid byte size: '{s}': {s}\n", .{200 fatal("invalid byte size: '{s}': {t}", .{ max_rss_text, err });
196 max_rss_text, @errorName(err),
197 });
198 process.exit(1);
199 };
200 } else if (mem.eql(u8, arg, "--skip-oom-steps")) {201 } else if (mem.eql(u8, arg, "--skip-oom-steps")) {
201 skip_oom_steps = true;202 skip_oom_steps = true;
202 } else if (mem.eql(u8, arg, "--test-timeout")) {203 } else if (mem.eql(u8, arg, "--test-timeout")) {
...@@ -270,9 +271,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -270,9 +271,7 @@ pub fn main(init: process.Init.Minimal) !void {
270 const next_arg = nextArg(args, &arg_idx) orelse271 const next_arg = nextArg(args, &arg_idx) orelse
271 fatalWithHint("expected u32 after '{s}'", .{arg});272 fatalWithHint("expected u32 after '{s}'", .{arg});
272 graph.random_seed = std.fmt.parseUnsigned(u32, next_arg, 0) catch |err| {273 graph.random_seed = std.fmt.parseUnsigned(u32, next_arg, 0) catch |err| {
273 fatal("unable to parse seed '{s}' as unsigned 32-bit integer: {s}\n", .{274 fatal("unable to parse seed '{s}' as unsigned 32-bit integer: {t}", .{ next_arg, err });
274 next_arg, @errorName(err),
275 });
276 };275 };
277 } else if (mem.eql(u8, arg, "--debounce")) {276 } else if (mem.eql(u8, arg, "--debounce")) {
278 const next_arg = nextArg(args, &arg_idx) orelse277 const next_arg = nextArg(args, &arg_idx) orelse
...@@ -288,7 +287,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -288,7 +287,7 @@ pub fn main(init: process.Init.Minimal) !void {
288 const addr_str = arg["--webui=".len..];287 const addr_str = arg["--webui=".len..];
289 if (std.mem.eql(u8, addr_str, "-")) fatal("web interface cannot listen on stdio", .{});288 if (std.mem.eql(u8, addr_str, "-")) fatal("web interface cannot listen on stdio", .{});
290 webui_listen = Io.net.IpAddress.parseLiteral(addr_str) catch |err| {289 webui_listen = Io.net.IpAddress.parseLiteral(addr_str) catch |err| {
291 fatal("invalid web UI address '{s}': {s}", .{ addr_str, @errorName(err) });290 fatal("invalid web UI address '{s}': {t}", .{ addr_str, err });
292 };291 };
293 } else if (mem.eql(u8, arg, "--debug-log")) {292 } else if (mem.eql(u8, arg, "--debug-log")) {
294 const next_arg = nextArgOrFatal(args, &arg_idx);293 const next_arg = nextArgOrFatal(args, &arg_idx);
...@@ -300,11 +299,6 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -300,11 +299,6 @@ pub fn main(init: process.Init.Minimal) !void {
300 } else if (mem.cutPrefix(u8, arg, "--debug-rt=")) |rest| {299 } else if (mem.cutPrefix(u8, arg, "--debug-rt=")) |rest| {
301 graph.debug_compiler_runtime_libs = std.meta.stringToEnum(std.builtin.OptimizeMode, rest) orelse300 graph.debug_compiler_runtime_libs = std.meta.stringToEnum(std.builtin.OptimizeMode, rest) orelse
302 fatal("unrecognized optimization mode: {s}", .{rest});301 fatal("unrecognized optimization mode: {s}", .{rest});
303 } else if (mem.eql(u8, arg, "--system")) {
304 // The usage text shows another argument after this parameter
305 // but it is handled by the parent process. The build runner
306 // only sees this flag.
307 graph.system_package_mode = true;
308 } else if (mem.eql(u8, arg, "--libc-runtimes") or mem.eql(u8, arg, "--glibc-runtimes")) {302 } else if (mem.eql(u8, arg, "--libc-runtimes") or mem.eql(u8, arg, "--glibc-runtimes")) {
309 // --glibc-runtimes was the old name of the flag; kept for compatibility for now.303 // --glibc-runtimes was the old name of the flag; kept for compatibility for now.
310 libc_runtimes_dir = nextArgOrFatal(args, &arg_idx);304 libc_runtimes_dir = nextArgOrFatal(args, &arg_idx);
...@@ -383,7 +377,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -383,7 +377,7 @@ pub fn main(init: process.Init.Minimal) !void {
383 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {377 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
384 const num = arg["-freference-trace=".len..];378 const num = arg["-freference-trace=".len..];
385 reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {379 reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {
386 std.debug.print("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) });380 std.debug.print("unable to parse reference_trace count '{s}': {t}", .{ num, err });
387 process.exit(1);381 process.exit(1);
388 };382 };
389 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {383 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {
...@@ -414,6 +408,29 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -414,6 +408,29 @@ pub fn main(init: process.Init.Minimal) !void {
414 .off => .no_color,408 .off => .no_color,
415 };409 };
416410
411 if (help_menu) {
412 var w = initStdoutWriter(io);
413 scanned_config.printUsage(&graph, w) catch |err| switch (err) {
414 error.WriteFailed => return stdout_writer_allocation.err.?,
415 else => |e| return e,
416 };
417 w.flush() catch return stdout_writer_allocation.err.?;
418 return;
419 } else if (steps_menu) {
420 var w = initStdoutWriter(io);
421 scanned_config.printSteps(&graph, w) catch |err| switch (err) {
422 error.WriteFailed => return stdout_writer_allocation.err.?,
423 else => |e| return e,
424 };
425 w.flush() catch return stdout_writer_allocation.err.?;
426 return;
427 } else if (print_configuration) {
428 var w = initStdoutWriter(io);
429 scanned_config.print(w) catch return stdout_writer_allocation.err.?;
430 w.flush() catch return stdout_writer_allocation.err.?;
431 return;
432 }
433
417 if (webui_listen != null) {434 if (webui_listen != null) {
418 if (watch) fatal("using '--webui' and '--watch' together is not yet supported; consider omitting '--watch' in favour of the web UI \"Rebuild\" button", .{});435 if (watch) fatal("using '--webui' and '--watch' together is not yet supported; consider omitting '--watch' in favour of the web UI \"Rebuild\" button", .{});
419 if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{});436 if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{});
...@@ -424,27 +441,33 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -424,27 +441,33 @@ pub fn main(init: process.Init.Minimal) !void {
424 });441 });
425 defer main_progress_node.end();442 defer main_progress_node.end();
426443
427 graph.resolveInstallPrefix(install_prefix, dir_list);444 const install_prefix_path: Path = if (graph.environ_map.get("DESTDIR")) |dest_dir| .{
445 .root_dir = .cwd(),
446 .sub_path = try Io.Dir.path.join(arena, &.{ dest_dir, override_install_prefix orelse "/usr" }),
447 } else if (override_install_prefix) |cwd_relative| .{
448 .root_dir = .cwd(),
449 .sub_path = cwd_relative,
450 } else .{
451 .root_dir = build_root_directory,
452 .sub_path = "zig-out",
453 };
428454
429 if (graph.validateUserInputDidItFail()) {455 const install_lib_path: Path = if (override_lib_dir) |cwd_relative| .{
430 fatal(" access the help menu with 'zig build -h'", .{});456 .root_dir = .cwd(),
431 }457 .sub_path = cwd_relative,
458 } else try install_prefix_path.join(arena, "lib");
432459
433 validateSystemLibraryOptions(&graph);460 const install_bin_path: Path = if (override_bin_dir) |cwd_relative| .{
461 .root_dir = .cwd(),
462 .sub_path = cwd_relative,
463 } else try install_prefix_path.join(arena, "bin");
434464
435 if (help_menu) {465 const install_include_path: Path = if (override_include_dir) |cwd_relative| .{
436 var w = initStdoutWriter(io);466 .root_dir = .cwd(),
437 printUsage(&graph, w) catch return stdout_writer_allocation.err.?;467 .sub_path = cwd_relative,
438 w.flush() catch return stdout_writer_allocation.err.?;468 } else try install_prefix_path.join(arena, "include");
439 return;
440 }
441469
442 if (steps_menu) {470 if (true) @panic("TODO");
443 var w = initStdoutWriter(io);
444 printSteps(&graph, w) catch return stdout_writer_allocation.err.?;
445 w.flush() catch return stdout_writer_allocation.err.?;
446 return;
447 }
448471
449 var run: Run = .{472 var run: Run = .{
450 .gpa = gpa,473 .gpa = gpa,
...@@ -463,6 +486,13 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -463,6 +486,13 @@ pub fn main(init: process.Init.Minimal) !void {
463 .error_style = error_style,486 .error_style = error_style,
464 .multiline_errors = multiline_errors,487 .multiline_errors = multiline_errors,
465 .summary = summary orelse if (watch or webui_listen != null) .line else .failures,488 .summary = summary orelse if (watch or webui_listen != null) .line else .failures,
489
490 .install_paths = .{
491 .prefix = install_prefix_path,
492 .lib = install_lib_path,
493 .bin = install_bin_path,
494 .include = install_include_path,
495 },
466 };496 };
467 defer {497 defer {
468 run.memory_blocked_steps.deinit(gpa);498 run.memory_blocked_steps.deinit(gpa);
...@@ -628,9 +658,9 @@ fn prepare(graph: *Graph, step_names: []const []const u8, run: *Run) !void {...@@ -628,9 +658,9 @@ fn prepare(graph: *Graph, step_names: []const []const u8, run: *Run) !void {
628 try step_stack.ensureUnusedCapacity(gpa, step_names.len);658 try step_stack.ensureUnusedCapacity(gpa, step_names.len);
629 for (0..step_names.len) |i| {659 for (0..step_names.len) |i| {
630 const step_name = step_names[step_names.len - i - 1];660 const step_name = step_names[step_names.len - i - 1];
631 const s = graph.top_level_steps.get(step_name) orelse {661 const s = run.top_level_steps.get(step_name) orelse {
632 std.log.info("access the help menu with \"zig build -h\"", .{});662 log.info("access the help menu with 'zig build -h'", .{});
633 fatal("no step named '{s}'", .{step_name});663 fatal("no such step: {s}", .{step_name});
634 };664 };
635 step_stack.putAssumeCapacity(&s.step, {});665 step_stack.putAssumeCapacity(&s.step, {});
636 }666 }
...@@ -873,11 +903,11 @@ fn runStepNames(...@@ -873,11 +903,11 @@ fn runStepNames(
873 print_node.last = true;903 print_node.last = true;
874 printTreeStep(graph, graph.default_step, run, t, &print_node, &step_stack_copy) catch {};904 printTreeStep(graph, graph.default_step, run, t, &print_node, &step_stack_copy) catch {};
875 } else {905 } else {
876 const last_index = if (run.summary == .all) graph.top_level_steps.count() else blk: {906 const last_index = if (run.summary == .all) run.top_level_steps.count() else blk: {
877 var i: usize = step_names.len;907 var i: usize = step_names.len;
878 while (i > 0) {908 while (i > 0) {
879 i -= 1;909 i -= 1;
880 const step = graph.top_level_steps.get(step_names[i]).?.step;910 const step = run.top_level_steps.get(step_names[i]).?.step;
881 const found = switch (run.summary) {911 const found = switch (run.summary) {
882 .all, .line, .none => unreachable,912 .all, .line, .none => unreachable,
883 .failures => step.state != .success,913 .failures => step.state != .success,
...@@ -885,10 +915,10 @@ fn runStepNames(...@@ -885,10 +915,10 @@ fn runStepNames(
885 };915 };
886 if (found) break :blk i;916 if (found) break :blk i;
887 }917 }
888 break :blk graph.top_level_steps.count();918 break :blk run.top_level_steps.count();
889 };919 };
890 for (step_names, 0..) |step_name, i| {920 for (step_names, 0..) |step_name, i| {
891 const tls = graph.top_level_steps.get(step_name).?;921 const tls = run.top_level_steps.get(step_name).?;
892 print_node.last = i + 1 == last_index;922 print_node.last = i + 1 == last_index;
893 printTreeStep(graph, &tls.step, run, t, &print_node, &step_stack_copy) catch {};923 printTreeStep(graph, &tls.step, run, t, &print_node, &step_stack_copy) catch {};
894 }924 }
...@@ -1207,7 +1237,7 @@ fn constructGraphAndCheckForDependencyLoop(...@@ -1207,7 +1237,7 @@ fn constructGraphAndCheckForDependencyLoop(
12071237
1208 // We dupe to avoid shuffling the steps in the summary, it depends1238 // We dupe to avoid shuffling the steps in the summary, it depends
1209 // on s.dependencies' order.1239 // on s.dependencies' order.
1210 const deps = gpa.dupe(*Step, s.dependencies.items) catch @panic("OOM");1240 const deps = try gpa.dupe(*Step, s.dependencies.items);
1211 defer gpa.free(deps);1241 defer gpa.free(deps);
12121242
1213 rand.shuffle(*Step, deps);1243 rand.shuffle(*Step, deps);
...@@ -1327,7 +1357,7 @@ fn makeStep(...@@ -1327,7 +1357,7 @@ fn makeStep(
1327 try run.max_rss_mutex.lock(io);1357 try run.max_rss_mutex.lock(io);
1328 defer run.max_rss_mutex.unlock(io);1358 defer run.max_rss_mutex.unlock(io);
1329 run.available_rss += s.max_rss;1359 run.available_rss += s.max_rss;
1330 dispatch_set.ensureUnusedCapacity(gpa, run.memory_blocked_steps.items.len) catch @panic("OOM");1360 try dispatch_set.ensureUnusedCapacity(gpa, run.memory_blocked_steps.items.len);
1331 while (run.memory_blocked_steps.getLast()) |candidate| {1361 while (run.memory_blocked_steps.getLast()) |candidate| {
1332 if (run.available_rss < candidate.max_rss) break;1362 if (run.available_rss < candidate.max_rss) break;
1333 assert(run.memory_blocked_steps.pop() == candidate);1363 assert(run.memory_blocked_steps.pop() == candidate);
...@@ -1360,7 +1390,7 @@ fn stepReady(...@@ -1360,7 +1390,7 @@ fn stepReady(
1360 defer run.max_rss_mutex.unlock(io);1390 defer run.max_rss_mutex.unlock(io);
1361 if (run.available_rss < s.max_rss) {1391 if (run.available_rss < s.max_rss) {
1362 // Running this step right now could possibly exceed the allotted RSS.1392 // Running this step right now could possibly exceed the allotted RSS.
1363 run.memory_blocked_steps.append(run.gpa, s) catch @panic("OOM");1393 try run.memory_blocked_steps.append(run.gpa, s);
1364 return;1394 return;
1365 }1395 }
1366 run.available_rss -= s.max_rss;1396 run.available_rss -= s.max_rss;
...@@ -1454,178 +1484,6 @@ pub fn printErrorMessages(...@@ -1454,178 +1484,6 @@ pub fn printErrorMessages(
1454 try writer.writeByte('\n');1484 try writer.writeByte('\n');
1455}1485}
14561486
1457fn printSteps(graph: *Graph, w: *Writer) !void {
1458 const arena = graph.arena;
1459 for (graph.top_level_steps.values()) |top_level_step| {
1460 const name = if (&top_level_step.step == graph.default_step)
1461 try fmt.allocPrint(arena, "{s} (default)", .{top_level_step.step.name})
1462 else
1463 top_level_step.step.name;
1464 try w.print(" {s:<28} {s}\n", .{ name, top_level_step.description });
1465 }
1466}
1467
1468fn printUsage(graph: *Graph, w: *Writer) !void {
1469 const arena = graph.arena;
1470
1471 try w.print(
1472 \\Usage: {s} build [steps] [options]
1473 \\
1474 \\Steps:
1475 \\
1476 , .{graph.zig_exe});
1477 try printSteps(graph, w);
1478 try w.writeAll(
1479 \\
1480 \\Project-Specific Options:
1481 \\
1482 );
1483
1484 if (graph.available_options_list.items.len == 0) {
1485 try w.print(" (none)\n", .{});
1486 } else {
1487 for (graph.available_options_list.items) |option| {
1488 const name = try fmt.allocPrint(arena, " -D{s}=[{t}]", .{ option.name, option.type_id });
1489 try w.print("{s:<30} {s}\n", .{ name, option.description });
1490 if (option.enum_options) |enum_options| {
1491 const padding: [33]u8 = @splat(' ');
1492 try w.writeAll(padding ++ "Supported Values:\n");
1493 for (enum_options) |enum_option| {
1494 try w.print(padding ++ " {s}\n", .{enum_option});
1495 }
1496 }
1497 }
1498 }
1499
1500 try w.writeAll(
1501 \\
1502 \\System Integration Options:
1503 \\ --search-prefix [path] Add a path to look for binaries, libraries, headers
1504 \\ --sysroot [path] Set the system root directory (usually /)
1505 \\ --libc [file] Provide a file which specifies libc paths
1506 \\
1507 \\ --system [pkgdir] Disable package fetching; enable all integrations
1508 \\ -fsys=[name] Enable a system integration
1509 \\ -fno-sys=[name] Disable a system integration
1510 \\
1511 \\ -fdarling, -fno-darling Integration with system-installed Darling to
1512 \\ execute macOS programs on Linux hosts
1513 \\ (default: no)
1514 \\ -fqemu, -fno-qemu Integration with system-installed QEMU to execute
1515 \\ foreign-architecture programs on Linux hosts
1516 \\ (default: no)
1517 \\ --libc-runtimes [path] Enhances QEMU integration by providing dynamic libc
1518 \\ (e.g. glibc or musl) built for multiple foreign
1519 \\ architectures, allowing execution of non-native
1520 \\ programs that link with libc.
1521 \\ -frosetta, -fno-rosetta Rely on Rosetta to execute x86_64 programs on
1522 \\ ARM64 macOS hosts. (default: no)
1523 \\ -fwasmtime, -fno-wasmtime Integration with system-installed wasmtime to
1524 \\ execute WASI binaries. (default: no)
1525 \\ -fwine, -fno-wine Integration with system-installed Wine to execute
1526 \\ Windows programs on Linux hosts. (default: no)
1527 \\
1528 \\ Available System Integrations: Enabled:
1529 \\
1530 );
1531 if (graph.system_library_options.entries.len == 0) {
1532 try w.writeAll(" (none) -\n");
1533 } else {
1534 for (graph.system_library_options.keys(), graph.system_library_options.values()) |k, v| {
1535 const status = switch (v) {
1536 .declared_enabled => "yes",
1537 .declared_disabled => "no",
1538 .user_enabled, .user_disabled => unreachable, // already emitted error
1539 };
1540 try w.print(" {s:<43} {s}\n", .{ k, status });
1541 }
1542 }
1543
1544 try w.writeAll(
1545 \\
1546 \\General Options:
1547 \\ -h, --help Print this help and exit
1548 \\ -l, --list-steps Print available steps
1549 \\
1550 \\ -p, --prefix [path] Where to install files (default: zig-out)
1551 \\ --prefix-lib-dir [path] Where to install libraries
1552 \\ --prefix-exe-dir [path] Where to install executables
1553 \\ --prefix-include-dir [path] Where to install C header files
1554 \\ --release[=mode] Request release mode, optionally specifying a
1555 \\ preferred optimization mode: fast, safe, small
1556 \\
1557 \\ --verbose Print commands before executing them
1558 \\ --color [auto|off|on] Enable or disable colored error messages
1559 \\ --error-style [style] Control how build errors are printed
1560 \\ verbose (Default) Report errors with full context
1561 \\ minimal Report errors after summary, excluding context like command lines
1562 \\ verbose_clear Like 'verbose', but clear the terminal at the start of each update
1563 \\ minimal_clear Like 'minimal', but clear the terminal at the start of each update
1564 \\ --multiline-errors [style] Control how multi-line error messages are printed
1565 \\ indent (Default) Indent non-initial lines to align with initial line
1566 \\ newline Include a leading newline so that the error message is on its own lines
1567 \\ none Print as usual so the first line is misaligned
1568 \\ --summary [mode] Control the printing of the build summary
1569 \\ all Print the build summary in its entirety
1570 \\ new Omit cached steps
1571 \\ failures (Default if short-lived) Only print failed steps
1572 \\ line (Default if long-lived) Only print the single-line summary
1573 \\ none Do not print the build summary
1574 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores)
1575 \\ --maxrss <bytes> Limit memory usage (default is to use available memory)
1576 \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss
1577 \\ --test-timeout <timeout> Limit execution time of unit tests, terminating if exceeded.
1578 \\ The timeout must include a unit: ns, us, ms, s, m, h
1579 \\ --watch Continuously rebuild when source files are modified
1580 \\ --debounce <ms> Delay before rebuilding after changed file detected
1581 \\ --webui[=ip] Enable the web interface on the given IP address
1582 \\ --fuzz[=limit] Continuously search for unit test failures with an optional
1583 \\ limit to the max number of iterations. The argument supports
1584 \\ an optional 'K', 'M', or 'G' suffix (e.g. '10K'). Implies
1585 \\ '--webui' when no limit is specified.
1586 \\ --time-report Force full rebuild and provide detailed information on
1587 \\ compilation time of Zig source code (implies '--webui')
1588 \\ -fincremental Enable incremental compilation
1589 \\ -fno-incremental Disable incremental compilation
1590 \\
1591 \\Package Management Options:
1592 \\ --fetch[=mode] Fetch dependency tree (optionally choose laziness) and exit
1593 \\ needed (Default) Lazy dependencies are fetched as needed
1594 \\ all Lazy dependencies are always fetched
1595 \\ --fork=[path] Override one or more projects from dependency tree
1596 \\
1597 \\Advanced Options:
1598 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
1599 \\ -fno-reference-trace Disable reference trace
1600 \\ -fallow-so-scripts Allows .so files to be GNU ld scripts
1601 \\ -fno-allow-so-scripts (default) .so files must be ELF files
1602 \\ --build-file [file] Override path to build.zig
1603 \\ --cache-dir [path] Override path to local Zig cache directory
1604 \\ --global-cache-dir [path] Override path to global Zig cache directory
1605 \\ --zig-lib-dir [arg] Override path to Zig lib directory
1606 \\ --build-runner [file] Override path to build runner
1607 \\ --seed [integer] For shuffling dependency traversal order (default: random)
1608 \\ --build-id[=style] At a minor link-time expense, embeds a build ID in binaries
1609 \\ fast 8-byte non-cryptographic hash (COFF, ELF, WASM)
1610 \\ sha1, tree 20-byte cryptographic hash (ELF, WASM)
1611 \\ md5 16-byte cryptographic hash (ELF)
1612 \\ uuid 16-byte random UUID (ELF, WASM)
1613 \\ 0x[hexstring] Constant ID, maximum 32 bytes (ELF, WASM)
1614 \\ none (default) No build ID
1615 \\ --debug-log [scope] Enable debugging the compiler
1616 \\ --debug-pkg-config Fail if unknown pkg-config flags encountered
1617 \\ --debug-rt Debug compiler runtime libraries
1618 \\ --verbose-link Enable compiler debug output for linking
1619 \\ --verbose-air Enable compiler debug output for Zig AIR
1620 \\ --verbose-llvm-ir[=file] Enable compiler debug output for LLVM IR
1621 \\ --verbose-llvm-bc=[file] Enable compiler debug output for LLVM BC
1622 \\ --verbose-cimport Enable compiler debug output for C imports
1623 \\ --verbose-cc Enable compiler debug output for C compilation
1624 \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
1625 \\
1626 );
1627}
1628
1629fn nextArg(args: []const [:0]const u8, idx: *usize) ?[:0]const u8 {1487fn nextArg(args: []const [:0]const u8, idx: *usize) ?[:0]const u8 {
1630 if (idx.* >= args.len) return null;1488 if (idx.* >= args.len) return null;
1631 defer idx.* += 1;1489 defer idx.* += 1;
...@@ -1633,17 +1491,17 @@ fn nextArg(args: []const [:0]const u8, idx: *usize) ?[:0]const u8 {...@@ -1633,17 +1491,17 @@ fn nextArg(args: []const [:0]const u8, idx: *usize) ?[:0]const u8 {
1633}1491}
16341492
1635fn nextArgOrFatal(args: []const [:0]const u8, idx: *usize) [:0]const u8 {1493fn nextArgOrFatal(args: []const [:0]const u8, idx: *usize) [:0]const u8 {
1636 return nextArg(args, idx) orelse1494 return nextArg(args, idx) orelse {
1637 fatal("expected argument after {q}\n access the help menu with \"zig build -h\"", .{args[idx.* - 1]});1495 log.info("access the help menu with \"zig build -h\"", .{});
1496 fatal("expected argument after {q}", .{args[idx.* - 1]});
1497 };
1638}1498}
16391499
1640fn cutArgPrefixOrFatal(args: []const [:0]const u8, idx: *usize, prefix: []const u8) []const u8 {1500fn expectArgOrFatal(args: []const [:0]const u8, index_ptr: *usize, first: []const u8) []const u8 {
1641 if (nextArg(args, idx)) |next_arg| {1501 const next_arg = nextArg(args, index_ptr) orelse fatal("missing {q} argument", .{first});
1642 if (mem.cutPrefix(u8, next_arg, prefix)) |arg| {1502 if (!mem.eql(u8, first, next_arg)) fatal("expected {q} instead of {q}", .{ first, next_arg });
1643 return arg;1503 const arg = nextArg(args, index_ptr) orelse fatal("expected argument after {q}", .{first});
1644 }1504 return arg;
1645 }
1646 fatal("expected argument after {q} to start with {q}", .{ args[idx.* - 1], prefix });
1647}1505}
16481506
1649fn argsRest(args: []const [:0]const u8, idx: usize) ?[]const [:0]const u8 {1507fn argsRest(args: []const [:0]const u8, idx: usize) ?[]const [:0]const u8 {
...@@ -1674,29 +1532,28 @@ const MultilineErrors = enum { indent, newline, none };...@@ -1674,29 +1532,28 @@ const MultilineErrors = enum { indent, newline, none };
1674const Summary = enum { all, new, failures, line, none };1532const Summary = enum { all, new, failures, line, none };
16751533
1676fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn {1534fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn {
1677 std.debug.print(f ++ "\n access the help menu with 'zig build -h'\n", args);1535 log.info("access the help menu with 'zig build -h'", .{});
1678 process.exit(1);1536 fatal(f, args);
1679}1537}
16801538
1681fn validateSystemLibraryOptions(graph: *Graph) void {1539fn cleanTmpFiles(io: Io, steps: []const *Step) void {
1682 var bad = false;1540 for (steps) |step| {
1683 for (graph.system_library_options.keys(), graph.system_library_options.values()) |k, v| {1541 const wf = step.cast(Step.WriteFile) orelse continue;
1684 switch (v) {1542 if (wf.mode != .tmp) continue;
1685 .user_disabled, .user_enabled => {1543 const path = wf.generated_directory.path orelse continue;
1686 // The user tried to enable or disable a system library integration, but1544 Io.Dir.cwd().deleteTree(io, path) catch |err| {
1687 // the build script did not recognize that option.1545 log.warn("failed to delete {s}: {t}", .{ path, err });
1688 std.debug.print("system library name not recognized by build script: '{s}'\n", .{k});1546 };
1689 bad = true;
1690 },
1691 .declared_disabled, .declared_enabled => {},
1692 }
1693 }
1694 if (bad) {
1695 std.debug.print(" access the help menu with 'zig build -h'\n", .{});
1696 process.exit(1);
1697 }1547 }
1698}1548}
16991549
1550const InstallPaths = struct {
1551 prefix: Path,
1552 lib: Path,
1553 bin: Path,
1554 include: Path,
1555};
1556
1700var stdio_buffer_allocation: [256]u8 = undefined;1557var stdio_buffer_allocation: [256]u8 = undefined;
1701var stdout_writer_allocation: Io.File.Writer = undefined;1558var stdout_writer_allocation: Io.File.Writer = undefined;
17021559
...@@ -1705,13 +1562,202 @@ fn initStdoutWriter(io: Io) *Writer {...@@ -1705,13 +1562,202 @@ fn initStdoutWriter(io: Io) *Writer {
1705 return &stdout_writer_allocation.interface;1562 return &stdout_writer_allocation.interface;
1706}1563}
17071564
1708fn cleanTmpFiles(io: Io, steps: []const *Step) void {1565const ScannedConfig = struct {
1709 for (steps) |step| {1566 configuration: Configuration,
1710 const wf = step.cast(Step.WriteFile) orelse continue;1567 top_level_steps: []const Configuration.Step.Index,
1711 if (wf.mode != .tmp) continue;1568
1712 const path = wf.generated_directory.path orelse continue;1569 fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
1713 Io.Dir.cwd().deleteTree(io, path) catch |err| {1570 var serializer: std.zon.Serializer = .{ .writer = w };
1714 std.log.warn("failed to delete {s}: {t}", .{ path, err });1571 var s = try serializer.beginStruct(.{});
1715 };1572
1573 try s.field("default_step", @intFromEnum(sc.configuration.default_step), .{});
1574 {
1575 var tuple = try s.beginTupleField("top_level_steps", .{});
1576 for (sc.top_level_steps) |step| try tuple.field(@intFromEnum(step), .{});
1577 try tuple.end();
1578 }
1579
1580 try s.end();
1716 }1581 }
1717}1582
1583 fn printSteps(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {
1584 const arena = graph.arena;
1585 const c = &sc.configuration;
1586 for (sc.top_level_steps) |step_index| {
1587 const step = step_index.ptr(c);
1588 const name = step.name.slice(c);
1589 const decorated_name = if (step_index == c.default_step)
1590 try fmt.allocPrint(arena, "{s} (default)", .{name})
1591 else
1592 name;
1593 const top_level = c.extraData(Configuration.Step.TopLevel, step.extra_index);
1594 const description = top_level.description.slice(c);
1595 try w.print(" {s:<28} {s}\n", .{ decorated_name, description });
1596 }
1597 }
1598
1599 fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {
1600 const arena = graph.arena;
1601
1602 try w.print(
1603 \\Usage: {s} build [steps] [options]
1604 \\
1605 \\Steps:
1606 \\
1607 , .{graph.zig_exe});
1608 try printSteps(sc, graph, w);
1609 try w.writeAll(
1610 \\
1611 \\Project-Specific Options:
1612 \\
1613 );
1614
1615 const available_options = sc.configuration.available_options;
1616 if (available_options.len == 0) {
1617 try w.print(" (none)\n", .{});
1618 } else {
1619 for (available_options) |option| {
1620 const name = option.name.slice(&sc.configuration);
1621 const description = option.description.slice(&sc.configuration);
1622 const help = try fmt.allocPrint(arena, " -D{s}=[{t}]", .{ name, option.type });
1623 try w.print("{s:<30} {s}\n", .{ help, description });
1624 if (option.enum_options.slice(&sc.configuration)) |enum_options| {
1625 const padding: [33]u8 = @splat(' ');
1626 try w.writeAll(padding ++ "Supported Values:\n");
1627 for (enum_options) |enum_option_index| {
1628 const enum_option = enum_option_index.slice(&sc.configuration);
1629 try w.print(padding ++ " {s}\n", .{enum_option});
1630 }
1631 }
1632 }
1633 }
1634
1635 try w.writeAll(
1636 \\
1637 \\System Integration Options:
1638 \\ --search-prefix [path] Add a path to look for binaries, libraries, headers
1639 \\ --sysroot [path] Set the system root directory (usually /)
1640 \\ --libc [file] Provide a file which specifies libc paths
1641 \\
1642 \\ --system [pkgdir] Disable package fetching; enable all integrations
1643 \\ -fsys=[name] Enable a system integration
1644 \\ -fno-sys=[name] Disable a system integration
1645 \\
1646 \\ -fdarling, -fno-darling Integration with system-installed Darling to
1647 \\ execute macOS programs on Linux hosts
1648 \\ (default: no)
1649 \\ -fqemu, -fno-qemu Integration with system-installed QEMU to execute
1650 \\ foreign-architecture programs on Linux hosts
1651 \\ (default: no)
1652 \\ --libc-runtimes [path] Enhances QEMU integration by providing dynamic libc
1653 \\ (e.g. glibc or musl) built for multiple foreign
1654 \\ architectures, allowing execution of non-native
1655 \\ programs that link with libc.
1656 \\ -frosetta, -fno-rosetta Rely on Rosetta to execute x86_64 programs on
1657 \\ ARM64 macOS hosts. (default: no)
1658 \\ -fwasmtime, -fno-wasmtime Integration with system-installed wasmtime to
1659 \\ execute WASI binaries. (default: no)
1660 \\ -fwine, -fno-wine Integration with system-installed Wine to execute
1661 \\ Windows programs on Linux hosts. (default: no)
1662 \\
1663 \\ Available System Integrations: Enabled:
1664 \\
1665 );
1666 if (sc.configuration.system_integrations.len == 0) {
1667 try w.writeAll(" (none) -\n");
1668 } else {
1669 for (sc.configuration.system_integrations) |system_integration| {
1670 const name = system_integration.name.slice(&sc.configuration);
1671 const status = switch (system_integration.status) {
1672 .disabled => "no",
1673 .enabled => "yes",
1674 };
1675 try w.print(" {s:<43} {s}\n", .{ name, status });
1676 }
1677 }
1678
1679 try w.writeAll(
1680 \\
1681 \\General Options:
1682 \\ -h, --help Print this help and exit
1683 \\ -l, --list-steps Print available steps
1684 \\
1685 \\ -p, --prefix [path] Where to install files (default: zig-out)
1686 \\ --prefix-lib-dir [path] Where to install libraries
1687 \\ --prefix-exe-dir [path] Where to install executables
1688 \\ --prefix-include-dir [path] Where to install C header files
1689 \\ --release[=mode] Request release mode, optionally specifying a
1690 \\ preferred optimization mode: fast, safe, small
1691 \\
1692 \\ --verbose Print commands before executing them
1693 \\ --color [auto|off|on] Enable or disable colored error messages
1694 \\ --error-style [style] Control how build errors are printed
1695 \\ verbose (Default) Report errors with full context
1696 \\ minimal Report errors after summary, excluding context like command lines
1697 \\ verbose_clear Like 'verbose', but clear the terminal at the start of each update
1698 \\ minimal_clear Like 'minimal', but clear the terminal at the start of each update
1699 \\ --multiline-errors [style] Control how multi-line error messages are printed
1700 \\ indent (Default) Indent non-initial lines to align with initial line
1701 \\ newline Include a leading newline so that the error message is on its own lines
1702 \\ none Print as usual so the first line is misaligned
1703 \\ --summary [mode] Control the printing of the build summary
1704 \\ all Print the build summary in its entirety
1705 \\ new Omit cached steps
1706 \\ failures (Default if short-lived) Only print failed steps
1707 \\ line (Default if long-lived) Only print the single-line summary
1708 \\ none Do not print the build summary
1709 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores)
1710 \\ --maxrss <bytes> Limit memory usage (default is to use available memory)
1711 \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss
1712 \\ --test-timeout <timeout> Limit execution time of unit tests, terminating if exceeded.
1713 \\ The timeout must include a unit: ns, us, ms, s, m, h
1714 \\ --watch Continuously rebuild when source files are modified
1715 \\ --debounce <ms> Delay before rebuilding after changed file detected
1716 \\ --webui[=ip] Enable the web interface on the given IP address
1717 \\ --fuzz[=limit] Continuously search for unit test failures with an optional
1718 \\ limit to the max number of iterations. The argument supports
1719 \\ an optional 'K', 'M', or 'G' suffix (e.g. '10K'). Implies
1720 \\ '--webui' when no limit is specified.
1721 \\ --time-report Force full rebuild and provide detailed information on
1722 \\ compilation time of Zig source code (implies '--webui')
1723 \\ -fincremental Enable incremental compilation
1724 \\ -fno-incremental Disable incremental compilation
1725 \\
1726 \\Package Management Options:
1727 \\ --fetch[=mode] Fetch dependency tree (optionally choose laziness) and exit
1728 \\ needed (Default) Lazy dependencies are fetched as needed
1729 \\ all Lazy dependencies are always fetched
1730 \\ --fork=[path] Override one or more projects from dependency tree
1731 \\
1732 \\Advanced Options:
1733 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
1734 \\ -fno-reference-trace Disable reference trace
1735 \\ -fallow-so-scripts Allows .so files to be GNU ld scripts
1736 \\ -fno-allow-so-scripts (default) .so files must be ELF files
1737 \\ --build-file [file] Override path to build.zig
1738 \\ --cache-dir [path] Override path to local Zig cache directory
1739 \\ --global-cache-dir [path] Override path to global Zig cache directory
1740 \\ --zig-lib-dir [arg] Override path to Zig lib directory
1741 \\ --build-runner [file] Override path to build runner
1742 \\ --seed [integer] For shuffling dependency traversal order (default: random)
1743 \\ --build-id[=style] At a minor link-time expense, embeds a build ID in binaries
1744 \\ fast 8-byte non-cryptographic hash (COFF, ELF, WASM)
1745 \\ sha1, tree 20-byte cryptographic hash (ELF, WASM)
1746 \\ md5 16-byte cryptographic hash (ELF)
1747 \\ uuid 16-byte random UUID (ELF, WASM)
1748 \\ 0x[hexstring] Constant ID, maximum 32 bytes (ELF, WASM)
1749 \\ none (default) No build ID
1750 \\ --debug-log [scope] Enable debugging the compiler
1751 \\ --debug-pkg-config Fail if unknown pkg-config flags encountered
1752 \\ --debug-rt Debug compiler runtime libraries
1753 \\ --verbose-link Enable compiler debug output for linking
1754 \\ --verbose-air Enable compiler debug output for Zig AIR
1755 \\ --verbose-llvm-ir[=file] Enable compiler debug output for LLVM IR
1756 \\ --verbose-llvm-bc=[file] Enable compiler debug output for LLVM BC
1757 \\ --verbose-cimport Enable compiler debug output for C imports
1758 \\ --verbose-cc Enable compiler debug output for C compilation
1759 \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
1760 \\
1761 );
1762 }
1763};
lib/compiler/maker/Fuzz.zig+10-8
...@@ -1,17 +1,19 @@...@@ -1,17 +1,19 @@
1const std = @import("Std");1const Fuzz = @This();
2
3const std = @import("std");
2const Io = std.Io;4const Io = std.Io;
3const Build = std.Build;5const Build = std.Build;
4const Cache = Build.Cache;6const Cache = std.Build.Cache;
5const Step = std.Build.Step;7const Step = std.Build.Step;
6const assert = std.debug.assert;8const assert = std.debug.assert;
7const fatal = std.process.fatal;9const fatal = std.process.fatal;
8const Allocator = std.mem.Allocator;10const Allocator = std.mem.Allocator;
9const log = std.log;11const log = std.log;
10const Coverage = std.debug.Coverage;12const Coverage = std.debug.Coverage;
11const abi = Build.abi.fuzz;13const abi = std.Build.abi.fuzz;
1214
13const Fuzz = @This();15const maker = @import("../maker.zig");
14const build_runner = @import("root");16const WebServer = @import("WebServer.zig");
1517
16gpa: Allocator,18gpa: Allocator,
17io: Io,19io: Io,
...@@ -33,7 +35,7 @@ queue_cond: Io.Condition,...@@ -33,7 +35,7 @@ queue_cond: Io.Condition,
33msg_queue: std.ArrayList(Msg),35msg_queue: std.ArrayList(Msg),
3436
35pub const Mode = union(enum) {37pub const Mode = union(enum) {
36 forever: struct { ws: *Build.WebServer },38 forever: struct { ws: *WebServer },
37 limit: Limited,39 limit: Limited,
3840
39 pub const Limited = struct {41 pub const Limited = struct {
...@@ -173,7 +175,7 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod...@@ -173,7 +175,7 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod
173 var buf: [256]u8 = undefined;175 var buf: [256]u8 = undefined;
174 const stderr = try io.lockStderr(&buf, graph.stderr_mode);176 const stderr = try io.lockStderr(&buf, graph.stderr_mode);
175 defer io.unlockStderr();177 defer io.unlockStderr();
176 build_runner.printErrorMessages(gpa, &compile.step, .{}, stderr.terminal(), .verbose, .indent) catch {};178 maker.printErrorMessages(gpa, &compile.step, .{}, stderr.terminal(), .verbose, .indent) catch {};
177 }179 }
178180
179 const rebuilt_bin_path = result catch |err| switch (err) {181 const rebuilt_bin_path = result catch |err| switch (err) {
...@@ -196,7 +198,7 @@ fn fuzzWorkerRun(fuzz: *Fuzz, run: *Step.Run) void {...@@ -196,7 +198,7 @@ fn fuzzWorkerRun(fuzz: *Fuzz, run: *Step.Run) void {
196 error.Canceled => return,198 error.Canceled => return,
197 };199 };
198 defer io.unlockStderr();200 defer io.unlockStderr();
199 build_runner.printErrorMessages(gpa, &run.step, .{}, stderr.terminal(), .verbose, .indent) catch {};201 maker.printErrorMessages(gpa, &run.step, .{}, stderr.terminal(), .verbose, .indent) catch {};
200 return;202 return;
201 },203 },
202 else => {204 else => {
lib/compiler/maker/Graph.zig+8-75
...@@ -6,87 +6,20 @@ const Io = std.Io;...@@ -6,87 +6,20 @@ const Io = std.Io;
6const Allocator = std.mem.Allocator;6const Allocator = std.mem.Allocator;
7const Configuration = std.Build.Configuration;7const Configuration = std.Build.Configuration;
88
9const Step = @import("Step.zig");
10const Package = @import("Package.zig");
11
12io: Io,9io: Io,
13/// Process lifetime.10/// Process lifetime.
14arena: Allocator,11arena: Allocator,
15system_library_options: std.StringArrayHashMapUnmanaged(std.Build.SystemLibraryMode),
16system_package_mode: bool,
17debug_compiler_runtime_libs: ?std.builtin.OptimizeMode = null,
18cache: std.Build.Cache,12cache: std.Build.Cache,
19zig_exe: [:0]const u8,13zig_exe: []const u8,
20environ_map: std.process.Environ.Map,14environ_map: std.process.Environ.Map,
21global_cache_root: std.Build.Cache.Directory,15global_cache_root: std.Build.Cache.Directory,
22zig_lib_directory: std.Build.Cache.Directory,16zig_lib_directory: std.Build.Cache.Directory,
23incremental: ?bool,17
24random_seed: u32,18debug_compiler_runtime_libs: ?std.builtin.OptimizeMode = null,
25allow_so_scripts: ?bool,19incremental: ?bool = null,
26time_report: bool,20random_seed: u32 = 0,
21allow_so_scripts: ?bool = null,
22time_report: bool = false,
27/// Similar to the `Io.Terminal.Mode` returned by `Io.lockStderr`, but also23/// Similar to the `Io.Terminal.Mode` returned by `Io.lockStderr`, but also
28/// respects the '--color' flag.24/// respects the '--color' flag.
29stderr_mode: ?Io.Terminal.Mode,25stderr_mode: ?Io.Terminal.Mode = null,
30
31configuration: *const Configuration,
32top_level_steps: std.AutoArrayHashMapUnmanaged(Configuration.String, Configuration.Step.Index),
33
34pub const DirList = struct {
35 lib_dir: ?[]const u8 = null,
36 exe_dir: ?[]const u8 = null,
37 include_dir: ?[]const u8 = null,
38};
39
40/// This function is intended to be called by lib/build_runner.zig, not a build.zig file.
41pub fn resolveInstallPrefix(graph: *Graph, p: *Package, install_prefix: ?[]const u8, dir_list: DirList) !void {
42 if (p.dest_dir) |dest_dir| {
43 p.install_prefix = install_prefix orelse "/usr";
44 p.install_path = b.pathJoin(&.{ dest_dir, p.install_prefix });
45 } else {
46 p.install_prefix = install_prefix orelse
47 (p.build_root.join(b.allocator, &.{"zig-out"}) catch @panic("unhandled error"));
48 b.install_path = b.install_prefix;
49 }
50
51 var lib_list = [_][]const u8{ b.install_path, "lib" };
52 var exe_list = [_][]const u8{ b.install_path, "bin" };
53 var h_list = [_][]const u8{ b.install_path, "include" };
54
55 if (dir_list.lib_dir) |dir| {
56 if (fs.path.isAbsolute(dir)) lib_list[0] = b.dest_dir orelse "";
57 lib_list[1] = dir;
58 }
59
60 if (dir_list.exe_dir) |dir| {
61 if (fs.path.isAbsolute(dir)) exe_list[0] = b.dest_dir orelse "";
62 exe_list[1] = dir;
63 }
64
65 if (dir_list.include_dir) |dir| {
66 if (fs.path.isAbsolute(dir)) h_list[0] = b.dest_dir orelse "";
67 h_list[1] = dir;
68 }
69
70 b.lib_dir = b.pathJoin(&lib_list);
71 b.exe_dir = b.pathJoin(&exe_list);
72 b.h_dir = b.pathJoin(&h_list);
73}
74
75fn determineAndApplyInstallPrefix(b: *Build) error{OutOfMemory}!void {
76 // Create an installation directory local to this package. This will be used when
77 // dependant packages require a standard prefix, such as include directories for C headers.
78 var hash = b.graph.cache.hash;
79 // Random bytes to make unique. Refresh this with new random bytes when
80 // implementation is modified in a non-backwards-compatible way.
81 hash.add(@as(u32, 0xd8cb0056));
82 hash.addBytes(b.dep_prefix);
83
84 var wyhash = std.hash.Wyhash.init(0);
85 hashUserInputOptionsMap(b.allocator, b.user_input_options, &wyhash);
86 hash.add(wyhash.final());
87
88 const digest = hash.final();
89 const install_prefix = try b.cache_root.join(b.allocator, &.{ "i", &digest });
90 b.resolveInstallPrefix(install_prefix, .{});
91}
92
lib/compiler/maker/Package.zig+18
...@@ -10,3 +10,21 @@ exe_dir: []const u8,...@@ -10,3 +10,21 @@ exe_dir: []const u8,
10h_dir: []const u8,10h_dir: []const u8,
11/// Path to the directory containing build.zig.11/// Path to the directory containing build.zig.
12build_root: std.Build.Cache.Path,12build_root: std.Build.Cache.Path,
13
14fn determineAndApplyInstallPrefix(p: *Package) error{OutOfMemory}!void {
15 // Create an installation directory local to this package. This will be used when
16 // dependant packages require a standard prefix, such as include directories for C headers.
17 var hash = p.graph.cache.hash;
18 // Random bytes to make unique. Refresh this with new random bytes when
19 // implementation is modified in a non-backwards-compatible way.
20 hash.add(@as(u32, 0xd8cb0056));
21 hash.addBytes(p.dep_prefix);
22
23 var wyhash = std.hash.Wyhash.init(0);
24 hashUserInputOptionsMap(p.allocator, p.user_input_options, &wyhash);
25 hash.add(wyhash.final());
26
27 const digest = hash.final();
28 const install_prefix = try p.cache_root.join(p.allocator, &.{ "i", &digest });
29 p.resolveInstallPrefix(install_prefix, .{});
30}
lib/compiler/maker/Step.zig+12
...@@ -848,3 +848,15 @@ pub fn allocPrintCmd(...@@ -848,3 +848,15 @@ pub fn allocPrintCmd(
848 return aw.toOwnedSlice();848 return aw.toOwnedSlice();
849}849}
850850
851pub fn getInstallPath(b: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 {
852 assert(!fs.path.isAbsolute(dest_rel_path)); // Install paths must be relative to the prefix
853 const base_dir = switch (dir) {
854 .prefix => b.install_path,
855 .bin => b.exe_dir,
856 .lib => b.lib_dir,
857 .header => b.h_dir,
858 .custom => |p| b.pathJoin(&.{ b.install_path, p }),
859 };
860 return b.pathResolve(&.{ base_dir, dest_rel_path });
861}
862
lib/compiler/maker/WebServer.zig+18-17
...@@ -1,3 +1,21 @@...@@ -1,3 +1,21 @@
1const WebServer = @This();
2
3const builtin = @import("builtin");
4
5const std = @import("std");
6const Allocator = std.mem.Allocator;
7const Build = std.Build;
8const Cache = std.Build.Cache;
9const Io = std.Io;
10const abi = std.Build.abi;
11const assert = std.debug.assert;
12const http = std.http;
13const log = std.log.scoped(.web_server);
14const mem = std.mem;
15const net = std.Io.net;
16
17const Fuzz = @import("Fuzz.zig");
18
1gpa: Allocator,19gpa: Allocator,
2graph: *const Build.Graph,20graph: *const Build.Graph,
3all_steps: []const *Build.Step,21all_steps: []const *Build.Step,
...@@ -907,20 +925,3 @@ const cache_control_header: http.Header = .{...@@ -907,20 +925,3 @@ const cache_control_header: http.Header = .{
907 .name = "Cache-Control",925 .name = "Cache-Control",
908 .value = "max-age=0, must-revalidate",926 .value = "max-age=0, must-revalidate",
909};927};
910
911const builtin = @import("builtin");
912
913const std = @import("std");
914const Io = std.Io;
915const net = std.Io.net;
916const assert = std.debug.assert;
917const mem = std.mem;
918const log = std.log.scoped(.web_server);
919const Allocator = std.mem.Allocator;
920const Build = std.Build;
921const Cache = Build.Cache;
922const Fuzz = Build.Fuzz;
923const abi = Build.abi;
924const http = std.http;
925
926const WebServer = @This();
lib/std/Build.zig+3-21
...@@ -92,9 +92,8 @@ pub const Graph = struct {...@@ -92,9 +92,8 @@ pub const Graph = struct {
92 io: Io,92 io: Io,
93 /// Process lifetime.93 /// Process lifetime.
94 arena: Allocator,94 arena: Allocator,
95 system_library_options: std.StringArrayHashMapUnmanaged(SystemLibraryMode) = .empty,95 system_integration_options: std.StringArrayHashMapUnmanaged(SystemLibraryMode) = .empty,
96 system_package_mode: bool = false,96 system_package_mode: bool = false,
97 debug_compiler_runtime_libs: ?std.builtin.OptimizeMode = null,
98 cache: Cache,97 cache: Cache,
99 zig_exe: []const u8,98 zig_exe: []const u8,
100 environ_map: process.Environ.Map,99 environ_map: process.Environ.Map,
...@@ -108,7 +107,7 @@ pub const Graph = struct {...@@ -108,7 +107,7 @@ pub const Graph = struct {
108 /// Steps should use `io` to limit the number of jobs, however in the case of107 /// Steps should use `io` to limit the number of jobs, however in the case of
109 /// a single step spawning a fixed number of processes this can be used.108 /// a single step spawning a fixed number of processes this can be used.
110 max_jobs: ?u32 = null,109 max_jobs: ?u32 = null,
111 time_report: bool,110 time_report: bool = false,
112 /// Similar to the `Io.Terminal.Mode` returned by `Io.lockStderr`, but also111 /// Similar to the `Io.Terminal.Mode` returned by `Io.lockStderr`, but also
113 /// respects the '--color' flag.112 /// respects the '--color' flag.
114 stderr_mode: ?Io.Terminal.Mode = null,113 stderr_mode: ?Io.Terminal.Mode = null,
...@@ -322,11 +321,6 @@ fn createChild(...@@ -322,11 +321,6 @@ fn createChild(
322 .invalid_user_input = false,321 .invalid_user_input = false,
323 .default_step = undefined,322 .default_step = undefined,
324 .top_level_steps = .{},323 .top_level_steps = .{},
325 .install_prefix = undefined,
326 .lib_dir = parent.lib_dir,
327 .exe_dir = parent.exe_dir,
328 .h_dir = parent.h_dir,
329 .install_path = parent.install_path,
330 .sysroot = parent.sysroot,324 .sysroot = parent.sysroot,
331 .build_root = build_root,325 .build_root = build_root,
332 .cache_root = parent.cache_root,326 .cache_root = parent.cache_root,
...@@ -1769,18 +1763,6 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 {...@@ -1769,18 +1763,6 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 {
1769 );1763 );
1770}1764}
17711765
1772pub fn getInstallPath(b: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 {
1773 assert(!fs.path.isAbsolute(dest_rel_path)); // Install paths must be relative to the prefix
1774 const base_dir = switch (dir) {
1775 .prefix => b.install_path,
1776 .bin => b.exe_dir,
1777 .lib => b.lib_dir,
1778 .header => b.h_dir,
1779 .custom => |p| b.pathJoin(&.{ b.install_path, p }),
1780 };
1781 return b.pathResolve(&.{ base_dir, dest_rel_path });
1782}
1783
1784pub const Dependency = struct {1766pub const Dependency = struct {
1785 builder: *Build,1767 builder: *Build,
17861768
...@@ -2572,7 +2554,7 @@ pub fn systemIntegrationOption(...@@ -2572,7 +2554,7 @@ pub fn systemIntegrationOption(
2572 name: []const u8,2554 name: []const u8,
2573 config: SystemIntegrationOptionConfig,2555 config: SystemIntegrationOptionConfig,
2574) bool {2556) bool {
2575 const gop = b.graph.system_library_options.getOrPut(b.allocator, name) catch @panic("OOM");2557 const gop = b.graph.system_integration_options.getOrPut(b.allocator, name) catch @panic("OOM");
2576 if (gop.found_existing) switch (gop.value_ptr.*) {2558 if (gop.found_existing) switch (gop.value_ptr.*) {
2577 .user_disabled => {2559 .user_disabled => {
2578 gop.value_ptr.* = .declared_disabled;2560 gop.value_ptr.* = .declared_disabled;
lib/std/zig/Configuration.zig+98-6
...@@ -11,7 +11,10 @@ steps: []Step,...@@ -11,7 +11,10 @@ steps: []Step,
11path_deps_base: []Path.Base,11path_deps_base: []Path.Base,
12path_deps_sub: []String,12path_deps_sub: []String,
13unlazy_deps: []String,13unlazy_deps: []String,
14system_integrations: []SystemIntegration,
15available_options: []AvailableOption,
14extra: []u32,16extra: []u32,
17default_step: Step.Index,
1518
16/// The field order here matches `Configuration` which documents the order in19/// The field order here matches `Configuration` which documents the order in
17/// the serialized format.20/// the serialized format.
...@@ -20,6 +23,8 @@ pub const Header = extern struct {...@@ -20,6 +23,8 @@ pub const Header = extern struct {
20 steps_len: u32,23 steps_len: u32,
21 path_deps_len: u32,24 path_deps_len: u32,
22 unlazy_deps_len: u32,25 unlazy_deps_len: u32,
26 system_integrations_len: u32,
27 available_options_len: u32,
23 extra_len: u32,28 extra_len: u32,
2429
25 default_step: Step.Index,30 default_step: Step.Index,
...@@ -33,6 +38,8 @@ pub const Wip = struct {...@@ -33,6 +38,8 @@ pub const Wip = struct {
3338
34 string_bytes: std.ArrayList(u8) = .empty,39 string_bytes: std.ArrayList(u8) = .empty,
35 unlazy_deps: std.ArrayList(String) = .empty,40 unlazy_deps: std.ArrayList(String) = .empty,
41 system_integrations: std.ArrayList(SystemIntegration) = .empty,
42 available_options: std.ArrayList(AvailableOption) = .empty,
36 steps: std.ArrayList(Step) = .empty,43 steps: std.ArrayList(Step) = .empty,
37 path_deps: std.MultiArrayList(Path) = .empty,44 path_deps: std.MultiArrayList(Path) = .empty,
38 extra: std.ArrayList(u32) = .empty,45 extra: std.ArrayList(u32) = .empty,
...@@ -107,6 +114,8 @@ pub const Wip = struct {...@@ -107,6 +114,8 @@ pub const Wip = struct {
107 const gpa = wip.gpa;114 const gpa = wip.gpa;
108 wip.string_bytes.deinit(gpa);115 wip.string_bytes.deinit(gpa);
109 wip.unlazy_deps.deinit(gpa);116 wip.unlazy_deps.deinit(gpa);
117 wip.system_integrations.deinit(gpa);
118 wip.available_options.deinit(gpa);
110 wip.steps.deinit(gpa);119 wip.steps.deinit(gpa);
111 wip.path_deps.deinit(gpa);120 wip.path_deps.deinit(gpa);
112 wip.extra.deinit(gpa);121 wip.extra.deinit(gpa);
...@@ -123,6 +132,8 @@ pub const Wip = struct {...@@ -123,6 +132,8 @@ pub const Wip = struct {
123 .steps_len = @intCast(wip.steps.items.len),132 .steps_len = @intCast(wip.steps.items.len),
124 .path_deps_len = @intCast(wip.path_deps.len),133 .path_deps_len = @intCast(wip.path_deps.len),
125 .unlazy_deps_len = @intCast(wip.unlazy_deps.items.len),134 .unlazy_deps_len = @intCast(wip.unlazy_deps.items.len),
135 .system_integrations_len = @intCast(wip.system_integrations.items.len),
136 .available_options_len = @intCast(wip.available_options.items.len),
126 .extra_len = @intCast(wip.extra.items.len),137 .extra_len = @intCast(wip.extra.items.len),
127138
128 .default_step = static.default_step,139 .default_step = static.default_step,
...@@ -134,6 +145,8 @@ pub const Wip = struct {...@@ -134,6 +145,8 @@ pub const Wip = struct {
134 @ptrCast(wip.path_deps.items(.base)),145 @ptrCast(wip.path_deps.items(.base)),
135 @ptrCast(wip.path_deps.items(.sub)),146 @ptrCast(wip.path_deps.items(.sub)),
136 @ptrCast(wip.unlazy_deps.items),147 @ptrCast(wip.unlazy_deps.items),
148 @ptrCast(wip.system_integrations.items),
149 @ptrCast(wip.available_options.items),
137 @ptrCast(wip.extra.items),150 @ptrCast(wip.extra.items),
138 };151 };
139 try w.writeVecAll(&buffers);152 try w.writeVecAll(&buffers);
...@@ -367,6 +380,37 @@ pub const Wip = struct {...@@ -367,6 +380,37 @@ pub const Wip = struct {
367 }380 }
368};381};
369382
383pub const SystemIntegration = extern struct {
384 name: String,
385 status: Status,
386
387 pub const Status = enum(u32) {
388 disabled = 0,
389 enabled = 1,
390 };
391};
392
393pub const AvailableOption = extern struct {
394 name: String,
395 description: String,
396 type: Type,
397 /// If the `type_id` is `enum` or `enum_list` this provides the list of enum options
398 enum_options: OptionalStringList,
399
400 pub const Type = enum(u8) {
401 bool,
402 int,
403 float,
404 @"enum",
405 enum_list,
406 string,
407 list,
408 build_id,
409 lazy_path,
410 lazy_path_list,
411 };
412};
413
370pub const Step = extern struct {414pub const Step = extern struct {
371 name: String,415 name: String,
372 deps: Deps,416 deps: Deps,
...@@ -375,8 +419,19 @@ pub const Step = extern struct {...@@ -375,8 +419,19 @@ pub const Step = extern struct {
375 /// with `Tag`.419 /// with `Tag`.
376 extra_index: u32,420 extra_index: u32,
377421
422 /// Points into `steps`.
378 pub const Index = enum(u32) {423 pub const Index = enum(u32) {
379 _,424 _,
425
426 pub fn ptr(i: Index, c: *const Configuration) *const Step {
427 return &c.steps[@intFromEnum(i)];
428 }
429 };
430
431 /// Shared by all steps.
432 pub const Flags = packed struct(u32) {
433 tag: Tag,
434 _: u27 = 0,
380 };435 };
381436
382 pub const Tag = enum(u5) {437 pub const Tag = enum(u5) {
...@@ -400,7 +455,7 @@ pub const Step = extern struct {...@@ -400,7 +455,7 @@ pub const Step = extern struct {
400 };455 };
401456
402 pub const TopLevel = struct {457 pub const TopLevel = struct {
403 flags: Flags = .{},458 flags: @This().Flags = .{},
404 description: String,459 description: String,
405460
406 pub const Flags = packed struct(u32) {461 pub const Flags = packed struct(u32) {
...@@ -410,7 +465,7 @@ pub const Step = extern struct {...@@ -410,7 +465,7 @@ pub const Step = extern struct {
410 };465 };
411466
412 pub const InstallArtifact = struct {467 pub const InstallArtifact = struct {
413 flags: Flags,468 flags: @This().Flags,
414469
415 dest_dir: InstallDir,470 dest_dir: InstallDir,
416 dest_sub_path: String,471 dest_sub_path: String,
...@@ -445,7 +500,7 @@ pub const Step = extern struct {...@@ -445,7 +500,7 @@ pub const Step = extern struct {
445 /// * stdio_limit: u64, // if stdio_limit is set500 /// * stdio_limit: u64, // if stdio_limit is set
446 /// * producer: Step.Index, // if producer is set. always compile step501 /// * producer: Step.Index, // if producer is set. always compile step
447 pub const Run = struct {502 pub const Run = struct {
448 flags: Flags,503 flags: @This().Flags,
449 file_inputs_len: u32,504 file_inputs_len: u32,
450 args_len: u32,505 args_len: u32,
451 cwd: OptionalLazyPath,506 cwd: OptionalLazyPath,
...@@ -554,7 +609,7 @@ pub const Step = extern struct {...@@ -554,7 +609,7 @@ pub const Step = extern struct {
554 /// * error_limit if flag is set609 /// * error_limit if flag is set
555 /// * Hexstring if build_id is hexstring610 /// * Hexstring if build_id is hexstring
556 pub const Compile = struct {611 pub const Compile = struct {
557 flags: Flags,612 flags: @This().Flags,
558 flags2: Flags2,613 flags2: Flags2,
559 flags3: Flags3,614 flags3: Flags3,
560 flags4: Flags4,615 flags4: Flags4,
...@@ -989,12 +1044,26 @@ pub const ImportTable = enum(u32) {...@@ -989,12 +1044,26 @@ pub const ImportTable = enum(u32) {
989 _,1044 _,
990};1045};
9911046
992/// Points into `extra`, where the first element is number of deps,1047/// Points into `extra`, where the first element is count of deps, following
993/// following elements is `Step.Index` per dep.1048/// elements is `Step.Index` per count.
994pub const Deps = enum(u32) {1049pub const Deps = enum(u32) {
995 _,1050 _,
996};1051};
9971052
1053/// Points into `extra`, where the first element is count of strings, following
1054/// elements is `String` per count.
1055///
1056/// Stored identically to `Deps`.
1057pub const OptionalStringList = enum(u32) {
1058 none = maxInt(u32),
1059 _,
1060
1061 pub fn slice(osl: OptionalStringList, c: *const Configuration) ?[]const String {
1062 const len = c.extra[@intFromEnum(osl)];
1063 return @ptrCast(c.extra[@intFromEnum(osl) + 1 ..][0..len]);
1064 }
1065};
1066
998pub const Path = extern struct {1067pub const Path = extern struct {
999 base: Base,1068 base: Base,
1000 sub: String,1069 sub: String,
...@@ -1444,6 +1513,23 @@ pub const TargetQuery = struct {...@@ -1444,6 +1513,23 @@ pub const TargetQuery = struct {
1444 };1513 };
1445};1514};
14461515
1516pub fn extraData(c: *const Configuration, comptime T: type, index: usize) T {
1517 const extra = c.extra;
1518 var i: usize = index;
1519 var result: T = undefined;
1520 inline for (@typeInfo(T).@"struct".fields) |field| {
1521 comptime assert(@sizeOf(field.type) == @sizeOf(u32));
1522 @field(result, field.name) = switch (@typeInfo(field.type)) {
1523 .int => extra[i],
1524 .@"enum" => @enumFromInt(extra[i]),
1525 .@"struct" => @bitCast(extra[i]),
1526 else => comptime unreachable,
1527 };
1528 i += 1;
1529 }
1530 return result;
1531}
1532
1447pub const LoadFileError = Io.File.Reader.Error || Allocator.Error || error{EndOfStream};1533pub const LoadFileError = Io.File.Reader.Error || Allocator.Error || error{EndOfStream};
14481534
1449pub fn loadFile(arena: Allocator, io: Io, file: Io.File) LoadFileError!Configuration {1535pub fn loadFile(arena: Allocator, io: Io, file: Io.File) LoadFileError!Configuration {
...@@ -1465,7 +1551,10 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {...@@ -1465,7 +1551,10 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
1465 .path_deps_sub = try arena.alloc(String, header.path_deps_len),1551 .path_deps_sub = try arena.alloc(String, header.path_deps_len),
1466 .path_deps_base = try arena.alloc(Path.Base, header.path_deps_len),1552 .path_deps_base = try arena.alloc(Path.Base, header.path_deps_len),
1467 .unlazy_deps = try arena.alloc(String, header.unlazy_deps_len),1553 .unlazy_deps = try arena.alloc(String, header.unlazy_deps_len),
1554 .system_integrations = try arena.alloc(SystemIntegration, header.system_integrations_len),
1555 .available_options = try arena.alloc(AvailableOption, header.available_options_len),
1468 .extra = try arena.alloc(u32, header.extra_len),1556 .extra = try arena.alloc(u32, header.extra_len),
1557 .default_step = header.default_step,
1469 };1558 };
1470 var vecs = [_][]u8{1559 var vecs = [_][]u8{
1471 result.string_bytes,1560 result.string_bytes,
...@@ -1473,6 +1562,9 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {...@@ -1473,6 +1562,9 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
1473 @ptrCast(result.path_deps_base),1562 @ptrCast(result.path_deps_base),
1474 @ptrCast(result.path_deps_sub),1563 @ptrCast(result.path_deps_sub),
1475 @ptrCast(result.unlazy_deps),1564 @ptrCast(result.unlazy_deps),
1565 @ptrCast(result.system_integrations),
1566 @ptrCast(result.available_options),
1567 @ptrCast(result.extra),
1476 };1568 };
1477 try reader.readVecAll(&vecs);1569 try reader.readVecAll(&vecs);
1478 return result;1570 return result;
src/Compilation.zig+1-3
...@@ -3233,9 +3233,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -3233,9 +3233,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
3233 }3233 }
32343234
3235 // Failure here only means an unnecessary cache miss.3235 // Failure here only means an unnecessary cache miss.
3236 man.writeManifest() catch |err| {3236 man.writeManifest() catch |err| log.warn("failed to write cache manifest: {t}", .{err});
3237 log.warn("failed to write cache manifest: {s}", .{@errorName(err)});
3238 };
32393237
3240 assert(whole.lock == null);3238 assert(whole.lock == null);
3241 whole.lock = man.toOwnedLock();3239 whole.lock = man.toOwnedLock();
src/main.zig+32-31
...@@ -3682,26 +3682,16 @@ fn buildOutputType(...@@ -3682,26 +3682,16 @@ fn buildOutputType(
3682 if (t.arch == target.cpu.arch and t.os == target.os.tag) {3682 if (t.arch == target.cpu.arch and t.os == target.os.tag) {
3683 // If there's a `glibc_min`, there's also an `os_ver`.3683 // If there's a `glibc_min`, there's also an `os_ver`.
3684 if (t.glibc_min) |glibc_min| {3684 if (t.glibc_min) |glibc_min| {
3685 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}.{d}.{d}", .{3685 std.log.info("zig can provide libc for related target {t}-{t}.{f}-{t}.{d}.{d}", .{
3686 @tagName(t.arch),3686 t.arch, t.os, t.os_ver.?, t.abi, glibc_min.major, glibc_min.minor,
3687 @tagName(t.os),
3688 t.os_ver.?,
3689 @tagName(t.abi),
3690 glibc_min.major,
3691 glibc_min.minor,
3692 });3687 });
3693 } else if (t.os_ver) |os_ver| {3688 } else if (t.os_ver) |os_ver| {
3694 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}", .{3689 std.log.info("zig can provide libc for related target {t}-{t}.{f}-{t}", .{
3695 @tagName(t.arch),3690 t.arch, t.os, os_ver, t.abi,
3696 @tagName(t.os),
3697 os_ver,
3698 @tagName(t.abi),
3699 });3691 });
3700 } else {3692 } else {
3701 std.log.info("zig can provide libc for related target {s}-{s}-{s}", .{3693 std.log.info("zig can provide libc for related target {t}-{t}-{t}", .{
3702 @tagName(t.arch),3694 t.arch, t.os, t.abi,
3703 @tagName(t.os),
3704 @tagName(t.abi),
3705 });3695 });
3706 }3696 }
3707 }3697 }
...@@ -3710,7 +3700,7 @@ fn buildOutputType(...@@ -3710,7 +3700,7 @@ fn buildOutputType(
3710 },3700 },
3711 else => fatal("{f}", .{create_diag}),3701 else => fatal("{f}", .{create_diag}),
3712 },3702 },
3713 else => fatal("failed to create compilation: {s}", .{@errorName(err)}),3703 else => fatal("failed to create compilation: {t}", .{err}),
3714 };3704 };
3715 var comp_destroyed = false;3705 var comp_destroyed = false;
3716 defer if (!comp_destroyed) comp.destroy();3706 defer if (!comp_destroyed) comp.destroy();
...@@ -4984,7 +4974,6 @@ fn cmdBuild(...@@ -4984,7 +4974,6 @@ fn cmdBuild(
4984 try configure_argv.ensureUnusedCapacity(arena, 16);4974 try configure_argv.ensureUnusedCapacity(arena, 16);
4985 try make_argv.ensureUnusedCapacity(arena, 16);4975 try make_argv.ensureUnusedCapacity(arena, 16);
49864976
4987 const argv_index_exe = configure_argv.items.len;
4988 _ = configure_argv.addOneAssumeCapacity();4977 _ = configure_argv.addOneAssumeCapacity();
4989 _ = make_argv.addOneAssumeCapacity();4978 _ = make_argv.addOneAssumeCapacity();
49904979
...@@ -5069,9 +5058,7 @@ fn cmdBuild(...@@ -5069,9 +5058,7 @@ fn cmdBuild(
5069 } else if (mem.cutPrefix(u8, arg, "--fetch=")) |sub_arg| {5058 } else if (mem.cutPrefix(u8, arg, "--fetch=")) |sub_arg| {
5070 fetch_only = true;5059 fetch_only = true;
5071 fetch_mode = std.meta.stringToEnum(Package.Fetch.JobQueue.Mode, sub_arg) orelse5060 fetch_mode = std.meta.stringToEnum(Package.Fetch.JobQueue.Mode, sub_arg) orelse
5072 fatal("expected [needed|all] after '--fetch=', found '{s}'", .{5061 fatal("expected [needed|all] after '--fetch=', found '{s}'", .{sub_arg});
5073 sub_arg,
5074 });
5075 } else if (mem.cutPrefix(u8, arg, "--fork=")) |sub_arg| {5062 } else if (mem.cutPrefix(u8, arg, "--fork=")) |sub_arg| {
5076 try forks.append(arena, .{5063 try forks.append(arena, .{
5077 .manifest_ast = undefined,5064 .manifest_ast = undefined,
...@@ -5093,7 +5080,7 @@ fn cmdBuild(...@@ -5093,7 +5080,7 @@ fn cmdBuild(
5093 continue;5080 continue;
5094 } else if (mem.cutPrefix(u8, arg, "-freference-trace=")) |num| {5081 } else if (mem.cutPrefix(u8, arg, "-freference-trace=")) |num| {
5095 reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {5082 reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {
5096 fatal("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) });5083 fatal("unable to parse reference_trace count '{s}': {t}", .{ num, err });
5097 };5084 };
5098 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {5085 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {
5099 reference_trace = null;5086 reference_trace = null;
...@@ -5169,7 +5156,8 @@ fn cmdBuild(...@@ -5169,7 +5156,8 @@ fn cmdBuild(
5169 } else if (mem.eql(u8, arg, "--")) {5156 } else if (mem.eql(u8, arg, "--")) {
5170 // The rest of the args are supposed to get passed onto5157 // The rest of the args are supposed to get passed onto
5171 // build runner's `build.args`5158 // build runner's `build.args`
5172 try configure_argv.appendSlice(arena, args[i..]);5159 try configure_argv.append(arena, "--have-run-args");
5160 try make_argv.appendSlice(arena, args[i..]);
5173 break;5161 break;
5174 }5162 }
5175 }5163 }
...@@ -5273,7 +5261,12 @@ fn cmdBuild(...@@ -5273,7 +5261,12 @@ fn cmdBuild(
52735261
5274 // Kick off an optimized compilation of the make runner.5262 // Kick off an optimized compilation of the make runner.
5275 var make_runner_task = io.async(compileMakeRunner, .{ gpa, arena, io, .{5263 var make_runner_task = io.async(compileMakeRunner, .{ gpa, arena, io, .{
5276 .dirs = &dirs,5264 .dirs = .{
5265 .cwd = dirs.cwd,
5266 .zig_lib = dirs.zig_lib,
5267 .global_cache = dirs.global_cache,
5268 .local_cache = dirs.global_cache,
5269 },
5277 .environ_map = environ_map,5270 .environ_map = environ_map,
5278 .parent_prog_node = root_prog_node,5271 .parent_prog_node = root_prog_node,
5279 .resolved_target = resolved_target,5272 .resolved_target = resolved_target,
...@@ -5281,6 +5274,7 @@ fn cmdBuild(...@@ -5281,6 +5274,7 @@ fn cmdBuild(
5281 .thread_limit = thread_limit,5274 .thread_limit = thread_limit,
5282 .self_exe_path = self_exe_path,5275 .self_exe_path = self_exe_path,
5283 .color = color,5276 .color = color,
5277 .reference_trace = reference_trace,
5284 } });5278 } });
5285 defer _ = make_runner_task.cancel(io) catch {};5279 defer _ = make_runner_task.cancel(io) catch {};
52865280
...@@ -5289,6 +5283,11 @@ fn cmdBuild(...@@ -5289,6 +5283,11 @@ fn cmdBuild(
5289 configure_argv.items[argv_index_global_cache_dir] = dirs.global_cache.path orelse cwd_path;5283 configure_argv.items[argv_index_global_cache_dir] = dirs.global_cache.path orelse cwd_path;
5290 configure_argv.items[argv_index_cache_dir] = dirs.local_cache.path orelse cwd_path;5284 configure_argv.items[argv_index_cache_dir] = dirs.local_cache.path orelse cwd_path;
52915285
5286 make_argv.items[argv_index_zig_lib_dir] = dirs.zig_lib.path orelse cwd_path;
5287 make_argv.items[argv_index_build_file] = build_root.directory.path orelse cwd_path;
5288 make_argv.items[argv_index_global_cache_dir] = dirs.global_cache.path orelse cwd_path;
5289 make_argv.items[argv_index_cache_dir] = dirs.local_cache.path orelse cwd_path;
5290
5292 // Dummy http client that is not actually used when fetch_command is unsupported.5291 // Dummy http client that is not actually used when fetch_command is unsupported.
5293 // Prevents bootstrap from depending on a bunch of unnecessary stuff.5292 // Prevents bootstrap from depending on a bunch of unnecessary stuff.
5294 var http_client: if (dev.env.supports(.fetch_command)) std.http.Client else struct {5293 var http_client: if (dev.env.supports(.fetch_command)) std.http.Client else struct {
...@@ -5601,7 +5600,7 @@ fn cmdBuild(...@@ -5601,7 +5600,7 @@ fn cmdBuild(
5601 .sub_path = try std.fmt.allocPrint(arena, "o/{s}/{s}", .{ hex_digest, comp.emit_bin.? }),5600 .sub_path = try std.fmt.allocPrint(arena, "o/{s}/{s}", .{ hex_digest, comp.emit_bin.? }),
5602 };5601 };
5603 _ = try config_man.addFilePath(exe_path, null);5602 _ = try config_man.addFilePath(exe_path, null);
5604 configure_argv.items[argv_index_exe] = try exe_path.toString(arena);5603 configure_argv.items[0] = try exe_path.toString(arena);
56055604
5606 if (try config_man.hit()) {5605 if (try config_man.hit()) {
5607 const digest = config_man.final();5606 const digest = config_man.final();
...@@ -5758,15 +5757,15 @@ fn cmdBuild(...@@ -5758,15 +5757,15 @@ fn cmdBuild(
5758 }) {5757 }) {
5759 .exited => |code| {5758 .exited => |code| {
5760 if (code == 0) return cleanExit(io);5759 if (code == 0) return cleanExit(io);
5761 const cmd = try std.mem.join(arena, " ", configure_argv.items);5760 const cmd = try std.mem.join(arena, " ", make_argv.items);
5762 fatal("the following maker command failed with exit code {d}:\n{s}", .{ code, cmd });5761 fatal("the following maker command failed with exit code {d}:\n{s}", .{ code, cmd });
5763 },5762 },
5764 .signal => |sig| {5763 .signal => |sig| {
5765 const cmd = try std.mem.join(arena, " ", configure_argv.items);5764 const cmd = try std.mem.join(arena, " ", make_argv.items);
5766 fatal("the following maker command terminated with signal {t}:\n{s}", .{ sig, cmd });5765 fatal("the following maker command terminated with signal {t}:\n{s}", .{ sig, cmd });
5767 },5766 },
5768 else => {5767 else => {
5769 const cmd = try std.mem.join(arena, " ", configure_argv.items);5768 const cmd = try std.mem.join(arena, " ", make_argv.items);
5770 fatal("the following maker command crashed:\n{s}", .{cmd});5769 fatal("the following maker command crashed:\n{s}", .{cmd});
5771 },5770 },
5772 }5771 }
...@@ -5777,13 +5776,14 @@ const MakeRunner = struct {...@@ -5777,13 +5776,14 @@ const MakeRunner = struct {
57775776
5778 const Options = struct {5777 const Options = struct {
5779 environ_map: *const process.Environ.Map,5778 environ_map: *const process.Environ.Map,
5780 dirs: *Compilation.Directories,5779 dirs: Compilation.Directories,
5781 parent_prog_node: std.Progress.Node,5780 parent_prog_node: std.Progress.Node,
5782 resolved_target: Package.Module.ResolvedTarget,5781 resolved_target: Package.Module.ResolvedTarget,
5783 libc_installation: ?*const LibCInstallation,5782 libc_installation: ?*const LibCInstallation,
5784 self_exe_path: []const u8,5783 self_exe_path: []const u8,
5785 thread_limit: usize,5784 thread_limit: usize,
5786 color: Color,5785 color: Color,
5786 reference_trace: ?u32,
5787 };5787 };
5788};5788};
57895789
...@@ -5798,7 +5798,7 @@ fn compileMakeRunner(gpa: Allocator, arena: Allocator, io: Io, options: MakeRunn...@@ -5798,7 +5798,7 @@ fn compileMakeRunner(gpa: Allocator, arena: Allocator, io: Io, options: MakeRunn
5798 const strip = optimize_mode != .Debug;5798 const strip = optimize_mode != .Debug;
57995799
5800 const main_mod_paths: Package.Module.CreateOptions.Paths = .{5800 const main_mod_paths: Package.Module.CreateOptions.Paths = .{
5801 .root = try .fromRoot(arena, options.dirs.*, .zig_lib, "compiler"),5801 .root = try .fromRoot(arena, options.dirs, .zig_lib, "compiler"),
5802 .root_src_path = "maker.zig",5802 .root_src_path = "maker.zig",
5803 };5803 };
58045804
...@@ -5827,7 +5827,7 @@ fn compileMakeRunner(gpa: Allocator, arena: Allocator, io: Io, options: MakeRunn...@@ -5827,7 +5827,7 @@ fn compileMakeRunner(gpa: Allocator, arena: Allocator, io: Io, options: MakeRunn
58275827
5828 var create_diag: Compilation.CreateDiagnostic = undefined;5828 var create_diag: Compilation.CreateDiagnostic = undefined;
5829 const comp = Compilation.create(gpa, arena, io, &create_diag, .{5829 const comp = Compilation.create(gpa, arena, io, &create_diag, .{
5830 .dirs = options.dirs.*,5830 .dirs = options.dirs,
5831 .root_name = "maker",5831 .root_name = "maker",
5832 .config = config,5832 .config = config,
5833 .root_mod = root_mod,5833 .root_mod = root_mod,
...@@ -5837,6 +5837,7 @@ fn compileMakeRunner(gpa: Allocator, arena: Allocator, io: Io, options: MakeRunn...@@ -5837,6 +5837,7 @@ fn compileMakeRunner(gpa: Allocator, arena: Allocator, io: Io, options: MakeRunn
5837 .thread_limit = options.thread_limit,5837 .thread_limit = options.thread_limit,
5838 .cache_mode = .whole,5838 .cache_mode = .whole,
5839 .environ_map = options.environ_map,5839 .environ_map = options.environ_map,
5840 .reference_trace = options.reference_trace,
5840 }) catch |err| switch (err) {5841 }) catch |err| switch (err) {
5841 error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}),5842 error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}),
5842 error.Canceled => |e| return e,5843 error.Canceled => |e| return e,