authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-24 19:42:49-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:34-07:00
logb04818644c958e05de9b0d5fb4a8a2a3da6d2164
treeb612dfe2fbae36626dc333454a119d1dc99e27b7
parenta180012dd2bdae6dd30e165e6c74923eeeeb95b7

rename configure_runner to configurer


3 files changed, 842 insertions(+), 842 deletions(-)

lib/compiler/configure_runner.zig deleted-841
......@@ -1,841 +0,0 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4const Allocator = std.mem.Allocator;
5const Color = std.zig.Color;
6const Configuration = std.Build.Configuration;
7const File = std.Io.File;
8const Io = std.Io;
9const Step = std.Build.Step;
10const Writer = std.Io.Writer;
11const assert = std.debug.assert;
12const fatal = std.process.fatal;
13const fmt = std.fmt;
14const log = std.log;
15const mem = std.mem;
16const process = std.process;
17
18pub const root = @import("@build");
19pub const dependencies = @import("@dependencies");
20
21pub const std_options: std.Options = .{
22 .side_channels_mitigations = .none,
23 .http_disable_tls = true,
24};
25
26pub fn main(init: process.Init.Minimal) !void {
27 // The build runner is often short-lived, but thanks to `--watch` and `--webui`, that's not
28 // always the case. So, we do need a true gpa for some things.
29 var debug_gpa_state: std.heap.DebugAllocator(.{
30 // We'd rather have `zig build` run faster than catch harmless leaks in
31 // the user's build.zig script.
32 .stack_trace_frames = 0,
33 }) = .init;
34 defer _ = debug_gpa_state.deinit();
35 const gpa = debug_gpa_state.allocator();
36
37 var threaded: std.Io.Threaded = .init(gpa, .{
38 .environ = init.environ,
39 .argv0 = .init(init.args),
40 });
41 defer threaded.deinit();
42 const io = threaded.io();
43
44 // ...but we'll back our arena by `std.heap.page_allocator` for efficiency.
45 var arena_allocator: std.heap.ArenaAllocator = .init(std.heap.page_allocator);
46 defer arena_allocator.deinit();
47 const arena = arena_allocator.allocator();
48
49 const args = try init.args.toSlice(arena);
50
51 // skip my own exe name
52 var arg_idx: usize = 1;
53
54 const zig_exe = expectArgOrFatal(args, &arg_idx, "--zig");
55 const zig_lib_dir = expectArgOrFatal(args, &arg_idx, "--zig-lib-dir");
56 const build_root = expectArgOrFatal(args, &arg_idx, "--build-root");
57 const local_cache_root = expectArgOrFatal(args, &arg_idx, "--local-cache");
58 const global_cache_root = expectArgOrFatal(args, &arg_idx, "--global-cache");
59
60 const cwd: Io.Dir = .cwd();
61
62 const zig_lib_directory: std.Build.Cache.Directory = .{
63 .path = zig_lib_dir,
64 .handle = try cwd.openDir(io, zig_lib_dir, .{}),
65 };
66
67 const build_root_directory: std.Build.Cache.Directory = .{
68 .path = build_root,
69 .handle = try cwd.openDir(io, build_root, .{}),
70 };
71
72 const local_cache_directory: std.Build.Cache.Directory = .{
73 .path = local_cache_root,
74 .handle = try cwd.createDirPathOpen(io, local_cache_root, .{}),
75 };
76
77 const global_cache_directory: std.Build.Cache.Directory = .{
78 .path = global_cache_root,
79 .handle = try cwd.createDirPathOpen(io, global_cache_root, .{}),
80 };
81
82 var graph: std.Build.Graph = .{
83 .io = io,
84 .arena = arena,
85 .cache = .{
86 .io = io,
87 .gpa = gpa,
88 .manifest_dir = try local_cache_directory.handle.createDirPathOpen(io, "h", .{}),
89 .cwd = try process.currentPathAlloc(io, arena),
90 },
91 .zig_exe = zig_exe,
92 .environ_map = try init.environ.createMap(arena),
93 .global_cache_root = global_cache_directory,
94 .zig_lib_directory = zig_lib_directory,
95 .host = .{
96 .query = .{},
97 .result = try std.zig.system.resolveTargetQuery(io, .{}),
98 },
99 };
100
101 graph.cache.addPrefix(.{ .path = null, .handle = cwd });
102 graph.cache.addPrefix(build_root_directory);
103 graph.cache.addPrefix(local_cache_directory);
104 graph.cache.addPrefix(global_cache_directory);
105 graph.cache.hash.addBytes(builtin.zig_version_string);
106
107 const builder = try std.Build.create(
108 &graph,
109 build_root_directory,
110 local_cache_directory,
111 dependencies.root_deps,
112 );
113
114 var error_style: ErrorStyle = .verbose;
115 var multiline_errors: MultilineErrors = .indent;
116 var color: Color = .auto;
117
118 if (std.zig.EnvVar.ZIG_BUILD_ERROR_STYLE.get(&graph.environ_map)) |str| {
119 if (std.meta.stringToEnum(ErrorStyle, str)) |style| {
120 error_style = style;
121 }
122 }
123
124 if (std.zig.EnvVar.ZIG_BUILD_MULTILINE_ERRORS.get(&graph.environ_map)) |str| {
125 if (std.meta.stringToEnum(MultilineErrors, str)) |style| {
126 multiline_errors = style;
127 }
128 }
129
130 while (nextArg(args, &arg_idx)) |arg| {
131 if (mem.cutPrefix(u8, arg, "-D")) |option_contents| {
132 if (option_contents.len == 0)
133 fatalWithHint("expected option name after '-D'", .{});
134 if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {
135 const option_name = option_contents[0..name_end];
136 const option_value = option_contents[name_end + 1 ..];
137 if (try builder.addUserInputOption(option_name, option_value))
138 fatal(" access the help menu with 'zig build -h'", .{});
139 } else {
140 if (try builder.addUserInputFlag(option_contents))
141 fatal(" access the help menu with 'zig build -h'", .{});
142 }
143 } else if (mem.cutPrefix(u8, arg, "-fsys=")) |name| {
144 try graph.system_integration_options.put(arena, name, .user_enabled);
145 } else if (mem.cutPrefix(u8, arg, "-fno-sys=")) |name| {
146 try graph.system_integration_options.put(arena, name, .user_disabled);
147 } else if (mem.eql(u8, arg, "--release")) {
148 graph.release_mode = .any;
149 } else if (mem.cutPrefix(u8, arg, "--release=")) |text| {
150 graph.release_mode = std.meta.stringToEnum(std.Build.ReleaseMode, text) orelse {
151 fatalWithHint("expected [off|any|fast|safe|small] in {q}, found {q}", .{
152 arg, text,
153 });
154 };
155 } else if (mem.eql(u8, arg, "--color")) {
156 const next_arg = nextArg(args, &arg_idx) orelse
157 fatalWithHint("expected [auto|on|off] after {q}", .{arg});
158 color = std.meta.stringToEnum(Color, next_arg) orelse {
159 fatalWithHint("expected [auto|on|off] after {q}, found {q}", .{
160 arg, next_arg,
161 });
162 };
163 } else if (mem.eql(u8, arg, "--error-style")) {
164 const next_arg = nextArg(args, &arg_idx) orelse
165 fatalWithHint("expected style after {q}", .{arg});
166 error_style = std.meta.stringToEnum(ErrorStyle, next_arg) orelse {
167 fatalWithHint("expected style after {q}, found {q}", .{ arg, next_arg });
168 };
169 } else if (mem.eql(u8, arg, "--multiline-errors")) {
170 const next_arg = nextArg(args, &arg_idx) orelse
171 fatalWithHint("expected style after {q}", .{arg});
172 multiline_errors = std.meta.stringToEnum(MultilineErrors, next_arg) orelse {
173 fatalWithHint("expected style after {q}, found {q}", .{ arg, next_arg });
174 };
175 } else if (mem.eql(u8, arg, "--system")) {
176 // The usage text shows another argument after this parameter
177 // but it is handled by the parent process. The build runner
178 // only sees this flag.
179 graph.system_package_mode = true;
180 } else if (mem.eql(u8, arg, "--have-run-args")) {
181 graph.have_run_args = true;
182 } else {
183 fatalWithHint("unrecognized argument: {q}", .{arg});
184 }
185 }
186
187 const NO_COLOR = std.zig.EnvVar.NO_COLOR.isSet(&graph.environ_map);
188 const CLICOLOR_FORCE = std.zig.EnvVar.CLICOLOR_FORCE.isSet(&graph.environ_map);
189
190 graph.stderr_mode = switch (color) {
191 .auto => try .detect(io, .stderr(), NO_COLOR, CLICOLOR_FORCE),
192 .on => .escape_codes,
193 .off => .no_color,
194 };
195
196 try builder.runBuild(root);
197
198 if (builder.validateUserInputDidItFail()) {
199 fatal(" access the help menu with 'zig build -h'", .{});
200 }
201
202 var wc: Configuration.Wip = .init(gpa);
203 defer wc.deinit();
204 assert(try wc.addString("") == .empty);
205
206 try serializeSystemIntegrationOptions(&graph, &wc);
207
208 var stdout_buffer: [1024]u8 = undefined;
209 var file_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer);
210 serialize(builder, &wc, &file_writer.interface) catch |err| switch (err) {
211 error.WriteFailed => fatal("failed to write configuration output: {t}", .{file_writer.err.?}),
212 error.OutOfMemory => |e| return e,
213 };
214
215 // This executable is short-lived and run in Debug mode, so we'd rather
216 // have `zig build` run faster than catch resource leaks in the user's
217 // build.zig script (or, frankly, this configure runner), therefore we call
218 // exit directly here rather than cleanExit.
219 process.exit(0);
220}
221
222const Serialize = struct {
223 arena: Allocator,
224 wc: *Configuration.Wip,
225 module_map: std.AutoArrayHashMapUnmanaged(*std.Build.Module, Configuration.Module.Index) = .empty,
226 package_map: std.AutoArrayHashMapUnmanaged(*std.Build, Configuration.Package.Index) = .empty,
227
228 fn builderToPackage(s: *Serialize, b: *std.Build) !Configuration.Package.Index {
229 if (b.pkg_hash.len == 0) return .root;
230 const arena = s.arena;
231 const wc = s.wc;
232 const gop = try s.package_map.getOrPut(arena, b);
233 if (!gop.found_existing) {
234 gop.value_ptr.* = @enumFromInt(try wc.addExtra(@as(Configuration.Package, .{
235 .hash = try wc.addString(b.pkg_hash),
236 .dep_prefix = try wc.addString(b.dep_prefix),
237 })));
238 }
239 return gop.value_ptr.*;
240 }
241
242 fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.OptionalLazyPath {
243 const wc = s.wc;
244 return @enumFromInt(switch (lp orelse return .none) {
245 .src_path => |src_path| i: {
246 const sub_path = try wc.addString(src_path.sub_path);
247 break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{
248 .flags = .{},
249 .owner = try s.builderToPackage(src_path.owner),
250 .sub_path = sub_path,
251 }));
252 },
253 .generated => |generated| i: {
254 const sub_path = try wc.addString(generated.sub_path);
255 break :i try wc.addExtra(@as(Configuration.LazyPath.Generated, .{
256 .flags = .{ .up = @intCast(generated.up) },
257 .sub_path = sub_path,
258 }));
259 },
260 .cwd_relative => |cwd_relative_sub_path| i: {
261 const sub_path = try wc.addString(cwd_relative_sub_path);
262 break :i try wc.addExtra(@as(Configuration.LazyPath.Relative, .{
263 .flags = .{ .base = .cwd },
264 .sub_path = sub_path,
265 }));
266 },
267 .dependency => |dependency| i: {
268 const sub_path = try wc.addString(dependency.sub_path);
269 break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{
270 .flags = .{},
271 .owner = try s.builderToPackage(dependency.dependency.builder),
272 .sub_path = sub_path,
273 }));
274 },
275 });
276 }
277
278 fn addOptionalLazyPath(s: *Serialize, lp: ?std.Build.LazyPath) !?Configuration.LazyPath {
279 return (try addOptionalLazyPathEnum(s, lp)).unwrap();
280 }
281
282 fn addLazyPath(s: *Serialize, lp: std.Build.LazyPath) !Configuration.LazyPath {
283 return @enumFromInt(@intFromEnum(try addOptionalLazyPathEnum(s, lp)));
284 }
285
286 fn addOptionalSemVer(s: *Serialize, sem_ver: ?std.SemanticVersion) !?Configuration.String {
287 return if (sem_ver) |sv| try s.wc.addSemVer(sv) else null;
288 }
289
290 fn addOptionalString(s: *Serialize, opt_slice: ?[]const u8) !?Configuration.String {
291 return if (opt_slice) |slice| try s.wc.addString(slice) else null;
292 }
293
294 fn initStringList(s: *Serialize, list: []const []const u8) ![]const Configuration.String {
295 const wc = s.wc;
296 const result = try s.arena.alloc(Configuration.String, list.len);
297 for (result, list) |*dest, src| dest.* = try wc.addString(src);
298 return result;
299 }
300
301 fn initOptionalStringList(s: *Serialize, list: []const ?[]const u8) ![]const Configuration.OptionalString {
302 const wc = s.wc;
303 const result = try s.arena.alloc(Configuration.OptionalString, list.len);
304 for (result, list) |*dest, src| dest.* = try wc.addOptionalString(src);
305 return result;
306 }
307
308 fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
309 if (s.module_map.get(m)) |index| return index;
310
311 const wc = s.wc;
312 const arena = s.arena;
313 const gpa = wc.gpa;
314
315 const lib_paths = try arena.alloc(Configuration.LazyPath, m.lib_paths.items.len);
316 for (lib_paths, m.lib_paths.items) |*dest, src| dest.* = try addLazyPath(s, src);
317
318 const c_macros = try initStringList(s, m.c_macros.items);
319 const export_symbol_names = try initStringList(s, m.export_symbol_names);
320
321 const import_table: Configuration.ImportTable = @enumFromInt(wc.extra.items.len);
322 const import_table_extra_len = 1 + 2 * m.import_table.entries.len;
323 try wc.extra.ensureUnusedCapacity(gpa, import_table_extra_len);
324 wc.extra.items.len += import_table_extra_len;
325 wc.extra.appendAssumeCapacity(@intCast(m.import_table.entries.len));
326 wc.extra.items[@intFromEnum(import_table)] = @intCast(m.import_table.entries.len);
327 for (
328 m.import_table.keys(),
329 @intFromEnum(import_table) + 1..,
330 ) |mod_name, extra_index| {
331 wc.extra.items[extra_index] = @intFromEnum(try wc.addString(mod_name));
332 }
333 for (
334 m.import_table.values(),
335 @intFromEnum(import_table) + 1 + m.import_table.entries.len..,
336 ) |dep, extra_index| {
337 log.err("TODO module dependencies can be cyclic", .{});
338 wc.extra.items[extra_index] = @intFromEnum(try addModule(s, dep));
339 }
340
341 const module_index: Configuration.Module.Index = @enumFromInt(try wc.addExtra(@as(Configuration.Module, .{
342 .flags = .{
343 .optimize = .init(m.optimize),
344 .strip = .init(m.strip),
345 .unwind_tables = .init(m.unwind_tables),
346 .dwarf_format = .init(m.dwarf_format),
347 .single_threaded = .init(m.strip),
348 .stack_protector = .init(m.strip),
349 .stack_check = .init(m.strip),
350 .sanitize_c = .init(m.sanitize_c),
351 .sanitize_thread = .init(m.strip),
352 .fuzz = .init(m.strip),
353 .code_model = m.code_model,
354 .c_macros = c_macros.len != 0,
355 .include_dirs = m.include_dirs.items.len != 0,
356 .lib_paths = lib_paths.len != 0,
357 .rpaths = m.rpaths.items.len != 0,
358 .frameworks = m.frameworks.entries.len != 0,
359 .link_objects = m.link_objects.items.len != 0,
360 .export_symbol_names = export_symbol_names.len != 0,
361 },
362 .flags2 = .{
363 .valgrind = .init(m.strip),
364 .pic = .init(m.strip),
365 .red_zone = .init(m.strip),
366 .omit_frame_pointer = .init(m.strip),
367 .error_tracing = .init(m.strip),
368 .link_libc = .init(m.strip),
369 .link_libcpp = .init(m.strip),
370 .no_builtin = .init(m.strip),
371 },
372 .owner = try s.builderToPackage(m.owner),
373 .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),
374 .import_table = import_table,
375 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),
376 .c_macros = .{ .slice = c_macros },
377 .lib_paths = .{ .slice = lib_paths },
378 .export_symbol_names = .{ .slice = export_symbol_names },
379 })));
380
381 log.err("TODO serialize the trailing Module data", .{});
382
383 try s.module_map.putNoClobber(arena, m, module_index);
384
385 return module_index;
386 }
387};
388
389fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
390 const graph = b.graph;
391 const arena = graph.arena;
392 const gpa = wc.gpa;
393
394 var s: Serialize = .{ .wc = wc, .arena = arena };
395
396 // Starting from all top-level steps in `b`, traverse the entire step graph
397 // and add all step dependencies implied by module graphs.
398 const top_level_steps = b.top_level_steps.values();
399 // Index corresponds to `Configuration.steps` index.
400 var step_map: std.AutoArrayHashMapUnmanaged(*Step, void) = .empty;
401 try step_map.ensureUnusedCapacity(arena, top_level_steps.len);
402 for (top_level_steps) |tls| {
403 step_map.putAssumeCapacityNoClobber(&tls.step, {});
404 }
405 {
406 while (wc.steps.items.len < step_map.count()) {
407 const step = step_map.keys()[wc.steps.items.len];
408
409 // Set up any implied dependencies for this step. It's important that we do this first, so
410 // that the loop below discovers steps implied by the module graph.
411 try createModuleDependenciesForStep(step);
412
413 try step_map.ensureUnusedCapacity(arena, step.dependencies.items.len);
414 for (step.dependencies.items) |other_step| {
415 step_map.putAssumeCapacity(other_step, {});
416 }
417
418 // Add and then de-duplicate dependencies.
419 const deps = d: {
420 const deps: Configuration.Deps = @enumFromInt(wc.extra.items.len);
421 for (try wc.reserveLengthPrefixed(step.dependencies.items.len), step.dependencies.items) |*dep, dep_step|
422 dep.* = @intCast(step_map.getIndex(dep_step).?);
423 break :d try wc.dedupeDeps(deps);
424 };
425
426 try wc.steps.ensureTotalCapacity(gpa, step_map.entries.capacity);
427 wc.steps.appendAssumeCapacity(.{
428 .name = try wc.addString(step.name),
429 .owner = try s.builderToPackage(step.owner),
430 .deps = deps,
431 .max_rss = .fromBytes(step.max_rss),
432 .extended = switch (step.tag) {
433 .top_level => e: {
434 const top_level: *Step.TopLevel = @fieldParentPtr("step", step);
435 break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.TopLevel, .{
436 .description = try wc.addString(top_level.description),
437 })));
438 },
439 .compile => e: {
440 const c: *Step.Compile = @fieldParentPtr("step", step);
441 const exec_cmd_args: []const ?[]const u8 = c.exec_cmd_args orelse &.{};
442 const installed_headers: []u32 = try arena.alloc(u32, c.installed_headers.items.len);
443 for (installed_headers, c.installed_headers.items) |*dst, src| switch (src) {
444 .file => |file| {
445 dst.* = try wc.addExtra(@as(Configuration.Step.Compile.InstalledHeader.File, .{
446 .source = try s.addLazyPath(file.source),
447 .dest_sub_path = try wc.addString(file.dest_rel_path),
448 }));
449 },
450 .directory => |directory| {
451 const include_extensions = directory.options.include_extensions orelse &.{};
452 dst.* = try wc.addExtra(@as(Configuration.Step.Compile.InstalledHeader.Directory, .{
453 .flags = .{
454 .include_extensions = include_extensions.len != 0,
455 .exclude_extensions = directory.options.exclude_extensions.len != 0,
456 },
457 .source = try s.addLazyPath(directory.source),
458 .dest_sub_path = try wc.addString(directory.dest_rel_path),
459 .exclude_extensions = .{ .slice = try s.initStringList(directory.options.exclude_extensions) },
460 .include_extensions = .{ .slice = try s.initStringList(include_extensions) },
461 }));
462 },
463 };
464
465 const extra_index = try wc.addExtra(@as(Configuration.Step.Compile, .{
466 .flags = .{
467 .filters_len = c.filters.len != 0,
468 .exec_cmd_args_len = exec_cmd_args.len != 0,
469 .installed_headers_len = installed_headers.len != 0,
470 .force_undefined_symbols_len = c.force_undefined_symbols.entries.len != 0,
471
472 .verbose_link = c.verbose_link,
473 .verbose_cc = c.verbose_cc,
474 .rdynamic = c.rdynamic,
475 .import_memory = c.import_memory,
476 .export_memory = c.export_memory,
477 .import_symbols = c.import_symbols,
478 .import_table = c.import_table,
479 .export_table = c.export_table,
480 .shared_memory = c.shared_memory,
481 .link_eh_frame_hdr = c.link_eh_frame_hdr,
482 .link_emit_relocs = c.link_emit_relocs,
483 .link_function_sections = c.link_function_sections,
484 .link_data_sections = c.link_data_sections,
485 .linker_dynamicbase = c.linker_dynamicbase,
486 .link_z_notext = c.link_z_notext,
487 .link_z_relro = c.link_z_relro,
488 .link_z_lazy = c.link_z_lazy,
489 .link_z_defs = c.link_z_defs,
490 .headerpad_max_install_names = c.headerpad_max_install_names,
491 .dead_strip_dylibs = c.dead_strip_dylibs,
492 .force_load_objc = c.force_load_objc,
493 .discard_local_symbols = c.discard_local_symbols,
494 .mingw_unicode_entry_point = c.mingw_unicode_entry_point,
495 },
496 .flags2 = .{
497 .pie = .init(c.pie),
498 .formatted_panics = .init(c.formatted_panics),
499 .bundle_compiler_rt = .init(c.bundle_compiler_rt),
500 .bundle_ubsan_rt = .init(c.bundle_ubsan_rt),
501 .each_lib_rpath = .init(c.each_lib_rpath),
502 .link_gc_sections = .init(c.link_gc_sections),
503 .linker_allow_shlib_undefined = .init(c.linker_allow_shlib_undefined),
504 .linker_allow_undefined_version = .init(c.linker_allow_undefined_version),
505 .linker_enable_new_dtags = .init(c.linker_enable_new_dtags),
506 .dll_export_fns = .init(c.dll_export_fns),
507 .use_llvm = .init(c.use_llvm),
508 .use_lld = .init(c.use_lld),
509 .use_new_linker = .init(c.use_new_linker),
510 .allow_so_scripts = .init(c.allow_so_scripts),
511 .sanitize_coverage_trace_pc_guard = .init(c.sanitize_coverage_trace_pc_guard),
512 .linkage = .init(c.linkage),
513 },
514 .flags3 = .{
515 .is_linking_libc = c.is_linking_libc,
516 .is_linking_libcpp = c.is_linking_libcpp,
517 .version = c.version != null,
518 .compress_debug_sections = c.compress_debug_sections,
519 .initial_memory = c.initial_memory != null,
520 .max_memory = c.max_memory != null,
521 .kind = c.kind,
522 .global_base = c.global_base != null,
523 .test_runner_mode = if (c.test_runner) |tr| switch (tr.mode) {
524 .simple => .simple,
525 .server => .server,
526 } else .default,
527 .wasi_exec_model = .init(c.wasi_exec_model),
528 .win32_manifest = c.win32_manifest != null,
529 .win32_module_definition = c.win32_module_definition != null,
530 .zig_lib_dir = c.zig_lib_dir != null,
531 .rc_includes = c.rc_includes,
532 .image_base = c.image_base != null,
533 .build_id = .init(c.build_id),
534 .entry = switch (c.entry) {
535 .default => .default,
536 .disabled => .disabled,
537 .enabled => .enabled,
538 .symbol_name => .symbol_name,
539 },
540 .lto = .init(c.lto),
541 .subsystem = .init(c.subsystem),
542 },
543 .flags4 = .{
544 .libc_file = c.libc_file != null,
545 .link_z_common_page_size = c.link_z_common_page_size != null,
546 .link_z_max_page_size = c.link_z_max_page_size != null,
547 .pagezero_size = c.pagezero_size != null,
548 .stack_size = c.stack_size != null,
549 .headerpad_size = c.headerpad_size != null,
550 .error_limit = c.error_limit != null,
551 .install_name = c.install_name != null,
552 .entitlements = c.entitlements != null,
553 .expect_errors = if (c.expect_errors) |x| switch (x) {
554 .contains => .contains,
555 .exact => .exact,
556 .starts_with => .starts_with,
557 .stderr_contains => .stderr_contains,
558 } else .none,
559 .linker_script = c.linker_script != null,
560 .version_script = c.version_script != null,
561 },
562 .root_module = try s.addModule(c.root_module),
563 .root_name = try wc.addString(c.name),
564 .linker_script = .{ .value = try s.addOptionalLazyPath(c.linker_script) },
565 .version_script = .{ .value = try s.addOptionalLazyPath(c.version_script) },
566 .zig_lib_dir = .{ .value = try s.addOptionalLazyPath(c.zig_lib_dir) },
567 .libc_file = .{ .value = try s.addOptionalLazyPath(c.libc_file) },
568 .win32_manifest = .{ .value = try s.addOptionalLazyPath(c.win32_manifest) },
569 .win32_module_definition = .{ .value = try s.addOptionalLazyPath(c.win32_module_definition) },
570 .entitlements = .{ .value = try s.addOptionalLazyPath(c.entitlements) },
571 .version = .{ .value = try s.addOptionalSemVer(c.version) },
572 .install_name = .{ .value = try s.addOptionalString(c.install_name) },
573 .initial_memory = .{ .value = c.initial_memory },
574 .max_memory = .{ .value = c.max_memory },
575 .global_base = .{ .value = c.global_base },
576 .image_base = .{ .value = c.image_base },
577 .link_z_common_page_size = .{ .value = c.link_z_common_page_size },
578 .link_z_max_page_size = .{ .value = c.link_z_max_page_size },
579 .pagezero_size = .{ .value = c.pagezero_size },
580 .stack_size = .{ .value = c.stack_size },
581 .headerpad_size = .{ .value = c.headerpad_size },
582 .error_limit = .{ .value = c.error_limit },
583 .entry = .{ .value = switch (c.entry) {
584 .symbol_name => |name| try wc.addString(name),
585 .default, .disabled, .enabled => null,
586 } },
587 .build_id = .{ .value = if (c.build_id) |id| switch (id) {
588 .hexstring => |*hexstring| try wc.addString(hexstring.toSlice()),
589 .none, .fast, .uuid, .sha1, .md5 => null,
590 } else null },
591 .filters = .{ .slice = try s.initStringList(c.filters) },
592 .exec_cmd_args = .{ .slice = try s.initOptionalStringList(exec_cmd_args) },
593 .installed_headers = .initErased(installed_headers),
594 .force_undefined_symbols = .{ .slice = try s.initStringList(c.force_undefined_symbols.keys()) },
595 }));
596
597 log.err("TODO serialize the trailing Compile step data", .{});
598
599 break :e @enumFromInt(extra_index);
600 },
601 .install_artifact => e: {
602 const ia: *Step.InstallArtifact = @fieldParentPtr("step", step);
603 break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.InstallArtifact, .{
604 .flags = .{
605 .dylib_symlinks = ia.dylib_symlinks != null,
606 },
607 .dest_dir = try addInstallDir(wc, ia.dest_dir),
608 .dest_sub_path = try wc.addString(ia.dest_sub_path),
609 .emitted_bin = try s.addOptionalLazyPathEnum(ia.emitted_bin),
610 .implib_dir = try addInstallDir(wc, ia.implib_dir),
611 .emitted_implib = try s.addOptionalLazyPathEnum(ia.emitted_implib),
612 .pdb_dir = try addInstallDir(wc, ia.pdb_dir),
613 .emitted_pdb = try s.addOptionalLazyPathEnum(ia.emitted_pdb),
614 .h_dir = try addInstallDir(wc, ia.h_dir),
615 .emitted_h = try s.addOptionalLazyPathEnum(ia.emitted_h),
616 .artifact = stepIndex(&step_map, &ia.artifact.step),
617 })));
618 },
619 .install_file => @panic("TODO"),
620 .install_dir => @panic("TODO"),
621 .remove_dir => @panic("TODO"),
622 .fail => @panic("TODO"),
623 .fmt => @panic("TODO"),
624 .translate_c => @panic("TODO"),
625 .write_file => @panic("TODO"),
626 .update_source_files => @panic("TODO"),
627 .run => e: {
628 const run: *Step.Run = @fieldParentPtr("step", step);
629
630 const captured_stdout: Configuration.OptionalString = if (run.captured_stdout) |cs|
631 .init(try wc.addString(cs.output.basename))
632 else
633 .none;
634
635 const captured_stderr: Configuration.OptionalString = if (run.captured_stderr) |cs|
636 .init(try wc.addString(cs.output.basename))
637 else
638 .none;
639
640 const extra_index = try wc.addExtra(@as(Configuration.Step.Run, .{
641 .flags = .{
642 .disable_zig_progress = run.disable_zig_progress,
643 .skip_foreign_checks = run.skip_foreign_checks,
644 .failing_to_execute_foreign_is_an_error = run.failing_to_execute_foreign_is_an_error,
645 .has_side_effects = run.has_side_effects,
646 .test_runner_mode = run.test_runner_mode,
647 .color = run.color,
648 .stdio = switch (run.stdio) {
649 .infer_from_args => .infer_from_args,
650 .inherit => .inherit,
651 .check => .check,
652 .zig_test => .zig_test,
653 },
654 .stdin = switch (run.stdin) {
655 .none => .none,
656 .bytes => .bytes,
657 .lazy_path => .lazy_path,
658 },
659 .stdout_trim_whitespace = if (run.captured_stdout) |cs| cs.trim_whitespace else .none,
660 .stderr_trim_whitespace = if (run.captured_stderr) |cs| cs.trim_whitespace else .none,
661 .stdio_limit = run.stdio_limit != .unlimited,
662 .producer = run.producer != null,
663 },
664 .file_inputs_len = @intCast(run.file_inputs.items.len),
665 .args_len = @intCast(run.argv.items.len),
666 .cwd = try s.addOptionalLazyPathEnum(run.cwd),
667 .captured_stdout = captured_stdout,
668 .captured_stderr = captured_stderr,
669 }));
670
671 log.err("TODO serialize the trailing Run step data", .{});
672
673 break :e @enumFromInt(extra_index);
674 },
675 .check_file => @panic("TODO"),
676 .check_object => @panic("TODO"),
677 .config_header => @panic("TODO"),
678 .objcopy => @panic("TODO"),
679 .options => @panic("TODO"),
680 },
681 });
682 }
683 }
684
685 try wc.unlazy_deps.ensureUnusedCapacity(gpa, graph.needed_lazy_dependencies.keys().len);
686 for (graph.needed_lazy_dependencies.keys()) |k| {
687 wc.unlazy_deps.appendAssumeCapacity(try wc.addString(k));
688 }
689
690 try wc.write(writer, .{
691 .default_step = stepIndex(&step_map, b.default_step),
692 });
693}
694
695fn addOptionalResolvedTarget(
696 wc: *Configuration.Wip,
697 optional_resolved_target: ?std.Build.ResolvedTarget,
698) !Configuration.ResolvedTarget.OptionalIndex {
699 const resolved_target = optional_resolved_target orelse return .none;
700 log.debug("TODO deduplicate resolved targets", .{});
701 return @enumFromInt(try wc.addExtra(@as(Configuration.ResolvedTarget, .{
702 .query = try wc.addTargetQuery(resolved_target.query),
703 .result = try wc.addTarget(resolved_target.result),
704 })));
705}
706
707fn addInstallDir(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !Configuration.InstallDestDir {
708 switch (install_dir orelse return .none) {
709 .prefix => return .prefix,
710 .lib => return .lib,
711 .bin => return .bin,
712 .header => return .header,
713 .custom => |sub_path| return .initCustom(try wc.addString(sub_path)),
714 }
715}
716
717fn stepIndex(step_map: *const std.AutoArrayHashMapUnmanaged(*Step, void), step: *Step) Configuration.Step.Index {
718 return @enumFromInt(step_map.getIndex(step).?);
719}
720
721/// If the given `Step` is a `Step.Compile`, adds any dependencies for that step which
722/// are implied by the module graph rooted at `step.cast(Step.Compile).?.root_module`.
723fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void {
724 const root_module = if (step.cast(Step.Compile)) |cs| root: {
725 break :root cs.root_module;
726 } else return; // not a compile step so no module dependencies
727
728 // Starting from `root_module`, discover all modules in this graph.
729 const modules = root_module.getGraph().modules;
730
731 // For each of those modules, set up the implied step dependencies.
732 for (modules) |mod| {
733 if (mod.root_source_file) |lp| lp.addStepDependencies(step);
734 for (mod.include_dirs.items) |include_dir| switch (include_dir) {
735 .path,
736 .path_system,
737 .path_after,
738 .framework_path,
739 .framework_path_system,
740 .embed_path,
741 => |lp| lp.addStepDependencies(step),
742
743 .other_step => |other| {
744 other.getEmittedIncludeTree().addStepDependencies(step);
745 step.dependOn(&other.step);
746 },
747
748 .config_header_step => |other| step.dependOn(&other.step),
749 };
750 for (mod.lib_paths.items) |lp| lp.addStepDependencies(step);
751 for (mod.rpaths.items) |rpath| switch (rpath) {
752 .lazy_path => |lp| lp.addStepDependencies(step),
753 .special => {},
754 };
755 for (mod.link_objects.items) |link_object| switch (link_object) {
756 .static_path,
757 .assembly_file,
758 => |lp| lp.addStepDependencies(step),
759 .other_step => |other| step.dependOn(&other.step),
760 .system_lib => {},
761 .c_source_file => |source| source.file.addStepDependencies(step),
762 .c_source_files => |source_files| source_files.root.addStepDependencies(step),
763 .win32_resource_file => |rc_source| {
764 rc_source.file.addStepDependencies(step);
765 for (rc_source.include_paths) |lp| lp.addStepDependencies(step);
766 },
767 };
768 }
769}
770
771fn nextArg(args: []const [:0]const u8, idx: *usize) ?[:0]const u8 {
772 if (idx.* >= args.len) return null;
773 defer idx.* += 1;
774 return args[idx.*];
775}
776
777fn nextArgOrFatal(args: []const [:0]const u8, idx: *usize) [:0]const u8 {
778 return nextArg(args, idx) orelse {
779 fatalWithHint("expected argument after: {s}", .{args[idx.* - 1]});
780 };
781}
782
783fn expectArgOrFatal(args: []const [:0]const u8, index_ptr: *usize, first: []const u8) []const u8 {
784 const next_arg = nextArg(args, index_ptr) orelse fatal("missing {q} argument", .{first});
785 if (!mem.eql(u8, first, next_arg)) fatal("expected {q} instead of {q}", .{ first, next_arg });
786 const arg = nextArg(args, index_ptr) orelse fatal("expected argument after {q}", .{first});
787 return arg;
788}
789
790const ErrorStyle = enum {
791 verbose,
792 minimal,
793 verbose_clear,
794 minimal_clear,
795 fn verboseContext(s: ErrorStyle) bool {
796 return switch (s) {
797 .verbose, .verbose_clear => true,
798 .minimal, .minimal_clear => false,
799 };
800 }
801 fn clearOnUpdate(s: ErrorStyle) bool {
802 return switch (s) {
803 .verbose, .minimal => false,
804 .verbose_clear, .minimal_clear => true,
805 };
806 }
807};
808const MultilineErrors = enum { indent, newline, none };
809const Summary = enum { all, new, failures, line, none };
810
811fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn {
812 log.info("to access the help menu: zig build -h", .{});
813 fatal(f, args);
814}
815
816fn serializeSystemIntegrationOptions(graph: *std.Build.Graph, wc: *Configuration.Wip) Allocator.Error!void {
817 const gpa = wc.gpa;
818
819 var bad = false;
820 try wc.system_integrations.ensureTotalCapacityPrecise(gpa, graph.system_integration_options.entries.len);
821 for (graph.system_integration_options.keys(), graph.system_integration_options.values()) |k, v| {
822 wc.system_integrations.appendAssumeCapacity(.{
823 .name = try wc.addString(k),
824 .status = switch (v) {
825 .user_disabled, .user_enabled => x: {
826 // The user tried to enable or disable a system library integration, but
827 // the configure script did not recognize that option.
828 log.err("system integration name not recognized by configure script: {s}", .{k});
829 bad = true;
830 break :x .disabled;
831 },
832 .declared_disabled => .disabled,
833 .declared_enabled => .enabled,
834 },
835 });
836 }
837 if (bad) {
838 log.info("help menu contains available options: zig build -h", .{});
839 process.exit(1);
840 }
841}
lib/compiler/configurer.zig created+841
......@@ -0,0 +1,841 @@
1const builtin = @import("builtin");
2
3const std = @import("std");
4const Allocator = std.mem.Allocator;
5const Color = std.zig.Color;
6const Configuration = std.Build.Configuration;
7const File = std.Io.File;
8const Io = std.Io;
9const Step = std.Build.Step;
10const Writer = std.Io.Writer;
11const assert = std.debug.assert;
12const fatal = std.process.fatal;
13const fmt = std.fmt;
14const log = std.log;
15const mem = std.mem;
16const process = std.process;
17
18pub const root = @import("@build");
19pub const dependencies = @import("@dependencies");
20
21pub const std_options: std.Options = .{
22 .side_channels_mitigations = .none,
23 .http_disable_tls = true,
24};
25
26pub fn main(init: process.Init.Minimal) !void {
27 // The build runner is often short-lived, but thanks to `--watch` and `--webui`, that's not
28 // always the case. So, we do need a true gpa for some things.
29 var debug_gpa_state: std.heap.DebugAllocator(.{
30 // We'd rather have `zig build` run faster than catch harmless leaks in
31 // the user's build.zig script.
32 .stack_trace_frames = 0,
33 }) = .init;
34 defer _ = debug_gpa_state.deinit();
35 const gpa = debug_gpa_state.allocator();
36
37 var threaded: std.Io.Threaded = .init(gpa, .{
38 .environ = init.environ,
39 .argv0 = .init(init.args),
40 });
41 defer threaded.deinit();
42 const io = threaded.io();
43
44 // ...but we'll back our arena by `std.heap.page_allocator` for efficiency.
45 var arena_allocator: std.heap.ArenaAllocator = .init(std.heap.page_allocator);
46 defer arena_allocator.deinit();
47 const arena = arena_allocator.allocator();
48
49 const args = try init.args.toSlice(arena);
50
51 // skip my own exe name
52 var arg_idx: usize = 1;
53
54 const zig_exe = expectArgOrFatal(args, &arg_idx, "--zig");
55 const zig_lib_dir = expectArgOrFatal(args, &arg_idx, "--zig-lib-dir");
56 const build_root = expectArgOrFatal(args, &arg_idx, "--build-root");
57 const local_cache_root = expectArgOrFatal(args, &arg_idx, "--local-cache");
58 const global_cache_root = expectArgOrFatal(args, &arg_idx, "--global-cache");
59
60 const cwd: Io.Dir = .cwd();
61
62 const zig_lib_directory: std.Build.Cache.Directory = .{
63 .path = zig_lib_dir,
64 .handle = try cwd.openDir(io, zig_lib_dir, .{}),
65 };
66
67 const build_root_directory: std.Build.Cache.Directory = .{
68 .path = build_root,
69 .handle = try cwd.openDir(io, build_root, .{}),
70 };
71
72 const local_cache_directory: std.Build.Cache.Directory = .{
73 .path = local_cache_root,
74 .handle = try cwd.createDirPathOpen(io, local_cache_root, .{}),
75 };
76
77 const global_cache_directory: std.Build.Cache.Directory = .{
78 .path = global_cache_root,
79 .handle = try cwd.createDirPathOpen(io, global_cache_root, .{}),
80 };
81
82 var graph: std.Build.Graph = .{
83 .io = io,
84 .arena = arena,
85 .cache = .{
86 .io = io,
87 .gpa = gpa,
88 .manifest_dir = try local_cache_directory.handle.createDirPathOpen(io, "h", .{}),
89 .cwd = try process.currentPathAlloc(io, arena),
90 },
91 .zig_exe = zig_exe,
92 .environ_map = try init.environ.createMap(arena),
93 .global_cache_root = global_cache_directory,
94 .zig_lib_directory = zig_lib_directory,
95 .host = .{
96 .query = .{},
97 .result = try std.zig.system.resolveTargetQuery(io, .{}),
98 },
99 };
100
101 graph.cache.addPrefix(.{ .path = null, .handle = cwd });
102 graph.cache.addPrefix(build_root_directory);
103 graph.cache.addPrefix(local_cache_directory);
104 graph.cache.addPrefix(global_cache_directory);
105 graph.cache.hash.addBytes(builtin.zig_version_string);
106
107 const builder = try std.Build.create(
108 &graph,
109 build_root_directory,
110 local_cache_directory,
111 dependencies.root_deps,
112 );
113
114 var error_style: ErrorStyle = .verbose;
115 var multiline_errors: MultilineErrors = .indent;
116 var color: Color = .auto;
117
118 if (std.zig.EnvVar.ZIG_BUILD_ERROR_STYLE.get(&graph.environ_map)) |str| {
119 if (std.meta.stringToEnum(ErrorStyle, str)) |style| {
120 error_style = style;
121 }
122 }
123
124 if (std.zig.EnvVar.ZIG_BUILD_MULTILINE_ERRORS.get(&graph.environ_map)) |str| {
125 if (std.meta.stringToEnum(MultilineErrors, str)) |style| {
126 multiline_errors = style;
127 }
128 }
129
130 while (nextArg(args, &arg_idx)) |arg| {
131 if (mem.cutPrefix(u8, arg, "-D")) |option_contents| {
132 if (option_contents.len == 0)
133 fatalWithHint("expected option name after '-D'", .{});
134 if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {
135 const option_name = option_contents[0..name_end];
136 const option_value = option_contents[name_end + 1 ..];
137 if (try builder.addUserInputOption(option_name, option_value))
138 fatal(" access the help menu with 'zig build -h'", .{});
139 } else {
140 if (try builder.addUserInputFlag(option_contents))
141 fatal(" access the help menu with 'zig build -h'", .{});
142 }
143 } else if (mem.cutPrefix(u8, arg, "-fsys=")) |name| {
144 try graph.system_integration_options.put(arena, name, .user_enabled);
145 } else if (mem.cutPrefix(u8, arg, "-fno-sys=")) |name| {
146 try graph.system_integration_options.put(arena, name, .user_disabled);
147 } else if (mem.eql(u8, arg, "--release")) {
148 graph.release_mode = .any;
149 } else if (mem.cutPrefix(u8, arg, "--release=")) |text| {
150 graph.release_mode = std.meta.stringToEnum(std.Build.ReleaseMode, text) orelse {
151 fatalWithHint("expected [off|any|fast|safe|small] in {q}, found {q}", .{
152 arg, text,
153 });
154 };
155 } else if (mem.eql(u8, arg, "--color")) {
156 const next_arg = nextArg(args, &arg_idx) orelse
157 fatalWithHint("expected [auto|on|off] after {q}", .{arg});
158 color = std.meta.stringToEnum(Color, next_arg) orelse {
159 fatalWithHint("expected [auto|on|off] after {q}, found {q}", .{
160 arg, next_arg,
161 });
162 };
163 } else if (mem.eql(u8, arg, "--error-style")) {
164 const next_arg = nextArg(args, &arg_idx) orelse
165 fatalWithHint("expected style after {q}", .{arg});
166 error_style = std.meta.stringToEnum(ErrorStyle, next_arg) orelse {
167 fatalWithHint("expected style after {q}, found {q}", .{ arg, next_arg });
168 };
169 } else if (mem.eql(u8, arg, "--multiline-errors")) {
170 const next_arg = nextArg(args, &arg_idx) orelse
171 fatalWithHint("expected style after {q}", .{arg});
172 multiline_errors = std.meta.stringToEnum(MultilineErrors, next_arg) orelse {
173 fatalWithHint("expected style after {q}, found {q}", .{ arg, next_arg });
174 };
175 } else if (mem.eql(u8, arg, "--system")) {
176 // The usage text shows another argument after this parameter
177 // but it is handled by the parent process. The build runner
178 // only sees this flag.
179 graph.system_package_mode = true;
180 } else if (mem.eql(u8, arg, "--have-run-args")) {
181 graph.have_run_args = true;
182 } else {
183 fatalWithHint("unrecognized argument: {q}", .{arg});
184 }
185 }
186
187 const NO_COLOR = std.zig.EnvVar.NO_COLOR.isSet(&graph.environ_map);
188 const CLICOLOR_FORCE = std.zig.EnvVar.CLICOLOR_FORCE.isSet(&graph.environ_map);
189
190 graph.stderr_mode = switch (color) {
191 .auto => try .detect(io, .stderr(), NO_COLOR, CLICOLOR_FORCE),
192 .on => .escape_codes,
193 .off => .no_color,
194 };
195
196 try builder.runBuild(root);
197
198 if (builder.validateUserInputDidItFail()) {
199 fatal(" access the help menu with 'zig build -h'", .{});
200 }
201
202 var wc: Configuration.Wip = .init(gpa);
203 defer wc.deinit();
204 assert(try wc.addString("") == .empty);
205
206 try serializeSystemIntegrationOptions(&graph, &wc);
207
208 var stdout_buffer: [1024]u8 = undefined;
209 var file_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer);
210 serialize(builder, &wc, &file_writer.interface) catch |err| switch (err) {
211 error.WriteFailed => fatal("failed to write configuration output: {t}", .{file_writer.err.?}),
212 error.OutOfMemory => |e| return e,
213 };
214
215 // This executable is short-lived and run in Debug mode, so we'd rather
216 // have `zig build` run faster than catch resource leaks in the user's
217 // build.zig script (or, frankly, this configure runner), therefore we call
218 // exit directly here rather than cleanExit.
219 process.exit(0);
220}
221
222const Serialize = struct {
223 arena: Allocator,
224 wc: *Configuration.Wip,
225 module_map: std.AutoArrayHashMapUnmanaged(*std.Build.Module, Configuration.Module.Index) = .empty,
226 package_map: std.AutoArrayHashMapUnmanaged(*std.Build, Configuration.Package.Index) = .empty,
227
228 fn builderToPackage(s: *Serialize, b: *std.Build) !Configuration.Package.Index {
229 if (b.pkg_hash.len == 0) return .root;
230 const arena = s.arena;
231 const wc = s.wc;
232 const gop = try s.package_map.getOrPut(arena, b);
233 if (!gop.found_existing) {
234 gop.value_ptr.* = @enumFromInt(try wc.addExtra(@as(Configuration.Package, .{
235 .hash = try wc.addString(b.pkg_hash),
236 .dep_prefix = try wc.addString(b.dep_prefix),
237 })));
238 }
239 return gop.value_ptr.*;
240 }
241
242 fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.OptionalLazyPath {
243 const wc = s.wc;
244 return @enumFromInt(switch (lp orelse return .none) {
245 .src_path => |src_path| i: {
246 const sub_path = try wc.addString(src_path.sub_path);
247 break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{
248 .flags = .{},
249 .owner = try s.builderToPackage(src_path.owner),
250 .sub_path = sub_path,
251 }));
252 },
253 .generated => |generated| i: {
254 const sub_path = try wc.addString(generated.sub_path);
255 break :i try wc.addExtra(@as(Configuration.LazyPath.Generated, .{
256 .flags = .{ .up = @intCast(generated.up) },
257 .sub_path = sub_path,
258 }));
259 },
260 .cwd_relative => |cwd_relative_sub_path| i: {
261 const sub_path = try wc.addString(cwd_relative_sub_path);
262 break :i try wc.addExtra(@as(Configuration.LazyPath.Relative, .{
263 .flags = .{ .base = .cwd },
264 .sub_path = sub_path,
265 }));
266 },
267 .dependency => |dependency| i: {
268 const sub_path = try wc.addString(dependency.sub_path);
269 break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{
270 .flags = .{},
271 .owner = try s.builderToPackage(dependency.dependency.builder),
272 .sub_path = sub_path,
273 }));
274 },
275 });
276 }
277
278 fn addOptionalLazyPath(s: *Serialize, lp: ?std.Build.LazyPath) !?Configuration.LazyPath {
279 return (try addOptionalLazyPathEnum(s, lp)).unwrap();
280 }
281
282 fn addLazyPath(s: *Serialize, lp: std.Build.LazyPath) !Configuration.LazyPath {
283 return @enumFromInt(@intFromEnum(try addOptionalLazyPathEnum(s, lp)));
284 }
285
286 fn addOptionalSemVer(s: *Serialize, sem_ver: ?std.SemanticVersion) !?Configuration.String {
287 return if (sem_ver) |sv| try s.wc.addSemVer(sv) else null;
288 }
289
290 fn addOptionalString(s: *Serialize, opt_slice: ?[]const u8) !?Configuration.String {
291 return if (opt_slice) |slice| try s.wc.addString(slice) else null;
292 }
293
294 fn initStringList(s: *Serialize, list: []const []const u8) ![]const Configuration.String {
295 const wc = s.wc;
296 const result = try s.arena.alloc(Configuration.String, list.len);
297 for (result, list) |*dest, src| dest.* = try wc.addString(src);
298 return result;
299 }
300
301 fn initOptionalStringList(s: *Serialize, list: []const ?[]const u8) ![]const Configuration.OptionalString {
302 const wc = s.wc;
303 const result = try s.arena.alloc(Configuration.OptionalString, list.len);
304 for (result, list) |*dest, src| dest.* = try wc.addOptionalString(src);
305 return result;
306 }
307
308 fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
309 if (s.module_map.get(m)) |index| return index;
310
311 const wc = s.wc;
312 const arena = s.arena;
313 const gpa = wc.gpa;
314
315 const lib_paths = try arena.alloc(Configuration.LazyPath, m.lib_paths.items.len);
316 for (lib_paths, m.lib_paths.items) |*dest, src| dest.* = try addLazyPath(s, src);
317
318 const c_macros = try initStringList(s, m.c_macros.items);
319 const export_symbol_names = try initStringList(s, m.export_symbol_names);
320
321 const import_table: Configuration.ImportTable = @enumFromInt(wc.extra.items.len);
322 const import_table_extra_len = 1 + 2 * m.import_table.entries.len;
323 try wc.extra.ensureUnusedCapacity(gpa, import_table_extra_len);
324 wc.extra.items.len += import_table_extra_len;
325 wc.extra.appendAssumeCapacity(@intCast(m.import_table.entries.len));
326 wc.extra.items[@intFromEnum(import_table)] = @intCast(m.import_table.entries.len);
327 for (
328 m.import_table.keys(),
329 @intFromEnum(import_table) + 1..,
330 ) |mod_name, extra_index| {
331 wc.extra.items[extra_index] = @intFromEnum(try wc.addString(mod_name));
332 }
333 for (
334 m.import_table.values(),
335 @intFromEnum(import_table) + 1 + m.import_table.entries.len..,
336 ) |dep, extra_index| {
337 log.err("TODO module dependencies can be cyclic", .{});
338 wc.extra.items[extra_index] = @intFromEnum(try addModule(s, dep));
339 }
340
341 const module_index: Configuration.Module.Index = @enumFromInt(try wc.addExtra(@as(Configuration.Module, .{
342 .flags = .{
343 .optimize = .init(m.optimize),
344 .strip = .init(m.strip),
345 .unwind_tables = .init(m.unwind_tables),
346 .dwarf_format = .init(m.dwarf_format),
347 .single_threaded = .init(m.strip),
348 .stack_protector = .init(m.strip),
349 .stack_check = .init(m.strip),
350 .sanitize_c = .init(m.sanitize_c),
351 .sanitize_thread = .init(m.strip),
352 .fuzz = .init(m.strip),
353 .code_model = m.code_model,
354 .c_macros = c_macros.len != 0,
355 .include_dirs = m.include_dirs.items.len != 0,
356 .lib_paths = lib_paths.len != 0,
357 .rpaths = m.rpaths.items.len != 0,
358 .frameworks = m.frameworks.entries.len != 0,
359 .link_objects = m.link_objects.items.len != 0,
360 .export_symbol_names = export_symbol_names.len != 0,
361 },
362 .flags2 = .{
363 .valgrind = .init(m.strip),
364 .pic = .init(m.strip),
365 .red_zone = .init(m.strip),
366 .omit_frame_pointer = .init(m.strip),
367 .error_tracing = .init(m.strip),
368 .link_libc = .init(m.strip),
369 .link_libcpp = .init(m.strip),
370 .no_builtin = .init(m.strip),
371 },
372 .owner = try s.builderToPackage(m.owner),
373 .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),
374 .import_table = import_table,
375 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),
376 .c_macros = .{ .slice = c_macros },
377 .lib_paths = .{ .slice = lib_paths },
378 .export_symbol_names = .{ .slice = export_symbol_names },
379 })));
380
381 log.err("TODO serialize the trailing Module data", .{});
382
383 try s.module_map.putNoClobber(arena, m, module_index);
384
385 return module_index;
386 }
387};
388
389fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
390 const graph = b.graph;
391 const arena = graph.arena;
392 const gpa = wc.gpa;
393
394 var s: Serialize = .{ .wc = wc, .arena = arena };
395
396 // Starting from all top-level steps in `b`, traverse the entire step graph
397 // and add all step dependencies implied by module graphs.
398 const top_level_steps = b.top_level_steps.values();
399 // Index corresponds to `Configuration.steps` index.
400 var step_map: std.AutoArrayHashMapUnmanaged(*Step, void) = .empty;
401 try step_map.ensureUnusedCapacity(arena, top_level_steps.len);
402 for (top_level_steps) |tls| {
403 step_map.putAssumeCapacityNoClobber(&tls.step, {});
404 }
405 {
406 while (wc.steps.items.len < step_map.count()) {
407 const step = step_map.keys()[wc.steps.items.len];
408
409 // Set up any implied dependencies for this step. It's important that we do this first, so
410 // that the loop below discovers steps implied by the module graph.
411 try createModuleDependenciesForStep(step);
412
413 try step_map.ensureUnusedCapacity(arena, step.dependencies.items.len);
414 for (step.dependencies.items) |other_step| {
415 step_map.putAssumeCapacity(other_step, {});
416 }
417
418 // Add and then de-duplicate dependencies.
419 const deps = d: {
420 const deps: Configuration.Deps = @enumFromInt(wc.extra.items.len);
421 for (try wc.reserveLengthPrefixed(step.dependencies.items.len), step.dependencies.items) |*dep, dep_step|
422 dep.* = @intCast(step_map.getIndex(dep_step).?);
423 break :d try wc.dedupeDeps(deps);
424 };
425
426 try wc.steps.ensureTotalCapacity(gpa, step_map.entries.capacity);
427 wc.steps.appendAssumeCapacity(.{
428 .name = try wc.addString(step.name),
429 .owner = try s.builderToPackage(step.owner),
430 .deps = deps,
431 .max_rss = .fromBytes(step.max_rss),
432 .extended = switch (step.tag) {
433 .top_level => e: {
434 const top_level: *Step.TopLevel = @fieldParentPtr("step", step);
435 break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.TopLevel, .{
436 .description = try wc.addString(top_level.description),
437 })));
438 },
439 .compile => e: {
440 const c: *Step.Compile = @fieldParentPtr("step", step);
441 const exec_cmd_args: []const ?[]const u8 = c.exec_cmd_args orelse &.{};
442 const installed_headers: []u32 = try arena.alloc(u32, c.installed_headers.items.len);
443 for (installed_headers, c.installed_headers.items) |*dst, src| switch (src) {
444 .file => |file| {
445 dst.* = try wc.addExtra(@as(Configuration.Step.Compile.InstalledHeader.File, .{
446 .source = try s.addLazyPath(file.source),
447 .dest_sub_path = try wc.addString(file.dest_rel_path),
448 }));
449 },
450 .directory => |directory| {
451 const include_extensions = directory.options.include_extensions orelse &.{};
452 dst.* = try wc.addExtra(@as(Configuration.Step.Compile.InstalledHeader.Directory, .{
453 .flags = .{
454 .include_extensions = include_extensions.len != 0,
455 .exclude_extensions = directory.options.exclude_extensions.len != 0,
456 },
457 .source = try s.addLazyPath(directory.source),
458 .dest_sub_path = try wc.addString(directory.dest_rel_path),
459 .exclude_extensions = .{ .slice = try s.initStringList(directory.options.exclude_extensions) },
460 .include_extensions = .{ .slice = try s.initStringList(include_extensions) },
461 }));
462 },
463 };
464
465 const extra_index = try wc.addExtra(@as(Configuration.Step.Compile, .{
466 .flags = .{
467 .filters_len = c.filters.len != 0,
468 .exec_cmd_args_len = exec_cmd_args.len != 0,
469 .installed_headers_len = installed_headers.len != 0,
470 .force_undefined_symbols_len = c.force_undefined_symbols.entries.len != 0,
471
472 .verbose_link = c.verbose_link,
473 .verbose_cc = c.verbose_cc,
474 .rdynamic = c.rdynamic,
475 .import_memory = c.import_memory,
476 .export_memory = c.export_memory,
477 .import_symbols = c.import_symbols,
478 .import_table = c.import_table,
479 .export_table = c.export_table,
480 .shared_memory = c.shared_memory,
481 .link_eh_frame_hdr = c.link_eh_frame_hdr,
482 .link_emit_relocs = c.link_emit_relocs,
483 .link_function_sections = c.link_function_sections,
484 .link_data_sections = c.link_data_sections,
485 .linker_dynamicbase = c.linker_dynamicbase,
486 .link_z_notext = c.link_z_notext,
487 .link_z_relro = c.link_z_relro,
488 .link_z_lazy = c.link_z_lazy,
489 .link_z_defs = c.link_z_defs,
490 .headerpad_max_install_names = c.headerpad_max_install_names,
491 .dead_strip_dylibs = c.dead_strip_dylibs,
492 .force_load_objc = c.force_load_objc,
493 .discard_local_symbols = c.discard_local_symbols,
494 .mingw_unicode_entry_point = c.mingw_unicode_entry_point,
495 },
496 .flags2 = .{
497 .pie = .init(c.pie),
498 .formatted_panics = .init(c.formatted_panics),
499 .bundle_compiler_rt = .init(c.bundle_compiler_rt),
500 .bundle_ubsan_rt = .init(c.bundle_ubsan_rt),
501 .each_lib_rpath = .init(c.each_lib_rpath),
502 .link_gc_sections = .init(c.link_gc_sections),
503 .linker_allow_shlib_undefined = .init(c.linker_allow_shlib_undefined),
504 .linker_allow_undefined_version = .init(c.linker_allow_undefined_version),
505 .linker_enable_new_dtags = .init(c.linker_enable_new_dtags),
506 .dll_export_fns = .init(c.dll_export_fns),
507 .use_llvm = .init(c.use_llvm),
508 .use_lld = .init(c.use_lld),
509 .use_new_linker = .init(c.use_new_linker),
510 .allow_so_scripts = .init(c.allow_so_scripts),
511 .sanitize_coverage_trace_pc_guard = .init(c.sanitize_coverage_trace_pc_guard),
512 .linkage = .init(c.linkage),
513 },
514 .flags3 = .{
515 .is_linking_libc = c.is_linking_libc,
516 .is_linking_libcpp = c.is_linking_libcpp,
517 .version = c.version != null,
518 .compress_debug_sections = c.compress_debug_sections,
519 .initial_memory = c.initial_memory != null,
520 .max_memory = c.max_memory != null,
521 .kind = c.kind,
522 .global_base = c.global_base != null,
523 .test_runner_mode = if (c.test_runner) |tr| switch (tr.mode) {
524 .simple => .simple,
525 .server => .server,
526 } else .default,
527 .wasi_exec_model = .init(c.wasi_exec_model),
528 .win32_manifest = c.win32_manifest != null,
529 .win32_module_definition = c.win32_module_definition != null,
530 .zig_lib_dir = c.zig_lib_dir != null,
531 .rc_includes = c.rc_includes,
532 .image_base = c.image_base != null,
533 .build_id = .init(c.build_id),
534 .entry = switch (c.entry) {
535 .default => .default,
536 .disabled => .disabled,
537 .enabled => .enabled,
538 .symbol_name => .symbol_name,
539 },
540 .lto = .init(c.lto),
541 .subsystem = .init(c.subsystem),
542 },
543 .flags4 = .{
544 .libc_file = c.libc_file != null,
545 .link_z_common_page_size = c.link_z_common_page_size != null,
546 .link_z_max_page_size = c.link_z_max_page_size != null,
547 .pagezero_size = c.pagezero_size != null,
548 .stack_size = c.stack_size != null,
549 .headerpad_size = c.headerpad_size != null,
550 .error_limit = c.error_limit != null,
551 .install_name = c.install_name != null,
552 .entitlements = c.entitlements != null,
553 .expect_errors = if (c.expect_errors) |x| switch (x) {
554 .contains => .contains,
555 .exact => .exact,
556 .starts_with => .starts_with,
557 .stderr_contains => .stderr_contains,
558 } else .none,
559 .linker_script = c.linker_script != null,
560 .version_script = c.version_script != null,
561 },
562 .root_module = try s.addModule(c.root_module),
563 .root_name = try wc.addString(c.name),
564 .linker_script = .{ .value = try s.addOptionalLazyPath(c.linker_script) },
565 .version_script = .{ .value = try s.addOptionalLazyPath(c.version_script) },
566 .zig_lib_dir = .{ .value = try s.addOptionalLazyPath(c.zig_lib_dir) },
567 .libc_file = .{ .value = try s.addOptionalLazyPath(c.libc_file) },
568 .win32_manifest = .{ .value = try s.addOptionalLazyPath(c.win32_manifest) },
569 .win32_module_definition = .{ .value = try s.addOptionalLazyPath(c.win32_module_definition) },
570 .entitlements = .{ .value = try s.addOptionalLazyPath(c.entitlements) },
571 .version = .{ .value = try s.addOptionalSemVer(c.version) },
572 .install_name = .{ .value = try s.addOptionalString(c.install_name) },
573 .initial_memory = .{ .value = c.initial_memory },
574 .max_memory = .{ .value = c.max_memory },
575 .global_base = .{ .value = c.global_base },
576 .image_base = .{ .value = c.image_base },
577 .link_z_common_page_size = .{ .value = c.link_z_common_page_size },
578 .link_z_max_page_size = .{ .value = c.link_z_max_page_size },
579 .pagezero_size = .{ .value = c.pagezero_size },
580 .stack_size = .{ .value = c.stack_size },
581 .headerpad_size = .{ .value = c.headerpad_size },
582 .error_limit = .{ .value = c.error_limit },
583 .entry = .{ .value = switch (c.entry) {
584 .symbol_name => |name| try wc.addString(name),
585 .default, .disabled, .enabled => null,
586 } },
587 .build_id = .{ .value = if (c.build_id) |id| switch (id) {
588 .hexstring => |*hexstring| try wc.addString(hexstring.toSlice()),
589 .none, .fast, .uuid, .sha1, .md5 => null,
590 } else null },
591 .filters = .{ .slice = try s.initStringList(c.filters) },
592 .exec_cmd_args = .{ .slice = try s.initOptionalStringList(exec_cmd_args) },
593 .installed_headers = .initErased(installed_headers),
594 .force_undefined_symbols = .{ .slice = try s.initStringList(c.force_undefined_symbols.keys()) },
595 }));
596
597 log.err("TODO serialize the trailing Compile step data", .{});
598
599 break :e @enumFromInt(extra_index);
600 },
601 .install_artifact => e: {
602 const ia: *Step.InstallArtifact = @fieldParentPtr("step", step);
603 break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.InstallArtifact, .{
604 .flags = .{
605 .dylib_symlinks = ia.dylib_symlinks != null,
606 },
607 .dest_dir = try addInstallDir(wc, ia.dest_dir),
608 .dest_sub_path = try wc.addString(ia.dest_sub_path),
609 .emitted_bin = try s.addOptionalLazyPathEnum(ia.emitted_bin),
610 .implib_dir = try addInstallDir(wc, ia.implib_dir),
611 .emitted_implib = try s.addOptionalLazyPathEnum(ia.emitted_implib),
612 .pdb_dir = try addInstallDir(wc, ia.pdb_dir),
613 .emitted_pdb = try s.addOptionalLazyPathEnum(ia.emitted_pdb),
614 .h_dir = try addInstallDir(wc, ia.h_dir),
615 .emitted_h = try s.addOptionalLazyPathEnum(ia.emitted_h),
616 .artifact = stepIndex(&step_map, &ia.artifact.step),
617 })));
618 },
619 .install_file => @panic("TODO"),
620 .install_dir => @panic("TODO"),
621 .remove_dir => @panic("TODO"),
622 .fail => @panic("TODO"),
623 .fmt => @panic("TODO"),
624 .translate_c => @panic("TODO"),
625 .write_file => @panic("TODO"),
626 .update_source_files => @panic("TODO"),
627 .run => e: {
628 const run: *Step.Run = @fieldParentPtr("step", step);
629
630 const captured_stdout: Configuration.OptionalString = if (run.captured_stdout) |cs|
631 .init(try wc.addString(cs.output.basename))
632 else
633 .none;
634
635 const captured_stderr: Configuration.OptionalString = if (run.captured_stderr) |cs|
636 .init(try wc.addString(cs.output.basename))
637 else
638 .none;
639
640 const extra_index = try wc.addExtra(@as(Configuration.Step.Run, .{
641 .flags = .{
642 .disable_zig_progress = run.disable_zig_progress,
643 .skip_foreign_checks = run.skip_foreign_checks,
644 .failing_to_execute_foreign_is_an_error = run.failing_to_execute_foreign_is_an_error,
645 .has_side_effects = run.has_side_effects,
646 .test_runner_mode = run.test_runner_mode,
647 .color = run.color,
648 .stdio = switch (run.stdio) {
649 .infer_from_args => .infer_from_args,
650 .inherit => .inherit,
651 .check => .check,
652 .zig_test => .zig_test,
653 },
654 .stdin = switch (run.stdin) {
655 .none => .none,
656 .bytes => .bytes,
657 .lazy_path => .lazy_path,
658 },
659 .stdout_trim_whitespace = if (run.captured_stdout) |cs| cs.trim_whitespace else .none,
660 .stderr_trim_whitespace = if (run.captured_stderr) |cs| cs.trim_whitespace else .none,
661 .stdio_limit = run.stdio_limit != .unlimited,
662 .producer = run.producer != null,
663 },
664 .file_inputs_len = @intCast(run.file_inputs.items.len),
665 .args_len = @intCast(run.argv.items.len),
666 .cwd = try s.addOptionalLazyPathEnum(run.cwd),
667 .captured_stdout = captured_stdout,
668 .captured_stderr = captured_stderr,
669 }));
670
671 log.err("TODO serialize the trailing Run step data", .{});
672
673 break :e @enumFromInt(extra_index);
674 },
675 .check_file => @panic("TODO"),
676 .check_object => @panic("TODO"),
677 .config_header => @panic("TODO"),
678 .objcopy => @panic("TODO"),
679 .options => @panic("TODO"),
680 },
681 });
682 }
683 }
684
685 try wc.unlazy_deps.ensureUnusedCapacity(gpa, graph.needed_lazy_dependencies.keys().len);
686 for (graph.needed_lazy_dependencies.keys()) |k| {
687 wc.unlazy_deps.appendAssumeCapacity(try wc.addString(k));
688 }
689
690 try wc.write(writer, .{
691 .default_step = stepIndex(&step_map, b.default_step),
692 });
693}
694
695fn addOptionalResolvedTarget(
696 wc: *Configuration.Wip,
697 optional_resolved_target: ?std.Build.ResolvedTarget,
698) !Configuration.ResolvedTarget.OptionalIndex {
699 const resolved_target = optional_resolved_target orelse return .none;
700 log.debug("TODO deduplicate resolved targets", .{});
701 return @enumFromInt(try wc.addExtra(@as(Configuration.ResolvedTarget, .{
702 .query = try wc.addTargetQuery(resolved_target.query),
703 .result = try wc.addTarget(resolved_target.result),
704 })));
705}
706
707fn addInstallDir(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !Configuration.InstallDestDir {
708 switch (install_dir orelse return .none) {
709 .prefix => return .prefix,
710 .lib => return .lib,
711 .bin => return .bin,
712 .header => return .header,
713 .custom => |sub_path| return .initCustom(try wc.addString(sub_path)),
714 }
715}
716
717fn stepIndex(step_map: *const std.AutoArrayHashMapUnmanaged(*Step, void), step: *Step) Configuration.Step.Index {
718 return @enumFromInt(step_map.getIndex(step).?);
719}
720
721/// If the given `Step` is a `Step.Compile`, adds any dependencies for that step which
722/// are implied by the module graph rooted at `step.cast(Step.Compile).?.root_module`.
723fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void {
724 const root_module = if (step.cast(Step.Compile)) |cs| root: {
725 break :root cs.root_module;
726 } else return; // not a compile step so no module dependencies
727
728 // Starting from `root_module`, discover all modules in this graph.
729 const modules = root_module.getGraph().modules;
730
731 // For each of those modules, set up the implied step dependencies.
732 for (modules) |mod| {
733 if (mod.root_source_file) |lp| lp.addStepDependencies(step);
734 for (mod.include_dirs.items) |include_dir| switch (include_dir) {
735 .path,
736 .path_system,
737 .path_after,
738 .framework_path,
739 .framework_path_system,
740 .embed_path,
741 => |lp| lp.addStepDependencies(step),
742
743 .other_step => |other| {
744 other.getEmittedIncludeTree().addStepDependencies(step);
745 step.dependOn(&other.step);
746 },
747
748 .config_header_step => |other| step.dependOn(&other.step),
749 };
750 for (mod.lib_paths.items) |lp| lp.addStepDependencies(step);
751 for (mod.rpaths.items) |rpath| switch (rpath) {
752 .lazy_path => |lp| lp.addStepDependencies(step),
753 .special => {},
754 };
755 for (mod.link_objects.items) |link_object| switch (link_object) {
756 .static_path,
757 .assembly_file,
758 => |lp| lp.addStepDependencies(step),
759 .other_step => |other| step.dependOn(&other.step),
760 .system_lib => {},
761 .c_source_file => |source| source.file.addStepDependencies(step),
762 .c_source_files => |source_files| source_files.root.addStepDependencies(step),
763 .win32_resource_file => |rc_source| {
764 rc_source.file.addStepDependencies(step);
765 for (rc_source.include_paths) |lp| lp.addStepDependencies(step);
766 },
767 };
768 }
769}
770
771fn nextArg(args: []const [:0]const u8, idx: *usize) ?[:0]const u8 {
772 if (idx.* >= args.len) return null;
773 defer idx.* += 1;
774 return args[idx.*];
775}
776
777fn nextArgOrFatal(args: []const [:0]const u8, idx: *usize) [:0]const u8 {
778 return nextArg(args, idx) orelse {
779 fatalWithHint("expected argument after: {s}", .{args[idx.* - 1]});
780 };
781}
782
783fn expectArgOrFatal(args: []const [:0]const u8, index_ptr: *usize, first: []const u8) []const u8 {
784 const next_arg = nextArg(args, index_ptr) orelse fatal("missing {q} argument", .{first});
785 if (!mem.eql(u8, first, next_arg)) fatal("expected {q} instead of {q}", .{ first, next_arg });
786 const arg = nextArg(args, index_ptr) orelse fatal("expected argument after {q}", .{first});
787 return arg;
788}
789
790const ErrorStyle = enum {
791 verbose,
792 minimal,
793 verbose_clear,
794 minimal_clear,
795 fn verboseContext(s: ErrorStyle) bool {
796 return switch (s) {
797 .verbose, .verbose_clear => true,
798 .minimal, .minimal_clear => false,
799 };
800 }
801 fn clearOnUpdate(s: ErrorStyle) bool {
802 return switch (s) {
803 .verbose, .minimal => false,
804 .verbose_clear, .minimal_clear => true,
805 };
806 }
807};
808const MultilineErrors = enum { indent, newline, none };
809const Summary = enum { all, new, failures, line, none };
810
811fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn {
812 log.info("to access the help menu: zig build -h", .{});
813 fatal(f, args);
814}
815
816fn serializeSystemIntegrationOptions(graph: *std.Build.Graph, wc: *Configuration.Wip) Allocator.Error!void {
817 const gpa = wc.gpa;
818
819 var bad = false;
820 try wc.system_integrations.ensureTotalCapacityPrecise(gpa, graph.system_integration_options.entries.len);
821 for (graph.system_integration_options.keys(), graph.system_integration_options.values()) |k, v| {
822 wc.system_integrations.appendAssumeCapacity(.{
823 .name = try wc.addString(k),
824 .status = switch (v) {
825 .user_disabled, .user_enabled => x: {
826 // The user tried to enable or disable a system library integration, but
827 // the configure script did not recognize that option.
828 log.err("system integration name not recognized by configure script: {s}", .{k});
829 bad = true;
830 break :x .disabled;
831 },
832 .declared_disabled => .disabled,
833 .declared_enabled => .enabled,
834 },
835 });
836 }
837 if (bad) {
838 log.info("help menu contains available options: zig build -h", .{});
839 process.exit(1);
840 }
841}
src/main.zig+1-1
......@@ -5333,7 +5333,7 @@ fn cmdBuild(
53335333 .root_src_path = fs.path.basename(runner),
53345334 } else .{
53355335 .root = try .fromRoot(arena, dirs, .zig_lib, "compiler"),
5336 .root_src_path = "configure_runner.zig",
5336 .root_src_path = "configurer.zig",
53375337 };
53385338
53395339 const config = try Compilation.Config.resolve(.{