diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig index 325fa1ff1d5c4aa940c9e668a53615cf367e9ea0..8055927d61e7276106d297c5950913e3a0e78980 100644 --- a/lib/compiler/Maker.zig +++ b/lib/compiler/Maker.zig @@ -23,7 +23,6 @@ const Color = std.zig.Color; const Client = std.zig.Client; const Server = std.zig.Server; const EnvVar = std.zig.EnvVar; -const ErrorBundle = std.zig.ErrorBundle; const default_local_zig_cache_basename = std.zig.default_local_zig_cache_basename; const stringToEnum = std.meta.stringToEnum; @@ -36,7 +35,6 @@ const ScannedConfig = @import("Maker/ScannedConfig.zig"); const PkgConfig = @import("Maker/PkgConfig.zig"); const Fetch = @import("Maker/Fetch.zig"); const Package = @import("Maker/Package.zig"); -const Manifest = Package.Manifest; pub const std_options: std.Options = .{ .side_channels_mitigations = .none, @@ -103,30 +101,8 @@ const InstallPaths = struct { }; const PrintNode = struct { - parent: ?*const PrintNode, + parent: ?*PrintNode, last: bool = false, - - fn printPrefix(node: *const PrintNode, writer: *Writer, mode: Io.Terminal.Mode) Writer.Error!void { - const parent = node.parent orelse return; - if (parent.parent == null) return; - try printPrefix(parent, writer, mode); - if (parent.last) { - try writer.writeAll(" "); - } else { - try printTreeSibling(writer, mode); - } - } - - fn printPrefixedChild(node: *const PrintNode, writer: *Writer, mode: Io.Terminal.Mode) Writer.Error!void { - try printPrefix(node, writer, mode); - if (node.parent != null) { - if (node.last) { - try printTreeChildLast(writer, mode); - } else { - try printTreeChild(writer, mode); - } - } - } }; const ErrorStyle = enum { @@ -149,7 +125,7 @@ const ErrorStyle = enum { }; const MultilineErrors = enum { indent, newline, none }; const Summary = enum { all, new, failures, line, none }; -const PrintConfiguration = enum { none, zon, path, tree, stop }; +const PrintConfiguration = enum { none, zon, path }; const GeneratedFile = struct { data: ?[]const u8, @@ -300,6 +276,7 @@ pub fn main(init: process.Init.Minimal) !void { var cached_passthru_configure: std.ArrayList(u32) = .empty; var forks: std.ArrayList(Fork) = .empty; var system_pkg_dir_path: ?[]const u8 = null; + var fetch_only = false; var fetch_mode: Fetch.JobQueue.Mode = .needed; var debug_target: ?[]const u8 = null; var cache_poison: std.Build.Graph.CachePoison = .pure; @@ -384,12 +361,12 @@ pub fn main(init: process.Init.Minimal) !void { override_local_cache_dir = nextArgOrFatal(args, &arg_i); } else if (mem.eql(u8, arg, "--pkg-dir")) { override_pkg_dir = nextArgOrFatal(args, &arg_i); - } else if (mem.eql(u8, arg, "--print-tree")) { - print_configuration = .tree; - } else if (mem.eql(u8, arg, "--configure")) { - print_configuration = .stop; } else if (mem.eql(u8, arg, "--fetch")) { - fetch_mode = .all; + fetch_only = true; + } else if (mem.cutPrefix(u8, arg, "--fetch=")) |rest| { + fetch_only = true; + fetch_mode = stringToEnum(Fetch.JobQueue.Mode, rest) orelse + fatal("expected [needed|all] after \"--fetch=\", found {q}", .{rest}); } else if (mem.cutPrefix(u8, arg, "--fork=")) |rest| { try forks.append(arena, .init(rest)); } else if (mem.eql(u8, arg, "--fork")) { @@ -616,7 +593,7 @@ pub fn main(init: process.Init.Minimal) !void { } } - const early_exit_mode = fetch_mode == .all or help_menu or steps_menu or print_configuration != .none; + const early_exit_mode = fetch_only or help_menu or steps_menu or print_configuration != .none; const server_mode = !early_exit_mode and (watch_flag or webui_listen != null or fuzz != null or listen); process.raiseFileDescriptorLimit(); @@ -624,16 +601,10 @@ pub fn main(init: process.Init.Minimal) !void { const cwd_path = std.zig.getResolvedCwd(io, arena) catch |err| fatal("resolving current directory path failed: {t}", .{err}); - var build_root = findBuildRoot(arena, io, .{ + var build_root = try findBuildRoot(arena, io, .{ .cwd_path = cwd_path, .build_file = build_file, - }) catch |err| switch (err) { - error.BuildZigNotFound => { - if (help_menu) printUsageWithoutConfiguration(&graph, "build.zig not found"); - process.exit(1); - }, - else => |e| return e, - }; + }); defer build_root.deinit(io); graph.build_root_directory = build_root.directory; @@ -769,7 +740,7 @@ pub fn main(init: process.Init.Minimal) !void { var configure_source_files: Cache.Manifest.SelfContainedFiles = .empty; defer configure_source_files.deinit(gpa); - var configure_error_bundle: ErrorBundle = .empty; + var configure_error_bundle: std.zig.ErrorBundle = .empty; defer configure_error_bundle.deinit(gpa); // 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 { .parent_progress_node = main_progress_node, .fetch_mode = fetch_mode, .system_pkg_dir_path = system_pkg_dir_path, + .fetch_only = fetch_only, .print_configuration = print_configuration, .forks = forks.items, .src_files = &configure_source_files, @@ -817,8 +789,6 @@ pub fn main(init: process.Init.Minimal) !void { return cleanExit(io, &scanned_config); }, .path => unreachable, - .tree => unreachable, - .stop => return cleanExit(io, &scanned_config), } var maker: Maker = .{ @@ -1073,10 +1043,7 @@ pub fn main(init: process.Init.Minimal) !void { } else |err| { const can_fs_watch = switch (err) { error.AlreadyReported => false, - error.FailedButCacheIntact => c: { - if (help_menu) printUsageWithoutConfiguration(&graph, "build.zig compilation failure"); - break :c true; - }, + error.FailedButCacheIntact => true, else => |e| w: { log.err("configuration failed: {t}", .{e}); break :w false; @@ -1098,17 +1065,6 @@ pub fn main(init: process.Init.Minimal) !void { } } -fn printUsageWithoutConfiguration(graph: *Graph, reason: []const u8) noreturn { - const io = graph.io; - _ = io.lockStderr(&.{}, graph.stderr_mode) catch {}; - const writer = initStdoutWriter(io); - ScannedConfig.printUsageWithoutConfiguration(graph.zig_exe, writer, reason) catch |err| switch (err) { - error.WriteFailed => fatal("failed writing to stdout: {t}", .{stdout_writer_allocation.err.?}), - }; - stdout_writer_allocation.flush() catch |err| fatal("failed writing to stdout: {t}", .{err}); - return process.exit(0); -} - /// Temporarily adds the reconfigure pseudostep to step_stack, calls /// `Watch.update`, and then pops it again. fn updateWatch(maker: *Maker, watch: *Watch) !void { @@ -1132,10 +1088,11 @@ const ConfigureOptions = struct { parent_progress_node: std.Progress.Node, fetch_mode: Fetch.JobQueue.Mode, system_pkg_dir_path: ?[]const u8, + fetch_only: bool, print_configuration: PrintConfiguration, forks: []Fork, src_files: *Cache.Manifest.SelfContainedFiles, - error_bundle: ?*ErrorBundle = null, + error_bundle: ?*std.zig.ErrorBundle = null, }; fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { @@ -1379,27 +1336,11 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { return error.FailedButCacheIntact; } - if (options.print_configuration == .tree) { - const NO_COLOR = EnvVar.NO_COLOR.isSet(&graph.environ_map); - const CLICOLOR_FORCE = EnvVar.CLICOLOR_FORCE.isSet(&graph.environ_map); - printPkgTree(.{ - .writer = initStdoutWriter(io), - .mode = try .detect(io, .stdout(), NO_COLOR, CLICOLOR_FORCE), - }, arena, &job_queue, &fetch) catch |err| switch (err) { - error.WriteFailed => return stdout_writer_allocation.err.?, - else => |e| return e, - }; - try stdout_writer_allocation.flush(); - process.exit(0); - } - - if (options.fetch_mode == .all) { + if (options.fetch_only) { _ = io.lockStderr(&.{}, .no_color) catch {}; process.exit(0); } - try validateFingerprints(gpa, &job_queue); - // Create the dependencies.zig file for configurer to // obtain via `@import("@dependencies")`. { @@ -1462,7 +1403,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { for (fetches) |f| { if (!f.have_manifest) continue; if (config_man) |man| { - const manifest_path = try f.package_root.join(arena, Manifest.basename); + const manifest_path = try f.package_root.join(arena, Package.Manifest.basename); _ = try man.addInputPath(manifest_path, .{}); } const mod = f.cli_module orelse continue; @@ -1678,8 +1619,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { _ = io.lockStderr(&.{}, .no_color) catch {}; process.exit(0); }, - .none, .zon, .stop => {}, - .tree => unreachable, + .none, .zon => {}, } const configuration = c: { @@ -1717,147 +1657,6 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { }; } -const ValidFingerprintKey = struct { - project_id: Package.ProjectId, - version: std.SemanticVersion, - - const Context = struct { - pub fn hash(this: @This(), a: ValidFingerprintKey) u32 { - _ = this; - var hasher: std.hash.Wyhash = .init(a.project_id.fingerprint_id); - hasher.update(&a.project_id.padded_name); - hasher.update(@ptrCast((&a.version.major)[0..1])); - hasher.update(@ptrCast((&a.version.minor)[0..1])); - hasher.update(@ptrCast((&a.version.patch)[0..1])); - if (a.version.pre) |pre| hasher.update(pre); - return @truncate(hasher.final()); - } - pub fn eql(this: @This(), a: ValidFingerprintKey, b: ValidFingerprintKey, i: usize) bool { - _ = this; - _ = i; - return a.project_id.eql(&b.project_id) and a.version.order(b.version) == .eq; - } - }; -}; - -const ValidFingerprintTable = std.array_hash_map.Custom( - ValidFingerprintKey, - struct { fetch: *Fetch, pkg_hash: Package.Hash, printed: bool }, - ValidFingerprintKey.Context, - true, -); - -/// Ensure that the dependency tree did not have any fingerprint matches with the same semantic version but -/// differing package hashes. -fn validateFingerprints(gpa: Allocator, job_queue: *const Fetch.JobQueue) !void { - var any_errors = false; - - var table: ValidFingerprintTable = .empty; - defer table.deinit(gpa); - - for (job_queue.table.keys(), job_queue.table.values()) |pkg_hash, fetch| { - if (!fetch.have_manifest) continue; - const gop = try table.getOrPut(gpa, .{ - .project_id = .init(fetch.manifest.name, fetch.manifest.id), - .version = fetch.manifest.version, - }); - if (gop.found_existing) { - any_errors = true; - const fingerprint: Package.Fingerprint = .init(fetch.manifest.id, fetch.manifest.name); - const stripped_version: std.SemanticVersion = .{ - .major = fetch.manifest.version.major, - .minor = fetch.manifest.version.minor, - .patch = fetch.manifest.version.patch, - .pre = fetch.manifest.version.pre, - }; - if (!gop.value_ptr.printed) { - gop.value_ptr.printed = true; - log.err("contradictory hash for package with fingerprint 0x{x} and version {f}: {s}", .{ - fingerprint.int(), stripped_version, gop.value_ptr.pkg_hash.toSlice(), - }); - } - log.err("contradictory hash for package with fingerprint 0x{x} and version {f}: {s}", .{ - fingerprint.int(), stripped_version, pkg_hash.toSlice(), - }); - } else { - gop.value_ptr.* = .{ .fetch = fetch, .pkg_hash = pkg_hash, .printed = false }; - } - } - if (any_errors) { - log.info("potential cause: package ownership dispute", .{}); - log.info("potential cause: maintainer neglected to bump version after making changes", .{}); - log.info("potential cause: dependency on unreleased changes", .{}); - log.info("hint: use --print-tree to visualize all package versions and hashes", .{}); - return error.FailedButCacheIntact; - } -} - -fn printPkgTree( - terminal: Io.Terminal, - arena: Allocator, - job_queue: *const Fetch.JobQueue, - root_fetch: *const Fetch, -) !void { - if (!root_fetch.have_manifest) return; - const names = root_fetch.manifest.dependencies.keys(); - for (names, root_fetch.manifest.dependencies.values(), 0..) |name, *dep, i| { - var print_node: PrintNode = .{ - .parent = null, - .last = i == names.len - 1, - }; - try printPkgTreeChild(terminal, arena, job_queue, &print_node, name, dep.hash); - } -} - -fn printPkgTreeChild( - terminal: Io.Terminal, - arena: Allocator, - job_queue: *const Fetch.JobQueue, - parent_print_node: *const PrintNode, - dep_name: []const u8, - opt_hash: ?[]const u8, -) !void { - const w = terminal.writer; - try parent_print_node.printPrefixedChild(w, terminal.mode); - try w.writeAll(dep_name); - - const hash = opt_hash orelse { - try terminal.setColor(.red); - try w.writeAll(" (missing hash)\n"); - try terminal.setColor(.reset); - return; - }; - try terminal.setColor(.dim); - try w.print(" {s}", .{hash}); - try terminal.setColor(.reset); - const child_fetch = job_queue.table.get(.fromSlice(hash)) orelse { - try terminal.setColor(.red); - try w.writeAll(" (fetch failed)\n"); - try terminal.setColor(.reset); - return; - }; - switch (child_fetch.lazy_status) { - .eager, .available => {}, - .unavailable => { - try terminal.setColor(.yellow); - try w.writeAll(" (not fetched)\n"); - try terminal.setColor(.reset); - return; - }, - } - try w.writeByte('\n'); - if (!child_fetch.have_manifest) return; - - const names = child_fetch.manifest.dependencies.keys(); - for (names, child_fetch.manifest.dependencies.values(), 0..) |name, *dep, i| { - var print_node: PrintNode = .{ - .parent = parent_print_node, - .last = i == names.len - 1, - }; - try printPkgTreeChild(terminal, arena, job_queue, &print_node, name, dep.hash); - } -} - fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void { const environ_map = &graph.environ_map; const io = graph.io; @@ -2134,8 +1933,8 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void { try ast.render(gpa, &aw.writer, fixups); const rendered = aw.written(); - build_root.directory.handle.writeFile(io, .{ .sub_path = Manifest.basename, .data = rendered }) catch |err| { - fatal("unable to write {s} file: {t}", .{ Manifest.basename, err }); + build_root.directory.handle.writeFile(io, .{ .sub_path = Package.Manifest.basename, .data = rendered }) catch |err| { + fatal("unable to write {s} file: {t}", .{ Package.Manifest.basename, err }); }; return process.cleanExit(io); @@ -2337,7 +2136,7 @@ fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void { const s = Dir.path.sep_str; const template_paths = [_][]const u8{ default_build_zig_basename, - Manifest.basename, + Package.Manifest.basename, "src" ++ s ++ "main.zig", "src" ++ s ++ "root.zig", }; @@ -2361,7 +2160,7 @@ fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void { return process.cleanExit(io); }, .minimal => { - Templates.writeSimpleFile(io, Io.Dir.cwd(), Manifest.basename, + Templates.writeSimpleFile(io, Io.Dir.cwd(), Package.Manifest.basename, \\.{{ \\ .name = .{s}, \\ .version = "0.0.1", @@ -2375,8 +2174,8 @@ fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void { builtin.zig_version_string, fingerprint.int(), }) catch |err| switch (err) { - else => fatal("failed to create {q}: {t}", .{ Manifest.basename, err }), - error.PathAlreadyExists => fatal("refusing to overwrite {q}", .{Manifest.basename}), + else => fatal("failed to create {q}: {t}", .{ Package.Manifest.basename, err }), + error.PathAlreadyExists => fatal("refusing to overwrite {q}", .{Package.Manifest.basename}), }; Templates.writeSimpleFile(io, Io.Dir.cwd(), default_build_zig_basename, \\const std = @import("std"); @@ -2391,12 +2190,12 @@ fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void { // their `build.zig.zon` *after* writing their `build.zig`. So this one isn't fatal. error.PathAlreadyExists => { log.info("successfully populated {q}, preserving existing {q}", .{ - Manifest.basename, default_build_zig_basename, + Package.Manifest.basename, default_build_zig_basename, }); return process.cleanExit(io); }, }; - log.info("successfully populated {q} and {q}", .{ Manifest.basename, default_build_zig_basename }); + log.info("successfully populated {q} and {q}", .{ Package.Manifest.basename, default_build_zig_basename }); return process.cleanExit(io); }, } @@ -3129,7 +2928,18 @@ fn printTreeStep( .failures => make_step.state == .success, }; if (skip) return; - try parent_node.printPrefixedChild(writer, stderr.mode); + try printPrefix(parent_node, stderr); + + if (parent_node.parent != null) { + if (parent_node.last) { + try printChildNodePrefix(stderr); + } else { + try writer.writeAll(switch (stderr.mode) { + .escape_codes => "\x1B\x28\x30\x74\x71\x1B\x28\x42 ", // ├─ + else => "+- ", + }); + } + } if (!first) try stderr.setColor(.dim); @@ -3358,22 +3168,23 @@ fn printStepFailure( } } -fn printTreeChild(writer: *Writer, mode: Io.Terminal.Mode) Writer.Error!void { - return writer.writeAll(switch (mode) { - .escape_codes => "\x1B\x28\x30\x74\x71\x1B\x28\x42 ", // ├─ - else => "+- ", - }); +fn printPrefix(node: *PrintNode, stderr: Io.Terminal) !void { + const parent = node.parent orelse return; + const writer = stderr.writer; + if (parent.parent == null) return; + try printPrefix(parent, stderr); + if (parent.last) { + try writer.writeAll(" "); + } else { + try writer.writeAll(switch (stderr.mode) { + .escape_codes => "\x1B\x28\x30\x78\x1B\x28\x42 ", // │ + else => "| ", + }); + } } -fn printTreeSibling(writer: *Writer, mode: Io.Terminal.Mode) Writer.Error!void { - return writer.writeAll(switch (mode) { - .escape_codes => "\x1B\x28\x30\x78\x1B\x28\x42 ", // │ - else => "| ", - }); -} - -fn printTreeChildLast(writer: *Writer, mode: Io.Terminal.Mode) !void { - try writer.writeAll(switch (mode) { +fn printChildNodePrefix(stderr: Io.Terminal) !void { + try stderr.writer.writeAll(switch (stderr.mode) { .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ else => "+- ", }); @@ -3467,7 +3278,7 @@ pub fn invalidateResult(maker: *Maker, step: *Step) error{MustReconfigure}!bool pub fn printErrorMessages( maker: *Maker, failing_step_index: Configuration.Step.Index, - options: ErrorBundle.RenderOptions, + options: std.zig.ErrorBundle.RenderOptions, stderr: Io.Terminal, error_style: ErrorStyle, multiline_errors: MultilineErrors, @@ -3493,7 +3304,7 @@ pub fn printErrorMessages( while (step_stack.pop()) |step_index| : (indent += 1) { if (indent > 0) { try writer.splatByteAll(' ', (indent - 1) * 3); - try printTreeChildLast(writer, stderr.mode); + try printChildNodePrefix(stderr); } try writer.writeAll(step_index.ptr(c).name.slice(c)); @@ -4227,9 +4038,7 @@ const FindBuildRootOptions = struct { cwd_path: []const u8, }; -const FindBuildRootError = error{ OutOfMemory, BuildZigNotFound }; - -fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) FindBuildRootError!BuildRoot { +fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) !BuildRoot { const build_zig_basename = if (options.build_file) |bf| Dir.path.basename(bf) else @@ -4280,12 +4089,11 @@ fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) FindBu dirname = Dir.path.dirname(dirname orelse options.cwd_path) orelse { log.info("initialize {s} template file with \"zig init\"", .{std.zig.build_zig_basename}); log.info("see \"zig --help\" for more options", .{}); - log.err("no build.zig file found, in the current directory or any parent directories", .{}); - return error.BuildZigNotFound; + fatal("no build.zig file found, in the current directory or any parent directories", .{}); }; continue; }, - else => |e| fatal("accessing {q} while searching for build.zig file failed: {t}", .{ joined_path, e }), + else => |e| return e, } } } @@ -4293,8 +4101,8 @@ fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) FindBu const Fork = struct { path: Path, manifest_ast: std.zig.Ast, - manifest: Manifest, - error_bundle: ErrorBundle.Wip, + manifest: Package.Manifest, + error_bundle: std.zig.ErrorBundle.Wip, failed: bool, arena_allocator: std.heap.ArenaAllocator, @@ -4327,12 +4135,12 @@ const Fork = struct { fork.arena_allocator = .init(gpa); const arena = fork.arena_allocator.allocator(); - var error_bundle: ErrorBundle.Wip = try .init(gpa); + var error_bundle: std.zig.ErrorBundle.Wip = try .init(gpa); defer error_bundle.deinit(); - const manifest_path = try fork.path.join(arena, Manifest.basename); + const manifest_path = try fork.path.join(arena, Package.Manifest.basename); - Manifest.load( + Package.Manifest.load( io, arena, manifest_path, @@ -4382,20 +4190,20 @@ fn loadManifest( arena: Allocator, io: Io, options: LoadManifestOptions, -) !struct { Manifest, std.zig.Ast } { +) !struct { Package.Manifest, std.zig.Ast } { const rng: std.Random.IoSource = .{ .io = io }; const manifest_bytes = while (true) { break options.dir.readFileAllocOptions( io, - Manifest.basename, + Package.Manifest.basename, arena, - .limited(Manifest.max_bytes), + .limited(Package.Manifest.max_bytes), .@"1", 0, ) catch |err| switch (err) { error.FileNotFound => { - Templates.writeSimpleFile(io, options.dir, Manifest.basename, + Templates.writeSimpleFile(io, options.dir, Package.Manifest.basename, \\.{{ \\ .name = .{s}, \\ .version = "0.0.1", @@ -4409,29 +4217,29 @@ fn loadManifest( builtin.zig_version_string, Package.Fingerprint.generate(rng.interface(), options.root_name).int(), }) catch |e| { - fatal("unable to write {s}: {t}", .{ Manifest.basename, e }); + fatal("unable to write {s}: {t}", .{ Package.Manifest.basename, e }); }; continue; }, - else => |e| fatal("unable to load {s}: {t}", .{ Manifest.basename, e }), + else => |e| fatal("unable to load {s}: {t}", .{ Package.Manifest.basename, e }), }; }; var ast = try std.zig.Ast.parse(gpa, manifest_bytes, .{ .mode = .zon }); errdefer ast.deinit(gpa); if (ast.errors.len > 0) { - try std.zig.printAstErrorsToStderr(gpa, io, ast, Manifest.basename, options.color); + try std.zig.printAstErrorsToStderr(gpa, io, ast, Package.Manifest.basename, options.color); process.exit(2); } - var manifest = try Manifest.parse(gpa, &ast, rng.interface(), .{}); + var manifest = try Package.Manifest.parse(gpa, &ast, rng.interface(), .{}); errdefer manifest.deinit(gpa); if (manifest.errors.len > 0) { - var wip_errors: ErrorBundle.Wip = try .init(gpa); + var wip_errors: std.zig.ErrorBundle.Wip = try .init(gpa); defer wip_errors.deinit(); - const src_path = try wip_errors.addString(Manifest.basename); + const src_path = try wip_errors.addString(Package.Manifest.basename); try manifest.copyErrorsIntoBundle(ast, src_path, &wip_errors); var error_bundle = try wip_errors.toOwnedBundle(""); @@ -4455,8 +4263,8 @@ fn sanitizeExampleName(arena: Allocator, bytes: []const u8) error{OutOfMemory}![ else => continue, }; if (!std.zig.isValidId(result.items)) return "foo"; - if (result.items.len > Manifest.max_name_len) - result.shrinkRetainingCapacity(Manifest.max_name_len); + if (result.items.len > Package.Manifest.max_name_len) + result.shrinkRetainingCapacity(Package.Manifest.max_name_len); return result.toOwnedSlice(arena); } diff --git a/lib/compiler/Maker/Package.zig b/lib/compiler/Maker/Package.zig index c31ecf6916ce4d8d279cc9dbe9f529ee99355372..8baef22f375f925534380176f618a470f988117e 100644 --- a/lib/compiler/Maker/Package.zig +++ b/lib/compiler/Maker/Package.zig @@ -8,15 +8,11 @@ pub const Fingerprint = packed struct(u64) { id: u32, checksum: u32, - pub fn init(id: u32, name: []const u8) Fingerprint { - return .{ - .id = id, - .checksum = std.hash.Crc32.hash(name), - }; - } - pub fn generate(rng: std.Random, name: []const u8) Fingerprint { - return .init(rng.intRangeLessThan(u32, 1, 0xffffffff), name); + return .{ + .id = rng.intRangeLessThan(u32, 1, 0xffffffff), + .checksum = std.hash.Crc32.hash(name), + }; } pub fn validate(n: Fingerprint, name: []const u8) bool { diff --git a/lib/compiler/Maker/ScannedConfig.zig b/lib/compiler/Maker/ScannedConfig.zig index bae416b9bb2523a6b042bfa118d8a60ae43213ed..0b98a78d877b69c06f9b8fdd5da3d9efa178abb2 100644 --- a/lib/compiler/Maker/ScannedConfig.zig +++ b/lib/compiler/Maker/ScannedConfig.zig @@ -238,18 +238,6 @@ pub fn printSteps(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void { } } -pub fn printUsageWithoutConfiguration(zig_exe: []const u8, w: *Writer, reason: []const u8) Writer.Error!void { - try w.print( - \\Usage: {s} build [steps] [options] - \\ - \\Steps: (unavailable due to {s}) - \\Project-Specific Options: (unavailable due to {s}) - \\{s} - \\ (unavailable due to {s}) - \\{s} - , .{ zig_exe, reason, reason, system_integration_usage, reason, general_usage }); -} - pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void { const arena = graph.arena; @@ -286,7 +274,37 @@ pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void { } } - try w.writeAll(system_integration_usage); + try w.writeAll( + \\ + \\System Integration Options: + \\ --search-prefix [path] Add a path to look for binaries, libraries, headers + \\ --sysroot [path] Set the system root directory (usually /) + \\ --libc [file] Provide a file which specifies libc paths + \\ + \\ --system [pkgdir] Disable package fetching; enable all integrations + \\ -fsys=[name] Enable a system integration + \\ -fno-sys=[name] Disable a system integration + \\ + \\ -fdarling, -fno-darling Integration with system-installed Darling to + \\ execute macOS programs on Linux hosts + \\ (default: no) + \\ -fqemu, -fno-qemu Integration with system-installed QEMU to execute + \\ foreign-architecture programs on Linux hosts + \\ (default: no) + \\ --libc-runtimes [path] Enhances QEMU integration by providing dynamic libc + \\ (e.g. glibc or musl) built for multiple foreign + \\ architectures, allowing execution of non-native + \\ programs that link with libc. + \\ -frosetta, -fno-rosetta Rely on Rosetta to execute x86_64 programs on + \\ ARM64 macOS hosts. (default: no) + \\ -fwasmtime, -fno-wasmtime Integration with system-installed wasmtime to + \\ execute WASI binaries. (default: no) + \\ -fwine, -fno-wine Integration with system-installed Wine to execute + \\ Windows programs on Linux hosts. (default: no) + \\ + \\ Available System Integrations: Enabled: + \\ + ); if (sc.configuration.system_integrations.len == 0) { try w.writeAll(" (none) -\n"); } else { @@ -300,126 +318,92 @@ pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void { } } - try w.writeAll(general_usage); + try w.writeAll( + \\ + \\General Options: + \\ -h, --help Print this help to stdout and exit + \\ -l, --list-steps Print available steps to stdout and exit + \\ + \\ -p, --prefix [path] Where to install files (default: zig-out) + \\ --prefix-lib-dir [path] Where to install libraries + \\ --prefix-exe-dir [path] Where to install executables + \\ --prefix-include-dir [path] Where to install C header files + \\ --release[=mode] Request release mode, optionally specifying a + \\ preferred optimization mode: fast, safe, small + \\ + \\ --verbose Print commands before executing them + \\ --color [auto|off|on] Enable or disable colored error messages + \\ --error-style [style] Control how build errors are printed + \\ verbose (Default) Report errors with full context + \\ minimal Report errors after summary, excluding context like command lines + \\ verbose_clear Like 'verbose', but clear the terminal at the start of each update + \\ minimal_clear Like 'minimal', but clear the terminal at the start of each update + \\ --multiline-errors [style] Control how multi-line error messages are printed + \\ indent (Default) Indent non-initial lines to align with initial line + \\ newline Include a leading newline so that the error message is on its own lines + \\ none Print as usual so the first line is misaligned + \\ --summary [mode] Control the printing of the build summary + \\ all Print the build summary in its entirety + \\ new Omit cached steps + \\ failures (Default if short-lived) Only print failed steps + \\ line (Default if long-lived) Only print the single-line summary + \\ none Do not print the build summary + \\ -j Limit concurrent jobs (default is to use all CPU cores) + \\ --maxrss Limit memory usage (default is to use available memory) + \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss + \\ --test-timeout Limit execution time of unit tests, terminating if exceeded. + \\ The timeout must include a unit: ns, us, ms, s, m, h + \\ --watch Continuously rebuild when source files are modified + \\ --debounce Delay before rebuilding after changed file detected + \\ --webui[=ip] Enable the web interface on the given IP address + \\ --fuzz[=limit] Continuously search for unit test failures with an optional + \\ limit to the max number of iterations. The argument supports + \\ an optional 'K', 'M', or 'G' suffix (e.g. '10K'). Implies + \\ '--webui' when no limit is specified. + \\ --listen=- Enable the build server protocol on stdio + \\ --time-report Force full rebuild and provide detailed information on + \\ compilation time of Zig source code (implies '--webui') + \\ -fincremental Enable incremental compilation + \\ -fno-incremental Disable incremental compilation + \\ + \\Package Management Options: + \\ --fetch[=mode] Fetch dependency tree (optionally choose laziness) and exit + \\ needed (Default) Lazy dependencies are fetched as needed + \\ all Lazy dependencies are always fetched + \\ --fork=[path], --fork [path] Override one or more projects from dependency tree + \\ + \\Advanced Options: + \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error + \\ -fno-reference-trace Disable reference trace + \\ -fallow-so-scripts Allows .so files to be GNU ld scripts + \\ -fno-allow-so-scripts (default) .so files must be ELF files + \\ --error-limit [num] Set the maximum amount of distinct error values + \\ --build-file [file] Override path to build.zig + \\ --cache-dir [path] Override path to local Zig cache directory + \\ --zig-lib=[arg] Override path to Zig lib directory + \\ --seed [integer] For shuffling dependency traversal order (default: random) + \\ --cache-poison[=mode] Override configuration caching behavior + \\ pure (default) Avoid false positive cache hits + \\ poisoned Don't cache the configuration + \\ disallowed Panics when cache would be poisoned + \\ ignored A little poison never hurt anybody + \\ --print-configuration Render configuration as .zon to stdout + \\ --print-configuration-path Print the path to the binary configuration file to stdout + \\ --build-id[=style] At a minor link-time expense, embeds a build ID in binaries + \\ fast 8-byte non-cryptographic hash (COFF, ELF, WASM) + \\ sha1, tree 20-byte cryptographic hash (ELF, WASM) + \\ md5 16-byte cryptographic hash (ELF) + \\ uuid 16-byte random UUID (ELF, WASM) + \\ 0x[hexstring] Constant ID, maximum 32 bytes (ELF, WASM) + \\ none (default) No build ID + \\ --debug-log [scope] Enable debugging the compiler + \\ --debug-pkg-config Fail if unknown pkg-config flags encountered + \\ --verbose-link Enable compiler debug output for linking + \\ --verbose-air Enable compiler debug output for Zig AIR + \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR + \\ --verbose-cimport Enable compiler debug output for C imports + \\ --verbose-cc Enable compiler debug output for C compilation + \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features + \\ + ); } - -const system_integration_usage = - \\ - \\System Integration Options: - \\ --search-prefix [path] Add a path to look for binaries, libraries, headers - \\ --sysroot [path] Set the system root directory (usually /) - \\ --libc [file] Provide a file which specifies libc paths - \\ - \\ --system [pkgdir] Disable package fetching; enable all integrations - \\ -fsys=[name] Enable a system integration - \\ -fno-sys=[name] Disable a system integration - \\ - \\ -fdarling, -fno-darling Integration with system-installed Darling to - \\ execute macOS programs on Linux hosts - \\ (default: no) - \\ -fqemu, -fno-qemu Integration with system-installed QEMU to execute - \\ foreign-architecture programs on Linux hosts - \\ (default: no) - \\ --libc-runtimes [path] Enhances QEMU integration by providing dynamic libc - \\ (e.g. glibc or musl) built for multiple foreign - \\ architectures, allowing execution of non-native - \\ programs that link with libc. - \\ -frosetta, -fno-rosetta Rely on Rosetta to execute x86_64 programs on - \\ ARM64 macOS hosts. (default: no) - \\ -fwasmtime, -fno-wasmtime Integration with system-installed wasmtime to - \\ execute WASI binaries. (default: no) - \\ -fwine, -fno-wine Integration with system-installed Wine to execute - \\ Windows programs on Linux hosts. (default: no) - \\ - \\ Available System Integrations: Enabled: - \\ -; - -const general_usage = - \\ - \\General Options: - \\ -h, --help Print this help to stdout and exit - \\ -l, --list-steps Print available steps to stdout and exit - \\ - \\ -p, --prefix [path] Where to install files (default: zig-out) - \\ --prefix-lib-dir [path] Where to install libraries - \\ --prefix-exe-dir [path] Where to install executables - \\ --prefix-include-dir [path] Where to install C header files - \\ --release[=mode] Request release mode, optionally specifying a - \\ preferred optimization mode: fast, safe, small - \\ - \\ --verbose Print commands before executing them - \\ --color [auto|off|on] Enable or disable colored error messages - \\ --error-style [style] Control how build errors are printed - \\ verbose (Default) Report errors with full context - \\ minimal Report errors after summary, excluding context like command lines - \\ verbose_clear Like "verbose", but clear the terminal at the start of each update - \\ minimal_clear Like "minimal", but clear the terminal at the start of each update - \\ --multiline-errors [style] Control how multi-line error messages are printed - \\ indent (Default) Indent non-initial lines to align with initial line - \\ newline Include a leading newline so that the error message is on its own lines - \\ none Print as usual so the first line is misaligned - \\ --summary [mode] Control the printing of the build summary - \\ all Print the build summary in its entirety - \\ new Omit cached steps - \\ failures (Default if short-lived) Only print failed steps - \\ line (Default if long-lived) Only print the single-line summary - \\ none Do not print the build summary - \\ -j Limit concurrent jobs (default is to use all CPU cores) - \\ --maxrss Limit memory usage (default is to use available memory) - \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss - \\ --test-timeout Limit execution time of unit tests, terminating if exceeded. - \\ The timeout must include a unit: ns, us, ms, s, m, h - \\ --watch Continuously rebuild when source files are modified - \\ --debounce Delay before rebuilding after changed file detected - \\ --webui[=ip] Enable the web interface on the given IP address - \\ --fuzz[=limit] Continuously search for unit test failures with an optional - \\ limit to the max number of iterations. The argument supports - \\ an optional 'K', 'M', or 'G' suffix (e.g. "10K"). Implies - \\ "--webui" when no limit is specified. - \\ --time-report Force full rebuild and provide detailed information on - \\ compilation time of Zig source code (implies "--webui") - \\ -fincremental Enable incremental compilation - \\ -fno-incremental Disable incremental compilation - \\ --configure Exit after the configuration phase - \\ - \\Package Management Options: - \\ --fetch Fetch all dependencies including lazy ones; exit without configuration - \\ --fork=[path], --fork [path] Override one or more projects from dependency tree - \\ --print-tree Write current state of package dependencies to stdout - \\ - \\Advanced Options: - \\ --listen=- Enable the build server protocol on stdio - \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error - \\ -fno-reference-trace Disable reference trace - \\ -fallow-so-scripts Allows .so files to be GNU ld scripts - \\ -fno-allow-so-scripts (default) .so files must be ELF files - \\ --error-limit [num] Set the maximum amount of distinct error values - \\ --build-file [file] Override path to build.zig - \\ --cache-dir [path] Override path to local Zig cache directory - \\ --zig-lib=[arg] Override path to Zig lib directory - \\ --seed [integer] For shuffling dependency traversal order (default: random) - \\ --cache-poison[=mode] Override configuration caching behavior - \\ pure (default) Avoid false positive cache hits - \\ poisoned Don't cache the configuration - \\ disallowed Panics when cache would be poisoned - \\ ignored A little poison never hurt anybody - \\ --print-configuration Render configuration as .zon to stdout. Implies "--configure" - \\ --print-configuration-path Print the path to the binary configuration file to stdout. - \\ --build-id[=style] At a minor link-time expense, embeds a build ID in binaries - \\ fast 8-byte non-cryptographic hash (COFF, ELF, WASM) - \\ sha1, tree 20-byte cryptographic hash (ELF, WASM) - \\ md5 16-byte cryptographic hash (ELF) - \\ uuid 16-byte random UUID (ELF, WASM) - \\ 0x[hexstring] Constant ID, maximum 32 bytes (ELF, WASM) - \\ none (default) No build ID - \\ --debug-log [scope] Enable debugging the compiler - \\ --debug-pkg-config Fail if unknown pkg-config flags encountered - \\ --verbose-link Enable compiler debug output for linking - \\ --verbose-air Enable compiler debug output for Zig AIR - \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR - \\ --verbose-cimport Enable compiler debug output for C imports - \\ --verbose-cc Enable compiler debug output for C compilation - \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features - \\ -;