authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-15 12:25:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-15 12:25:05-07:00
log2190eeb23f9948e3bd22a3c542c7536168410ba9
tree8ecd3dbfe027f215b01d4cfb45198f5f282c9c41
parent27f5843b753b7d16e4ef73cf6ef3fe2136aeabfd

Revert "Merge pull request 'package management: --help enhancement, --print-tree, and validate package hash consistency' (#37214) from build-print-tree into master"

This reverts commit b9ea8ac3d350a7461b110946bfc6dd02465d3eee. Not intended for the patch release.

3 files changed, 197 insertions(+), 409 deletions(-)

lib/compiler/Maker.zig+76-268
......@@ -23,7 +23,6 @@ const Color = std.zig.Color;
2323const Client = std.zig.Client;
2424const Server = std.zig.Server;
2525const EnvVar = std.zig.EnvVar;
26const ErrorBundle = std.zig.ErrorBundle;
2726const default_local_zig_cache_basename = std.zig.default_local_zig_cache_basename;
2827const stringToEnum = std.meta.stringToEnum;
2928
......@@ -36,7 +35,6 @@ const ScannedConfig = @import("Maker/ScannedConfig.zig");
3635const PkgConfig = @import("Maker/PkgConfig.zig");
3736const Fetch = @import("Maker/Fetch.zig");
3837const Package = @import("Maker/Package.zig");
39const Manifest = Package.Manifest;
4038
4139pub const std_options: std.Options = .{
4240 .side_channels_mitigations = .none,
......@@ -103,30 +101,8 @@ const InstallPaths = struct {
103101};
104102
105103const PrintNode = struct {
106 parent: ?*const PrintNode,
104 parent: ?*PrintNode,
107105 last: bool = false,
108
109 fn printPrefix(node: *const PrintNode, writer: *Writer, mode: Io.Terminal.Mode) Writer.Error!void {
110 const parent = node.parent orelse return;
111 if (parent.parent == null) return;
112 try printPrefix(parent, writer, mode);
113 if (parent.last) {
114 try writer.writeAll(" ");
115 } else {
116 try printTreeSibling(writer, mode);
117 }
118 }
119
120 fn printPrefixedChild(node: *const PrintNode, writer: *Writer, mode: Io.Terminal.Mode) Writer.Error!void {
121 try printPrefix(node, writer, mode);
122 if (node.parent != null) {
123 if (node.last) {
124 try printTreeChildLast(writer, mode);
125 } else {
126 try printTreeChild(writer, mode);
127 }
128 }
129 }
130106};
131107
132108const ErrorStyle = enum {
......@@ -149,7 +125,7 @@ const ErrorStyle = enum {
149125};
150126const MultilineErrors = enum { indent, newline, none };
151127const Summary = enum { all, new, failures, line, none };
152const PrintConfiguration = enum { none, zon, path, tree, stop };
128const PrintConfiguration = enum { none, zon, path };
153129
154130const GeneratedFile = struct {
155131 data: ?[]const u8,
......@@ -300,6 +276,7 @@ pub fn main(init: process.Init.Minimal) !void {
300276 var cached_passthru_configure: std.ArrayList(u32) = .empty;
301277 var forks: std.ArrayList(Fork) = .empty;
302278 var system_pkg_dir_path: ?[]const u8 = null;
279 var fetch_only = false;
303280 var fetch_mode: Fetch.JobQueue.Mode = .needed;
304281 var debug_target: ?[]const u8 = null;
305282 var cache_poison: std.Build.Graph.CachePoison = .pure;
......@@ -384,12 +361,12 @@ pub fn main(init: process.Init.Minimal) !void {
384361 override_local_cache_dir = nextArgOrFatal(args, &arg_i);
385362 } else if (mem.eql(u8, arg, "--pkg-dir")) {
386363 override_pkg_dir = nextArgOrFatal(args, &arg_i);
387 } else if (mem.eql(u8, arg, "--print-tree")) {
388 print_configuration = .tree;
389 } else if (mem.eql(u8, arg, "--configure")) {
390 print_configuration = .stop;
391364 } else if (mem.eql(u8, arg, "--fetch")) {
392 fetch_mode = .all;
365 fetch_only = true;
366 } else if (mem.cutPrefix(u8, arg, "--fetch=")) |rest| {
367 fetch_only = true;
368 fetch_mode = stringToEnum(Fetch.JobQueue.Mode, rest) orelse
369 fatal("expected [needed|all] after \"--fetch=\", found {q}", .{rest});
393370 } else if (mem.cutPrefix(u8, arg, "--fork=")) |rest| {
394371 try forks.append(arena, .init(rest));
395372 } else if (mem.eql(u8, arg, "--fork")) {
......@@ -616,7 +593,7 @@ pub fn main(init: process.Init.Minimal) !void {
616593 }
617594 }
618595
619 const early_exit_mode = fetch_mode == .all or help_menu or steps_menu or print_configuration != .none;
596 const early_exit_mode = fetch_only or help_menu or steps_menu or print_configuration != .none;
620597 const server_mode = !early_exit_mode and (watch_flag or webui_listen != null or fuzz != null or listen);
621598
622599 process.raiseFileDescriptorLimit();
......@@ -624,16 +601,10 @@ pub fn main(init: process.Init.Minimal) !void {
624601 const cwd_path = std.zig.getResolvedCwd(io, arena) catch |err|
625602 fatal("resolving current directory path failed: {t}", .{err});
626603
627 var build_root = findBuildRoot(arena, io, .{
604 var build_root = try findBuildRoot(arena, io, .{
628605 .cwd_path = cwd_path,
629606 .build_file = build_file,
630 }) catch |err| switch (err) {
631 error.BuildZigNotFound => {
632 if (help_menu) printUsageWithoutConfiguration(&graph, "build.zig not found");
633 process.exit(1);
634 },
635 else => |e| return e,
636 };
607 });
637608 defer build_root.deinit(io);
638609
639610 graph.build_root_directory = build_root.directory;
......@@ -769,7 +740,7 @@ pub fn main(init: process.Init.Minimal) !void {
769740 var configure_source_files: Cache.Manifest.SelfContainedFiles = .empty;
770741 defer configure_source_files.deinit(gpa);
771742
772 var configure_error_bundle: ErrorBundle = .empty;
743 var configure_error_bundle: std.zig.ErrorBundle = .empty;
773744 defer configure_error_bundle.deinit(gpa);
774745
775746 // If this fails, we can still start the server and wait for user
......@@ -790,6 +761,7 @@ pub fn main(init: process.Init.Minimal) !void {
790761 .parent_progress_node = main_progress_node,
791762 .fetch_mode = fetch_mode,
792763 .system_pkg_dir_path = system_pkg_dir_path,
764 .fetch_only = fetch_only,
793765 .print_configuration = print_configuration,
794766 .forks = forks.items,
795767 .src_files = &configure_source_files,
......@@ -817,8 +789,6 @@ pub fn main(init: process.Init.Minimal) !void {
817789 return cleanExit(io, &scanned_config);
818790 },
819791 .path => unreachable,
820 .tree => unreachable,
821 .stop => return cleanExit(io, &scanned_config),
822792 }
823793
824794 var maker: Maker = .{
......@@ -1073,10 +1043,7 @@ pub fn main(init: process.Init.Minimal) !void {
10731043 } else |err| {
10741044 const can_fs_watch = switch (err) {
10751045 error.AlreadyReported => false,
1076 error.FailedButCacheIntact => c: {
1077 if (help_menu) printUsageWithoutConfiguration(&graph, "build.zig compilation failure");
1078 break :c true;
1079 },
1046 error.FailedButCacheIntact => true,
10801047 else => |e| w: {
10811048 log.err("configuration failed: {t}", .{e});
10821049 break :w false;
......@@ -1098,17 +1065,6 @@ pub fn main(init: process.Init.Minimal) !void {
10981065 }
10991066}
11001067
1101fn printUsageWithoutConfiguration(graph: *Graph, reason: []const u8) noreturn {
1102 const io = graph.io;
1103 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};
1104 const writer = initStdoutWriter(io);
1105 ScannedConfig.printUsageWithoutConfiguration(graph.zig_exe, writer, reason) catch |err| switch (err) {
1106 error.WriteFailed => fatal("failed writing to stdout: {t}", .{stdout_writer_allocation.err.?}),
1107 };
1108 stdout_writer_allocation.flush() catch |err| fatal("failed writing to stdout: {t}", .{err});
1109 return process.exit(0);
1110}
1111
11121068/// Temporarily adds the reconfigure pseudostep to step_stack, calls
11131069/// `Watch.update`, and then pops it again.
11141070fn updateWatch(maker: *Maker, watch: *Watch) !void {
......@@ -1132,10 +1088,11 @@ const ConfigureOptions = struct {
11321088 parent_progress_node: std.Progress.Node,
11331089 fetch_mode: Fetch.JobQueue.Mode,
11341090 system_pkg_dir_path: ?[]const u8,
1091 fetch_only: bool,
11351092 print_configuration: PrintConfiguration,
11361093 forks: []Fork,
11371094 src_files: *Cache.Manifest.SelfContainedFiles,
1138 error_bundle: ?*ErrorBundle = null,
1095 error_bundle: ?*std.zig.ErrorBundle = null,
11391096};
11401097
11411098fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
......@@ -1379,27 +1336,11 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
13791336 return error.FailedButCacheIntact;
13801337 }
13811338
1382 if (options.print_configuration == .tree) {
1383 const NO_COLOR = EnvVar.NO_COLOR.isSet(&graph.environ_map);
1384 const CLICOLOR_FORCE = EnvVar.CLICOLOR_FORCE.isSet(&graph.environ_map);
1385 printPkgTree(.{
1386 .writer = initStdoutWriter(io),
1387 .mode = try .detect(io, .stdout(), NO_COLOR, CLICOLOR_FORCE),
1388 }, arena, &job_queue, &fetch) catch |err| switch (err) {
1389 error.WriteFailed => return stdout_writer_allocation.err.?,
1390 else => |e| return e,
1391 };
1392 try stdout_writer_allocation.flush();
1393 process.exit(0);
1394 }
1395
1396 if (options.fetch_mode == .all) {
1339 if (options.fetch_only) {
13971340 _ = io.lockStderr(&.{}, .no_color) catch {};
13981341 process.exit(0);
13991342 }
14001343
1401 try validateFingerprints(gpa, &job_queue);
1402
14031344 // Create the dependencies.zig file for configurer to
14041345 // obtain via `@import("@dependencies")`.
14051346 {
......@@ -1462,7 +1403,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
14621403 for (fetches) |f| {
14631404 if (!f.have_manifest) continue;
14641405 if (config_man) |man| {
1465 const manifest_path = try f.package_root.join(arena, Manifest.basename);
1406 const manifest_path = try f.package_root.join(arena, Package.Manifest.basename);
14661407 _ = try man.addInputPath(manifest_path, .{});
14671408 }
14681409 const mod = f.cli_module orelse continue;
......@@ -1678,8 +1619,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
16781619 _ = io.lockStderr(&.{}, .no_color) catch {};
16791620 process.exit(0);
16801621 },
1681 .none, .zon, .stop => {},
1682 .tree => unreachable,
1622 .none, .zon => {},
16831623 }
16841624
16851625 const configuration = c: {
......@@ -1717,147 +1657,6 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
17171657 };
17181658}
17191659
1720const ValidFingerprintKey = struct {
1721 project_id: Package.ProjectId,
1722 version: std.SemanticVersion,
1723
1724 const Context = struct {
1725 pub fn hash(this: @This(), a: ValidFingerprintKey) u32 {
1726 _ = this;
1727 var hasher: std.hash.Wyhash = .init(a.project_id.fingerprint_id);
1728 hasher.update(&a.project_id.padded_name);
1729 hasher.update(@ptrCast((&a.version.major)[0..1]));
1730 hasher.update(@ptrCast((&a.version.minor)[0..1]));
1731 hasher.update(@ptrCast((&a.version.patch)[0..1]));
1732 if (a.version.pre) |pre| hasher.update(pre);
1733 return @truncate(hasher.final());
1734 }
1735 pub fn eql(this: @This(), a: ValidFingerprintKey, b: ValidFingerprintKey, i: usize) bool {
1736 _ = this;
1737 _ = i;
1738 return a.project_id.eql(&b.project_id) and a.version.order(b.version) == .eq;
1739 }
1740 };
1741};
1742
1743const ValidFingerprintTable = std.array_hash_map.Custom(
1744 ValidFingerprintKey,
1745 struct { fetch: *Fetch, pkg_hash: Package.Hash, printed: bool },
1746 ValidFingerprintKey.Context,
1747 true,
1748);
1749
1750/// Ensure that the dependency tree did not have any fingerprint matches with the same semantic version but
1751/// differing package hashes.
1752fn validateFingerprints(gpa: Allocator, job_queue: *const Fetch.JobQueue) !void {
1753 var any_errors = false;
1754
1755 var table: ValidFingerprintTable = .empty;
1756 defer table.deinit(gpa);
1757
1758 for (job_queue.table.keys(), job_queue.table.values()) |pkg_hash, fetch| {
1759 if (!fetch.have_manifest) continue;
1760 const gop = try table.getOrPut(gpa, .{
1761 .project_id = .init(fetch.manifest.name, fetch.manifest.id),
1762 .version = fetch.manifest.version,
1763 });
1764 if (gop.found_existing) {
1765 any_errors = true;
1766 const fingerprint: Package.Fingerprint = .init(fetch.manifest.id, fetch.manifest.name);
1767 const stripped_version: std.SemanticVersion = .{
1768 .major = fetch.manifest.version.major,
1769 .minor = fetch.manifest.version.minor,
1770 .patch = fetch.manifest.version.patch,
1771 .pre = fetch.manifest.version.pre,
1772 };
1773 if (!gop.value_ptr.printed) {
1774 gop.value_ptr.printed = true;
1775 log.err("contradictory hash for package with fingerprint 0x{x} and version {f}: {s}", .{
1776 fingerprint.int(), stripped_version, gop.value_ptr.pkg_hash.toSlice(),
1777 });
1778 }
1779 log.err("contradictory hash for package with fingerprint 0x{x} and version {f}: {s}", .{
1780 fingerprint.int(), stripped_version, pkg_hash.toSlice(),
1781 });
1782 } else {
1783 gop.value_ptr.* = .{ .fetch = fetch, .pkg_hash = pkg_hash, .printed = false };
1784 }
1785 }
1786 if (any_errors) {
1787 log.info("potential cause: package ownership dispute", .{});
1788 log.info("potential cause: maintainer neglected to bump version after making changes", .{});
1789 log.info("potential cause: dependency on unreleased changes", .{});
1790 log.info("hint: use --print-tree to visualize all package versions and hashes", .{});
1791 return error.FailedButCacheIntact;
1792 }
1793}
1794
1795fn printPkgTree(
1796 terminal: Io.Terminal,
1797 arena: Allocator,
1798 job_queue: *const Fetch.JobQueue,
1799 root_fetch: *const Fetch,
1800) !void {
1801 if (!root_fetch.have_manifest) return;
1802 const names = root_fetch.manifest.dependencies.keys();
1803 for (names, root_fetch.manifest.dependencies.values(), 0..) |name, *dep, i| {
1804 var print_node: PrintNode = .{
1805 .parent = null,
1806 .last = i == names.len - 1,
1807 };
1808 try printPkgTreeChild(terminal, arena, job_queue, &print_node, name, dep.hash);
1809 }
1810}
1811
1812fn printPkgTreeChild(
1813 terminal: Io.Terminal,
1814 arena: Allocator,
1815 job_queue: *const Fetch.JobQueue,
1816 parent_print_node: *const PrintNode,
1817 dep_name: []const u8,
1818 opt_hash: ?[]const u8,
1819) !void {
1820 const w = terminal.writer;
1821 try parent_print_node.printPrefixedChild(w, terminal.mode);
1822 try w.writeAll(dep_name);
1823
1824 const hash = opt_hash orelse {
1825 try terminal.setColor(.red);
1826 try w.writeAll(" (missing hash)\n");
1827 try terminal.setColor(.reset);
1828 return;
1829 };
1830 try terminal.setColor(.dim);
1831 try w.print(" {s}", .{hash});
1832 try terminal.setColor(.reset);
1833 const child_fetch = job_queue.table.get(.fromSlice(hash)) orelse {
1834 try terminal.setColor(.red);
1835 try w.writeAll(" (fetch failed)\n");
1836 try terminal.setColor(.reset);
1837 return;
1838 };
1839 switch (child_fetch.lazy_status) {
1840 .eager, .available => {},
1841 .unavailable => {
1842 try terminal.setColor(.yellow);
1843 try w.writeAll(" (not fetched)\n");
1844 try terminal.setColor(.reset);
1845 return;
1846 },
1847 }
1848 try w.writeByte('\n');
1849 if (!child_fetch.have_manifest) return;
1850
1851 const names = child_fetch.manifest.dependencies.keys();
1852 for (names, child_fetch.manifest.dependencies.values(), 0..) |name, *dep, i| {
1853 var print_node: PrintNode = .{
1854 .parent = parent_print_node,
1855 .last = i == names.len - 1,
1856 };
1857 try printPkgTreeChild(terminal, arena, job_queue, &print_node, name, dep.hash);
1858 }
1859}
1860
18611660fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
18621661 const environ_map = &graph.environ_map;
18631662 const io = graph.io;
......@@ -2134,8 +1933,8 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
21341933 try ast.render(gpa, &aw.writer, fixups);
21351934 const rendered = aw.written();
21361935
2137 build_root.directory.handle.writeFile(io, .{ .sub_path = Manifest.basename, .data = rendered }) catch |err| {
2138 fatal("unable to write {s} file: {t}", .{ Manifest.basename, err });
1936 build_root.directory.handle.writeFile(io, .{ .sub_path = Package.Manifest.basename, .data = rendered }) catch |err| {
1937 fatal("unable to write {s} file: {t}", .{ Package.Manifest.basename, err });
21391938 };
21401939
21411940 return process.cleanExit(io);
......@@ -2337,7 +2136,7 @@ fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
23372136 const s = Dir.path.sep_str;
23382137 const template_paths = [_][]const u8{
23392138 default_build_zig_basename,
2340 Manifest.basename,
2139 Package.Manifest.basename,
23412140 "src" ++ s ++ "main.zig",
23422141 "src" ++ s ++ "root.zig",
23432142 };
......@@ -2361,7 +2160,7 @@ fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
23612160 return process.cleanExit(io);
23622161 },
23632162 .minimal => {
2364 Templates.writeSimpleFile(io, Io.Dir.cwd(), Manifest.basename,
2163 Templates.writeSimpleFile(io, Io.Dir.cwd(), Package.Manifest.basename,
23652164 \\.{{
23662165 \\ .name = .{s},
23672166 \\ .version = "0.0.1",
......@@ -2375,8 +2174,8 @@ fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
23752174 builtin.zig_version_string,
23762175 fingerprint.int(),
23772176 }) catch |err| switch (err) {
2378 else => fatal("failed to create {q}: {t}", .{ Manifest.basename, err }),
2379 error.PathAlreadyExists => fatal("refusing to overwrite {q}", .{Manifest.basename}),
2177 else => fatal("failed to create {q}: {t}", .{ Package.Manifest.basename, err }),
2178 error.PathAlreadyExists => fatal("refusing to overwrite {q}", .{Package.Manifest.basename}),
23802179 };
23812180 Templates.writeSimpleFile(io, Io.Dir.cwd(), default_build_zig_basename,
23822181 \\const std = @import("std");
......@@ -2391,12 +2190,12 @@ fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
23912190 // their `build.zig.zon` *after* writing their `build.zig`. So this one isn't fatal.
23922191 error.PathAlreadyExists => {
23932192 log.info("successfully populated {q}, preserving existing {q}", .{
2394 Manifest.basename, default_build_zig_basename,
2193 Package.Manifest.basename, default_build_zig_basename,
23952194 });
23962195 return process.cleanExit(io);
23972196 },
23982197 };
2399 log.info("successfully populated {q} and {q}", .{ Manifest.basename, default_build_zig_basename });
2198 log.info("successfully populated {q} and {q}", .{ Package.Manifest.basename, default_build_zig_basename });
24002199 return process.cleanExit(io);
24012200 },
24022201 }
......@@ -3129,7 +2928,18 @@ fn printTreeStep(
31292928 .failures => make_step.state == .success,
31302929 };
31312930 if (skip) return;
3132 try parent_node.printPrefixedChild(writer, stderr.mode);
2931 try printPrefix(parent_node, stderr);
2932
2933 if (parent_node.parent != null) {
2934 if (parent_node.last) {
2935 try printChildNodePrefix(stderr);
2936 } else {
2937 try writer.writeAll(switch (stderr.mode) {
2938 .escape_codes => "\x1B\x28\x30\x74\x71\x1B\x28\x42 ", // ├─
2939 else => "+- ",
2940 });
2941 }
2942 }
31332943
31342944 if (!first) try stderr.setColor(.dim);
31352945
......@@ -3358,22 +3168,23 @@ fn printStepFailure(
33583168 }
33593169}
33603170
3361fn printTreeChild(writer: *Writer, mode: Io.Terminal.Mode) Writer.Error!void {
3362 return writer.writeAll(switch (mode) {
3363 .escape_codes => "\x1B\x28\x30\x74\x71\x1B\x28\x42 ", // ├─
3364 else => "+- ",
3365 });
3366}
3367
3368fn printTreeSibling(writer: *Writer, mode: Io.Terminal.Mode) Writer.Error!void {
3369 return writer.writeAll(switch (mode) {
3370 .escape_codes => "\x1B\x28\x30\x78\x1B\x28\x42 ", // │
3371 else => "| ",
3372 });
3171fn printPrefix(node: *PrintNode, stderr: Io.Terminal) !void {
3172 const parent = node.parent orelse return;
3173 const writer = stderr.writer;
3174 if (parent.parent == null) return;
3175 try printPrefix(parent, stderr);
3176 if (parent.last) {
3177 try writer.writeAll(" ");
3178 } else {
3179 try writer.writeAll(switch (stderr.mode) {
3180 .escape_codes => "\x1B\x28\x30\x78\x1B\x28\x42 ", // │
3181 else => "| ",
3182 });
3183 }
33733184}
33743185
3375fn printTreeChildLast(writer: *Writer, mode: Io.Terminal.Mode) !void {
3376 try writer.writeAll(switch (mode) {
3186fn printChildNodePrefix(stderr: Io.Terminal) !void {
3187 try stderr.writer.writeAll(switch (stderr.mode) {
33773188 .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─
33783189 else => "+- ",
33793190 });
......@@ -3467,7 +3278,7 @@ pub fn invalidateResult(maker: *Maker, step: *Step) error{MustReconfigure}!bool
34673278pub fn printErrorMessages(
34683279 maker: *Maker,
34693280 failing_step_index: Configuration.Step.Index,
3470 options: ErrorBundle.RenderOptions,
3281 options: std.zig.ErrorBundle.RenderOptions,
34713282 stderr: Io.Terminal,
34723283 error_style: ErrorStyle,
34733284 multiline_errors: MultilineErrors,
......@@ -3493,7 +3304,7 @@ pub fn printErrorMessages(
34933304 while (step_stack.pop()) |step_index| : (indent += 1) {
34943305 if (indent > 0) {
34953306 try writer.splatByteAll(' ', (indent - 1) * 3);
3496 try printTreeChildLast(writer, stderr.mode);
3307 try printChildNodePrefix(stderr);
34973308 }
34983309
34993310 try writer.writeAll(step_index.ptr(c).name.slice(c));
......@@ -4227,9 +4038,7 @@ const FindBuildRootOptions = struct {
42274038 cwd_path: []const u8,
42284039};
42294040
4230const FindBuildRootError = error{ OutOfMemory, BuildZigNotFound };
4231
4232fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) FindBuildRootError!BuildRoot {
4041fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) !BuildRoot {
42334042 const build_zig_basename = if (options.build_file) |bf|
42344043 Dir.path.basename(bf)
42354044 else
......@@ -4280,12 +4089,11 @@ fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) FindBu
42804089 dirname = Dir.path.dirname(dirname orelse options.cwd_path) orelse {
42814090 log.info("initialize {s} template file with \"zig init\"", .{std.zig.build_zig_basename});
42824091 log.info("see \"zig --help\" for more options", .{});
4283 log.err("no build.zig file found, in the current directory or any parent directories", .{});
4284 return error.BuildZigNotFound;
4092 fatal("no build.zig file found, in the current directory or any parent directories", .{});
42854093 };
42864094 continue;
42874095 },
4288 else => |e| fatal("accessing {q} while searching for build.zig file failed: {t}", .{ joined_path, e }),
4096 else => |e| return e,
42894097 }
42904098 }
42914099}
......@@ -4293,8 +4101,8 @@ fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) FindBu
42934101const Fork = struct {
42944102 path: Path,
42954103 manifest_ast: std.zig.Ast,
4296 manifest: Manifest,
4297 error_bundle: ErrorBundle.Wip,
4104 manifest: Package.Manifest,
4105 error_bundle: std.zig.ErrorBundle.Wip,
42984106 failed: bool,
42994107 arena_allocator: std.heap.ArenaAllocator,
43004108
......@@ -4327,12 +4135,12 @@ const Fork = struct {
43274135 fork.arena_allocator = .init(gpa);
43284136 const arena = fork.arena_allocator.allocator();
43294137
4330 var error_bundle: ErrorBundle.Wip = try .init(gpa);
4138 var error_bundle: std.zig.ErrorBundle.Wip = try .init(gpa);
43314139 defer error_bundle.deinit();
43324140
4333 const manifest_path = try fork.path.join(arena, Manifest.basename);
4141 const manifest_path = try fork.path.join(arena, Package.Manifest.basename);
43344142
4335 Manifest.load(
4143 Package.Manifest.load(
43364144 io,
43374145 arena,
43384146 manifest_path,
......@@ -4382,20 +4190,20 @@ fn loadManifest(
43824190 arena: Allocator,
43834191 io: Io,
43844192 options: LoadManifestOptions,
4385) !struct { Manifest, std.zig.Ast } {
4193) !struct { Package.Manifest, std.zig.Ast } {
43864194 const rng: std.Random.IoSource = .{ .io = io };
43874195
43884196 const manifest_bytes = while (true) {
43894197 break options.dir.readFileAllocOptions(
43904198 io,
4391 Manifest.basename,
4199 Package.Manifest.basename,
43924200 arena,
4393 .limited(Manifest.max_bytes),
4201 .limited(Package.Manifest.max_bytes),
43944202 .@"1",
43954203 0,
43964204 ) catch |err| switch (err) {
43974205 error.FileNotFound => {
4398 Templates.writeSimpleFile(io, options.dir, Manifest.basename,
4206 Templates.writeSimpleFile(io, options.dir, Package.Manifest.basename,
43994207 \\.{{
44004208 \\ .name = .{s},
44014209 \\ .version = "0.0.1",
......@@ -4409,29 +4217,29 @@ fn loadManifest(
44094217 builtin.zig_version_string,
44104218 Package.Fingerprint.generate(rng.interface(), options.root_name).int(),
44114219 }) catch |e| {
4412 fatal("unable to write {s}: {t}", .{ Manifest.basename, e });
4220 fatal("unable to write {s}: {t}", .{ Package.Manifest.basename, e });
44134221 };
44144222 continue;
44154223 },
4416 else => |e| fatal("unable to load {s}: {t}", .{ Manifest.basename, e }),
4224 else => |e| fatal("unable to load {s}: {t}", .{ Package.Manifest.basename, e }),
44174225 };
44184226 };
44194227 var ast = try std.zig.Ast.parse(gpa, manifest_bytes, .{ .mode = .zon });
44204228 errdefer ast.deinit(gpa);
44214229
44224230 if (ast.errors.len > 0) {
4423 try std.zig.printAstErrorsToStderr(gpa, io, ast, Manifest.basename, options.color);
4231 try std.zig.printAstErrorsToStderr(gpa, io, ast, Package.Manifest.basename, options.color);
44244232 process.exit(2);
44254233 }
44264234
4427 var manifest = try Manifest.parse(gpa, &ast, rng.interface(), .{});
4235 var manifest = try Package.Manifest.parse(gpa, &ast, rng.interface(), .{});
44284236 errdefer manifest.deinit(gpa);
44294237
44304238 if (manifest.errors.len > 0) {
4431 var wip_errors: ErrorBundle.Wip = try .init(gpa);
4239 var wip_errors: std.zig.ErrorBundle.Wip = try .init(gpa);
44324240 defer wip_errors.deinit();
44334241
4434 const src_path = try wip_errors.addString(Manifest.basename);
4242 const src_path = try wip_errors.addString(Package.Manifest.basename);
44354243 try manifest.copyErrorsIntoBundle(ast, src_path, &wip_errors);
44364244
44374245 var error_bundle = try wip_errors.toOwnedBundle("");
......@@ -4455,8 +4263,8 @@ fn sanitizeExampleName(arena: Allocator, bytes: []const u8) error{OutOfMemory}![
44554263 else => continue,
44564264 };
44574265 if (!std.zig.isValidId(result.items)) return "foo";
4458 if (result.items.len > Manifest.max_name_len)
4459 result.shrinkRetainingCapacity(Manifest.max_name_len);
4266 if (result.items.len > Package.Manifest.max_name_len)
4267 result.shrinkRetainingCapacity(Package.Manifest.max_name_len);
44604268
44614269 return result.toOwnedSlice(arena);
44624270}
lib/compiler/Maker/Package.zig+2-6
......@@ -8,17 +8,13 @@ pub const Fingerprint = packed struct(u64) {
88 id: u32,
99 checksum: u32,
1010
11 pub fn init(id: u32, name: []const u8) Fingerprint {
11 pub fn generate(rng: std.Random, name: []const u8) Fingerprint {
1212 return .{
13 .id = id,
13 .id = rng.intRangeLessThan(u32, 1, 0xffffffff),
1414 .checksum = std.hash.Crc32.hash(name),
1515 };
1616 }
1717
18 pub fn generate(rng: std.Random, name: []const u8) Fingerprint {
19 return .init(rng.intRangeLessThan(u32, 1, 0xffffffff), name);
20 }
21
2218 pub fn validate(n: Fingerprint, name: []const u8) bool {
2319 switch (n.id) {
2420 0x00000000, 0xffffffff => return false,
lib/compiler/Maker/ScannedConfig.zig+119-135
......@@ -238,18 +238,6 @@ pub fn printSteps(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {
238238 }
239239}
240240
241pub fn printUsageWithoutConfiguration(zig_exe: []const u8, w: *Writer, reason: []const u8) Writer.Error!void {
242 try w.print(
243 \\Usage: {s} build [steps] [options]
244 \\
245 \\Steps: (unavailable due to {s})
246 \\Project-Specific Options: (unavailable due to {s})
247 \\{s}
248 \\ (unavailable due to {s})
249 \\{s}
250 , .{ zig_exe, reason, reason, system_integration_usage, reason, general_usage });
251}
252
253241pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {
254242 const arena = graph.arena;
255243
......@@ -286,7 +274,37 @@ pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {
286274 }
287275 }
288276
289 try w.writeAll(system_integration_usage);
277 try w.writeAll(
278 \\
279 \\System Integration Options:
280 \\ --search-prefix [path] Add a path to look for binaries, libraries, headers
281 \\ --sysroot [path] Set the system root directory (usually /)
282 \\ --libc [file] Provide a file which specifies libc paths
283 \\
284 \\ --system [pkgdir] Disable package fetching; enable all integrations
285 \\ -fsys=[name] Enable a system integration
286 \\ -fno-sys=[name] Disable a system integration
287 \\
288 \\ -fdarling, -fno-darling Integration with system-installed Darling to
289 \\ execute macOS programs on Linux hosts
290 \\ (default: no)
291 \\ -fqemu, -fno-qemu Integration with system-installed QEMU to execute
292 \\ foreign-architecture programs on Linux hosts
293 \\ (default: no)
294 \\ --libc-runtimes [path] Enhances QEMU integration by providing dynamic libc
295 \\ (e.g. glibc or musl) built for multiple foreign
296 \\ architectures, allowing execution of non-native
297 \\ programs that link with libc.
298 \\ -frosetta, -fno-rosetta Rely on Rosetta to execute x86_64 programs on
299 \\ ARM64 macOS hosts. (default: no)
300 \\ -fwasmtime, -fno-wasmtime Integration with system-installed wasmtime to
301 \\ execute WASI binaries. (default: no)
302 \\ -fwine, -fno-wine Integration with system-installed Wine to execute
303 \\ Windows programs on Linux hosts. (default: no)
304 \\
305 \\ Available System Integrations: Enabled:
306 \\
307 );
290308 if (sc.configuration.system_integrations.len == 0) {
291309 try w.writeAll(" (none) -\n");
292310 } else {
......@@ -300,126 +318,92 @@ pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {
300318 }
301319 }
302320
303 try w.writeAll(general_usage);
321 try w.writeAll(
322 \\
323 \\General Options:
324 \\ -h, --help Print this help to stdout and exit
325 \\ -l, --list-steps Print available steps to stdout and exit
326 \\
327 \\ -p, --prefix [path] Where to install files (default: zig-out)
328 \\ --prefix-lib-dir [path] Where to install libraries
329 \\ --prefix-exe-dir [path] Where to install executables
330 \\ --prefix-include-dir [path] Where to install C header files
331 \\ --release[=mode] Request release mode, optionally specifying a
332 \\ preferred optimization mode: fast, safe, small
333 \\
334 \\ --verbose Print commands before executing them
335 \\ --color [auto|off|on] Enable or disable colored error messages
336 \\ --error-style [style] Control how build errors are printed
337 \\ verbose (Default) Report errors with full context
338 \\ minimal Report errors after summary, excluding context like command lines
339 \\ verbose_clear Like 'verbose', but clear the terminal at the start of each update
340 \\ minimal_clear Like 'minimal', but clear the terminal at the start of each update
341 \\ --multiline-errors [style] Control how multi-line error messages are printed
342 \\ indent (Default) Indent non-initial lines to align with initial line
343 \\ newline Include a leading newline so that the error message is on its own lines
344 \\ none Print as usual so the first line is misaligned
345 \\ --summary [mode] Control the printing of the build summary
346 \\ all Print the build summary in its entirety
347 \\ new Omit cached steps
348 \\ failures (Default if short-lived) Only print failed steps
349 \\ line (Default if long-lived) Only print the single-line summary
350 \\ none Do not print the build summary
351 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores)
352 \\ --maxrss <bytes> Limit memory usage (default is to use available memory)
353 \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss
354 \\ --test-timeout <timeout> Limit execution time of unit tests, terminating if exceeded.
355 \\ The timeout must include a unit: ns, us, ms, s, m, h
356 \\ --watch Continuously rebuild when source files are modified
357 \\ --debounce <ms> Delay before rebuilding after changed file detected
358 \\ --webui[=ip] Enable the web interface on the given IP address
359 \\ --fuzz[=limit] Continuously search for unit test failures with an optional
360 \\ limit to the max number of iterations. The argument supports
361 \\ an optional 'K', 'M', or 'G' suffix (e.g. '10K'). Implies
362 \\ '--webui' when no limit is specified.
363 \\ --listen=- Enable the build server protocol on stdio
364 \\ --time-report Force full rebuild and provide detailed information on
365 \\ compilation time of Zig source code (implies '--webui')
366 \\ -fincremental Enable incremental compilation
367 \\ -fno-incremental Disable incremental compilation
368 \\
369 \\Package Management Options:
370 \\ --fetch[=mode] Fetch dependency tree (optionally choose laziness) and exit
371 \\ needed (Default) Lazy dependencies are fetched as needed
372 \\ all Lazy dependencies are always fetched
373 \\ --fork=[path], --fork [path] Override one or more projects from dependency tree
374 \\
375 \\Advanced Options:
376 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
377 \\ -fno-reference-trace Disable reference trace
378 \\ -fallow-so-scripts Allows .so files to be GNU ld scripts
379 \\ -fno-allow-so-scripts (default) .so files must be ELF files
380 \\ --error-limit [num] Set the maximum amount of distinct error values
381 \\ --build-file [file] Override path to build.zig
382 \\ --cache-dir [path] Override path to local Zig cache directory
383 \\ --zig-lib=[arg] Override path to Zig lib directory
384 \\ --seed [integer] For shuffling dependency traversal order (default: random)
385 \\ --cache-poison[=mode] Override configuration caching behavior
386 \\ pure (default) Avoid false positive cache hits
387 \\ poisoned Don't cache the configuration
388 \\ disallowed Panics when cache would be poisoned
389 \\ ignored A little poison never hurt anybody
390 \\ --print-configuration Render configuration as .zon to stdout
391 \\ --print-configuration-path Print the path to the binary configuration file to stdout
392 \\ --build-id[=style] At a minor link-time expense, embeds a build ID in binaries
393 \\ fast 8-byte non-cryptographic hash (COFF, ELF, WASM)
394 \\ sha1, tree 20-byte cryptographic hash (ELF, WASM)
395 \\ md5 16-byte cryptographic hash (ELF)
396 \\ uuid 16-byte random UUID (ELF, WASM)
397 \\ 0x[hexstring] Constant ID, maximum 32 bytes (ELF, WASM)
398 \\ none (default) No build ID
399 \\ --debug-log [scope] Enable debugging the compiler
400 \\ --debug-pkg-config Fail if unknown pkg-config flags encountered
401 \\ --verbose-link Enable compiler debug output for linking
402 \\ --verbose-air Enable compiler debug output for Zig AIR
403 \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
404 \\ --verbose-cimport Enable compiler debug output for C imports
405 \\ --verbose-cc Enable compiler debug output for C compilation
406 \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
407 \\
408 );
304409}
305
306const system_integration_usage =
307 \\
308 \\System Integration Options:
309 \\ --search-prefix [path] Add a path to look for binaries, libraries, headers
310 \\ --sysroot [path] Set the system root directory (usually /)
311 \\ --libc [file] Provide a file which specifies libc paths
312 \\
313 \\ --system [pkgdir] Disable package fetching; enable all integrations
314 \\ -fsys=[name] Enable a system integration
315 \\ -fno-sys=[name] Disable a system integration
316 \\
317 \\ -fdarling, -fno-darling Integration with system-installed Darling to
318 \\ execute macOS programs on Linux hosts
319 \\ (default: no)
320 \\ -fqemu, -fno-qemu Integration with system-installed QEMU to execute
321 \\ foreign-architecture programs on Linux hosts
322 \\ (default: no)
323 \\ --libc-runtimes [path] Enhances QEMU integration by providing dynamic libc
324 \\ (e.g. glibc or musl) built for multiple foreign
325 \\ architectures, allowing execution of non-native
326 \\ programs that link with libc.
327 \\ -frosetta, -fno-rosetta Rely on Rosetta to execute x86_64 programs on
328 \\ ARM64 macOS hosts. (default: no)
329 \\ -fwasmtime, -fno-wasmtime Integration with system-installed wasmtime to
330 \\ execute WASI binaries. (default: no)
331 \\ -fwine, -fno-wine Integration with system-installed Wine to execute
332 \\ Windows programs on Linux hosts. (default: no)
333 \\
334 \\ Available System Integrations: Enabled:
335 \\
336;
337
338const general_usage =
339 \\
340 \\General Options:
341 \\ -h, --help Print this help to stdout and exit
342 \\ -l, --list-steps Print available steps to stdout and exit
343 \\
344 \\ -p, --prefix [path] Where to install files (default: zig-out)
345 \\ --prefix-lib-dir [path] Where to install libraries
346 \\ --prefix-exe-dir [path] Where to install executables
347 \\ --prefix-include-dir [path] Where to install C header files
348 \\ --release[=mode] Request release mode, optionally specifying a
349 \\ preferred optimization mode: fast, safe, small
350 \\
351 \\ --verbose Print commands before executing them
352 \\ --color [auto|off|on] Enable or disable colored error messages
353 \\ --error-style [style] Control how build errors are printed
354 \\ verbose (Default) Report errors with full context
355 \\ minimal Report errors after summary, excluding context like command lines
356 \\ verbose_clear Like "verbose", but clear the terminal at the start of each update
357 \\ minimal_clear Like "minimal", but clear the terminal at the start of each update
358 \\ --multiline-errors [style] Control how multi-line error messages are printed
359 \\ indent (Default) Indent non-initial lines to align with initial line
360 \\ newline Include a leading newline so that the error message is on its own lines
361 \\ none Print as usual so the first line is misaligned
362 \\ --summary [mode] Control the printing of the build summary
363 \\ all Print the build summary in its entirety
364 \\ new Omit cached steps
365 \\ failures (Default if short-lived) Only print failed steps
366 \\ line (Default if long-lived) Only print the single-line summary
367 \\ none Do not print the build summary
368 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores)
369 \\ --maxrss <bytes> Limit memory usage (default is to use available memory)
370 \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss
371 \\ --test-timeout <timeout> Limit execution time of unit tests, terminating if exceeded.
372 \\ The timeout must include a unit: ns, us, ms, s, m, h
373 \\ --watch Continuously rebuild when source files are modified
374 \\ --debounce <ms> Delay before rebuilding after changed file detected
375 \\ --webui[=ip] Enable the web interface on the given IP address
376 \\ --fuzz[=limit] Continuously search for unit test failures with an optional
377 \\ limit to the max number of iterations. The argument supports
378 \\ an optional 'K', 'M', or 'G' suffix (e.g. "10K"). Implies
379 \\ "--webui" when no limit is specified.
380 \\ --time-report Force full rebuild and provide detailed information on
381 \\ compilation time of Zig source code (implies "--webui")
382 \\ -fincremental Enable incremental compilation
383 \\ -fno-incremental Disable incremental compilation
384 \\ --configure Exit after the configuration phase
385 \\
386 \\Package Management Options:
387 \\ --fetch Fetch all dependencies including lazy ones; exit without configuration
388 \\ --fork=[path], --fork [path] Override one or more projects from dependency tree
389 \\ --print-tree Write current state of package dependencies to stdout
390 \\
391 \\Advanced Options:
392 \\ --listen=- Enable the build server protocol on stdio
393 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
394 \\ -fno-reference-trace Disable reference trace
395 \\ -fallow-so-scripts Allows .so files to be GNU ld scripts
396 \\ -fno-allow-so-scripts (default) .so files must be ELF files
397 \\ --error-limit [num] Set the maximum amount of distinct error values
398 \\ --build-file [file] Override path to build.zig
399 \\ --cache-dir [path] Override path to local Zig cache directory
400 \\ --zig-lib=[arg] Override path to Zig lib directory
401 \\ --seed [integer] For shuffling dependency traversal order (default: random)
402 \\ --cache-poison[=mode] Override configuration caching behavior
403 \\ pure (default) Avoid false positive cache hits
404 \\ poisoned Don't cache the configuration
405 \\ disallowed Panics when cache would be poisoned
406 \\ ignored A little poison never hurt anybody
407 \\ --print-configuration Render configuration as .zon to stdout. Implies "--configure"
408 \\ --print-configuration-path Print the path to the binary configuration file to stdout.
409 \\ --build-id[=style] At a minor link-time expense, embeds a build ID in binaries
410 \\ fast 8-byte non-cryptographic hash (COFF, ELF, WASM)
411 \\ sha1, tree 20-byte cryptographic hash (ELF, WASM)
412 \\ md5 16-byte cryptographic hash (ELF)
413 \\ uuid 16-byte random UUID (ELF, WASM)
414 \\ 0x[hexstring] Constant ID, maximum 32 bytes (ELF, WASM)
415 \\ none (default) No build ID
416 \\ --debug-log [scope] Enable debugging the compiler
417 \\ --debug-pkg-config Fail if unknown pkg-config flags encountered
418 \\ --verbose-link Enable compiler debug output for linking
419 \\ --verbose-air Enable compiler debug output for Zig AIR
420 \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
421 \\ --verbose-cimport Enable compiler debug output for C imports
422 \\ --verbose-cc Enable compiler debug output for C compilation
423 \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
424 \\
425;