authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-09 22:09:12-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:34-07:00
log71ac3f15b3740974e1bac091f32fc56933134ca2
treeddf8ea622f1cbb1b3945d5efa54a6b190054f1f5
parenteaffd5551349be6132ab33827e307f28ca8ac051

build system: implement LazyPath

Number of generated files is recorded in serialized Configuration. Maker preallocates array of generated files so that loads and stores can be synchronization-free (protected by the dependency tree ordering). More progress on Compile Step Zig CLI lowering.

15 files changed, 726 insertions(+), 458 deletions(-)

BRANCH_TODO created+12
......@@ -0,0 +1,12 @@
1* rename std.zig.Configuration to std.Build.Configuration
2* replace union(@This().Tag)
3* replace b.dupe() with string internment
4* don't forget to add -listen arg back
5* get zig init template working
6* finish migrating the rest of the build steps
7* make zig-pkg path root configurable in maker (make sure --system still works)
8* eliminate calls to getPath, getPath2, getPath3
9* solve the TODOs added in this branch
10* get zig tests passing
11* test a bunch of third party projects / help people migrate
12* refactor with DefaultingEnum
lib/compiler/Maker.zig+104
......@@ -33,6 +33,7 @@ graph: *Graph,
3333install_paths: InstallPaths,
3434scanned_config: *const ScannedConfig,
3535steps: []Step,
36generated_files: []Path,
3637
3738available_rss: usize,
3839max_rss_is_default: bool,
......@@ -115,7 +116,13 @@ pub fn main(init: process.Init.Minimal) !void {
115116 .zig_exe = zig_exe,
116117 .environ_map = try init.environ.createMap(arena),
117118 .global_cache_root = global_cache_directory,
119 .local_cache_root = local_cache_directory,
118120 .zig_lib_directory = zig_lib_directory,
121 .build_root_directory = build_root_directory,
122 .pkg_root = .{
123 .root_dir = build_root_directory,
124 .sub_path = "zig-pkg",
125 },
119126 };
120127
121128 graph.cache.addPrefix(.{ .path = null, .handle = cwd });
......@@ -525,6 +532,7 @@ pub fn main(init: process.Init.Minimal) !void {
525532 .include = install_include_path,
526533 },
527534 .steps = try arena.alloc(Step, scanned_config.configuration.steps.len),
535 .generated_files = try arena.alloc(Path, scanned_config.configuration.generated_files_len),
528536
529537 .available_rss = max_rss,
530538 .max_rss_is_default = false,
......@@ -1679,3 +1687,99 @@ fn initStdoutWriter(io: Io) *Writer {
16791687 stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation);
16801688 return &stdout_writer_allocation.interface;
16811689}
1690
1691/// `asking_step` is only used for debugging purposes; it's the step being run
1692/// that is asking for the path.
1693pub fn resolveLazyPath(
1694 maker: *const Maker,
1695 arena: Allocator,
1696 lazy_path: Configuration.LazyPath,
1697 asking_step_index: Configuration.Step.Index,
1698) Allocator.Error!Path {
1699 _ = asking_step_index; // TODO use this to enhance debugability when this function fails
1700 const c = &maker.scanned_config.configuration;
1701 const graph = maker.graph;
1702 return switch (lazy_path) {
1703 .source_path => |sp| try packagePath(maker, arena, sp.owner, sp.sub_path.slice(c)),
1704 .relative => |relative| switch (relative.flags.base) {
1705 .cwd => .{
1706 .root_dir = .cwd(),
1707 .sub_path = relative.sub_path.slice(c),
1708 },
1709 .local_cache => .{
1710 .root_dir = graph.local_cache_root,
1711 },
1712 .global_cache => .{
1713 .root_dir = graph.global_cache_root,
1714 },
1715 .build_root => .{
1716 .root_dir = graph.build_root_directory,
1717 },
1718 },
1719 .generated => |gen| {
1720 const base = maker.generated_files[@intFromEnum(gen.index)];
1721 var file_path = base;
1722 for (0..gen.flags.up) |_| {
1723 file_path.sub_path = Io.Dir.path.dirname(file_path.sub_path) orelse
1724 fatal("invalid LazyPath traversal: up {d} times from {f}", .{ gen.flags.up, base });
1725 }
1726 return file_path.join(arena, gen.sub_path.slice(c));
1727 },
1728 };
1729}
1730
1731pub fn resolveLazyPathIndex(
1732 maker: *const Maker,
1733 arena: Allocator,
1734 lazy_path_index: Configuration.LazyPath.Index,
1735 asking_step_index: Configuration.Step.Index,
1736) Allocator.Error!Path {
1737 const c = &maker.scanned_config.configuration;
1738 return resolveLazyPath(maker, arena, lazy_path_index.get(c), asking_step_index);
1739}
1740
1741/// `resolveLazyPath` is preferred, but this can be necessary when passing Path
1742/// objects to child processes.
1743pub fn resolveLazyPathAbs(
1744 maker: *const Maker,
1745 arena: Allocator,
1746 lazy_path: Configuration.LazyPath,
1747 asking_step_index: Configuration.Step.Index,
1748) Allocator.Error![]const u8 {
1749 const p = try resolveLazyPath(maker, arena, lazy_path, asking_step_index);
1750 const root_dir_path = p.root_dir.path orelse return p.subPathOrDot();
1751 if (p.sub_path.len == 0) return root_dir_path;
1752 return Io.Dir.path.join(arena, &.{ root_dir_path, p.sub_path });
1753}
1754
1755/// `resolveLazyPath` is preferred, but this can be necessary when passing Path
1756/// objects to child processes.
1757pub fn resolveLazyPathIndexAbs(
1758 maker: *const Maker,
1759 arena: Allocator,
1760 lazy_path_index: Configuration.LazyPath.Index,
1761 asking_step_index: Configuration.Step.Index,
1762) Allocator.Error![]const u8 {
1763 const c = &maker.scanned_config.configuration;
1764 return resolveLazyPathAbs(maker, arena, lazy_path_index.get(c), asking_step_index);
1765}
1766
1767fn packagePath(
1768 maker: *const Maker,
1769 arena: Allocator,
1770 package_index: Configuration.Package.Index,
1771 sub_path: []const u8,
1772) Allocator.Error!Path {
1773 const c = &maker.scanned_config.configuration;
1774 const graph = maker.graph;
1775 const package = package_index.get(c) orelse return .{
1776 .root_dir = graph.build_root_directory,
1777 .sub_path = sub_path,
1778 };
1779 const hash = package.hash.slice(c);
1780 const pkg_root = graph.pkg_root;
1781 return .{
1782 .root_dir = pkg_root.root_dir,
1783 .sub_path = try Io.Dir.path.join(arena, &.{ pkg_root.sub_path, hash, sub_path }),
1784 };
1785}
lib/compiler/Maker/Graph.zig+3
......@@ -13,7 +13,10 @@ cache: std.Build.Cache,
1313zig_exe: []const u8,
1414environ_map: std.process.Environ.Map,
1515global_cache_root: std.Build.Cache.Directory,
16local_cache_root: std.Build.Cache.Directory,
1617zig_lib_directory: std.Build.Cache.Directory,
18build_root_directory: std.Build.Cache.Directory,
19pkg_root: std.Build.Cache.Path,
1720
1821debug_compiler_runtime_libs: ?std.builtin.OptimizeMode = null,
1922incremental: ?bool = null,
lib/compiler/Maker/Step/Compile.zig+253-103
......@@ -129,6 +129,7 @@ fn lowerZigArgs(
129129 const conf = &maker.scanned_config.configuration;
130130 const conf_step = compile_index.ptr(conf);
131131 const conf_comp = conf_step.extended.get(conf.extra).compile;
132 const root_module_target = conf_comp.rootModuleTarget(conf);
132133
133134 try zig_args.append(gpa, graph.zig_exe);
134135
......@@ -232,17 +233,17 @@ fn lowerZigArgs(
232233 }
233234 }
234235
235 if (true) @panic("TODO");
236
237236 // Inherit dependencies on system libraries and static libraries.
238237 for (0..mod.link_objects.len) |lo_i| switch (mod.link_objects.get(conf.extra, lo_i)) {
239238 .static_path => |static_path| {
240239 if (my_responsibility) {
241 try zig_args.append(gpa, static_path.getPath2(step));
240 try zig_args.append(gpa, try maker.resolveLazyPathIndexAbs(arena, static_path, compile_index));
242241 total_linker_objects += 1;
243242 }
244243 },
245 .system_lib => |system_lib| {
244 .system_lib => |system_lib_index| {
245 const system_lib = system_lib_index.get(conf);
246 const system_lib_name = system_lib.name.slice(conf);
246247 const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name);
247248 if (system_lib_gop.found_existing) {
248249 try zig_args.appendSlice(gpa, system_lib_gop.value_ptr.*);
......@@ -254,37 +255,39 @@ fn lowerZigArgs(
254255 if (already_linked)
255256 continue;
256257
257 if ((system_lib.search_strategy != prev_search_strategy or
258 system_lib.preferred_link_mode != prev_preferred_link_mode) and
259 compile.linkage != .static)
258 if ((system_lib.flags.search_strategy != prev_search_strategy or
259 system_lib.flags.preferred_link_mode != prev_preferred_link_mode) and
260 conf_comp.flags2.linkage != .static)
260261 {
261 switch (system_lib.search_strategy) {
262 .no_fallback => switch (system_lib.preferred_link_mode) {
262 switch (system_lib.flags.search_strategy) {
263 .no_fallback => switch (system_lib.flags.preferred_link_mode) {
263264 .dynamic => try zig_args.append(gpa, "-search_dylibs_only"),
264265 .static => try zig_args.append(gpa, "-search_static_only"),
265266 },
266 .paths_first => switch (system_lib.preferred_link_mode) {
267 .paths_first => switch (system_lib.flags.preferred_link_mode) {
267268 .dynamic => try zig_args.append(gpa, "-search_paths_first"),
268269 .static => try zig_args.append(gpa, "-search_paths_first_static"),
269270 },
270 .mode_first => switch (system_lib.preferred_link_mode) {
271 .mode_first => switch (system_lib.flags.preferred_link_mode) {
271272 .dynamic => try zig_args.append(gpa, "-search_dylibs_first"),
272273 .static => try zig_args.append(gpa, "-search_static_first"),
273274 },
274275 }
275 prev_search_strategy = system_lib.search_strategy;
276 prev_preferred_link_mode = system_lib.preferred_link_mode;
276 prev_search_strategy = system_lib.flags.search_strategy;
277 prev_preferred_link_mode = system_lib.flags.preferred_link_mode;
277278 }
278279
279280 const prefix: []const u8 = prefix: {
280 if (system_lib.needed) break :prefix "-needed-l";
281 if (system_lib.weak) break :prefix "-weak-l";
281 if (system_lib.flags.needed) break :prefix "-needed-l";
282 if (system_lib.flags.weak) break :prefix "-weak-l";
282283 break :prefix "-l";
283284 };
284 switch (system_lib.use_pkg_config) {
285 .no => try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{ prefix, system_lib.name })),
285 switch (system_lib.flags.use_pkg_config) {
286 .no => try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{
287 prefix, system_lib_name,
288 })),
286289 .yes, .force => {
287 if (compile.runPkgConfig(maker, system_lib.name)) |result| {
290 if (compile.runPkgConfig(maker, system_lib_name)) |result| {
288291 try zig_args.appendSlice(gpa, result.cflags);
289292 try zig_args.appendSlice(gpa, result.libs);
290293 try seen_system_libs.put(arena, system_lib.name, result.cflags);
......@@ -294,17 +297,18 @@ fn lowerZigArgs(
294297 error.PkgConfigFailed,
295298 error.PkgConfigNotInstalled,
296299 error.PackageNotFound,
297 => switch (system_lib.use_pkg_config) {
300 => switch (system_lib.flags.use_pkg_config) {
298301 .yes => {
299302 // pkg-config failed, so fall back to linking the library
300303 // by name directly.
301304 try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{
302 prefix,
303 system_lib.name,
305 prefix, system_lib_name,
304306 }));
305307 },
306308 .force => {
307 return step.fail(maker, "pkg-config failed for library {s}", .{system_lib.name});
309 return step.fail(maker, "pkg-config failed for library {s}", .{
310 system_lib_name,
311 });
308312 },
309313 .no => unreachable,
310314 },
......@@ -314,23 +318,31 @@ fn lowerZigArgs(
314318 },
315319 }
316320 },
317 .other_step => |other| {
318 switch (other.kind) {
321 .other_step => |other_step_index| {
322 const other = other_step_index.ptr(conf);
323 const other_compile = other.extended.get(conf.extra).compile;
324 switch (other_compile.flags3.kind) {
319325 .exe => return step.fail(maker, "cannot link with an executable build artifact", .{}),
320326 .@"test" => return step.fail(maker, "cannot link with a test", .{}),
321327 .obj, .test_obj => {
322 const included_in_lib_or_obj = !my_responsibility and
323 (dep_compile.kind == .lib or dep_compile.kind == .obj or dep_compile.kind == .test_obj);
328 const included_in_lib_or_obj = switch (dep_compile.flags3.kind) {
329 .lib, .obj, .test_obj => !my_responsibility,
330 else => false,
331 };
324332 if (!already_linked and !included_in_lib_or_obj) {
325 try zig_args.append(gpa, other.getEmittedBin().getPath2(step));
333 try zig_args.append(gpa, try maker.resolveLazyPathAbs(
334 arena,
335 .{ .generated = .{ .index = other_compile.generated_bin.value.? } },
336 compile_index,
337 ));
326338 total_linker_objects += 1;
327339 }
328340 },
329341 .lib => l: {
330 const other_produces_implib = other.producesImplib();
331 const other_is_static = other_produces_implib or other.isStaticLibrary();
342 const other_produces_implib = other_compile.producesImplib(conf);
343 const other_is_static = other_produces_implib or other_compile.isStaticLibrary();
332344
333 if (compile.isStaticLibrary() and other_is_static) {
345 if (conf_comp.isStaticLibrary() and other_is_static) {
334346 // Avoid putting a static library inside a static library.
335347 break :l;
336348 }
......@@ -338,20 +350,25 @@ fn lowerZigArgs(
338350 // For DLLs, we must link against the implib.
339351 // For everything else, we directly link
340352 // against the library file.
341 const full_path_lib = if (other_produces_implib)
342 try other.getGeneratedFilePath("generated_implib", &compile.step)
343 else
344 try other.getGeneratedFilePath("generated_bin", &compile.step);
353 const full_path_lib = try maker.resolveLazyPathAbs(
354 arena,
355 .{ .generated = .{
356 .index = if (other_produces_implib)
357 other_compile.generated_implib.value.?
358 else
359 other_compile.generated_bin.value.?,
360 } },
361 compile_index,
362 );
345363
346364 try zig_args.append(gpa, full_path_lib);
347365 total_linker_objects += 1;
348366
349 if (other.linkage == .dynamic and
350 compile.rootModuleTarget().os.tag != .windows)
367 if (other_compile.flags2.linkage == .dynamic and
368 root_module_target.flags.os_tag != .windows)
351369 {
352370 if (Dir.path.dirname(full_path_lib)) |dirname| {
353 try zig_args.append(gpa, "-rpath");
354 try zig_args.append(gpa, dirname);
371 try zig_args.appendSlice(gpa, &.{ "-rpath", dirname });
355372 }
356373 }
357374 },
......@@ -361,92 +378,96 @@ fn lowerZigArgs(
361378 if (!my_responsibility) break :l;
362379
363380 if (prev_has_cflags) {
364 try zig_args.append(gpa, "-cflags");
365 try zig_args.append(gpa, "--");
381 try zig_args.appendSlice(gpa, &.{ "-cflags", "--" });
366382 prev_has_cflags = false;
367383 }
368 try zig_args.append(gpa, asm_file.getPath2(mod.owner, step));
384 try zig_args.append(gpa, try maker.resolveLazyPathIndexAbs(arena, asm_file, compile_index));
369385 total_linker_objects += 1;
370386 },
371387
372 .c_source_file => |c_source_file| l: {
388 .c_source_file => |c_source_file_index| l: {
373389 if (!my_responsibility) break :l;
374390
375 if (prev_has_cflags or c_source_file.flags.len != 0) {
376 try zig_args.append(gpa, "-cflags");
377 for (c_source_file.flags) |arg| {
378 try zig_args.append(gpa, arg);
391 const c_source_file = c_source_file_index.get(conf);
392
393 if (prev_has_cflags or c_source_file.args.slice.len != 0) {
394 try zig_args.ensureUnusedCapacity(gpa, 2 + c_source_file.args.slice.len);
395 zig_args.appendAssumeCapacity("-cflags");
396 for (c_source_file.args.slice) |arg| {
397 zig_args.appendAssumeCapacity(arg.slice(conf));
379398 }
380 try zig_args.append(gpa, "--");
399 zig_args.appendAssumeCapacity("--");
381400 }
382 prev_has_cflags = (c_source_file.flags.len != 0);
401 prev_has_cflags = (c_source_file.args.slice.len != 0);
383402
384 if (c_source_file.language) |lang| {
385 try zig_args.append(gpa, "-x");
386 try zig_args.append(gpa, lang.internalIdentifier());
387 }
403 if (c_source_file.flags.lang.get()) |lang|
404 (try zig_args.addManyAsArray(gpa, 2)).* = .{ "-x", lang.clangIdentifier() };
388405
389 try zig_args.append(gpa, c_source_file.file.getPath2(mod.owner, step));
406 try zig_args.append(gpa, try maker.resolveLazyPathIndexAbs(arena, c_source_file.file, compile_index));
407
408 if (c_source_file.flags.lang != .default)
409 (try zig_args.addManyAsArray(gpa, 2)).* = .{ "-x", "none" };
390410
391 if (c_source_file.language != null) {
392 try zig_args.append(gpa, "-x");
393 try zig_args.append(gpa, "none");
394 }
395411 total_linker_objects += 1;
396412 },
397413
398 .c_source_files => |c_source_files| l: {
414 .c_source_files => |c_source_files_index| l: {
399415 if (!my_responsibility) break :l;
400416
401 if (prev_has_cflags or c_source_files.flags.len != 0) {
402 try zig_args.append(gpa, "-cflags");
403 for (c_source_files.flags) |arg| {
404 try zig_args.append(gpa, arg);
417 const c_source_files = c_source_files_index.get(conf);
418
419 if (prev_has_cflags or c_source_files.args.slice.len != 0) {
420 try zig_args.ensureUnusedCapacity(gpa, 2 + c_source_files.args.slice.len);
421 zig_args.appendAssumeCapacity("-cflags");
422 for (c_source_files.args.slice) |arg| {
423 zig_args.appendAssumeCapacity(arg.slice(conf));
405424 }
406 try zig_args.append(gpa, "--");
425 zig_args.appendAssumeCapacity("--");
407426 }
408 prev_has_cflags = (c_source_files.flags.len != 0);
427 prev_has_cflags = (c_source_files.args.slice.len != 0);
409428
410 if (c_source_files.language) |lang| {
411 try zig_args.append(gpa, "-x");
412 try zig_args.append(gpa, lang.internalIdentifier());
413 }
429 if (c_source_files.flags.lang.get()) |lang|
430 (try zig_args.addManyAsArray(gpa, 2)).* = .{ "-x", lang.clangIdentifier() };
414431
415 const root_path = c_source_files.root.getPath2(mod.owner, step);
416 for (c_source_files.files) |file| {
417 try zig_args.append(gpa, try Dir.path.join(arena, &.{ root_path, file }));
432 const root_path = try maker.resolveLazyPathIndexAbs(arena, c_source_files.root, compile_index);
433 try zig_args.ensureUnusedCapacity(gpa, c_source_files.sub_paths.slice.len);
434 for (c_source_files.sub_paths.slice) |sub_path| {
435 zig_args.appendAssumeCapacity(try Dir.path.join(arena, &.{
436 root_path, sub_path.slice(conf),
437 }));
418438 }
419439
420 if (c_source_files.language != null) {
421 try zig_args.append(gpa, "-x");
422 try zig_args.append(gpa, "none");
423 }
440 if (c_source_files.flags.lang != .default)
441 (try zig_args.addManyAsArray(gpa, 2)).* = .{ "-x", "none" };
424442
425 total_linker_objects += c_source_files.files.len;
443 total_linker_objects += c_source_files.sub_paths.slice.len;
426444 },
427445
428 .win32_resource_file => |rc_source_file| l: {
446 .win32_resource_file => |rc_source_file_index| l: {
429447 if (!my_responsibility) break :l;
430448
431 if (rc_source_file.flags.len == 0 and rc_source_file.include_paths.len == 0) {
449 const rc_source_file = rc_source_file_index.get(conf);
450
451 if (rc_source_file.args.slice.len == 0 and rc_source_file.include_paths.slice.len == 0) {
432452 if (prev_has_rcflags) {
433 try zig_args.append(gpa, "-rcflags");
434 try zig_args.append(gpa, "--");
453 (try zig_args.addManyAsArray(gpa, 2)).* = .{ "-rcflags", "--" };
435454 prev_has_rcflags = false;
436455 }
437456 } else {
438 try zig_args.append(gpa, "-rcflags");
439 for (rc_source_file.flags) |arg| {
440 try zig_args.append(gpa, arg);
457 try zig_args.ensureUnusedCapacity(gpa, 1 + rc_source_file.args.slice.len);
458 zig_args.appendAssumeCapacity("-rcflags");
459 for (rc_source_file.args.slice) |arg| {
460 zig_args.appendAssumeCapacity(arg.slice(conf));
441461 }
442 for (rc_source_file.include_paths) |include_path| {
443 try zig_args.append(gpa, "/I");
444 try zig_args.append(gpa, include_path.getPath2(mod.owner, step));
462 try zig_args.ensureUnusedCapacity(gpa, 1 + 2 * rc_source_file.include_paths.slice.len);
463 for (rc_source_file.include_paths.slice) |include_path| {
464 zig_args.appendAssumeCapacity("/I");
465 zig_args.appendAssumeCapacity(try maker.resolveLazyPathIndexAbs(arena, include_path, compile_index));
445466 }
446 try zig_args.append(gpa, "--");
467 zig_args.appendAssumeCapacity("--");
447468 prev_has_rcflags = true;
448469 }
449 try zig_args.append(gpa, rc_source_file.file.getPath2(mod.owner, step));
470 try zig_args.append(gpa, try maker.resolveLazyPathIndexAbs(arena, rc_source_file.file, compile_index));
450471 total_linker_objects += 1;
451472 },
452473 };
......@@ -455,9 +476,10 @@ fn lowerZigArgs(
455476 // have the correct parent module, but only if the module is part of
456477 // this compilation.
457478 if (!my_responsibility) continue;
458 if (cli_named_modules.modules.getIndex(mod)) |module_cli_index| {
479 if (cli_named_modules.modules.getIndex(mod_index)) |module_cli_index| {
459480 const module_cli_name = cli_named_modules.names.keys()[module_cli_index];
460 try mod.appendZigProcessFlags(zig_args, step);
481 if (true) @panic("TODO");
482 try appendModuleFlags(zig_args, step);
461483
462484 // --dep arguments
463485 try zig_args.ensureUnusedCapacity(mod.import_table.count() * 2);
......@@ -510,12 +532,12 @@ fn lowerZigArgs(
510532 if (is_linking_libc) zig_args.appendAssumeCapacity("-lc");
511533 }
512534
513 if (true) @panic("TODO");
514
515 if (conf_comp.win32_manifest) |manifest_file| {
516 try zig_args.append(gpa, manifest_file.getPath2(step));
535 if (conf_comp.win32_manifest.value) |manifest_file| {
536 try zig_args.append(gpa, try maker.resolveLazyPathIndexAbs(arena, manifest_file, compile_index));
517537 }
518538
539 if (true) @panic("TODO");
540
519541 if (conf_comp.win32_module_definition) |module_file| {
520542 try zig_args.append(gpa, module_file.getPath2(step));
521543 }
......@@ -623,27 +645,26 @@ fn lowerZigArgs(
623645 "--version", try allocPrint(arena, "{f}", .{version}),
624646 });
625647
626 if (compile.rootModuleTarget().os.tag.isDarwin()) {
648 if (root_module_target.flags.os_tag.isDarwin()) {
627649 const install_name = compile.install_name orelse try allocPrint(arena, "@rpath/{s}{s}{s}", .{
628 compile.rootModuleTarget().libPrefix(),
650 root_module_target.libPrefix(),
629651 compile.name,
630 compile.rootModuleTarget().dynamicLibSuffix(),
652 root_module_target.dynamicLibSuffix(),
631653 });
632 try zig_args.append(gpa, "-install_name");
633 try zig_args.append(gpa, install_name);
654 try zig_args.appendSlice(gpa, &.{ "-install_name", install_name });
634655 }
635656 }
636657
637658 if (compile.entitlements) |entitlements| {
638 try zig_args.appendSlice(gpa, &[_][]const u8{ "--entitlements", entitlements });
659 try zig_args.appendSlice(gpa, &.{ "--entitlements", entitlements });
639660 }
640661 if (compile.pagezero_size) |pagezero_size| {
641662 const size = try allocPrint(arena, "{x}", .{pagezero_size});
642 try zig_args.appendSlice(gpa, &[_][]const u8{ "-pagezero_size", size });
663 try zig_args.appendSlice(gpa, &.{ "-pagezero_size", size });
643664 }
644665 if (compile.headerpad_size) |headerpad_size| {
645666 const size = try allocPrint(arena, "{x}", .{headerpad_size});
646 try zig_args.appendSlice(gpa, &[_][]const u8{ "-headerpad", size });
667 try zig_args.appendSlice(gpa, &.{ "-headerpad", size });
647668 }
648669 if (compile.headerpad_max_install_names) {
649670 try zig_args.append(gpa, "-headerpad_max_install_names");
......@@ -1019,7 +1040,8 @@ const PkgConfigResult = struct {
10191040
10201041/// Run pkg-config for the given library name and parse the output, returning the arguments
10211042/// that should be passed to zig to link the given library.
1022fn runPkgConfig(compile: *Compile, maker: *Maker, lib_name: []const u8) !PkgConfigResult {
1043fn runPkgConfig(compile: *const Compile, maker: *const Maker, lib_name: []const u8) !PkgConfigResult {
1044 if (true) @panic("TODO");
10231045 const graph = maker.graph;
10241046 const wl_rpath_prefix = "-Wl,-rpath,";
10251047
......@@ -1365,3 +1387,131 @@ fn getModuleList(
13651387
13661388 return modules;
13671389}
1390
1391fn appendModuleFlags(
1392 m: *Module,
1393 zig_args: *std.array_list.Managed([]const u8),
1394 asking_step: ?*Step,
1395) !void {
1396 const b = m.owner;
1397
1398 try addFlag(zig_args, m.strip, "-fstrip", "-fno-strip");
1399 try addFlag(zig_args, m.single_threaded, "-fsingle-threaded", "-fno-single-threaded");
1400 try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check");
1401 try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector");
1402 try addFlag(zig_args, m.omit_frame_pointer, "-fomit-frame-pointer", "-fno-omit-frame-pointer");
1403 try addFlag(zig_args, m.error_tracing, "-ferror-tracing", "-fno-error-tracing");
1404 try addFlag(zig_args, m.sanitize_thread, "-fsanitize-thread", "-fno-sanitize-thread");
1405 try addFlag(zig_args, m.fuzz, "-ffuzz", "-fno-fuzz");
1406 try addFlag(zig_args, m.valgrind, "-fvalgrind", "-fno-valgrind");
1407 try addFlag(zig_args, m.pic, "-fPIC", "-fno-PIC");
1408 try addFlag(zig_args, m.red_zone, "-mred-zone", "-mno-red-zone");
1409 try addFlag(zig_args, m.no_builtin, "-fno-builtin", "-fbuiltin");
1410
1411 if (m.sanitize_c) |sc| switch (sc) {
1412 .off => try zig_args.append("-fno-sanitize-c"),
1413 .trap => try zig_args.append("-fsanitize-c=trap"),
1414 .full => try zig_args.append("-fsanitize-c=full"),
1415 };
1416
1417 if (m.dwarf_format) |dwarf_format| {
1418 try zig_args.append(switch (dwarf_format) {
1419 .@"32" => "-gdwarf32",
1420 .@"64" => "-gdwarf64",
1421 });
1422 }
1423
1424 if (m.unwind_tables) |unwind_tables| {
1425 try zig_args.append(switch (unwind_tables) {
1426 .none => "-fno-unwind-tables",
1427 .sync => "-funwind-tables",
1428 .async => "-fasync-unwind-tables",
1429 });
1430 }
1431
1432 try zig_args.ensureUnusedCapacity(1);
1433 if (m.optimize) |optimize| switch (optimize) {
1434 .Debug => zig_args.appendAssumeCapacity("-ODebug"),
1435 .ReleaseSmall => zig_args.appendAssumeCapacity("-OReleaseSmall"),
1436 .ReleaseFast => zig_args.appendAssumeCapacity("-OReleaseFast"),
1437 .ReleaseSafe => zig_args.appendAssumeCapacity("-OReleaseSafe"),
1438 };
1439
1440 if (m.code_model != .default) {
1441 try zig_args.append("-mcmodel");
1442 try zig_args.append(@tagName(m.code_model));
1443 }
1444
1445 if (m.resolved_target) |*target| {
1446 // Communicate the query via CLI since it's more compact.
1447 if (!target.query.isNative()) {
1448 try zig_args.appendSlice(&.{
1449 "-target", try target.query.zigTriple(b.allocator),
1450 "-mcpu", try target.query.serializeCpuAlloc(b.allocator),
1451 });
1452 if (target.query.dynamic_linker) |*dynamic_linker| {
1453 if (dynamic_linker.get()) |dynamic_linker_path| {
1454 try zig_args.append("--dynamic-linker");
1455 try zig_args.append(dynamic_linker_path);
1456 } else {
1457 try zig_args.append("--no-dynamic-linker");
1458 }
1459 }
1460 }
1461 }
1462
1463 for (m.export_symbol_names) |symbol_name| {
1464 try zig_args.append(b.fmt("--export={s}", .{symbol_name}));
1465 }
1466
1467 for (m.include_dirs.items) |include_dir| {
1468 try appendIncludeDirFlags(include_dir, b, zig_args, asking_step);
1469 }
1470
1471 try zig_args.appendSlice(m.c_macros.items);
1472
1473 try zig_args.ensureUnusedCapacity(2 * m.lib_paths.items.len);
1474 for (m.lib_paths.items) |lib_path| {
1475 zig_args.appendAssumeCapacity("-L");
1476 zig_args.appendAssumeCapacity(lib_path.getPath2(b, asking_step));
1477 }
1478
1479 try zig_args.ensureUnusedCapacity(2 * m.rpaths.items.len);
1480 for (m.rpaths.items) |rpath| switch (rpath) {
1481 .lazy_path => |lp| {
1482 zig_args.appendAssumeCapacity("-rpath");
1483 zig_args.appendAssumeCapacity(lp.getPath2(b, asking_step));
1484 },
1485 .special => |bytes| {
1486 zig_args.appendAssumeCapacity("-rpath");
1487 zig_args.appendAssumeCapacity(bytes);
1488 },
1489 };
1490}
1491
1492fn appendIncludeDirFlags(
1493 include_dir: Configuration.Module.IncludeDir,
1494 b: *std.Build,
1495 zig_args: *std.array_list.Managed([]const u8),
1496 asking_step: ?*Step,
1497) !void {
1498 const flag: []const u8, const lazy_path: Configuration.LazyPath = switch (include_dir) {
1499 // zig fmt: off
1500 .path => |lp| .{ "-I", lp },
1501 .path_system => |lp| .{ "-isystem", lp },
1502 .path_after => |lp| .{ "-idirafter", lp },
1503 .framework_path => |lp| .{ "-F", lp },
1504 .framework_path_system => |lp| .{ "-iframework", lp },
1505 .config_header_step => |ch| .{ "-I", ch.getOutputDir() },
1506 .other_step => |comp| .{ "-I", comp.installed_headers_include_tree.?.getDirectory() },
1507 // zig fmt: on
1508 .embed_path => |lazy_path| {
1509 // Special case: this is a single arg.
1510 const resolved = lazy_path.getPath3(b, asking_step);
1511 const arg = b.fmt("--embed-dir={f}", .{resolved});
1512 return zig_args.append(arg);
1513 },
1514 };
1515 const resolved_str = try lazy_path.getPath3(b, asking_step).toString(b.graph.arena);
1516 return zig_args.appendSlice(&.{ flag, resolved_str });
1517}
lib/compiler/configurer.zig+27-5
......@@ -96,6 +96,7 @@ pub fn main(init: process.Init.Minimal) !void {
9696 .query = .{},
9797 .result = try std.zig.system.resolveTargetQuery(io, .{}),
9898 },
99 .generated_files = .empty,
99100 };
100101
101102 graph.cache.addPrefix(.{ .path = null, .handle = cwd });
......@@ -242,7 +243,7 @@ const Serialize = struct {
242243 return gop.value_ptr.*;
243244 }
244245
245 fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.OptionalLazyPath {
246 fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex {
246247 const wc = s.wc;
247248 return @enumFromInt(switch (lp orelse return .none) {
248249 .src_path => |src_path| i: {
......@@ -257,6 +258,7 @@ const Serialize = struct {
257258 const sub_path = try wc.addString(generated.sub_path);
258259 break :i try wc.addExtra(@as(Configuration.LazyPath.Generated, .{
259260 .flags = .{ .up = @intCast(generated.up) },
261 .index = generated.index,
260262 .sub_path = sub_path,
261263 }));
262264 },
......@@ -278,11 +280,11 @@ const Serialize = struct {
278280 });
279281 }
280282
281 fn addOptionalLazyPath(s: *Serialize, lp: ?std.Build.LazyPath) !?Configuration.LazyPath {
283 fn addOptionalLazyPath(s: *Serialize, lp: ?std.Build.LazyPath) !?Configuration.LazyPath.Index {
282284 return (try addOptionalLazyPathEnum(s, lp)).unwrap();
283285 }
284286
285 fn addLazyPath(s: *Serialize, lp: std.Build.LazyPath) !Configuration.LazyPath {
287 fn addLazyPath(s: *Serialize, lp: std.Build.LazyPath) !Configuration.LazyPath.Index {
286288 return @enumFromInt(@intFromEnum(try addOptionalLazyPathEnum(s, lp)));
287289 }
288290
......@@ -351,8 +353,8 @@ const Serialize = struct {
351353 })));
352354 }
353355
354 fn initLazyPathList(s: *Serialize, list: []const std.Build.LazyPath) ![]const Configuration.LazyPath {
355 const result = try s.arena.alloc(Configuration.LazyPath, list.len);
356 fn initLazyPathList(s: *Serialize, list: []const std.Build.LazyPath) ![]const Configuration.LazyPath.Index {
357 const result = try s.arena.alloc(Configuration.LazyPath.Index, list.len);
356358 for (result, list) |*dest, src| dest.* = try addLazyPath(s, src);
357359 return result;
358360 }
......@@ -665,6 +667,15 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
665667 } else .none,
666668 .linker_script = c.linker_script != null,
667669 .version_script = c.version_script != null,
670 .emit_directory = c.emit_directory != .none,
671 .generated_docs = c.generated_docs != .none,
672 .generated_asm = c.generated_asm != .none,
673 .generated_bin = c.generated_bin != .none,
674 .generated_pdb = c.generated_pdb != .none,
675 .generated_implib = c.generated_implib != .none,
676 .generated_llvm_bc = c.generated_llvm_bc != .none,
677 .generated_llvm_ir = c.generated_llvm_ir != .none,
678 .generated_h = c.generated_h != .none,
668679 },
669680 .root_module = try s.addModule(c.root_module),
670681 .root_name = try wc.addString(c.name),
......@@ -709,6 +720,16 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
709720 .simple => .{ .simple = try s.addLazyPath(tr.path) },
710721 .server => .{ .server = try s.addLazyPath(tr.path) },
711722 } else .default },
723
724 .emit_directory = .{ .value = c.emit_directory.unwrap() },
725 .generated_docs = .{ .value = c.generated_docs.unwrap() },
726 .generated_asm = .{ .value = c.generated_asm.unwrap() },
727 .generated_bin = .{ .value = c.generated_bin.unwrap() },
728 .generated_pdb = .{ .value = c.generated_pdb.unwrap() },
729 .generated_implib = .{ .value = c.generated_implib.unwrap() },
730 .generated_llvm_bc = .{ .value = c.generated_llvm_bc.unwrap() },
731 .generated_llvm_ir = .{ .value = c.generated_llvm_ir.unwrap() },
732 .generated_h = .{ .value = c.generated_h.unwrap() },
712733 }));
713734
714735 break :e @enumFromInt(extra_index);
......@@ -804,6 +825,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
804825
805826 try wc.write(writer, .{
806827 .default_step = s.stepIndex(b.default_step),
828 .generated_files_len = @intCast(graph.generated_files.items.len),
807829 });
808830}
809831
lib/std/Build.zig+19-13
......@@ -1,4 +1,5 @@
11const Build = @This();
2
23const builtin = @import("builtin");
34
45const std = @import("std.zig");
......@@ -111,6 +112,14 @@ pub const Graph = struct {
111112 /// process via `Step.Run` API but cannot be observed in the configure
112113 /// phase.
113114 have_run_args: bool = false,
115
116 /// Indexes correspond to `Configuration.GeneratedFileIndex`.
117 generated_files: std.ArrayList(*Step),
118
119 pub fn addGeneratedFile(graph: *Graph, owner: *Step) Configuration.GeneratedFileIndex {
120 graph.generated_files.append(graph.arena, owner) catch @panic("OOM");
121 return @enumFromInt(graph.generated_files.items.len - 1);
122 }
114123};
115124
116125const AvailableDeps = []const struct { []const u8, []const u8 };
......@@ -865,7 +874,7 @@ pub fn dupe(b: *Build, bytes: []const u8) []u8 {
865874 return dupeInner(b.allocator, bytes);
866875}
867876
868pub fn dupeInner(allocator: std.mem.Allocator, bytes: []const u8) []u8 {
877pub fn dupeInner(allocator: Allocator, bytes: []const u8) []u8 {
869878 return allocator.dupe(u8, bytes) catch @panic("OOM");
870879}
871880
......@@ -881,7 +890,7 @@ pub fn dupePath(b: *Build, bytes: []const u8) []u8 {
881890 return dupePathInner(b.allocator, bytes);
882891}
883892
884fn dupePathInner(allocator: std.mem.Allocator, bytes: []const u8) []u8 {
893fn dupePathInner(allocator: Allocator, bytes: []const u8) []u8 {
885894 const the_copy = dupeInner(allocator, bytes);
886895 for (the_copy) |*byte| {
887896 switch (byte.*) {
......@@ -2068,13 +2077,6 @@ pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void {
20682077 }
20692078}
20702079
2071/// A file that is generated by a build step.
2072/// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic.
2073pub const GeneratedFile = struct {
2074 /// The step that generates the file.
2075 step: *Step,
2076};
2077
20782080// dirnameAllowEmpty is a variant of fs.path.dirname
20792081// that allows "" to refer to the root for relative paths.
20802082//
......@@ -2114,7 +2116,7 @@ pub const LazyPath = union(enum) {
21142116 },
21152117
21162118 generated: struct {
2117 file: *const GeneratedFile,
2119 index: Configuration.GeneratedFileIndex,
21182120
21192121 /// The number of parent directories to go up.
21202122 /// 0 means the generated file itself.
......@@ -2242,7 +2244,11 @@ pub const LazyPath = union(enum) {
22422244 pub fn addStepDependencies(lazy_path: LazyPath, other_step: *Step) void {
22432245 switch (lazy_path) {
22442246 .src_path, .cwd_relative, .dependency => {},
2245 .generated => |gen| other_step.dependOn(gen.file.step),
2247 .generated => |gen| {
2248 const graph = other_step.owner.graph;
2249 const generated_owner_step = graph.generated_files.items[@intFromEnum(gen.index)];
2250 other_step.dependOn(generated_owner_step);
2251 },
22462252 }
22472253 }
22482254
......@@ -2266,7 +2272,7 @@ pub const LazyPath = union(enum) {
22662272 return lazy_path.dupeInner(b.allocator);
22672273 }
22682274
2269 fn dupeInner(lazy_path: LazyPath, allocator: std.mem.Allocator) LazyPath {
2275 fn dupeInner(lazy_path: LazyPath, allocator: Allocator) LazyPath {
22702276 return switch (lazy_path) {
22712277 .src_path => |sp| .{ .src_path = .{
22722278 .owner = sp.owner,
......@@ -2274,7 +2280,7 @@ pub const LazyPath = union(enum) {
22742280 } },
22752281 .cwd_relative => |p| .{ .cwd_relative = dupePathInner(allocator, p) },
22762282 .generated => |gen| .{ .generated = .{
2277 .file = gen.file,
2283 .index = gen.index,
22782284 .up = gen.up,
22792285 .sub_path = dupePathInner(allocator, gen.sub_path),
22802286 } },
lib/std/Build/Module.zig+2-139
......@@ -89,7 +89,8 @@ pub const CSourceLanguage = enum {
8989 /// Assembly with the C preprocessor
9090 assembly_with_preprocessor,
9191
92 pub fn internalIdentifier(self: CSourceLanguage) []const u8 {
92 /// The value passed to "-x" CLI flag of Clang.
93 pub fn clangIdentifier(self: CSourceLanguage) [:0]const u8 {
9394 return switch (self) {
9495 .c => "c",
9596 .cpp => "c++",
......@@ -164,33 +165,6 @@ pub const IncludeDir = union(enum) {
164165 other_step: *Step.Compile,
165166 config_header_step: *Step.ConfigHeader,
166167 embed_path: LazyPath,
167
168 pub fn appendZigProcessFlags(
169 include_dir: IncludeDir,
170 b: *std.Build,
171 zig_args: *std.array_list.Managed([]const u8),
172 asking_step: ?*Step,
173 ) !void {
174 const flag: []const u8, const lazy_path: LazyPath = switch (include_dir) {
175 // zig fmt: off
176 .path => |lp| .{ "-I", lp },
177 .path_system => |lp| .{ "-isystem", lp },
178 .path_after => |lp| .{ "-idirafter", lp },
179 .framework_path => |lp| .{ "-F", lp },
180 .framework_path_system => |lp| .{ "-iframework", lp },
181 .config_header_step => |ch| .{ "-I", ch.getOutputDir() },
182 .other_step => |comp| .{ "-I", comp.installed_headers_include_tree.?.getDirectory() },
183 // zig fmt: on
184 .embed_path => |lazy_path| {
185 // Special case: this is a single arg.
186 const resolved = lazy_path.getPath3(b, asking_step);
187 const arg = b.fmt("--embed-dir={f}", .{resolved});
188 return zig_args.append(arg);
189 },
190 };
191 const resolved_str = try lazy_path.getPath3(b, asking_step).toString(b.graph.arena);
192 return zig_args.appendSlice(&.{ flag, resolved_str });
193 }
194168};
195169
196170pub const LinkFrameworkOptions = struct {
......@@ -533,117 +507,6 @@ pub fn addCMacro(m: *Module, name: []const u8, value: []const u8) void {
533507 m.c_macros.append(b.allocator, b.fmt("-D{s}={s}", .{ name, value })) catch @panic("OOM");
534508}
535509
536pub fn appendZigProcessFlags(
537 m: *Module,
538 zig_args: *std.array_list.Managed([]const u8),
539 asking_step: ?*Step,
540) !void {
541 const b = m.owner;
542
543 try addFlag(zig_args, m.strip, "-fstrip", "-fno-strip");
544 try addFlag(zig_args, m.single_threaded, "-fsingle-threaded", "-fno-single-threaded");
545 try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check");
546 try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector");
547 try addFlag(zig_args, m.omit_frame_pointer, "-fomit-frame-pointer", "-fno-omit-frame-pointer");
548 try addFlag(zig_args, m.error_tracing, "-ferror-tracing", "-fno-error-tracing");
549 try addFlag(zig_args, m.sanitize_thread, "-fsanitize-thread", "-fno-sanitize-thread");
550 try addFlag(zig_args, m.fuzz, "-ffuzz", "-fno-fuzz");
551 try addFlag(zig_args, m.valgrind, "-fvalgrind", "-fno-valgrind");
552 try addFlag(zig_args, m.pic, "-fPIC", "-fno-PIC");
553 try addFlag(zig_args, m.red_zone, "-mred-zone", "-mno-red-zone");
554 try addFlag(zig_args, m.no_builtin, "-fno-builtin", "-fbuiltin");
555
556 if (m.sanitize_c) |sc| switch (sc) {
557 .off => try zig_args.append("-fno-sanitize-c"),
558 .trap => try zig_args.append("-fsanitize-c=trap"),
559 .full => try zig_args.append("-fsanitize-c=full"),
560 };
561
562 if (m.dwarf_format) |dwarf_format| {
563 try zig_args.append(switch (dwarf_format) {
564 .@"32" => "-gdwarf32",
565 .@"64" => "-gdwarf64",
566 });
567 }
568
569 if (m.unwind_tables) |unwind_tables| {
570 try zig_args.append(switch (unwind_tables) {
571 .none => "-fno-unwind-tables",
572 .sync => "-funwind-tables",
573 .async => "-fasync-unwind-tables",
574 });
575 }
576
577 try zig_args.ensureUnusedCapacity(1);
578 if (m.optimize) |optimize| switch (optimize) {
579 .Debug => zig_args.appendAssumeCapacity("-ODebug"),
580 .ReleaseSmall => zig_args.appendAssumeCapacity("-OReleaseSmall"),
581 .ReleaseFast => zig_args.appendAssumeCapacity("-OReleaseFast"),
582 .ReleaseSafe => zig_args.appendAssumeCapacity("-OReleaseSafe"),
583 };
584
585 if (m.code_model != .default) {
586 try zig_args.append("-mcmodel");
587 try zig_args.append(@tagName(m.code_model));
588 }
589
590 if (m.resolved_target) |*target| {
591 // Communicate the query via CLI since it's more compact.
592 if (!target.query.isNative()) {
593 try zig_args.appendSlice(&.{
594 "-target", try target.query.zigTriple(b.allocator),
595 "-mcpu", try target.query.serializeCpuAlloc(b.allocator),
596 });
597 if (target.query.dynamic_linker) |*dynamic_linker| {
598 if (dynamic_linker.get()) |dynamic_linker_path| {
599 try zig_args.append("--dynamic-linker");
600 try zig_args.append(dynamic_linker_path);
601 } else {
602 try zig_args.append("--no-dynamic-linker");
603 }
604 }
605 }
606 }
607
608 for (m.export_symbol_names) |symbol_name| {
609 try zig_args.append(b.fmt("--export={s}", .{symbol_name}));
610 }
611
612 for (m.include_dirs.items) |include_dir| {
613 try include_dir.appendZigProcessFlags(b, zig_args, asking_step);
614 }
615
616 try zig_args.appendSlice(m.c_macros.items);
617
618 try zig_args.ensureUnusedCapacity(2 * m.lib_paths.items.len);
619 for (m.lib_paths.items) |lib_path| {
620 zig_args.appendAssumeCapacity("-L");
621 zig_args.appendAssumeCapacity(lib_path.getPath2(b, asking_step));
622 }
623
624 try zig_args.ensureUnusedCapacity(2 * m.rpaths.items.len);
625 for (m.rpaths.items) |rpath| switch (rpath) {
626 .lazy_path => |lp| {
627 zig_args.appendAssumeCapacity("-rpath");
628 zig_args.appendAssumeCapacity(lp.getPath2(b, asking_step));
629 },
630 .special => |bytes| {
631 zig_args.appendAssumeCapacity("-rpath");
632 zig_args.appendAssumeCapacity(bytes);
633 },
634 };
635}
636
637fn addFlag(
638 args: *std.array_list.Managed([]const u8),
639 opt: ?bool,
640 then_name: []const u8,
641 else_name: []const u8,
642) !void {
643 const cond = opt orelse return;
644 return args.append(if (cond) then_name else else_name);
645}
646
647510fn linkLibraryOrObject(m: *Module, other: *Step.Compile) void {
648511 const allocator = m.owner.allocator;
649512 _ = other.getEmittedBin(); // Indicate there is a dependency on the outputted binary.
lib/std/Build/Step/Compile.zig+26-77
......@@ -1,4 +1,5 @@
11const Compile = @This();
2
23const builtin = @import("builtin");
34
45const std = @import("std");
......@@ -13,8 +14,8 @@ const Step = std.Build.Step;
1314const LazyPath = std.Build.LazyPath;
1415const Module = std.Build.Module;
1516const InstallDir = std.Build.InstallDir;
16const GeneratedFile = std.Build.GeneratedFile;
1717const Path = std.Build.Cache.Path;
18const Configuration = std.Build.Configuration;
1819
1920pub const base_tag: Step.Tag = .compile;
2021
......@@ -212,19 +213,6 @@ allow_so_scripts: ?bool = null,
212213/// otherwise.
213214expect_errors: ?ExpectedCompileErrors = null,
214215
215emit_directory: ?*GeneratedFile,
216
217generated_docs: ?*GeneratedFile,
218generated_asm: ?*GeneratedFile,
219generated_bin: ?*GeneratedFile,
220generated_pdb: ?*GeneratedFile,
221// hack for stage2_x86_64 + coff
222generated_compiler_rt_dyn_lib: ?*GeneratedFile,
223generated_implib: ?*GeneratedFile,
224generated_llvm_bc: ?*GeneratedFile,
225generated_llvm_ir: ?*GeneratedFile,
226generated_h: ?*GeneratedFile,
227
228216/// The maximum number of distinct errors within a compilation step Defaults to
229217/// `std.math.maxInt(u16)`. Overrides the argument passed to `zig build`.
230218error_limit: ?u32 = null,
......@@ -248,6 +236,16 @@ is_linking_libcpp: bool = false,
248236/// builtin fuzzer, see the `fuzz` flag in `Module`.
249237sanitize_coverage_trace_pc_guard: ?bool = null,
250238
239emit_directory: Configuration.OptionalGeneratedFileIndex = .none,
240generated_docs: Configuration.OptionalGeneratedFileIndex = .none,
241generated_asm: Configuration.OptionalGeneratedFileIndex = .none,
242generated_bin: Configuration.OptionalGeneratedFileIndex = .none,
243generated_pdb: Configuration.OptionalGeneratedFileIndex = .none,
244generated_implib: Configuration.OptionalGeneratedFileIndex = .none,
245generated_llvm_bc: Configuration.OptionalGeneratedFileIndex = .none,
246generated_llvm_ir: Configuration.OptionalGeneratedFileIndex = .none,
247generated_h: Configuration.OptionalGeneratedFileIndex = .none,
248
251249pub const ExpectedCompileErrors = union(enum) {
252250 contains: []const u8,
253251 exact: []const []const u8,
......@@ -291,7 +289,7 @@ pub const Options = struct {
291289 entitlements: ?LazyPath = null,
292290};
293291
294pub const Kind = std.Build.Configuration.Step.Compile.Kind;
292pub const Kind = Configuration.Step.Compile.Kind;
295293
296294pub const HeaderInstallation = union(enum) {
297295 file: File,
......@@ -362,6 +360,9 @@ pub const TestRunner = struct {
362360};
363361
364362pub fn create(owner: *std.Build, options: Options) *Compile {
363 const graph = owner.graph;
364 const arena = graph.arena;
365
365366 const name = owner.dupe(options.name);
366367 if (mem.find(u8, name, "/") != null or mem.find(u8, name, "\\") != null) {
367368 panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});
......@@ -376,12 +377,12 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
376377 if (options.kind.isTest() and mem.eql(u8, name, "test"))
377378 @tagName(options.kind)
378379 else
379 owner.fmt("{s} {s}", .{ @tagName(options.kind), name }),
380 owner.fmt("{t} {s}", .{ options.kind, name }),
380381 @tagName(options.root_module.optimize orelse .Debug),
381 resolved_target.query.zigTriple(owner.allocator) catch @panic("OOM"),
382 resolved_target.query.zigTriple(arena) catch @panic("OOM"),
382383 });
383384
384 const out_filename = std.zig.binNameAlloc(owner.allocator, .{
385 const out_filename = std.zig.binNameAlloc(arena, .{
385386 .root_name = name,
386387 .target = target,
387388 .output_mode = switch (options.kind) {
......@@ -393,7 +394,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
393394 .version = options.version,
394395 }) catch @panic("OOM");
395396
396 const compile = owner.allocator.create(Compile) catch @panic("OOM");
397 const compile = arena.create(Compile) catch @panic("OOM");
397398 compile.* = .{
398399 .root_module = options.root_module,
399400 .verbose_link = false,
......@@ -420,17 +421,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
420421 .rdynamic = false,
421422 .force_undefined_symbols = .empty,
422423
423 .emit_directory = null,
424 .generated_docs = null,
425 .generated_asm = null,
426 .generated_bin = null,
427 .generated_pdb = null,
428 .generated_compiler_rt_dyn_lib = null,
429 .generated_implib = null,
430 .generated_llvm_bc = null,
431 .generated_llvm_ir = null,
432 .generated_h = null,
433
434424 .use_llvm = options.use_llvm,
435425 .use_lld = options.use_lld,
436426 .use_new_linker = null,
......@@ -706,13 +696,12 @@ pub fn setLibCFile(compile: *Compile, libc_file: ?LazyPath) void {
706696 }
707697}
708698
709fn getEmittedFileGeneric(compile: *Compile, output_file: *?*GeneratedFile) LazyPath {
710 if (output_file.*) |file| return .{ .generated = .{ .file = file } };
711 const arena = compile.step.owner.allocator;
712 const generated_file = arena.create(GeneratedFile) catch @panic("OOM");
713 generated_file.* = .{ .step = &compile.step };
714 output_file.* = generated_file;
715 return .{ .generated = .{ .file = generated_file } };
699fn getEmittedFileGeneric(compile: *Compile, output_file: *Configuration.OptionalGeneratedFileIndex) LazyPath {
700 if (output_file.unwrap()) |index| return .{ .generated = .{ .index = index } };
701 const graph = compile.step.owner.graph;
702 const index = graph.addGeneratedFile(&compile.step);
703 output_file.* = .init(index);
704 return .{ .generated = .{ .index = index } };
716705}
717706
718707/// Returns the path to the directory that contains the emitted binary file.
......@@ -785,46 +774,6 @@ pub fn setExecCmd(compile: *Compile, args: []const ?[]const u8) void {
785774 compile.exec_cmd_args = duped_args;
786775}
787776
788fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) ![]const u8 {
789 const step = &compile.step;
790 const b = step.owner;
791 const graph = b.graph;
792 const io = graph.io;
793 const maybe_path: ?*GeneratedFile = @field(compile, tag_name);
794
795 const generated_file = maybe_path orelse {
796 const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
797 std.Build.dumpBadGetPathHelp(&compile.step, stderr.terminal(), compile.step.owner, asking_step) catch {};
798 io.unlockStderr();
799 @panic("missing emit option for " ++ tag_name);
800 };
801
802 const path = generated_file.path orelse {
803 const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
804 std.Build.dumpBadGetPathHelp(&compile.step, stderr.terminal(), compile.step.owner, asking_step) catch {};
805 io.unlockStderr();
806 @panic(tag_name ++ " is null. Is there a missing step dependency?");
807 };
808
809 return path;
810}
811
812fn outputPath(c: *Compile, out_dir: std.Build.Cache.Path, ea: std.zig.EmitArtifact) []const u8 {
813 const arena = c.step.owner.graph.arena;
814 const name = ea.cacheName(arena, .{
815 .root_name = c.name,
816 .target = &c.root_module.resolved_target.?.result,
817 .output_mode = switch (c.kind) {
818 .lib => .Lib,
819 .obj, .test_obj => .Obj,
820 .exe, .@"test" => .Exe,
821 },
822 .link_mode = c.linkage,
823 .version = c.version,
824 }) catch @panic("OOM");
825 return out_dir.joinString(arena, name) catch @panic("OOM");
826}
827
828777pub fn rootModuleTarget(c: *Compile) std.Target {
829778 // The root module is always given a target, so we know this to be non-null.
830779 return c.root_module.resolved_target.?.result;
lib/std/Build/Step/ConfigHeader.zig+9-8
......@@ -5,6 +5,7 @@ const Io = std.Io;
55const Step = std.Build.Step;
66const Allocator = std.mem.Allocator;
77const Writer = std.Io.Writer;
8const Configuration = std.Build.Configuration;
89
910pub const Style = union(enum) {
1011 /// A configure format supported by autotools that uses `#undef foo` to
......@@ -40,7 +41,7 @@ pub const Value = union(enum) {
4041step: Step,
4142values: std.array_hash_map.String(Value),
4243/// This directory contains the generated file under the name `include_path`.
43generated_dir: std.Build.GeneratedFile,
44generated_dir: Configuration.GeneratedFileIndex,
4445
4546style: Style,
4647max_bytes: usize,
......@@ -58,7 +59,9 @@ pub const Options = struct {
5859};
5960
6061pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
61 const config_header = owner.allocator.create(ConfigHeader) catch @panic("OOM");
62 const graph = owner.graph;
63 const arena = graph.arena;
64 const config_header = arena.create(ConfigHeader) catch @panic("OOM");
6265
6366 var include_path: []const u8 = "config.h";
6467
......@@ -80,11 +83,9 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
8083 }
8184
8285 const name = if (options.style.getPath()) |s|
83 owner.fmt("configure {s} header {s} to {s}", .{
84 @tagName(options.style), s.getDisplayName(), include_path,
85 })
86 owner.fmt("configure {t} header {s} to {s}", .{ options.style, s.getDisplayName(), include_path })
8687 else
87 owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path });
88 owner.fmt("configure {t} header to {s}", .{ options.style, include_path });
8889
8990 config_header.* = .{
9091 .step = .init(.{
......@@ -100,7 +101,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
100101 .max_bytes = options.max_bytes,
101102 .include_path = include_path,
102103 .include_guard_override = options.include_guard_override,
103 .generated_dir = .{ .step = &config_header.step },
104 .generated_dir = graph.addGeneratedFile(&config_header.step),
104105 };
105106
106107 if (options.style.getPath()) |s| {
......@@ -125,7 +126,7 @@ pub fn addValues(config_header: *ConfigHeader, values: anytype) void {
125126}
126127
127128pub fn getOutputDir(ch: *ConfigHeader) std.Build.LazyPath {
128 return .{ .generated = .{ .file = &ch.generated_dir } };
129 return .{ .generated = .{ .index = &ch.generated_dir } };
129130}
130131pub fn getOutputFile(ch: *ConfigHeader) std.Build.LazyPath {
131132 return ch.getOutputDir().path(ch.step.owner, ch.include_path);
lib/std/Build/Step/ObjCopy.zig+14-7
......@@ -9,6 +9,7 @@ const Step = std.Build.Step;
99const elf = std.elf;
1010const fs = std.fs;
1111const sort = std.sort;
12const Configuration = std.Build.Configuration;
1213
1314pub const base_tag: Step.Tag = .objcopy;
1415
......@@ -71,8 +72,8 @@ pub const SetSectionFlags = struct {
7172step: Step,
7273input_file: std.Build.LazyPath,
7374basename: []const u8,
74output_file: std.Build.GeneratedFile,
75output_file_debug: ?std.Build.GeneratedFile,
75output_file: Configuration.GeneratedFileIndex,
76output_file_debug: Configuration.OptionalGeneratedFileIndex,
7677
7778format: ?RawFormat,
7879only_section: ?[]const u8,
......@@ -108,7 +109,10 @@ pub fn create(
108109 input_file: std.Build.LazyPath,
109110 options: Options,
110111) *ObjCopy {
111 const objcopy = owner.allocator.create(ObjCopy) catch @panic("OOM");
112 const graph = owner.graph;
113 const arena = graph.arena;
114
115 const objcopy = arena.create(ObjCopy) catch @panic("OOM");
112116 objcopy.* = ObjCopy{
113117 .step = Step.init(.{
114118 .tag = base_tag,
......@@ -118,8 +122,11 @@ pub fn create(
118122 }),
119123 .input_file = input_file,
120124 .basename = options.basename orelse input_file.getDisplayName(),
121 .output_file = std.Build.GeneratedFile{ .step = &objcopy.step },
122 .output_file_debug = if (options.strip != .none and options.extract_to_separate_file) std.Build.GeneratedFile{ .step = &objcopy.step } else null,
125 .output_file = graph.addGeneratedFile(&objcopy.step),
126 .output_file_debug = if (options.strip != .none and options.extract_to_separate_file)
127 .init(graph.addGeneratedFile(&objcopy.step))
128 else
129 .none,
123130 .format = options.format,
124131 .only_section = options.only_section,
125132 .pad_to = options.pad_to,
......@@ -134,10 +141,10 @@ pub fn create(
134141}
135142
136143pub fn getOutput(objcopy: *const ObjCopy) std.Build.LazyPath {
137 return .{ .generated = .{ .file = &objcopy.output_file } };
144 return .{ .generated = .{ .index = objcopy.output_file } };
138145}
139146pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath {
140 return if (objcopy.output_file_debug) |*file| .{ .generated = .{ .file = file } } else null;
147 return if (objcopy.output_file_debug.unwrap()) |index| .{ .generated = .{ .index = index } } else null;
141148}
142149
143150fn make(step: *Step, options: Step.MakeOptions) !void {
lib/std/Build/Step/Options.zig+9-6
......@@ -1,24 +1,28 @@
11const Options = @This();
2
23const builtin = @import("builtin");
34
45const std = @import("std");
56const Io = std.Io;
67const fs = std.fs;
78const Step = std.Build.Step;
8const GeneratedFile = std.Build.GeneratedFile;
99const LazyPath = std.Build.LazyPath;
10const Configuration = std.Build.Configuration;
1011
1112pub const base_tag: Step.Tag = .options;
1213
1314step: Step,
14generated_file: GeneratedFile,
15generated_file: Configuration.GeneratedFileIndex,
1516
1617contents: std.ArrayList(u8),
1718args: std.ArrayList(Arg),
1819encountered_types: std.StringHashMapUnmanaged(void),
1920
2021pub fn create(owner: *std.Build) *Options {
21 const options = owner.allocator.create(Options) catch @panic("OOM");
22 const graph = owner.graph;
23 const arena = graph.arena;
24
25 const options = arena.create(Options) catch @panic("OOM");
2226 options.* = .{
2327 .step = .init(.{
2428 .tag = base_tag,
......@@ -26,12 +30,11 @@ pub fn create(owner: *std.Build) *Options {
2630 .owner = owner,
2731 .makeFn = make,
2832 }),
29 .generated_file = undefined,
33 .generated_file = graph.addGeneratedFile(&options.step),
3034 .contents = .empty,
3135 .args = .empty,
3236 .encountered_types = .empty,
3337 };
34 options.generated_file = .{ .step = &options.step };
3538
3639 return options;
3740}
......@@ -434,7 +437,7 @@ pub fn createModule(options: *Options) *std.Build.Module {
434437/// Returns the main artifact of this Build Step which is a Zig source file
435438/// generated from the key-value pairs of the Options.
436439pub fn getOutput(options: *Options) LazyPath {
437 return .{ .generated = .{ .file = &options.generated_file } };
440 return .{ .generated = .{ .index = options.generated_file } };
438441}
439442
440443fn make(step: *Step, make_options: Step.MakeOptions) !void {
lib/std/Build/Step/Run.zig+26-17
......@@ -11,6 +11,7 @@ const process = std.process;
1111const EnvMap = std.process.Environ.Map;
1212const assert = std.debug.assert;
1313const Path = std.Build.Cache.Path;
14const Configuration = std.Build.Configuration;
1415
1516pub const base_tag: Step.Tag = .run;
1617
......@@ -162,7 +163,7 @@ pub const DecoratedLazyPath = struct {
162163};
163164
164165pub const Output = struct {
165 generated_file: std.Build.GeneratedFile,
166 generated_file: Configuration.GeneratedFileIndex,
166167 prefix: []const u8,
167168 basename: []const u8,
168169};
......@@ -272,21 +273,23 @@ pub fn addPrefixedOutputFileArg(
272273 basename: []const u8,
273274) std.Build.LazyPath {
274275 const b = run.step.owner;
276 const graph = b.graph;
277 const arena = graph.arena;
275278 if (basename.len == 0) @panic("basename must not be empty");
276279
277 const output = b.allocator.create(Output) catch @panic("OOM");
280 const output = arena.create(Output) catch @panic("OOM");
278281 output.* = .{
279282 .prefix = b.dupe(prefix),
280283 .basename = b.dupe(basename),
281 .generated_file = .{ .step = &run.step },
284 .generated_file = graph.addGeneratedFile(&run.step),
282285 };
283 run.argv.append(b.allocator, .{ .output_file = output }) catch @panic("OOM");
286 run.argv.append(arena, .{ .output_file = output }) catch @panic("OOM");
284287
285288 if (run.rename_step_with_output_arg) {
286289 run.setName(b.fmt("{s} ({s})", .{ run.step.name, basename }));
287290 }
288291
289 return .{ .generated = .{ .file = &output.generated_file } };
292 return .{ .generated = .{ .index = output.generated_file } };
290293}
291294
292295/// Appends an input file to the command line arguments.
......@@ -470,20 +473,22 @@ pub fn addDepFileOutputArg(run: *Run, basename: []const u8) std.Build.LazyPath {
470473/// Only one dep file argument is allowed by instance.
471474pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []const u8) std.Build.LazyPath {
472475 const b = run.step.owner;
476 const graph = b.graph;
477 const arena = graph.arena;
473478 assert(run.dep_output_file == null);
474479
475 const dep_file = b.allocator.create(Output) catch @panic("OOM");
480 const dep_file = arena.create(Output) catch @panic("OOM");
476481 dep_file.* = .{
477482 .prefix = b.dupe(prefix),
478483 .basename = b.dupe(basename),
479 .generated_file = .{ .step = &run.step },
484 .generated_file = graph.addGeneratedFile(&run.step),
480485 };
481486
482487 run.dep_output_file = dep_file;
483488
484 run.argv.append(b.allocator, .{ .output_file = dep_file }) catch @panic("OOM");
489 run.argv.append(arena, .{ .output_file = dep_file }) catch @panic("OOM");
485490
486 return .{ .generated = .{ .file = &dep_file.generated_file } };
491 return .{ .generated = .{ .index = dep_file.generated_file } };
487492}
488493
489494pub fn addArg(run: *Run, arg: []const u8) void {
......@@ -627,20 +632,22 @@ pub fn captureStdErr(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPa
627632 assert(run.stdio != .zig_test);
628633
629634 const b = run.step.owner;
635 const graph = b.graph;
636 const arena = graph.arena;
630637
631 if (run.captured_stderr) |captured| return .{ .generated = .{ .file = &captured.output.generated_file } };
638 if (run.captured_stderr) |captured| return .{ .generated = .{ .index = captured.output.generated_file } };
632639
633 const captured = b.allocator.create(CapturedStdIo) catch @panic("OOM");
640 const captured = arena.create(CapturedStdIo) catch @panic("OOM");
634641 captured.* = .{
635642 .output = .{
636643 .prefix = "",
637644 .basename = if (options.basename) |basename| b.dupe(basename) else "stderr",
638 .generated_file = .{ .step = &run.step },
645 .generated_file = graph.addGeneratedFile(&run.step),
639646 },
640647 .trim_whitespace = options.trim_whitespace,
641648 };
642649 run.captured_stderr = captured;
643 return .{ .generated = .{ .file = &captured.output.generated_file } };
650 return .{ .generated = .{ .index = captured.output.generated_file } };
644651}
645652
646653pub fn captureStdOut(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPath {
......@@ -648,20 +655,22 @@ pub fn captureStdOut(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPa
648655 assert(run.stdio != .zig_test);
649656
650657 const b = run.step.owner;
658 const graph = b.graph;
659 const arena = graph.arena;
651660
652 if (run.captured_stdout) |captured| return .{ .generated = .{ .file = &captured.output.generated_file } };
661 if (run.captured_stdout) |captured| return .{ .generated = .{ .index = captured.output.generated_file } };
653662
654 const captured = b.allocator.create(CapturedStdIo) catch @panic("OOM");
663 const captured = arena.create(CapturedStdIo) catch @panic("OOM");
655664 captured.* = .{
656665 .output = .{
657666 .prefix = "",
658667 .basename = if (options.basename) |basename| b.dupe(basename) else "stdout",
659 .generated_file = .{ .step = &run.step },
668 .generated_file = graph.addGeneratedFile(&run.step),
660669 },
661670 .trim_whitespace = options.trim_whitespace,
662671 };
663672 run.captured_stdout = captured;
664 return .{ .generated = .{ .file = &captured.output.generated_file } };
673 return .{ .generated = .{ .index = captured.output.generated_file } };
665674}
666675
667676/// Adds an additional input files that, when modified, indicates that this Run
lib/std/Build/Step/TranslateC.zig+11-8
......@@ -1,10 +1,11 @@
1const TranslateC = @This();
2
13const std = @import("std");
24const Step = std.Build.Step;
35const LazyPath = std.Build.LazyPath;
46const fs = std.fs;
57const mem = std.mem;
6
7const TranslateC = @This();
8const Configuration = std.Build.Configuration;
89
910pub const base_tag: Step.Tag = .translate_c;
1011
......@@ -16,7 +17,7 @@ c_macros: std.array_list.Managed([]const u8),
1617out_basename: []const u8,
1718target: std.Build.ResolvedTarget,
1819optimize: std.builtin.OptimizeMode,
19output_file: std.Build.GeneratedFile,
20output_file: Configuration.GeneratedFileIndex,
2021link_libc: bool,
2122
2223pub const Options = struct {
......@@ -27,7 +28,9 @@ pub const Options = struct {
2728};
2829
2930pub fn create(owner: *std.Build, options: Options) *TranslateC {
30 const translate_c = owner.allocator.create(TranslateC) catch @panic("OOM");
31 const graph = owner.graph;
32 const arena = graph.arena;
33 const translate_c = arena.create(TranslateC) catch @panic("OOM");
3134 const source = options.root_source_file.dupe(owner);
3235 translate_c.* = .{
3336 .step = Step.init(.{
......@@ -37,12 +40,12 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC {
3740 .makeFn = make,
3841 }),
3942 .source = source,
40 .include_dirs = std.array_list.Managed(std.Build.Module.IncludeDir).init(owner.allocator),
41 .c_macros = std.array_list.Managed([]const u8).init(owner.allocator),
43 .include_dirs = std.array_list.Managed(std.Build.Module.IncludeDir).init(arena),
44 .c_macros = std.array_list.Managed([]const u8).init(arena),
4245 .out_basename = undefined,
4346 .target = options.target,
4447 .optimize = options.optimize,
45 .output_file = .{ .step = &translate_c.step },
48 .output_file = graph.addGeneratedFile(&translate_c.step),
4649 .link_libc = options.link_libc,
4750 .system_libs = .empty,
4851 };
......@@ -59,7 +62,7 @@ pub const AddExecutableOptions = struct {
5962};
6063
6164pub fn getOutput(translate_c: *TranslateC) std.Build.LazyPath {
62 return .{ .generated = .{ .file = &translate_c.output_file } };
65 return .{ .generated = .{ .index = translate_c.output_file } };
6366}
6467
6568/// Creates a module from the translated source and adds it to the package's
lib/std/Build/Step/WriteFile.zig+10-8
......@@ -9,13 +9,13 @@ const Dir = std.Io.Dir;
99const Step = std.Build.Step;
1010const ArrayList = std.ArrayList;
1111const assert = std.debug.assert;
12const Configuration = std.Build.Configuration;
1213
1314step: Step,
1415
15/// The elements here are pointers because we need stable pointers for the GeneratedFile field.
1616files: std.ArrayList(File),
1717directories: std.ArrayList(Directory),
18generated_directory: std.Build.GeneratedFile,
18generated_directory: Configuration.GeneratedFileIndex,
1919mode: Mode = .whole_cached,
2020
2121pub const base_tag: Step.Tag = .write_file;
......@@ -86,7 +86,9 @@ pub const Contents = union(enum) {
8686};
8787
8888pub fn create(owner: *std.Build) *WriteFile {
89 const write_file = owner.allocator.create(WriteFile) catch @panic("OOM");
89 const graph = owner.graph;
90 const arena = graph.arena;
91 const write_file = arena.create(WriteFile) catch @panic("OOM");
9092 write_file.* = .{
9193 .step = Step.init(.{
9294 .tag = base_tag,
......@@ -95,7 +97,7 @@ pub fn create(owner: *std.Build) *WriteFile {
9597 }),
9698 .files = .empty,
9799 .directories = .empty,
98 .generated_directory = .{ .step = &write_file.step },
100 .generated_directory = graph.addGeneratedFile(&write_file.step),
99101 };
100102 return write_file;
101103}
......@@ -111,7 +113,7 @@ pub fn add(write_file: *WriteFile, sub_path: []const u8, bytes: []const u8) std.
111113 write_file.maybeUpdateName();
112114 return .{
113115 .generated = .{
114 .file = &write_file.generated_directory,
116 .index = write_file.generated_directory,
115117 .sub_path = file.sub_path,
116118 },
117119 };
......@@ -137,7 +139,7 @@ pub fn addCopyFile(write_file: *WriteFile, source: std.Build.LazyPath, sub_path:
137139 source.addStepDependencies(&write_file.step);
138140 return .{
139141 .generated = .{
140 .file = &write_file.generated_directory,
142 .index = write_file.generated_directory,
141143 .sub_path = file.sub_path,
142144 },
143145 };
......@@ -165,7 +167,7 @@ pub fn addCopyDirectory(
165167 source.addStepDependencies(&write_file.step);
166168 return .{
167169 .generated = .{
168 .file = &write_file.generated_directory,
170 .index = write_file.generated_directory,
169171 .sub_path = dir.sub_path,
170172 },
171173 };
......@@ -174,7 +176,7 @@ pub fn addCopyDirectory(
174176/// Returns a `LazyPath` representing the base directory that contains all the
175177/// files from this `WriteFile`.
176178pub fn getDirectory(write_file: *WriteFile) std.Build.LazyPath {
177 return .{ .generated = .{ .file = &write_file.generated_directory } };
179 return .{ .generated = .{ .index = write_file.generated_directory } };
178180}
179181
180182fn maybeUpdateName(write_file: *WriteFile) void {
lib/std/zig/Configuration.zig+201-67
......@@ -15,6 +15,7 @@ system_integrations: []SystemIntegration,
1515available_options: []AvailableOption,
1616extra: []u32,
1717default_step: Step.Index,
18generated_files_len: u32,
1819
1920/// The field order here matches `Configuration` which documents the order in
2021/// the serialized format.
......@@ -28,6 +29,9 @@ pub const Header = extern struct {
2829 extra_len: u32,
2930
3031 default_step: Step.Index,
32 /// There is not actually any data stored for this - it just provides a way
33 /// for maker process to preallocate an array for these.
34 generated_files_len: u32,
3135};
3236
3337pub const Wip = struct {
......@@ -44,6 +48,7 @@ pub const Wip = struct {
4448 steps: std.ArrayList(Step) = .empty,
4549 path_deps: std.MultiArrayList(Path) = .empty,
4650 extra: std.ArrayList(u32) = .empty,
51 next_generated_file_index: u32 = 0,
4752
4853 const DedupeTable = std.HashMapUnmanaged(ExtraSlice, void, ExtraSlice.Context, std.hash_map.default_max_load_percentage);
4954 const TargetsTable = std.HashMapUnmanaged(TargetQuery.Index, void, TargetsTableContext, std.hash_map.default_max_load_percentage);
......@@ -127,6 +132,7 @@ pub const Wip = struct {
127132
128133 pub const Static = struct {
129134 default_step: Step.Index,
135 generated_files_len: u32,
130136 };
131137
132138 pub fn write(wip: *Wip, w: *Io.Writer, static: Static) Io.Writer.Error!void {
......@@ -140,6 +146,7 @@ pub const Wip = struct {
140146 .extra_len = @intCast(wip.extra.items.len),
141147
142148 .default_step = static.default_step,
149 .generated_files_len = static.generated_files_len,
143150 };
144151 var buffers = [_][]const u8{
145152 @ptrCast(&header),
......@@ -363,6 +370,11 @@ pub const Wip = struct {
363370 const string = optional_string orelse return;
364371 wip.extra.appendAssumeCapacity(@intFromEnum(string));
365372 }
373
374 pub fn addGeneratedFile(wip: *Wip) GeneratedFileIndex {
375 defer wip.next_generated_file_index += 1;
376 return @enumFromInt(wip.next_generated_file_index);
377 }
366378};
367379
368380pub const SystemIntegration = extern struct {
......@@ -471,16 +483,16 @@ pub const Step = extern struct {
471483
472484 dest_dir: InstallDestDir,
473485 dest_sub_path: String,
474 emitted_bin: OptionalLazyPath,
486 emitted_bin: LazyPath.OptionalIndex,
475487
476488 implib_dir: InstallDestDir,
477 emitted_implib: OptionalLazyPath,
489 emitted_implib: LazyPath.OptionalIndex,
478490
479491 pdb_dir: InstallDestDir,
480 emitted_pdb: OptionalLazyPath,
492 emitted_pdb: LazyPath.OptionalIndex,
481493
482494 h_dir: InstallDestDir,
483 emitted_h: OptionalLazyPath,
495 emitted_h: LazyPath.OptionalIndex,
484496
485497 /// Always a compile step.
486498 artifact: Step.Index,
......@@ -493,11 +505,11 @@ pub const Step = extern struct {
493505 };
494506
495507 /// Trailing:
496 /// * LazyPath for each file_inputs_len
508 /// * LazyPath.Index for each file_inputs_len
497509 /// * Arg for each args_len
498510 /// * environ_map if corresponding flag is set
499511 /// * stdin: Bytes, // if StdIn.bytes is chosen
500 /// * stdin: LazyPath, // if StdIn.lazy_path is chosen
512 /// * stdin: LazyPath.Index, // if StdIn.lazy_path is chosen
501513 /// * checks: Checks, // if StdIo.check is chosen
502514 /// * stdio_limit: u64, // if stdio_limit is set
503515 /// * producer: Step.Index, // if producer is set. always compile step
......@@ -505,7 +517,7 @@ pub const Step = extern struct {
505517 flags: @This().Flags,
506518 file_inputs_len: u32,
507519 args_len: u32,
508 cwd: OptionalLazyPath,
520 cwd: LazyPath.OptionalIndex,
509521 captured_stdout: OptionalString, // basename
510522 captured_stderr: OptionalString, // basename
511523
......@@ -514,7 +526,7 @@ pub const Step = extern struct {
514526 /// * String if suffix set
515527 /// * String if basename set
516528 /// * Step.Index which is always a compile step if tag is artifact
517 /// * LazyPath if tag is path_file, path_directory, or file_content
529 /// * LazyPath.Index if tag is path_file, path_directory, or file_content
518530 pub const Arg = struct {
519531 flags: Arg.Flags,
520532
......@@ -591,13 +603,13 @@ pub const Step = extern struct {
591603 installed_headers: Storage.FlagLengthPrefixedList(.flags, .installed_headers_len, Storage.Extended(InstalledHeader.Flags, InstalledHeader)),
592604 force_undefined_symbols: Storage.FlagLengthPrefixedList(.flags, .force_undefined_symbols_len, String),
593605 expect_errors: Storage.FlagUnion(.flags4, .expect_errors, ExpectErrors),
594 linker_script: Storage.FlagOptional(.flags4, .linker_script, LazyPath),
595 version_script: Storage.FlagOptional(.flags4, .version_script, LazyPath),
596 zig_lib_dir: Storage.FlagOptional(.flags3, .zig_lib_dir, LazyPath),
597 libc_file: Storage.FlagOptional(.flags4, .libc_file, LazyPath),
598 win32_manifest: Storage.FlagOptional(.flags3, .win32_manifest, LazyPath),
599 win32_module_definition: Storage.FlagOptional(.flags3, .win32_module_definition, LazyPath),
600 entitlements: Storage.FlagOptional(.flags4, .entitlements, LazyPath),
606 linker_script: Storage.FlagOptional(.flags4, .linker_script, LazyPath.Index),
607 version_script: Storage.FlagOptional(.flags4, .version_script, LazyPath.Index),
608 zig_lib_dir: Storage.FlagOptional(.flags3, .zig_lib_dir, LazyPath.Index),
609 libc_file: Storage.FlagOptional(.flags4, .libc_file, LazyPath.Index),
610 win32_manifest: Storage.FlagOptional(.flags3, .win32_manifest, LazyPath.Index),
611 win32_module_definition: Storage.FlagOptional(.flags3, .win32_module_definition, LazyPath.Index),
612 entitlements: Storage.FlagOptional(.flags4, .entitlements, LazyPath.Index),
601613 version: Storage.FlagOptional(.flags3, .version, String), // semantic version string
602614 entry: Storage.EnumOptional(.flags3, .entry, .symbol_name, String),
603615 install_name: Storage.FlagOptional(.flags4, .install_name, String),
......@@ -614,6 +626,16 @@ pub const Step = extern struct {
614626 build_id: Storage.EnumOptional(.flags3, .build_id, .hexstring, String),
615627 test_runner: Storage.FlagUnion(.flags3, .test_runner, TestRunner),
616628
629 emit_directory: Storage.FlagOptional(.flags4, .emit_directory, GeneratedFileIndex),
630 generated_docs: Storage.FlagOptional(.flags4, .generated_docs, GeneratedFileIndex),
631 generated_asm: Storage.FlagOptional(.flags4, .generated_asm, GeneratedFileIndex),
632 generated_bin: Storage.FlagOptional(.flags4, .generated_bin, GeneratedFileIndex),
633 generated_pdb: Storage.FlagOptional(.flags4, .generated_pdb, GeneratedFileIndex),
634 generated_implib: Storage.FlagOptional(.flags4, .generated_implib, GeneratedFileIndex),
635 generated_llvm_bc: Storage.FlagOptional(.flags4, .generated_llvm_bc, GeneratedFileIndex),
636 generated_llvm_ir: Storage.FlagOptional(.flags4, .generated_llvm_ir, GeneratedFileIndex),
637 generated_h: Storage.FlagOptional(.flags4, .generated_h, GeneratedFileIndex),
638
617639 pub const InstalledHeader = union(@This().Tag) {
618640 file: File,
619641 directory: Directory,
......@@ -630,7 +652,7 @@ pub const Step = extern struct {
630652
631653 pub const File = struct {
632654 flags: @This().Flags = .{},
633 source: LazyPath,
655 source: LazyPath.Index,
634656 dest_sub_path: String,
635657
636658 pub const Flags = packed struct(u32) {
......@@ -641,7 +663,7 @@ pub const Step = extern struct {
641663
642664 pub const Directory = struct {
643665 flags: @This().Flags,
644 source: LazyPath,
666 source: LazyPath.Index,
645667 dest_sub_path: String,
646668 exclude_extensions: Storage.FlagLengthPrefixedList(.flags, .exclude_extensions, String),
647669 include_extensions: Storage.FlagLengthPrefixedList(.flags, .include_extensions, String),
......@@ -667,8 +689,8 @@ pub const Step = extern struct {
667689 pub const Tag = enum(u2) { default, simple, server };
668690
669691 default: void,
670 simple: LazyPath,
671 server: LazyPath,
692 simple: LazyPath.Index,
693 server: LazyPath.Index,
672694 };
673695 pub const Entry = enum(u2) { default, disabled, enabled, symbol_name };
674696
......@@ -857,12 +879,37 @@ pub const Step = extern struct {
857879 expect_errors: ExpectErrors.Tag,
858880 linker_script: bool,
859881 version_script: bool,
860 _: u18 = 0,
882 emit_directory: bool,
883 generated_docs: bool,
884 generated_asm: bool,
885 generated_bin: bool,
886 generated_pdb: bool,
887 generated_implib: bool,
888 generated_llvm_bc: bool,
889 generated_llvm_ir: bool,
890 generated_h: bool,
891 _: u9 = 0,
861892 };
862893
863894 pub fn isDynamicLibrary(compile: *const Compile) bool {
864895 return compile.flags3.kind == .lib and compile.flags2.linkage == .dynamic;
865896 }
897
898 pub fn isStaticLibrary(compile: *const Compile) bool {
899 return compile.flags3.kind == .lib and compile.flags2.linkage != .dynamic;
900 }
901
902 pub fn producesImplib(compile: *const Compile, c: *const Configuration) bool {
903 return isDll(compile, c);
904 }
905
906 pub fn isDll(compile: *const Compile, c: *const Configuration) bool {
907 return isDynamicLibrary(compile) and rootModuleTarget(compile, c).flags.os_tag == .windows;
908 }
909
910 pub fn rootModuleTarget(compile: *const Compile, c: *const Configuration) TargetQuery {
911 return compile.root_module.get(c).resolved_target.get(c).?.result.get(c);
912 }
866913 };
867914
868915 pub const CheckFile = struct {
......@@ -1001,32 +1048,49 @@ pub const MaxRss = enum(u32) {
10011048 }
10021049};
10031050
1004/// An index into `extra`, or `null`.
1005pub const OptionalLazyPath = enum(u32) {
1006 none = maxInt(u32),
1007 _,
1008
1009 pub fn unwrap(this: @This()) ?LazyPath {
1010 return switch (this) {
1011 .none => null,
1012 else => @enumFromInt(@intFromEnum(this)),
1013 };
1014 }
1015};
1016
1017/// An index into `extra`.
1018pub const LazyPath = enum(u32) {
1019 _,
1051pub const LazyPath = union(@This().Tag) {
1052 source_path: SourcePath,
1053 relative: Relative,
1054 generated: Generated,
10201055
10211056 pub const Tag = enum(u8) {
10221057 /// A source file path relative to build root.
10231058 source_path,
1024 generated,
1059 /// Relative to the directory indicated in flags.
10251060 relative,
1061 /// Path is available only after it is populated by its owning step.
1062 generated,
1063 };
1064
1065 pub const Flags = packed struct(u32) {
1066 tag: Tag,
1067 _: u24 = 0,
1068 };
1069
1070 /// An index into `extra`.
1071 pub const Index = enum(u32) {
1072 _,
1073
1074 pub fn get(this: @This(), c: *const Configuration) LazyPath {
1075 return extraData(c, LazyPath, @intFromEnum(this));
1076 }
1077 };
1078
1079 /// An index into `extra`, or `null`.
1080 pub const OptionalIndex = enum(u32) {
1081 none = maxInt(u32),
1082 _,
1083
1084 pub fn unwrap(this: @This()) ?Index {
1085 return switch (this) {
1086 .none => null,
1087 else => @enumFromInt(@intFromEnum(this)),
1088 };
1089 }
10261090 };
10271091
10281092 pub const SourcePath = struct {
1029 flags: Flags,
1093 flags: @This().Flags,
10301094 owner: Package.Index,
10311095 sub_path: String,
10321096
......@@ -1037,9 +1101,10 @@ pub const LazyPath = enum(u32) {
10371101 };
10381102
10391103 pub const Generated = struct {
1040 flags: Flags,
1104 flags: @This().Flags = .{},
1105 index: GeneratedFileIndex,
10411106 /// Applied after `up`.
1042 sub_path: String,
1107 sub_path: String = .empty,
10431108
10441109 pub const Flags = packed struct(u32) {
10451110 tag: Tag = .generated,
......@@ -1047,12 +1112,12 @@ pub const LazyPath = enum(u32) {
10471112 /// 0 means the generated file itself.
10481113 /// 1 means the directory of the generated file.
10491114 /// 2 means the parent of that directory, and so on.
1050 up: u24,
1115 up: u24 = 0,
10511116 };
10521117 };
10531118
10541119 pub const Relative = struct {
1055 flags: Flags,
1120 flags: @This().Flags,
10561121 sub_path: String,
10571122
10581123 pub const Flags = packed struct(u32) {
......@@ -1063,6 +1128,26 @@ pub const LazyPath = enum(u32) {
10631128 };
10641129};
10651130
1131pub const GeneratedFileIndex = enum(u32) {
1132 _,
1133};
1134
1135pub const OptionalGeneratedFileIndex = enum(u32) {
1136 none = maxInt(u32),
1137 _,
1138
1139 pub fn init(i: ?GeneratedFileIndex) OptionalGeneratedFileIndex {
1140 return @enumFromInt(@intFromEnum(i orelse return .none));
1141 }
1142
1143 pub fn unwrap(this: @This()) ?GeneratedFileIndex {
1144 return switch (this) {
1145 .none => null,
1146 else => @enumFromInt(@intFromEnum(this)),
1147 };
1148 }
1149};
1150
10661151pub const Package = struct {
10671152 dep_prefix: String,
10681153 hash: String,
......@@ -1071,9 +1156,15 @@ pub const Package = struct {
10711156 root = maxInt(u32),
10721157 _,
10731158
1074 pub fn depPrefixSlice(i: Index, c: *const Configuration) [:0]const u8 {
1075 if (i == .root) return "";
1076 return extraData(c, Package, @intFromEnum(i)).dep_prefix.slice(c);
1159 /// Returns `null` for root package.
1160 pub fn get(i: @This(), c: *const Configuration) ?Package {
1161 if (i == .root) return null;
1162 return extraData(c, Package, @intFromEnum(i));
1163 }
1164
1165 pub fn depPrefixSlice(i: @This(), c: *const Configuration) [:0]const u8 {
1166 const package = get(i, c) orelse return "";
1167 return package.dep_prefix.slice(c);
10771168 }
10781169 };
10791170};
......@@ -1083,10 +1174,10 @@ pub const Module = struct {
10831174 flags2: Flags2,
10841175 import_table: ImportTable.Index,
10851176 owner: Package.Index,
1086 root_source_file: OptionalLazyPath,
1177 root_source_file: LazyPath.OptionalIndex,
10871178 resolved_target: ResolvedTarget.OptionalIndex,
10881179 c_macros: Storage.FlagLengthPrefixedList(.flags, .c_macros, String),
1089 lib_paths: Storage.FlagLengthPrefixedList(.flags, .lib_paths, LazyPath),
1180 lib_paths: Storage.FlagLengthPrefixedList(.flags, .lib_paths, LazyPath.Index),
10901181 export_symbol_names: Storage.FlagLengthPrefixedList(.flags, .export_symbol_names, String),
10911182 include_dirs: Storage.UnionList(.flags, .include_dirs, IncludeDir),
10921183 rpaths: Storage.UnionList(.flags, .rpaths, RPath),
......@@ -1195,29 +1286,29 @@ pub const Module = struct {
11951286 };
11961287
11971288 pub const IncludeDir = union(enum(u3)) {
1198 path: LazyPath,
1199 path_system: LazyPath,
1200 path_after: LazyPath,
1201 framework_path: LazyPath,
1202 framework_path_system: LazyPath,
1289 path: LazyPath.Index,
1290 path_system: LazyPath.Index,
1291 path_after: LazyPath.Index,
1292 framework_path: LazyPath.Index,
1293 framework_path_system: LazyPath.Index,
12031294 /// Always `Step.Tag.compile`.
12041295 other_step: Step.Index,
12051296 /// Always `Step.Tag.config_header`.
12061297 config_header_step: Step.Index,
1207 embed_path: LazyPath,
1298 embed_path: LazyPath.Index,
12081299 };
12091300
12101301 pub const RPath = union(enum(u1)) {
1211 lazy_path: LazyPath,
1302 lazy_path: LazyPath.Index,
12121303 special: String,
12131304 };
12141305
12151306 pub const LinkObject = union(enum(u3)) {
1216 static_path: LazyPath,
1307 static_path: LazyPath.Index,
12171308 /// Always `Step.Tag.compile`.
12181309 other_step: Step.Index,
12191310 system_lib: SystemLib.Index,
1220 assembly_file: LazyPath,
1311 assembly_file: LazyPath.Index,
12211312 c_source_file: CSourceFile.Index,
12221313 c_source_files: CSourceFiles.Index,
12231314 win32_resource_file: RcSourceFile.Index,
......@@ -1376,6 +1467,10 @@ pub const SystemLib = struct {
13761467
13771468 pub const Index = enum(u32) {
13781469 _,
1470
1471 pub fn get(this: @This(), c: *const Configuration) SystemLib {
1472 return extraData(c, SystemLib, @intFromEnum(this));
1473 }
13791474 };
13801475
13811476 pub const UsePkgConfig = enum(u2) {
......@@ -1405,12 +1500,16 @@ pub const SystemLib = struct {
14051500
14061501pub const CSourceFiles = struct {
14071502 flags: Flags,
1408 root: LazyPath,
1503 root: LazyPath.Index,
14091504 args: Storage.FlagList(.flags, .args_len, String),
14101505 sub_paths: Storage.LengthPrefixedList(String),
14111506
14121507 pub const Index = enum(u32) {
14131508 _,
1509
1510 pub fn get(this: @This(), c: *const Configuration) CSourceFiles {
1511 return extraData(c, CSourceFiles, @intFromEnum(this));
1512 }
14141513 };
14151514
14161515 pub const Flags = packed struct(u32) {
......@@ -1422,11 +1521,15 @@ pub const CSourceFiles = struct {
14221521
14231522pub const CSourceFile = struct {
14241523 flags: Flags,
1425 file: LazyPath,
1524 file: LazyPath.Index,
14261525 args: Storage.FlagList(.flags, .args_len, String),
14271526
14281527 pub const Index = enum(u32) {
14291528 _,
1529
1530 pub fn get(this: @This(), c: *const Configuration) CSourceFile {
1531 return extraData(c, CSourceFile, @intFromEnum(this));
1532 }
14301533 };
14311534
14321535 pub const Flags = packed struct(u32) {
......@@ -1438,12 +1541,16 @@ pub const CSourceFile = struct {
14381541
14391542pub const RcSourceFile = struct {
14401543 flags: Flags,
1441 file: LazyPath,
1544 file: LazyPath.Index,
14421545 args: Storage.FlagList(.flags, .args_len, String),
1443 include_paths: Storage.FlagLengthPrefixedList(.flags, .include_paths, LazyPath),
1546 include_paths: Storage.FlagLengthPrefixedList(.flags, .include_paths, LazyPath.Index),
14441547
14451548 pub const Index = enum(u32) {
14461549 _,
1550
1551 pub fn get(this: @This(), c: *const Configuration) RcSourceFile {
1552 return extraData(c, RcSourceFile, @intFromEnum(this));
1553 }
14471554 };
14481555
14491556 pub const Flags = packed struct(u32) {
......@@ -1472,6 +1579,18 @@ pub const OptionalCSourceLanguage = enum(u3) {
14721579 .assembly_with_preprocessor => .assembly_with_preprocessor,
14731580 };
14741581 }
1582
1583 pub fn get(this: @This()) ?std.Build.Module.CSourceLanguage {
1584 return switch (this) {
1585 .c => .c,
1586 .cpp => .cpp,
1587 .objective_c => .objective_c,
1588 .objective_cpp => .objective_cpp,
1589 .assembly => .assembly,
1590 .assembly_with_preprocessor => .assembly_with_preprocessor,
1591 .default => null,
1592 };
1593 }
14751594};
14761595
14771596pub const ResolvedTarget = struct {
......@@ -1483,7 +1602,7 @@ pub const ResolvedTarget = struct {
14831602 pub const Index = enum(u32) {
14841603 _,
14851604
1486 pub fn get(this: @This(), c: *const Configuration) ?ResolvedTarget {
1605 pub fn get(this: @This(), c: *const Configuration) ResolvedTarget {
14871606 return extraData(c, ResolvedTarget, @intFromEnum(this));
14881607 }
14891608 };
......@@ -2006,13 +2125,27 @@ pub const Storage = enum {
20062125 return end - i;
20072126 }
20082127
2009 pub fn data(buffer: []const u32, i: *usize, comptime S: type) S {
2010 var result: S = undefined;
2011 const fields = @typeInfo(S).@"struct".fields;
2012 inline for (fields) |field| {
2013 @field(result, field.name) = dataField(buffer, i, &result, field.type);
2128 pub fn data(buffer: []const u32, i: *usize, comptime T: type) T {
2129 switch (@typeInfo(T)) {
2130 .@"struct" => |info| {
2131 var result: T = undefined;
2132 inline for (info.fields) |field| {
2133 @field(result, field.name) = dataField(buffer, i, &result, field.type);
2134 }
2135 return result;
2136 },
2137 .@"union" => |info| {
2138 const flags: T.Flags = @bitCast(buffer[i.*]);
2139 return switch (flags.tag) {
2140 inline else => |comptime_tag| @unionInit(
2141 T,
2142 @tagName(comptime_tag),
2143 data(buffer, i, info.fields[@intFromEnum(comptime_tag)].type),
2144 ),
2145 };
2146 },
2147 else => comptime unreachable,
20142148 }
2015 return result;
20162149 }
20172150
20182151 fn dataField(buffer: []const u32, i: *usize, container: anytype, comptime Field: type) Field {
......@@ -2332,6 +2465,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
23322465 .available_options = try arena.alloc(AvailableOption, header.available_options_len),
23332466 .extra = try arena.alloc(u32, header.extra_len),
23342467 .default_step = header.default_step,
2468 .generated_files_len = header.generated_files_len,
23352469 };
23362470 var vecs = [_][]u8{
23372471 result.string_bytes,