From ae9fef9c62aff00dfd27443c59cbed8ccb3db213 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 15 Feb 2026 23:23:17 -0800 Subject: [PATCH] configure runner: serialization of compile step --- lib/compiler/configure_runner.zig | 106 +++++++++++- lib/compiler/maker/Step/Compile.zig | 130 +++++++++++++- lib/std/Build/Step/Compile.zig | 164 ++---------------- lib/std/zig.zig | 4 +- lib/std/zig/Configuration.zig | 258 +++++++++++++++++++++++++++- 5 files changed, 500 insertions(+), 162 deletions(-) diff --git a/lib/compiler/configure_runner.zig b/lib/compiler/configure_runner.zig index a687af8765..64ebf844ae 100644 --- a/lib/compiler/configure_runner.zig +++ b/lib/compiler/configure_runner.zig @@ -269,7 +269,105 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { .description = try wc.addString(top_level.description), })); }, - .compile => @panic("TODO"), + .compile => e: { + const c: *Step.Compile = @fieldParentPtr("step", step); + const extra_index = try wc.addExtra(@as(Configuration.Step.Compile, .{ + .flags = .{ + .filters_len = c.filters.len != 0, + .exec_cmd_args_len = if (c.exec_cmd_args) |a| a.len != 0 else false, + .installed_headers_len = c.installed_headers.items.len != 0, + .force_undefined_symbols_len = c.force_undefined_symbols.entries.len != 0, + + .verbose_link = c.verbose_link, + .verbose_cc = c.verbose_cc, + .rdynamic = c.rdynamic, + .import_memory = c.import_memory, + .export_memory = c.export_memory, + .import_symbols = c.import_symbols, + .import_table = c.import_table, + .export_table = c.export_table, + .shared_memory = c.shared_memory, + .link_eh_frame_hdr = c.link_eh_frame_hdr, + .link_emit_relocs = c.link_emit_relocs, + .link_function_sections = c.link_function_sections, + .link_data_sections = c.link_data_sections, + .linker_dynamicbase = c.linker_dynamicbase, + .link_z_notext = c.link_z_notext, + .link_z_relro = c.link_z_relro, + .link_z_lazy = c.link_z_lazy, + .link_z_defs = c.link_z_defs, + .headerpad_max_install_names = c.headerpad_max_install_names, + .dead_strip_dylibs = c.dead_strip_dylibs, + .force_load_objc = c.force_load_objc, + .discard_local_symbols = c.discard_local_symbols, + .mingw_unicode_entry_point = c.mingw_unicode_entry_point, + }, + .flags2 = .{ + .pie = .init(c.pie), + .formatted_panics = .init(c.formatted_panics), + .bundle_compiler_rt = .init(c.bundle_compiler_rt), + .bundle_ubsan_rt = .init(c.bundle_ubsan_rt), + .each_lib_rpath = .init(c.each_lib_rpath), + .link_gc_sections = .init(c.link_gc_sections), + .linker_allow_shlib_undefined = .init(c.linker_allow_shlib_undefined), + .linker_allow_undefined_version = .init(c.linker_allow_undefined_version), + .linker_enable_new_dtags = .init(c.linker_enable_new_dtags), + .dll_export_fns = .init(c.dll_export_fns), + .use_llvm = .init(c.use_llvm), + .use_lld = .init(c.use_lld), + .use_new_linker = .init(c.use_new_linker), + .allow_so_scripts = .init(c.allow_so_scripts), + .sanitize_coverage_trace_pc_guard = .init(c.sanitize_coverage_trace_pc_guard), + .linkage = .init(c.linkage), + }, + .flags3 = .{ + .is_linking_libc = c.is_linking_libc, + .is_linking_libcpp = c.is_linking_libcpp, + .version = c.version != null, + .compress_debug_sections = c.compress_debug_sections, + .initial_memory = c.initial_memory != null, + .max_memory = c.max_memory != null, + .kind = c.kind, + .global_base = c.global_base != null, + .test_runner_mode = if (c.test_runner) |tr| switch (tr.mode) { + .simple => .simple, + .server => .server, + } else .default, + .wasi_exec_model = .init(c.wasi_exec_model), + .win32_manifest = c.win32_manifest != null, + .win32_module_definition = c.win32_module_definition != null, + .zig_lib_dir = c.zig_lib_dir != null, + .rc_includes = c.rc_includes, + .image_base = c.image_base != null, + .build_id = .init(c.build_id), + .entry = switch (c.entry) { + .default => .default, + .disabled => .disabled, + .enabled => .enabled, + .symbol_name => .symbol_name, + }, + .lto = .init(c.lto), + .subsystem = .init(c.subsystem), + }, + .flags4 = .{ + .libc_file = c.libc_file != null, + .link_z_common_page_size = c.link_z_common_page_size != null, + .link_z_max_page_size = c.link_z_max_page_size != null, + .pagezero_size = c.pagezero_size != null, + .stack_size = c.stack_size != null, + .headerpad_size = c.headerpad_size != null, + .error_limit = c.error_limit != null, + .install_name = c.install_name != null, + .entitlements = c.entitlements != null, + }, + .root_module = try addModule(wc, c.root_module), + .root_name = try wc.addString(c.name), + })); + + std.log.err("TODO serialize the trailing Compile step data", .{}); + + break :e extra_index; + }, .install_artifact => e: { const ia: *Step.InstallArtifact = @fieldParentPtr("step", step); break :e try wc.addExtra(@as(Configuration.Step.InstallArtifact, .{ @@ -364,6 +462,12 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { }); } +fn addModule(wc: *Configuration.Wip, module: *std.Build.Module) !Configuration.Module { + _ = wc; + _ = module; + @panic("TODO"); +} + fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configuration.OptionalLazyPath { return @enumFromInt(switch (lp orelse return .none) { .src_path => |src_path| i: { diff --git a/lib/compiler/maker/Step/Compile.zig b/lib/compiler/maker/Step/Compile.zig index e3727025e2..5ffbc23cfc 100644 --- a/lib/compiler/maker/Step/Compile.zig +++ b/lib/compiler/maker/Step/Compile.zig @@ -98,8 +98,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { } { - var symbol_it = compile.force_undefined_symbols.keyIterator(); - while (symbol_it.next()) |symbol_name| { + for (compile.force_undefined_symbols.keys()) |symbol_name| { try zig_args.append("--force_undefined"); try zig_args.append(symbol_name.*); } @@ -1071,4 +1070,131 @@ fn runPkgConfig(compile: *Compile, lib_name: []const u8) !PkgConfigResult { }; } +fn checkCompileErrors(compile: *Compile) !void { + // Clear this field so that it does not get printed by the build runner. + const actual_eb = compile.step.result_error_bundle; + compile.step.result_error_bundle = .empty; + + const arena = compile.step.owner.allocator; + + const actual_errors = ae: { + var aw: std.Io.Writer.Allocating = .init(arena); + defer aw.deinit(); + try actual_eb.renderToWriter(.{ + .include_reference_trace = false, + .include_source_line = false, + }, &aw.writer); + break :ae try aw.toOwnedSlice(); + }; + + // Render the expected lines into a string that we can compare verbatim. + var expected_generated: std.ArrayList(u8) = .empty; + const expect_errors = compile.expect_errors.?; + + var actual_line_it = mem.splitScalar(u8, actual_errors, '\n'); + + // TODO merge this with the testing.expectEqualStrings logic, and also CheckFile + switch (expect_errors) { + .starts_with => |expect_starts_with| { + if (std.mem.startsWith(u8, actual_errors, expect_starts_with)) return; + return compile.step.fail( + \\ + \\========= should start with: ============ + \\{s} + \\========= but not found: ================ + \\{s} + \\========================================= + , .{ expect_starts_with, actual_errors }); + }, + .contains => |expect_line| { + while (actual_line_it.next()) |actual_line| { + if (!matchCompileError(actual_line, expect_line)) continue; + return; + } + + return compile.step.fail( + \\ + \\========= should contain: =============== + \\{s} + \\========= but not found: ================ + \\{s} + \\========================================= + , .{ expect_line, actual_errors }); + }, + .stderr_contains => |expect_line| { + const actual_stderr: []const u8 = if (compile.step.result_error_msgs.items.len > 0) + compile.step.result_error_msgs.items[0] + else + &.{}; + compile.step.result_error_msgs.clearRetainingCapacity(); + + var stderr_line_it = mem.splitScalar(u8, actual_stderr, '\n'); + + while (stderr_line_it.next()) |actual_line| { + if (!matchCompileError(actual_line, expect_line)) continue; + return; + } + + return compile.step.fail( + \\ + \\========= should contain: =============== + \\{s} + \\========= but not found: ================ + \\{s} + \\========================================= + , .{ expect_line, actual_stderr }); + }, + .exact => |expect_lines| { + for (expect_lines) |expect_line| { + const actual_line = actual_line_it.next() orelse { + try expected_generated.appendSlice(arena, expect_line); + try expected_generated.append(arena, '\n'); + continue; + }; + if (matchCompileError(actual_line, expect_line)) { + try expected_generated.appendSlice(arena, actual_line); + try expected_generated.append(arena, '\n'); + continue; + } + try expected_generated.appendSlice(arena, expect_line); + try expected_generated.append(arena, '\n'); + } + + if (mem.eql(u8, expected_generated.items, actual_errors)) return; + + return compile.step.fail( + \\ + \\========= expected: ===================== + \\{s} + \\========= but found: ==================== + \\{s} + \\========================================= + , .{ expected_generated.items, actual_errors }); + }, + } +} + +fn matchCompileError(actual: []const u8, expected: []const u8) bool { + if (mem.endsWith(u8, actual, expected)) return true; + if (mem.startsWith(u8, expected, ":?:?: ")) { + if (mem.endsWith(u8, actual, expected[":?:?: ".len..])) return true; + } + // We scan for /?/ in expected line and if there is a match, we match everything + // up to and after /?/. + const expected_trim = mem.trim(u8, expected, " "); + if (mem.find(u8, expected_trim, "/?/")) |index| { + const actual_trim = mem.trim(u8, actual, " "); + const lhs = expected_trim[0..index]; + const rhs = expected_trim[index + "/?/".len ..]; + if (mem.startsWith(u8, actual_trim, lhs) and mem.endsWith(u8, actual_trim, rhs)) return true; + } + return false; +} + +fn moduleNeedsCliArg(mod: *const Module) bool { + return for (mod.link_objects.items) |o| switch (o) { + .c_source_file, .c_source_files, .assembly_file, .win32_resource_file => break true, + else => continue, + } else false; +} diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 2897fddb74..8b580f3a5d 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -60,7 +60,7 @@ filters: []const []const u8, test_runner: ?TestRunner, wasi_exec_model: ?std.builtin.WasiExecModel = null, -installed_headers: std.array_list.Managed(HeaderInstallation), +installed_headers: std.ArrayList(HeaderInstallation), /// This step is used to create an include tree that dependent modules can add to their include /// search paths. Installed headers are copied to this step. @@ -83,8 +83,6 @@ win32_manifest: ?LazyPath = null, /// Set via options; intended to be read-only after that. win32_module_definition: ?LazyPath = null, -installed_path: ?[]const u8, - /// Base address for an executable image. image_base: ?u64 = null, @@ -189,7 +187,7 @@ entry: Entry = .default, /// List of symbols forced as undefined in the symbol table /// thus forcing their resolution by the linker. /// Corresponds to `-u ` for ELF/MachO and `/include:` for COFF/PE. -force_undefined_symbols: std.StringHashMap(void), +force_undefined_symbols: std.StringArrayHashMapUnmanaged(void), /// Overrides the default stack size stack_size: ?u64 = null, @@ -290,20 +288,7 @@ pub const Options = struct { win32_module_definition: ?LazyPath = null, }; -pub const Kind = enum { - exe, - lib, - obj, - @"test", - test_obj, - - pub fn isTest(kind: Kind) bool { - return switch (kind) { - .exe, .lib, .obj => false, - .@"test", .test_obj => true, - }; - } -}; +pub const Kind = std.Build.Configuration.Step.Compile.Kind; pub const HeaderInstallation = union(enum) { file: File, @@ -424,14 +409,13 @@ pub fn create(owner: *std.Build, options: Options) *Compile { .out_lib_filename = undefined, .major_only_filename = null, .name_only_filename = null, - .installed_headers = std.array_list.Managed(HeaderInstallation).init(owner.allocator), + .installed_headers = .empty, .zig_lib_dir = null, .exec_cmd_args = null, .filters = options.filters, .test_runner = null, // set below .rdynamic = false, - .installed_path = null, - .force_undefined_symbols = StringHashMap(void).init(owner.allocator), + .force_undefined_symbols = .empty, .emit_directory = null, .generated_docs = null, @@ -519,7 +503,7 @@ pub fn installHeader(cs: *Compile, source: LazyPath, dest_rel_path: []const u8) .source = source.dupe(b), .dest_rel_path = b.dupePath(dest_rel_path), } }; - cs.installed_headers.append(installation) catch @panic("OOM"); + cs.installed_headers.append(b.allocator, installation) catch @panic("OOM"); cs.addHeaderInstallationToIncludeTree(installation); installation.getSource().addStepDependencies(&cs.step); } @@ -539,7 +523,7 @@ pub fn installHeadersDirectory( .dest_rel_path = b.dupePath(dest_rel_path), .options = options.dupe(b), } }; - cs.installed_headers.append(installation) catch @panic("OOM"); + cs.installed_headers.append(b.allocator, installation) catch @panic("OOM"); cs.addHeaderInstallationToIncludeTree(installation); installation.getSource().addStepDependencies(&cs.step); } @@ -556,9 +540,10 @@ pub fn installConfigHeader(cs: *Compile, config_header: *Step.ConfigHeader) void /// module's include search path. pub fn installLibraryHeaders(cs: *Compile, lib: *Compile) void { assert(lib.kind == .lib); + const arena = cs.owner.allocator; for (lib.installed_headers.items) |installation| { const installation_copy = installation.dupe(lib.step.owner); - cs.installed_headers.append(installation_copy) catch @panic("OOM"); + cs.installed_headers.append(arena, installation_copy) catch @panic("OOM"); cs.addHeaderInstallationToIncludeTree(installation_copy); installation_copy.getSource().addStepDependencies(&cs.step); } @@ -618,7 +603,8 @@ pub fn setVersionScript(compile: *Compile, source: LazyPath) void { pub fn forceUndefinedSymbol(compile: *Compile, symbol_name: []const u8) void { const b = compile.step.owner; - compile.force_undefined_symbols.put(b.dupe(symbol_name), {}) catch @panic("OOM"); + const arena = b.allocator; + compile.force_undefined_symbols.put(arena, b.dupe(symbol_name), {}) catch @panic("OOM"); } /// Returns whether the library, executable, or object depends on a particular system library. @@ -867,139 +853,11 @@ fn outputPath(c: *Compile, out_dir: std.Build.Cache.Path, ea: std.zig.EmitArtifa return out_dir.joinString(arena, name) catch @panic("OOM"); } -fn checkCompileErrors(compile: *Compile) !void { - // Clear this field so that it does not get printed by the build runner. - const actual_eb = compile.step.result_error_bundle; - compile.step.result_error_bundle = .empty; - - const arena = compile.step.owner.allocator; - - const actual_errors = ae: { - var aw: std.Io.Writer.Allocating = .init(arena); - defer aw.deinit(); - try actual_eb.renderToWriter(.{ - .include_reference_trace = false, - .include_source_line = false, - }, &aw.writer); - break :ae try aw.toOwnedSlice(); - }; - - // Render the expected lines into a string that we can compare verbatim. - var expected_generated: std.ArrayList(u8) = .empty; - const expect_errors = compile.expect_errors.?; - - var actual_line_it = mem.splitScalar(u8, actual_errors, '\n'); - - // TODO merge this with the testing.expectEqualStrings logic, and also CheckFile - switch (expect_errors) { - .starts_with => |expect_starts_with| { - if (std.mem.startsWith(u8, actual_errors, expect_starts_with)) return; - return compile.step.fail( - \\ - \\========= should start with: ============ - \\{s} - \\========= but not found: ================ - \\{s} - \\========================================= - , .{ expect_starts_with, actual_errors }); - }, - .contains => |expect_line| { - while (actual_line_it.next()) |actual_line| { - if (!matchCompileError(actual_line, expect_line)) continue; - return; - } - - return compile.step.fail( - \\ - \\========= should contain: =============== - \\{s} - \\========= but not found: ================ - \\{s} - \\========================================= - , .{ expect_line, actual_errors }); - }, - .stderr_contains => |expect_line| { - const actual_stderr: []const u8 = if (compile.step.result_error_msgs.items.len > 0) - compile.step.result_error_msgs.items[0] - else - &.{}; - compile.step.result_error_msgs.clearRetainingCapacity(); - - var stderr_line_it = mem.splitScalar(u8, actual_stderr, '\n'); - - while (stderr_line_it.next()) |actual_line| { - if (!matchCompileError(actual_line, expect_line)) continue; - return; - } - - return compile.step.fail( - \\ - \\========= should contain: =============== - \\{s} - \\========= but not found: ================ - \\{s} - \\========================================= - , .{ expect_line, actual_stderr }); - }, - .exact => |expect_lines| { - for (expect_lines) |expect_line| { - const actual_line = actual_line_it.next() orelse { - try expected_generated.appendSlice(arena, expect_line); - try expected_generated.append(arena, '\n'); - continue; - }; - if (matchCompileError(actual_line, expect_line)) { - try expected_generated.appendSlice(arena, actual_line); - try expected_generated.append(arena, '\n'); - continue; - } - try expected_generated.appendSlice(arena, expect_line); - try expected_generated.append(arena, '\n'); - } - - if (mem.eql(u8, expected_generated.items, actual_errors)) return; - - return compile.step.fail( - \\ - \\========= expected: ===================== - \\{s} - \\========= but found: ==================== - \\{s} - \\========================================= - , .{ expected_generated.items, actual_errors }); - }, - } -} - -fn matchCompileError(actual: []const u8, expected: []const u8) bool { - if (mem.endsWith(u8, actual, expected)) return true; - if (mem.startsWith(u8, expected, ":?:?: ")) { - if (mem.endsWith(u8, actual, expected[":?:?: ".len..])) return true; - } - // We scan for /?/ in expected line and if there is a match, we match everything - // up to and after /?/. - const expected_trim = mem.trim(u8, expected, " "); - if (mem.find(u8, expected_trim, "/?/")) |index| { - const actual_trim = mem.trim(u8, actual, " "); - const lhs = expected_trim[0..index]; - const rhs = expected_trim[index + "/?/".len ..]; - if (mem.startsWith(u8, actual_trim, lhs) and mem.endsWith(u8, actual_trim, rhs)) return true; - } - return false; -} - pub fn rootModuleTarget(c: *Compile) std.Target { // The root module is always given a target, so we know this to be non-null. return c.root_module.resolved_target.?.result; } -fn moduleNeedsCliArg(mod: *const Module) bool { - return for (mod.link_objects.items) |o| switch (o) { - .c_source_file, .c_source_files, .assembly_file, .win32_resource_file => break true, - else => continue, - } else false; -} - /// Return the full set of `Step.Compile` which `start` depends on, recursively. `start` itself is /// always returned as the first element. If `chase_dynamic` is `false`, then dynamic libraries are /// not included, and their dependencies are not considered; if `chase_dynamic` is `true`, dynamic diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 141b6c8bf5..9cd4d805cb 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -374,9 +374,9 @@ pub const Subsystem = enum { pub const EfiRuntimeDriver: Subsystem = .efi_runtime_driver; }; -pub const CompressDebugSections = enum { none, zlib, zstd }; +pub const CompressDebugSections = enum(u2) { none, zlib, zstd }; -pub const RcIncludes = enum { +pub const RcIncludes = enum(u2) { /// Use MSVC if available, fall back to MinGW. any, /// Use MSVC include paths (MSVC install + Windows SDK, must be present on the system). diff --git a/lib/std/zig/Configuration.zig b/lib/std/zig/Configuration.zig index 9ee0578910..9009156191 100644 --- a/lib/std/zig/Configuration.zig +++ b/lib/std/zig/Configuration.zig @@ -206,7 +206,7 @@ pub const Step = extern struct { _, }; - pub const Tag = enum(u8) { + pub const Tag = enum(u5) { top_level, compile, install_artifact, @@ -232,7 +232,7 @@ pub const Step = extern struct { pub const Flags = packed struct(u32) { tag: Tag = .top_level, - _: u24 = 0, + _: u27 = 0, }; }; @@ -258,7 +258,7 @@ pub const Step = extern struct { pub const Flags = packed struct(u32) { tag: Tag = .install_artifact, dylib_symlinks: bool, - _: u23 = 0, + _: u26 = 0, }; }; @@ -342,7 +342,253 @@ pub const Step = extern struct { stderr_trim_whitespace: TrimWhitespace, stdio_limit: bool, producer: bool, - _: u5 = 0, + _: u8 = 0, + }; + }; + + /// Trailing: + /// * filters_len: u32, // if flag is set + /// * exec_cmd_args_len: u32, // if flag is set + /// * installed_headers_len: u32, // if flag is set + /// * force_undefined_symbols_len: u32, // if flag is set + /// * exacts_len: u32 if expected_compile_errors is exact + /// * filter: String for each filters_len + /// * exec_cmd_arg: String for each exec_cmd_args_len + /// * InstalledHeader for each installed_headers_len + /// * force_undefined_symbol: String for each force_undefined_symbols_len + /// * String for each exacts_len + /// * linker_script: LazyPath if flag is set + /// * version_script: LazyPath if flag is set + /// * zig_lib_dir: LazyPath if flag is set + /// * libc_file: LazyPath if flag is set + /// * test_runner: LazyPath if test_runner_mode is not default + /// * win32_manifest: LazyPath if flag is set + /// * win32_module_definition: LazyPath if flag is set + /// * entitlements: LazyPath if flag is set + /// * version: String if flag is set (semantic version string) + /// * entry: String if entry is symbol + /// * install_name: String if flag is set + /// * String if expected_compile_errors is contains, starts_with, or stderr_contains + /// * initial_memory: u64 if flag is set + /// * max_memory: u64 if flag is set + /// * global_base: u64 if flag is set + /// * image_base: u64 if flag is set + /// * link_z_common_page_size if flag is set + /// * link_z_max_page_size if flag is set + /// * pagezero_size if flag is set + /// * stack_size if flag is set + /// * headerpad_size if flag is set + /// * error_limit if flag is set + /// * Hexstring if build_id is hexstring + pub const Compile = struct { + flags: Flags, + flags2: Flags2, + flags3: Flags3, + flags4: Flags4, + + root_module: Module, + root_name: String, + + pub const ExpectedCompileErrors = enum(u3) { contains, exact, starts_with, stderr_contains, none }; + pub const TestRunnerMode = enum(u2) { default, simple, server }; + pub const Entry = enum(u2) { default, disabled, enabled, symbol_name }; + + pub const Lto = enum(u2) { + none, + full, + thin, + default, + + pub fn init(lto: ?std.zig.LtoMode) Lto { + return switch (lto orelse return .default) { + .none => .none, + .full => .full, + .thin => .thin, + }; + } + }; + + pub const BuildId = enum(u3) { + none, + fast, + uuid, + sha1, + md5, + hexstring, + default, + + pub fn init(build_id: ?std.zig.BuildId) BuildId { + return switch (build_id orelse return .default) { + .none => .none, + .fast => .fast, + .uuid => .uuid, + .sha1 => .sha1, + .md5 => .md5, + .hexstring => .hexstring, + }; + } + }; + pub const WasiExecModel = enum(u2) { + default, + command, + reactor, + + pub fn init(wasi_exec_model: ?std.builtin.WasiExecModel) WasiExecModel { + return switch (wasi_exec_model orelse return .default) { + .command => .command, + .reactor => .reactor, + }; + } + }; + pub const Linkage = enum(u2) { + static, + dynamic, + default, + + pub fn init(link_mode: ?std.builtin.LinkMode) Linkage { + return switch (link_mode orelse return .default) { + .static => .static, + .dynamic => .dynamic, + }; + } + }; + pub const Kind = enum(u3) { + exe, + lib, + obj, + @"test", + test_obj, + + pub fn isTest(kind: Kind) bool { + return switch (kind) { + .exe, .lib, .obj => false, + .@"test", .test_obj => true, + }; + } + }; + pub const DefaultingBool = enum(u2) { + false, + true, + default, + + pub fn init(b: ?bool) DefaultingBool { + return switch (b orelse return .default) { + false => .false, + true => .true, + }; + } + }; + + pub const Subsystem = enum(u4) { + console, + windows, + posix, + native, + efi_application, + efi_boot_service_driver, + efi_rom, + efi_runtime_driver, + default, + + pub fn init(subsystem: ?std.zig.Subsystem) Subsystem { + return switch (subsystem orelse return .default) { + .console => .console, + .windows => .windows, + .posix => .posix, + .native => .native, + .efi_application => .efi_application, + .efi_boot_service_driver => .efi_boot_service_driver, + .efi_rom => .efi_rom, + .efi_runtime_driver => .efi_runtime_driver, + }; + } + }; + + pub const Flags = packed struct(u32) { + tag: Tag = .compile, + + filters_len: bool, + exec_cmd_args_len: bool, + installed_headers_len: bool, + force_undefined_symbols_len: bool, + + verbose_link: bool, + verbose_cc: bool, + rdynamic: bool, + import_memory: bool, + export_memory: bool, + import_symbols: bool, + import_table: bool, + export_table: bool, + shared_memory: bool, + link_eh_frame_hdr: bool, + link_emit_relocs: bool, + link_function_sections: bool, + link_data_sections: bool, + linker_dynamicbase: bool, + link_z_notext: bool, + link_z_relro: bool, + link_z_lazy: bool, + link_z_defs: bool, + headerpad_max_install_names: bool, + dead_strip_dylibs: bool, + force_load_objc: bool, + discard_local_symbols: bool, + mingw_unicode_entry_point: bool, + }; + + pub const Flags2 = packed struct(u32) { + pie: DefaultingBool, + formatted_panics: DefaultingBool, + bundle_compiler_rt: DefaultingBool, + bundle_ubsan_rt: DefaultingBool, + each_lib_rpath: DefaultingBool, + link_gc_sections: DefaultingBool, + linker_allow_shlib_undefined: DefaultingBool, + linker_allow_undefined_version: DefaultingBool, + linker_enable_new_dtags: DefaultingBool, + dll_export_fns: DefaultingBool, + use_llvm: DefaultingBool, + use_lld: DefaultingBool, + use_new_linker: DefaultingBool, + allow_so_scripts: DefaultingBool, + sanitize_coverage_trace_pc_guard: DefaultingBool, + linkage: Linkage, + }; + + pub const Flags3 = packed struct(u32) { + is_linking_libc: bool, + is_linking_libcpp: bool, + version: bool, + initial_memory: bool, + max_memory: bool, + kind: Kind, + compress_debug_sections: std.zig.CompressDebugSections, + global_base: bool, + test_runner_mode: TestRunnerMode, + wasi_exec_model: WasiExecModel, + win32_manifest: bool, + win32_module_definition: bool, + zig_lib_dir: bool, + rc_includes: std.zig.RcIncludes, + image_base: bool, + build_id: BuildId, + entry: Entry, + lto: Lto, + subsystem: Subsystem, + }; + + pub const Flags4 = packed struct(u32) { + libc_file: bool, + link_z_common_page_size: bool, + link_z_max_page_size: bool, + pagezero_size: bool, + stack_size: bool, + headerpad_size: bool, + error_limit: bool, + install_name: bool, + entitlements: bool, + _: u23 = 0, }; }; }; @@ -420,6 +666,10 @@ pub const Package = enum(u32) { _, }; +pub const Module = enum(u32) { + _, +}; + /// Points into `extra`, where the first element is number of deps, /// following elements is `Step.Index` per dep. pub const Deps = enum(u32) {