configure runner: serialization of compile step

This commit is contained in:
Andrew Kelley
2026-02-15 23:23:17 -08:00
parent cc947866c4
commit ae9fef9c62
5 changed files with 500 additions and 162 deletions
+105 -1
View File
@@ -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: {
+128 -2
View File
@@ -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;
}
+11 -153
View File
@@ -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 <symbol>` for ELF/MachO and `/include:<symbol>` 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
+2 -2
View File
@@ -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).
+254 -4
View File
@@ -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) {