authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-16 16:02:31-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:33-07:00
log3e6bebbbca2acdcde7578c12e618cbcea233dc49
tree4125eb29d92ad656add921563bda806189f554e7
parent648e0e0cc0d6d1940d3bb2ebc265067f7eb62432

configure runner: serialization of Module


4 files changed, 824 insertions(+), 36 deletions(-)

lib/compiler/configure_runner.zig+89-10
...@@ -227,6 +227,9 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {...@@ -227,6 +227,9 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
227 const arena = graph.arena;227 const arena = graph.arena;
228 const gpa = wc.gpa;228 const gpa = wc.gpa;
229229
230 var module_map: std.AutoArrayHashMapUnmanaged(*std.Build.Module, Configuration.Module.Index) = .empty;
231 defer module_map.deinit(gpa);
232
230 // Starting from all top-level steps in `b`, traverse the entire step graph233 // Starting from all top-level steps in `b`, traverse the entire step graph
231 // and add all step dependencies implied by module graphs.234 // and add all step dependencies implied by module graphs.
232 const top_level_steps = b.top_level_steps.values();235 const top_level_steps = b.top_level_steps.values();
...@@ -360,7 +363,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {...@@ -360,7 +363,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
360 .install_name = c.install_name != null,363 .install_name = c.install_name != null,
361 .entitlements = c.entitlements != null,364 .entitlements = c.entitlements != null,
362 },365 },
363 .root_module = try addModule(wc, c.root_module),366 .root_module = try addModule(wc, &module_map, c.root_module),
364 .root_name = try wc.addString(c.name),367 .root_name = try wc.addString(c.name),
365 }));368 }));
366369
...@@ -462,20 +465,97 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {...@@ -462,20 +465,97 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
462 });465 });
463}466}
464467
465fn addModule(wc: *Configuration.Wip, module: *std.Build.Module) !Configuration.Module {468fn addModule(
466 _ = wc;469 wc: *Configuration.Wip,
467 _ = module;470 module_map: *std.AutoArrayHashMapUnmanaged(*std.Build.Module, Configuration.Module.Index),
468 @panic("TODO");471 m: *std.Build.Module,
472) !Configuration.Module.Index {
473 if (module_map.get(m)) |index| return index;
474
475 const gpa = wc.gpa;
476 const import_table: Configuration.ImportTable = @enumFromInt(wc.extra.items.len);
477 const import_table_extra_len = 1 + 2 * m.import_table.entries.len;
478 try wc.extra.ensureUnusedCapacity(gpa, import_table_extra_len);
479 wc.extra.items.len += import_table_extra_len;
480 wc.extra.appendAssumeCapacity(@intCast(m.import_table.entries.len));
481 wc.extra.items[@intFromEnum(import_table)] = @intCast(m.import_table.entries.len);
482 for (
483 m.import_table.keys(),
484 @intFromEnum(import_table) + 1..,
485 ) |mod_name, extra_index| {
486 wc.extra.items[extra_index] = @intFromEnum(try wc.addString(mod_name));
487 }
488 for (
489 m.import_table.values(),
490 @intFromEnum(import_table) + 1 + m.import_table.entries.len..,
491 ) |dep, extra_index| {
492 // TODO module dependencies can be cyclic
493 wc.extra.items[extra_index] = @intFromEnum(try addModule(wc, module_map, dep));
494 }
495
496 const module_index: Configuration.Module.Index = @enumFromInt(try wc.addExtra(@as(Configuration.Module, .{
497 .flags = .{
498 .optimize = .init(m.optimize),
499 .strip = .init(m.strip),
500 .unwind_tables = .init(m.unwind_tables),
501 .dwarf_format = .init(m.dwarf_format),
502 .single_threaded = .init(m.strip),
503 .stack_protector = .init(m.strip),
504 .stack_check = .init(m.strip),
505 .sanitize_c = .init(m.sanitize_c),
506 .sanitize_thread = .init(m.strip),
507 .fuzz = .init(m.strip),
508 .code_model = m.code_model,
509 .c_macros = m.c_macros.items.len != 0,
510 .include_dirs = m.include_dirs.items.len != 0,
511 .lib_paths = m.lib_paths.items.len != 0,
512 .rpaths = m.rpaths.items.len != 0,
513 .frameworks = m.frameworks.entries.len != 0,
514 .link_objects = m.link_objects.items.len != 0,
515 .export_symbol_names = m.export_symbol_names.len != 0,
516 },
517 .flags2 = .{
518 .valgrind = .init(m.strip),
519 .pic = .init(m.strip),
520 .red_zone = .init(m.strip),
521 .omit_frame_pointer = .init(m.strip),
522 .error_tracing = .init(m.strip),
523 .link_libc = .init(m.strip),
524 .link_libcpp = .init(m.strip),
525 .no_builtin = .init(m.strip),
526 },
527 .owner = builderToPackage(m.owner),
528 .root_source_file = try addOptionalLazyPath(wc, m.root_source_file),
529 .import_table = import_table,
530 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),
531 })));
532
533 std.log.err("TODO serialize the trailing Module data", .{});
534
535 try module_map.putNoClobber(gpa, m, module_index);
536
537 return module_index;
538}
539
540fn addOptionalResolvedTarget(
541 wc: *Configuration.Wip,
542 optional_resolved_target: ?std.Build.ResolvedTarget,
543) !Configuration.ResolvedTarget.OptionalIndex {
544 const resolved_target = optional_resolved_target orelse return .none;
545 // TODO dedupe
546 return @enumFromInt(try wc.addExtra(@as(Configuration.ResolvedTarget, .{
547 .query = try wc.addTargetQuery(resolved_target.query),
548 .result = try wc.addTarget(resolved_target.result),
549 })));
469}550}
470551
471fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configuration.OptionalLazyPath {552fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configuration.OptionalLazyPath {
472 return @enumFromInt(switch (lp orelse return .none) {553 return @enumFromInt(switch (lp orelse return .none) {
473 .src_path => |src_path| i: {554 .src_path => |src_path| i: {
474 const owner = builderToPackage(src_path.owner);
475 const sub_path = try wc.addString(src_path.sub_path);555 const sub_path = try wc.addString(src_path.sub_path);
476 break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{556 break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{
477 .flags = .{},557 .flags = .{},
478 .owner = owner,558 .owner = builderToPackage(src_path.owner),
479 .sub_path = sub_path,559 .sub_path = sub_path,
480 }));560 }));
481 },561 },
...@@ -494,18 +574,17 @@ fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configu...@@ -494,18 +574,17 @@ fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configu
494 }));574 }));
495 },575 },
496 .dependency => |dependency| i: {576 .dependency => |dependency| i: {
497 const owner = builderToPackage(dependency.dependency.builder);
498 const sub_path = try wc.addString(dependency.sub_path);577 const sub_path = try wc.addString(dependency.sub_path);
499 break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{578 break :i try wc.addExtra(@as(Configuration.LazyPath.SourcePath, .{
500 .flags = .{},579 .flags = .{},
501 .owner = owner,580 .owner = builderToPackage(dependency.dependency.builder),
502 .sub_path = sub_path,581 .sub_path = sub_path,
503 }));582 }));
504 },583 },
505 });584 });
506}585}
507586
508fn builderToPackage(b: *std.Build) Configuration.Package {587fn builderToPackage(b: *std.Build) Configuration.Package.Index {
509 _ = b;588 _ = b;
510 @panic("TODO");589 @panic("TODO");
511}590}
lib/std/Build/Module.zig+8-7
...@@ -1,3 +1,11 @@...@@ -1,3 +1,11 @@
1const Module = @This();
2
3const std = @import("std");
4const assert = std.debug.assert;
5const LazyPath = std.Build.LazyPath;
6const Step = std.Build.Step;
7const ArrayList = std.ArrayList;
8
1/// The one responsible for creating this module.9/// The one responsible for creating this module.
2owner: *std.Build,10owner: *std.Build,
3root_source_file: ?LazyPath,11root_source_file: ?LazyPath,
...@@ -703,10 +711,3 @@ pub fn getGraph(root: *Module) Graph {...@@ -703,10 +711,3 @@ pub fn getGraph(root: *Module) Graph {
703 root.cached_graph = result;711 root.cached_graph = result;
704 return result;712 return result;
705}713}
706
707const Module = @This();
708const std = @import("std");
709const assert = std.debug.assert;
710const LazyPath = std.Build.LazyPath;
711const Step = std.Build.Step;
712const ArrayList = std.ArrayList;
lib/std/lang.zig+1-1
...@@ -93,7 +93,7 @@ pub const AtomicRmwOp = enum {...@@ -93,7 +93,7 @@ pub const AtomicRmwOp = enum {
93///93///
94/// This data structure is used by the Zig language code generation and94/// This data structure is used by the Zig language code generation and
95/// therefore must be kept in sync with the compiler implementation.95/// therefore must be kept in sync with the compiler implementation.
96pub const CodeModel = enum {96pub const CodeModel = enum(u4) {
97 default,97 default,
98 extreme,98 extreme,
99 kernel,99 kernel,
lib/std/zig/Configuration.zig+726-18
...@@ -29,6 +29,7 @@ pub const Wip = struct {...@@ -29,6 +29,7 @@ pub const Wip = struct {
29 gpa: Allocator,29 gpa: Allocator,
30 string_table: StringTable = .empty,30 string_table: StringTable = .empty,
31 deps_table: DepsTable = .empty,31 deps_table: DepsTable = .empty,
32 targets_table: TargetsTable = .empty,
3233
33 string_bytes: std.ArrayList(u8) = .empty,34 string_bytes: std.ArrayList(u8) = .empty,
34 unlazy_deps: std.ArrayList(String) = .empty,35 unlazy_deps: std.ArrayList(String) = .empty,
...@@ -37,6 +38,7 @@ pub const Wip = struct {...@@ -37,6 +38,7 @@ pub const Wip = struct {
37 extra: std.ArrayList(u32) = .empty,38 extra: std.ArrayList(u32) = .empty,
3839
39 const DepsTable = std.HashMapUnmanaged(Deps, void, DepsTableContext, std.hash_map.default_max_load_percentage);40 const DepsTable = std.HashMapUnmanaged(Deps, void, DepsTableContext, std.hash_map.default_max_load_percentage);
41 const TargetsTable = std.HashMapUnmanaged(TargetQuery.Index, void, TargetsTableContext, std.hash_map.default_max_load_percentage);
4042
41 const DepsTableContext = struct {43 const DepsTableContext = struct {
42 extra: []const u32,44 extra: []const u32,
...@@ -56,6 +58,21 @@ pub const Wip = struct {...@@ -56,6 +58,21 @@ pub const Wip = struct {
56 }58 }
57 };59 };
5860
61 const TargetsTableContext = struct {
62 extra: []const u32,
63
64 pub fn eql(ctx: @This(), a: TargetQuery.Index, b: TargetQuery.Index) bool {
65 const slice_a = a.extraSlice(ctx.extra);
66 const slice_b = b.extraSlice(ctx.extra);
67 return std.mem.eql(u32, slice_a, slice_b);
68 }
69
70 pub fn hash(ctx: @This(), key: TargetQuery.Index) u64 {
71 const slice = key.extraSlice(ctx.extra);
72 return std.hash_map.hashString(@ptrCast(slice));
73 }
74 };
75
59 const StringTable = std.HashMapUnmanaged(String, void, StringTableContext, std.hash_map.default_max_load_percentage);76 const StringTable = std.HashMapUnmanaged(String, void, StringTableContext, std.hash_map.default_max_load_percentage);
60 const StringTableContext = struct {77 const StringTableContext = struct {
61 bytes: []const u8,78 bytes: []const u8,
...@@ -144,6 +161,157 @@ pub const Wip = struct {...@@ -144,6 +161,157 @@ pub const Wip = struct {
144 return new_off;161 return new_off;
145 }162 }
146163
164 pub fn addSemVer(wip: *Wip, sv: std.SemanticVersion) Allocator.Error!String {
165 var buffer: [256]u8 = undefined;
166 var writer: std.Io.Writer = .fixed(&buffer);
167 sv.format(&writer) catch return error.OutOfMemory;
168 return addString(wip, writer.buffered());
169 }
170
171 pub fn addTargetQuery(wip: *Wip, q: std.Target.Query) !TargetQuery.OptionalIndex {
172 if (q.isNative()) return .none;
173 const gpa = wip.gpa;
174 const cpu_name: ?String = switch (q.cpu_model) {
175 .native, .baseline, .determined_by_arch_os => null,
176 .explicit => |model| try wip.addString(model.name),
177 };
178 const os_version_min: ?u32 = if (q.os_version_min) |ver| switch (ver) {
179 .none => null,
180 .semver => |sem_ver| @intFromEnum(try wip.addSemVer(sem_ver)),
181 .windows => |win_ver| @intFromEnum(win_ver),
182 } else null;
183 const os_version_max: ?u32 = if (q.os_version_max) |ver| switch (ver) {
184 .none => null,
185 .semver => |sem_ver| @intFromEnum(try wip.addSemVer(sem_ver)),
186 .windows => |win_ver| @intFromEnum(win_ver),
187 } else null;
188 const glibc_version: ?String = if (q.glibc_version) |sem_ver| try wip.addSemVer(sem_ver) else null;
189 const dynamic_linker: ?String = if (q.dynamic_linker) |*dl|
190 if (dl.get()) |s| try wip.addString(s) else .empty
191 else
192 null;
193 const cpu_features_add_empty = q.cpu_features_add.isEmpty();
194 const cpu_features_sub_empty = q.cpu_features_sub.isEmpty();
195 try wip.extra.ensureUnusedCapacity(gpa, @typeInfo(TargetQuery).@"struct".fields.len + 6 +
196 2 * ((@sizeOf(std.Target.Cpu.Feature.Set) + 3) / 4));
197 const result_index: TargetQuery.Index = @enumFromInt(wip.addExtraAssumeCapacity(@as(TargetQuery, .{
198 .flags = .{
199 .cpu_arch = .init(q.cpu_arch),
200 .cpu_model = .init(q.cpu_model),
201 .cpu_features_add = !cpu_features_add_empty,
202 .cpu_features_sub = !cpu_features_sub_empty,
203 .os_tag = .init(q.os_tag),
204 .abi = .init(q.abi),
205 .object_format = .init(q.ofmt),
206 .os_version_min = .init(q.os_version_min),
207 .os_version_max = .init(q.os_version_max),
208 .glibc_version = q.glibc_version != null,
209 .android_api_level = q.android_api_level != null,
210 .dynamic_linker = q.dynamic_linker != null,
211 },
212 })));
213 if (!cpu_features_add_empty) wip.extra.appendSliceAssumeCapacity(@ptrCast(&q.cpu_features_add.ints));
214 if (!cpu_features_sub_empty) wip.extra.appendSliceAssumeCapacity(@ptrCast(&q.cpu_features_sub.ints));
215 wip.addExtraOptionalStringAssumeCapacity(cpu_name);
216 if (os_version_min) |v| wip.extra.appendAssumeCapacity(v);
217 if (os_version_max) |v| wip.extra.appendAssumeCapacity(v);
218 wip.addExtraOptionalStringAssumeCapacity(glibc_version);
219 if (q.android_api_level) |x| wip.extra.appendAssumeCapacity(x);
220 wip.addExtraOptionalStringAssumeCapacity(dynamic_linker);
221
222 // Deduplicate.
223 const gop = try wip.targets_table.getOrPutContext(gpa, result_index, @as(TargetsTableContext, .{
224 .extra = wip.extra.items,
225 }));
226 if (gop.found_existing) {
227 wip.extra.items.len = @intFromEnum(result_index);
228 return .init(gop.key_ptr.*);
229 } else {
230 return .init(result_index);
231 }
232 }
233
234 pub fn addTarget(wip: *Wip, t: std.Target) !TargetQuery.Index {
235 const gpa = wip.gpa;
236 const cpu_name: String = try wip.addString(t.cpu.model.name);
237
238 const os_version_min: ?u32, const os_version_max: ?u32, const glibc_version: ?String, const android_api_level: ?u32 = switch (t.os.versionRange()) {
239 .none => .{
240 null,
241 null,
242 null,
243 null,
244 },
245 .semver => |range| .{
246 @intFromEnum(try wip.addSemVer(range.min)),
247 @intFromEnum(try wip.addSemVer(range.max)),
248 null,
249 null,
250 },
251 .hurd => |hurd| .{
252 @intFromEnum(try wip.addSemVer(hurd.range.min)),
253 @intFromEnum(try wip.addSemVer(hurd.range.max)),
254 try wip.addSemVer(hurd.glibc),
255 null,
256 },
257 .linux => |linux| .{
258 @intFromEnum(try wip.addSemVer(linux.range.min)),
259 @intFromEnum(try wip.addSemVer(linux.range.max)),
260 try wip.addSemVer(linux.glibc),
261 linux.android,
262 },
263 .windows => |range| .{
264 @intFromEnum(range.min),
265 @intFromEnum(range.max),
266 null,
267 null,
268 },
269 };
270 const dynamic_linker: ?String = if (t.dynamic_linker.get()) |dl| try wip.addString(dl) else null;
271 const cpu_features_add_empty = t.cpu.features.isEmpty();
272 const os_version: TargetQuery.OsVersion = switch (t.os.versionRange()) {
273 .none => .none,
274 .semver, .linux, .hurd => .semver,
275 .windows => .windows,
276 };
277 try wip.extra.ensureUnusedCapacity(gpa, @typeInfo(TargetQuery).@"struct".fields.len + 6 +
278 2 * ((@sizeOf(std.Target.Cpu.Feature.Set) + 3) / 4));
279 const result_index: TargetQuery.Index = @enumFromInt(wip.addExtraAssumeCapacity(@as(TargetQuery, .{
280 .flags = .{
281 .cpu_arch = .init(t.cpu.arch),
282 .cpu_model = .explicit,
283 .cpu_features_add = !cpu_features_add_empty,
284 .cpu_features_sub = false,
285 .os_tag = .init(t.os.tag),
286 .abi = .init(t.abi),
287 .object_format = .init(t.ofmt),
288 .os_version_min = os_version,
289 .os_version_max = os_version,
290 .glibc_version = glibc_version != null,
291 .android_api_level = android_api_level != null,
292 .dynamic_linker = dynamic_linker != null,
293 },
294 })));
295 if (!cpu_features_add_empty) wip.extra.appendSliceAssumeCapacity(@ptrCast(&t.cpu.features.ints));
296 wip.addExtraOptionalStringAssumeCapacity(cpu_name);
297 if (os_version_min) |v| wip.extra.appendAssumeCapacity(v);
298 if (os_version_max) |v| wip.extra.appendAssumeCapacity(v);
299 wip.addExtraOptionalStringAssumeCapacity(glibc_version);
300 if (android_api_level) |x| wip.extra.appendAssumeCapacity(x);
301 wip.addExtraOptionalStringAssumeCapacity(dynamic_linker);
302
303 // Deduplicate.
304 const gop = try wip.targets_table.getOrPutContext(gpa, result_index, @as(TargetsTableContext, .{
305 .extra = wip.extra.items,
306 }));
307 if (gop.found_existing) {
308 wip.extra.items.len = @intFromEnum(result_index);
309 return gop.key_ptr.*;
310 } else {
311 return result_index;
312 }
313 }
314
147 pub fn prepareDeps(wip: *Wip, n: usize) Allocator.Error![]u32 {315 pub fn prepareDeps(wip: *Wip, n: usize) Allocator.Error![]u32 {
148 const slice = try wip.extra.addManyAsSlice(wip.gpa, n + 1);316 const slice = try wip.extra.addManyAsSlice(wip.gpa, n + 1);
149 slice[0] = @intCast(n);317 slice[0] = @intCast(n);
...@@ -178,6 +346,11 @@ pub const Wip = struct {...@@ -178,6 +346,11 @@ pub const Wip = struct {
178 return result;346 return result;
179 }347 }
180348
349 fn addExtraOptionalStringAssumeCapacity(wip: *Wip, optional_string: ?String) void {
350 const string = optional_string orelse return;
351 wip.extra.appendAssumeCapacity(@intFromEnum(string));
352 }
353
181 fn setExtra(wip: *Wip, index: usize, extra: anytype) void {354 fn setExtra(wip: *Wip, index: usize, extra: anytype) void {
182 const fields = @typeInfo(@TypeOf(extra)).@"struct".fields;355 const fields = @typeInfo(@TypeOf(extra)).@"struct".fields;
183 var i = index;356 var i = index;
...@@ -386,7 +559,7 @@ pub const Step = extern struct {...@@ -386,7 +559,7 @@ pub const Step = extern struct {
386 flags3: Flags3,559 flags3: Flags3,
387 flags4: Flags4,560 flags4: Flags4,
388561
389 root_module: Module,562 root_module: Module.Index,
390 root_name: String,563 root_name: String,
391564
392 pub const ExpectedCompileErrors = enum(u3) { contains, exact, starts_with, stderr_contains, none };565 pub const ExpectedCompileErrors = enum(u3) { contains, exact, starts_with, stderr_contains, none };
...@@ -466,19 +639,6 @@ pub const Step = extern struct {...@@ -466,19 +639,6 @@ pub const Step = extern struct {
466 };639 };
467 }640 }
468 };641 };
469 pub const DefaultingBool = enum(u2) {
470 false,
471 true,
472 default,
473
474 pub fn init(b: ?bool) DefaultingBool {
475 return switch (b orelse return .default) {
476 false => .false,
477 true => .true,
478 };
479 }
480 };
481
482 pub const Subsystem = enum(u4) {642 pub const Subsystem = enum(u4) {
483 console,643 console,
484 windows,644 windows,
...@@ -626,7 +786,7 @@ pub const LazyPath = enum(u32) {...@@ -626,7 +786,7 @@ pub const LazyPath = enum(u32) {
626786
627 pub const SourcePath = struct {787 pub const SourcePath = struct {
628 flags: Flags,788 flags: Flags,
629 owner: Package,789 owner: Package.Index,
630 sub_path: String,790 sub_path: String,
631791
632 pub const Flags = packed struct(u32) {792 pub const Flags = packed struct(u32) {
...@@ -662,11 +822,168 @@ pub const LazyPath = enum(u32) {...@@ -662,11 +822,168 @@ pub const LazyPath = enum(u32) {
662 };822 };
663};823};
664824
665pub const Package = enum(u32) {825pub const Package = extern struct {
666 _,826 hash: String,
827 build_root: OptionalString,
828
829 pub const Index = enum(u32) {
830 root = maxInt(u32),
831 _,
832 };
833};
834
835/// Trailing:
836/// * c_macros: LengthPrefixedList(String), // if flag is set
837/// * lib_paths: LengthPrefixedList(LazyPath), // if flag is set
838/// * export_symbol_names: LengthPrefixedList(String), // if flag is set
839/// * frameworks: FlagsPrefixedList(FrameworkFlags), // if flag is set
840/// * include_dirs: UnionList(IncludeDir), // if flag is set
841/// * rpaths: UnionList(RPath), // if flag is set
842/// * link_objects: UnionList(LinkObject), // if flag is set
843pub const Module = struct {
844 flags: Flags,
845 flags2: Flags2,
846 owner: Package.Index,
847 root_source_file: OptionalLazyPath,
848 import_table: ImportTable,
849 resolved_target: ResolvedTarget.OptionalIndex,
850
851 pub const Optimize = enum(u3) {
852 debug,
853 safe,
854 fast,
855 small,
856 default,
857
858 pub fn init(o: ?std.builtin.OptimizeMode) Optimize {
859 return switch (o orelse return .default) {
860 .Debug => .debug,
861 .ReleaseSafe => .safe,
862 .ReleaseFast => .fast,
863 .ReleaseSmall => .small,
864 };
865 }
866 };
867
868 pub const UnwindTables = enum(u2) {
869 none,
870 sync,
871 async,
872 default,
873
874 pub fn init(ut: ?std.builtin.UnwindTables) UnwindTables {
875 return switch (ut orelse return .default) {
876 .none => .none,
877 .sync => .sync,
878 .async => .async,
879 };
880 }
881 };
882
883 pub const SanitizeC = enum(u2) {
884 off,
885 trap,
886 full,
887 default,
888
889 pub fn init(sc: ?std.zig.SanitizeC) SanitizeC {
890 return switch (sc orelse return .default) {
891 .off => .off,
892 .trap => .trap,
893 .full => .full,
894 };
895 }
896 };
897
898 pub const DwarfFormat = enum(u2) {
899 @"32",
900 @"64",
901 default,
902
903 pub fn init(df: ?std.dwarf.Format) DwarfFormat {
904 return switch (df orelse return .default) {
905 .@"32" => .@"32",
906 .@"64" => .@"64",
907 };
908 }
909 };
910
911 pub const Index = enum(u32) {
912 _,
913 };
914
915 pub const Flags = packed struct(u32) {
916 optimize: Optimize,
917 strip: DefaultingBool,
918 unwind_tables: UnwindTables,
919 dwarf_format: DwarfFormat,
920 single_threaded: DefaultingBool,
921 stack_protector: DefaultingBool,
922 stack_check: DefaultingBool,
923 sanitize_c: SanitizeC,
924 sanitize_thread: DefaultingBool,
925 fuzz: DefaultingBool,
926 code_model: std.builtin.CodeModel,
927 c_macros: bool,
928 include_dirs: bool,
929 lib_paths: bool,
930 rpaths: bool,
931 frameworks: bool,
932 link_objects: bool,
933 export_symbol_names: bool,
934 };
935
936 pub const Flags2 = packed struct(u32) {
937 valgrind: DefaultingBool,
938 pic: DefaultingBool,
939 red_zone: DefaultingBool,
940 omit_frame_pointer: DefaultingBool,
941 error_tracing: DefaultingBool,
942 link_libc: DefaultingBool,
943 link_libcpp: DefaultingBool,
944 no_builtin: DefaultingBool,
945 _: u16 = 0,
946 };
947
948 pub const IncludeDir = union(enum(u3)) {
949 path: LazyPath,
950 path_system: LazyPath,
951 path_after: LazyPath,
952 framework_path: LazyPath,
953 framework_path_system: LazyPath,
954 /// Always `Step.Tag.compile`.
955 other_step: Step.Index,
956 /// Always `Step.Tag.config_header`.
957 config_header_step: Step.Index,
958 embed_path: LazyPath,
959 };
960
961 pub const RPath = union(enum(u1)) {
962 lazy_path: LazyPath,
963 special: String,
964 };
965
966 pub const LinkObject = union(enum(u3)) {
967 static_path: LazyPath,
968 /// Always `Step.Tag.compile`.
969 other_step: Step.Index,
970 system_lib: SystemLib,
971 assembly_file: LazyPath,
972 c_source_file: CSourceFile.Index,
973 c_source_files: CSourceFiles.Index,
974 win32_resource_file: RcSourceFile.Index,
975 };
976
977 pub const FrameworkFlags = packed struct(u2) {
978 needed: bool,
979 weak: bool,
980 };
667};981};
668982
669pub const Module = enum(u32) {983/// Points into `extra`, first element is len, then:
984/// * import_name: String, // for each len
985/// * Module.Index, // for each len
986pub const ImportTable = enum(u32) {
670 _,987 _,
671};988};
672989
...@@ -734,6 +1051,397 @@ pub const String = enum(u32) {...@@ -734,6 +1051,397 @@ pub const String = enum(u32) {
734 }1051 }
735};1052};
7361053
1054pub const DefaultingBool = enum(u2) {
1055 false,
1056 true,
1057 default,
1058
1059 pub fn init(b: ?bool) DefaultingBool {
1060 return switch (b orelse return .default) {
1061 false => .false,
1062 true => .true,
1063 };
1064 }
1065};
1066
1067pub const SystemLib = struct {
1068 name: String,
1069 flags: Flags,
1070
1071 pub const Index = enum(u32) {
1072 _,
1073 };
1074
1075 pub const UsePkgConfig = enum(u2) { no, yes, force };
1076 pub const LinkMode = enum { static, dynamic };
1077
1078 pub const Flags = packed struct(u32) {
1079 needed: bool,
1080 weak: bool,
1081 use_pkg_config: UsePkgConfig,
1082 preferred_link_mode: LinkMode,
1083 search_strategy: SearchStrategy,
1084 };
1085
1086 pub const SearchStrategy = enum(u2) { paths_first, mode_first, no_fallback };
1087};
1088
1089/// Trailing:
1090/// * flag: String, // for each flags_len
1091/// * sub_path: String, // for each files_len
1092pub const CSourceFiles = struct {
1093 root: LazyPath,
1094 files_len: u32,
1095 flags: Flags,
1096
1097 pub const Index = enum(u32) {
1098 _,
1099 };
1100
1101 pub const Flags = packed struct(u32) {
1102 /// C compiler CLI flags.
1103 flags_len: u29,
1104 lang: OptionalCSourceLanguage,
1105 };
1106};
1107
1108/// Trailing:
1109/// * flag: String, // for each flags_len
1110pub const CSourceFile = struct {
1111 file: LazyPath,
1112 flags: Flags,
1113
1114 pub const Index = enum(u32) {
1115 _,
1116 };
1117
1118 pub const Flags = packed struct(u32) {
1119 /// C compiler CLI flags.
1120 flags_len: u29,
1121 lang: OptionalCSourceLanguage,
1122 };
1123};
1124
1125pub const OptionalCSourceLanguage = enum(u3) {
1126 c,
1127 cpp,
1128 objective_c,
1129 objective_cpp,
1130 assembly,
1131 assembly_with_preprocessor,
1132 default,
1133};
1134
1135pub const RcSourceFile = struct {
1136 file: LazyPath,
1137 /// Any option that rc.exe accepts will work here, with the exception of:
1138 /// - `/fo`: The output filename is set by the build system
1139 /// - `/p`: Only running the preprocessor is not supported in this context
1140 /// - `/:no-preprocess` (non-standard option): Not supported in this context
1141 /// - Any MUI-related option
1142 /// https://learn.microsoft.com/en-us/windows/win32/menurc/using-rc-the-rc-command-line-
1143 ///
1144 /// Implicitly defined options:
1145 /// /x (ignore the INCLUDE environment variable)
1146 /// /D_DEBUG or /DNDEBUG depending on the optimization mode
1147 flags: []const []const u8 = &.{},
1148 /// Include paths that may or may not exist yet and therefore need to be
1149 /// specified as a LazyPath. Each path will be appended to the flags
1150 /// as `/I <resolved path>`.
1151 include_paths: []const LazyPath = &.{},
1152
1153 pub const Index = enum(u32) {
1154 _,
1155 };
1156};
1157
1158pub const ResolvedTarget = struct {
1159 /// none indicates host.
1160 query: TargetQuery.OptionalIndex,
1161 /// defaults will be resolved.
1162 result: TargetQuery.Index,
1163
1164 pub const Index = enum(u32) {
1165 _,
1166 };
1167
1168 pub const OptionalIndex = enum(u32) {
1169 none = maxInt(u32),
1170 _,
1171 };
1172};
1173
1174/// Trailing:
1175/// * cpu_features_add: std.Target.Feature.Set, // if flag set
1176/// * cpu_features_sub: std.Target.Feature.Set, // if flag set
1177/// * cpu_name: String, // if cpu_model is explicit
1178/// * os_version_min: WindowsVersion // if os_version_min is windows
1179/// * os_version_min: String // if os_version_min is semver
1180/// * os_version_max: WindowsVersion // if os_version_max is windows
1181/// * os_version_max: String // if os_version_max is semver
1182/// * glibc_version: String, // if flag is set
1183/// * android_api_level: u32, // if flag is set
1184/// * dynamic_linker: String, // if flag is set
1185pub const TargetQuery = struct {
1186 flags: Flags,
1187
1188 pub const Index = enum(u32) {
1189 _,
1190
1191 pub fn extraSlice(i: Index, extra: []const u32) []const u32 {
1192 return extra[@intFromEnum(i)..][0..length(i, extra)];
1193 }
1194
1195 pub fn length(i: Index, extra: []const u32) usize {
1196 //const flags = getExtra(extra, @intFromEnum(i), TargetQuery).flags;
1197 const flags: Flags = @bitCast(extra[@intFromEnum(i)]);
1198 const feature_set_size: usize = (@sizeOf(std.Target.Cpu.Feature.Set) + 3) / 4;
1199 return @typeInfo(TargetQuery).@"struct".fields.len +
1200 (if (flags.cpu_features_add) feature_set_size else 0) +
1201 (if (flags.cpu_features_sub) feature_set_size else 0) +
1202 @intFromBool(flags.cpu_model == .explicit) +
1203 @as(usize, switch (flags.os_version_min) {
1204 .semver, .windows => 1,
1205 else => 0,
1206 }) +
1207 @as(usize, switch (flags.os_version_max) {
1208 .semver, .windows => 1,
1209 else => 0,
1210 }) +
1211 @intFromBool(flags.glibc_version) +
1212 @intFromBool(flags.android_api_level) +
1213 @intFromBool(flags.dynamic_linker);
1214 }
1215 };
1216
1217 pub const OptionalIndex = enum(u32) {
1218 none = maxInt(u32),
1219 _,
1220
1221 pub fn init(i: Index) OptionalIndex {
1222 const result: OptionalIndex = @enumFromInt(@intFromEnum(i));
1223 assert(result != .none);
1224 return result;
1225 }
1226 };
1227
1228 pub const CpuModel = enum(u2) {
1229 native,
1230 baseline,
1231 determined_by_arch_os,
1232 explicit,
1233
1234 pub fn init(x: std.Target.Query.CpuModel) @This() {
1235 return switch (x) {
1236 .native => .native,
1237 .baseline => .baseline,
1238 .determined_by_arch_os => .determined_by_arch_os,
1239 .explicit => .explicit,
1240 };
1241 }
1242 };
1243 pub const OsVersion = enum(u2) {
1244 none,
1245 semver,
1246 windows,
1247 default,
1248
1249 pub fn init(x: ?std.Target.Query.OsVersion) @This() {
1250 return switch (x orelse return .default) {
1251 .none => .none,
1252 .semver => .semver,
1253 .windows => .windows,
1254 };
1255 }
1256 };
1257 pub const Abi = enum(u5) {
1258 none,
1259 gnu,
1260 gnuabin32,
1261 gnuabi64,
1262 gnueabi,
1263 gnueabihf,
1264 gnuf32,
1265 gnusf,
1266 gnux32,
1267 eabi,
1268 eabihf,
1269 ilp32,
1270 android,
1271 androideabi,
1272 musl,
1273 muslabin32,
1274 muslabi64,
1275 musleabi,
1276 musleabihf,
1277 muslf32,
1278 muslsf,
1279 muslx32,
1280 msvc,
1281 itanium,
1282 simulator,
1283 ohos,
1284 ohoseabi,
1285
1286 default,
1287
1288 pub fn init(x: ?std.Target.Abi) @This() {
1289 // TODO comptime assert the enums match
1290 return @enumFromInt(@intFromEnum(x orelse return .default));
1291 }
1292 };
1293 pub const CpuArch = enum(u6) {
1294 aarch64,
1295 aarch64_be,
1296 alpha,
1297 amdgcn,
1298 arc,
1299 arceb,
1300 arm,
1301 armeb,
1302 avr,
1303 bpfeb,
1304 bpfel,
1305 csky,
1306 hexagon,
1307 hppa,
1308 hppa64,
1309 kalimba,
1310 kvx,
1311 lanai,
1312 loongarch32,
1313 loongarch64,
1314 m68k,
1315 microblaze,
1316 microblazeel,
1317 mips,
1318 mipsel,
1319 mips64,
1320 mips64el,
1321 msp430,
1322 nvptx,
1323 nvptx64,
1324 or1k,
1325 powerpc,
1326 powerpcle,
1327 powerpc64,
1328 powerpc64le,
1329 propeller,
1330 riscv32,
1331 riscv32be,
1332 riscv64,
1333 riscv64be,
1334 s390x,
1335 sh,
1336 sheb,
1337 sparc,
1338 sparc64,
1339 spirv32,
1340 spirv64,
1341 thumb,
1342 thumbeb,
1343 ve,
1344 wasm32,
1345 wasm64,
1346 x86_16,
1347 x86,
1348 x86_64,
1349 xcore,
1350 xtensa,
1351 xtensaeb,
1352
1353 default,
1354
1355 pub fn init(x: ?std.Target.Cpu.Arch) @This() {
1356 // TODO comptime assert the enums match
1357 return @enumFromInt(@intFromEnum(x orelse return .default));
1358 }
1359 };
1360 pub const OsTag = enum(u6) {
1361 freestanding,
1362 other,
1363 contiki,
1364 fuchsia,
1365 hermit,
1366 managarm,
1367 haiku,
1368 hurd,
1369 illumos,
1370 linux,
1371 plan9,
1372 rtems,
1373 serenity,
1374 dragonfly,
1375 freebsd,
1376 netbsd,
1377 openbsd,
1378 driverkit,
1379 ios,
1380 maccatalyst,
1381 macos,
1382 tvos,
1383 visionos,
1384 watchos,
1385 windows,
1386 uefi,
1387 @"3ds",
1388 ps3,
1389 ps4,
1390 ps5,
1391 vita,
1392 emscripten,
1393 wasi,
1394 amdhsa,
1395 amdpal,
1396 cuda,
1397 mesa3d,
1398 nvcl,
1399 opencl,
1400 opengl,
1401 vulkan,
1402
1403 default,
1404
1405 pub fn init(x: ?std.Target.Os.Tag) @This() {
1406 // TODO comptime assert the enums match
1407 return @enumFromInt(@intFromEnum(x orelse return .default));
1408 }
1409 };
1410 pub const ObjectFormat = enum(u4) {
1411 c,
1412 coff,
1413 elf,
1414 hex,
1415 macho,
1416 plan9,
1417 raw,
1418 spirv,
1419 wasm,
1420
1421 default,
1422
1423 pub fn init(x: ?std.Target.ObjectFormat) @This() {
1424 // TODO comptime assert the enums match
1425 return @enumFromInt(@intFromEnum(x orelse return .default));
1426 }
1427 };
1428
1429 pub const Flags = packed struct(u32) {
1430 cpu_arch: CpuArch,
1431 cpu_model: CpuModel,
1432 cpu_features_add: bool,
1433 cpu_features_sub: bool,
1434 os_tag: OsTag,
1435 abi: Abi,
1436 object_format: ObjectFormat,
1437 os_version_min: OsVersion,
1438 os_version_max: OsVersion,
1439 glibc_version: bool,
1440 android_api_level: bool,
1441 dynamic_linker: bool,
1442 };
1443};
1444
737pub const LoadFileError = Io.File.Reader.Error || Allocator.Error || error{EndOfStream};1445pub const LoadFileError = Io.File.Reader.Error || Allocator.Error || error{EndOfStream};
7381446
739pub fn loadFile(arena: Allocator, io: Io, file: Io.File) LoadFileError!Configuration {1447pub fn loadFile(arena: Allocator, io: Io, file: Io.File) LoadFileError!Configuration {