authorgravatar for hemisputnik@proton.mehemisputnik <hemisputnik@proton.me> 2026-08-09 11:12:22+03:00
committergravatar for hemisputnik@proton.mehemisputnik <hemisputnik@proton.me> 2026-08-10 11:20:19+03:00
log3d50222f9b20fb2cb4ab5ae6e8bcb35f74adbda9
tree5ffb999dc6de6632c509f84c4e9668ff478a1708
parent27bf90f12b70c427411779c4fed99a6288c43710
signaturebadge-check Signed by SSH key SHA256:iUK/EffQPyeXTXChJNV0UrxsscinNLxnk+0pu4OGU7Q

std.Build.Configuration: reintroduce serialization of std.Build instances


5 files changed, 256 insertions(+), 22 deletions(-)

lib/compiler/Maker.zig+5-5
...@@ -2226,7 +2226,7 @@ fn prepare(maker: *Maker, step_indices: []const Configuration.Step.Index) !void...@@ -2226,7 +2226,7 @@ fn prepare(maker: *Maker, step_indices: []const Configuration.Step.Index) !void
2226 }2226 }
2227 } else {2227 } else {
2228 log.err("{s}{s}: this step declares an upper bound of {d} bytes of memory, exceeding the available {d} bytes of memory", .{2228 log.err("{s}{s}: this step declares an upper bound of {d} bytes of memory, exceeding the available {d} bytes of memory", .{
2229 conf_step.owner.depPrefixSlice(c),2229 conf_step.owner.package(c).depPrefixSlice(c),
2230 conf_step.name.slice(c),2230 conf_step.name.slice(c),
2231 max_rss,2231 max_rss,
2232 maker.available_rss,2232 maker.available_rss,
...@@ -3320,13 +3320,13 @@ pub fn generatedPath(maker: *const Maker, index: Configuration.GeneratedFileInde...@@ -3320,13 +3320,13 @@ pub fn generatedPath(maker: *const Maker, index: Configuration.GeneratedFileInde
3320pub fn packagePath(3320pub fn packagePath(
3321 maker: *const Maker,3321 maker: *const Maker,
3322 arena: Allocator,3322 arena: Allocator,
3323 package_index: Configuration.Package.Index,3323 inst_index: Configuration.PackageInstance.Index,
3324 sub_path: []const u8,3324 sub_path: []const u8,
3325) Allocator.Error!Path {3325) Allocator.Error!Path {
3326 const c = &maker.scanned_config.configuration;3326 const c = &maker.scanned_config.configuration;
3327 const graph = maker.graph;3327 const graph = maker.graph;
33283328
3329 if (package_index == .root) return .{3329 if (inst_index == .root) return .{
3330 .root_dir = graph.build_root_directory,3330 .root_dir = graph.build_root_directory,
3331 .sub_path = sub_path,3331 .sub_path = sub_path,
3332 };3332 };
...@@ -3337,7 +3337,7 @@ pub fn packagePath(...@@ -3337,7 +3337,7 @@ pub fn packagePath(
3337 // construct a cwd relative path here.3337 // construct a cwd relative path here.
3338 return .{3338 return .{
3339 .root_dir = .cwd(),3339 .root_dir = .cwd(),
3340 .sub_path = try Dir.path.join(arena, &.{ package_index.ptr(c).root_path.slice(c), sub_path }),3340 .sub_path = try Dir.path.join(arena, &.{ inst_index.package(c).ptr(c).root_path.slice(c), sub_path }),
3341 };3341 };
3342}3342}
33433343
...@@ -3967,7 +3967,7 @@ fn confPathDepToCachePath(...@@ -3967,7 +3967,7 @@ fn confPathDepToCachePath(
3967 .root_dir = graph.build_root_directory,3967 .root_dir = graph.build_root_directory,
3968 .sub_path = switch (path_dep.pkg.unwrap().?) {3968 .sub_path = switch (path_dep.pkg.unwrap().?) {
3969 .root => sub_path,3969 .root => sub_path,
3970 else => |index| try Dir.path.join(arena, &.{ index.ptr(c).root_path.slice(c), sub_path }),3970 else => |index| try Dir.path.join(arena, &.{ index.package(c).ptr(c).root_path.slice(c), sub_path }),
3971 },3971 },
3972 },3972 },
3973 .zig_lib => .{3973 .zig_lib => .{
lib/compiler/Maker/ScannedConfig.zig+24
...@@ -104,6 +104,30 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {...@@ -104,6 +104,30 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
104 try tf.end();104 try tf.end();
105 }105 }
106106
107 {
108 var tf = try s.beginTupleField("package_instances", .{});
109 for (c.package_instances) |inst| {
110 var sf = try tf.beginStructField(.{});
111
112 try sf.fieldPrefix("package");
113 if (std.enums.tagName(Configuration.Package.Index, inst.package)) |name| {
114 try sf.container.serializer.ident(name);
115 } else {
116 try sf.container.serializer.int(@backingInt(inst.package));
117 }
118
119 var otf = try sf.beginTupleField("user_input_options", .{});
120 for (inst.user_input_options.slice(c)) |option| {
121 var osf = try otf.beginStructField(.{});
122 try sc.printStruct(&osf, Configuration.PackageInstance.UserInputOption, option.get(c));
123 try osf.end();
124 }
125 try otf.end();
126
127 try sf.end();
128 }
129 }
130
107 try s.end();131 try s.end();
108}132}
109133
lib/std/Build.zig+3-3
...@@ -272,7 +272,7 @@ const InitializedDepContext = struct {...@@ -272,7 +272,7 @@ const InitializedDepContext = struct {
272 }272 }
273};273};
274274
275const UserInputOptionsMap = StringHashMap(UserInputOption);275pub const UserInputOptionsMap = StringHashMap(UserInputOption);
276276
277const AvailableOption = struct {277const AvailableOption = struct {
278 name: []const u8,278 name: []const u8,
...@@ -282,13 +282,13 @@ const AvailableOption = struct {...@@ -282,13 +282,13 @@ const AvailableOption = struct {
282 enum_options: ?[]const []const u8,282 enum_options: ?[]const []const u8,
283};283};
284284
285const UserInputOption = struct {285pub const UserInputOption = struct {
286 name: []const u8,286 name: []const u8,
287 value: UserValue,287 value: UserValue,
288 used: bool,288 used: bool,
289};289};
290290
291const UserValue = union(enum) {291pub const UserValue = union(enum) {
292 flag: void,292 flag: void,
293 scalar: []const u8,293 scalar: []const u8,
294 list: std.array_list.Managed([]const u8),294 list: std.array_list.Managed([]const u8),
lib/std/Build/Configuration.zig+128-4
...@@ -17,6 +17,12 @@ available_options: []AvailableOption,...@@ -17,6 +17,12 @@ available_options: []AvailableOption,
17search_prefixes: []String,17search_prefixes: []String,
18/// Index 0 always exists and is the root package.18/// Index 0 always exists and is the root package.
19packages: []Package,19packages: []Package,
20/// Index 0 always exists and is the root package instance.
21///
22/// Unlike `packages`, each item corresponds to a `std.Build`, which is a
23/// package that was instantiated by running its build script with specific
24/// input options.
25package_instances: []PackageInstance,
20extra: []u32,26extra: []u32,
21default_step: Step.Index,27default_step: Step.Index,
22generated_files_len: u32,28generated_files_len: u32,
...@@ -33,6 +39,7 @@ pub const Header = extern struct {...@@ -33,6 +39,7 @@ pub const Header = extern struct {
33 available_options_len: u32,39 available_options_len: u32,
34 search_prefixes_len: u32,40 search_prefixes_len: u32,
35 packages_len: u32,41 packages_len: u32,
42 package_instances_len: u32,
36 extra_len: u32,43 extra_len: u32,
3744
38 default_step: Step.Index,45 default_step: Step.Index,
...@@ -62,6 +69,7 @@ pub const Wip = struct {...@@ -62,6 +69,7 @@ pub const Wip = struct {
62 path_deps: std.ArrayList(PathDep) = .empty,69 path_deps: std.ArrayList(PathDep) = .empty,
63 search_prefixes: std.ArrayList(String) = .empty,70 search_prefixes: std.ArrayList(String) = .empty,
64 packages: std.ArrayList(Package) = .empty,71 packages: std.ArrayList(Package) = .empty,
72 package_instances: std.ArrayList(PackageInstance) = .empty,
65 extra: std.ArrayList(u32) = .empty,73 extra: std.ArrayList(u32) = .empty,
66 next_generated_file_index: u32 = 0,74 next_generated_file_index: u32 = 0,
67 cache_poison: bool = false,75 cache_poison: bool = false,
...@@ -144,6 +152,7 @@ pub const Wip = struct {...@@ -144,6 +152,7 @@ pub const Wip = struct {
144 wip.path_deps.deinit(gpa);152 wip.path_deps.deinit(gpa);
145 wip.search_prefixes.deinit(gpa);153 wip.search_prefixes.deinit(gpa);
146 wip.packages.deinit(gpa);154 wip.packages.deinit(gpa);
155 wip.package_instances.deinit(gpa);
147 wip.extra.deinit(gpa);156 wip.extra.deinit(gpa);
148 wip.* = undefined;157 wip.* = undefined;
149 }158 }
...@@ -164,6 +173,7 @@ pub const Wip = struct {...@@ -164,6 +173,7 @@ pub const Wip = struct {
164 .available_options_len = @intCast(wip.available_options.items.len),173 .available_options_len = @intCast(wip.available_options.items.len),
165 .search_prefixes_len = @intCast(wip.search_prefixes.items.len),174 .search_prefixes_len = @intCast(wip.search_prefixes.items.len),
166 .packages_len = @intCast(wip.packages.items.len),175 .packages_len = @intCast(wip.packages.items.len),
176 .package_instances_len = @intCast(wip.package_instances.items.len),
167 .extra_len = @intCast(wip.extra.items.len),177 .extra_len = @intCast(wip.extra.items.len),
168178
169 .default_step = static.default_step,179 .default_step = static.default_step,
...@@ -182,6 +192,7 @@ pub const Wip = struct {...@@ -182,6 +192,7 @@ pub const Wip = struct {
182 @ptrCast(wip.available_options.items),192 @ptrCast(wip.available_options.items),
183 @ptrCast(wip.search_prefixes.items),193 @ptrCast(wip.search_prefixes.items),
184 @ptrCast(wip.packages.items),194 @ptrCast(wip.packages.items),
195 @ptrCast(wip.package_instances.items),
185 @ptrCast(wip.extra.items),196 @ptrCast(wip.extra.items),
186 };197 };
187 try w.writeVecAll(&buffers);198 try w.writeVecAll(&buffers);
...@@ -483,7 +494,7 @@ pub const AvailableOption = extern struct {...@@ -483,7 +494,7 @@ pub const AvailableOption = extern struct {
483494
484pub const Step = extern struct {495pub const Step = extern struct {
485 name: String,496 name: String,
486 owner: Package.Index,497 owner: PackageInstance.Index,
487 deps: Deps.Index,498 deps: Deps.Index,
488 max_rss: MaxRss,499 max_rss: MaxRss,
489 extended: Storage.Extended(Flags, union(Tag) {500 extended: Storage.Extended(Flags, union(Tag) {
...@@ -1532,7 +1543,7 @@ pub const LazyPath = union(@This().Tag) {...@@ -1532,7 +1543,7 @@ pub const LazyPath = union(@This().Tag) {
15321543
1533 pub const SourcePath = struct {1544 pub const SourcePath = struct {
1534 flags: @This().Flags = .{},1545 flags: @This().Flags = .{},
1535 owner: Package.Index,1546 owner: PackageInstance.Index,
1536 sub_path: String,1547 sub_path: String,
15371548
1538 pub const Flags = packed struct(u32) {1549 pub const Flags = packed struct(u32) {
...@@ -1665,11 +1676,122 @@ pub const Package = extern struct {...@@ -1665,11 +1676,122 @@ pub const Package = extern struct {
1665 };1676 };
1666};1677};
16671678
1679pub const PackageInstance = extern struct {
1680 package: Package.Index,
1681 user_input_options: UserInputOption.List.Index,
1682
1683 pub const UserInputOption = struct {
1684 flags: Flags,
1685 name: String,
1686 value: Storage.FlagUnion(.flags, .tag, UserValue),
1687
1688 pub const Flags = packed struct(u32) {
1689 tag: UserValue.Tag,
1690 used: bool,
1691 _: u28 = 0,
1692 };
1693
1694 pub const List = struct {
1695 options: Storage.LengthPrefixedList(UserInputOption.Index),
1696
1697 pub const Index = enum(u32) {
1698 _,
1699
1700 pub fn get(this: @This(), c: *const Configuration) List {
1701 return extraData(c, List, @backingInt(this));
1702 }
1703
1704 pub fn slice(this: @This(), c: *const Configuration) []const UserInputOption.Index {
1705 return this.get(c).options.slice;
1706 }
1707 };
1708 };
1709
1710 pub const Index = IndexType(@This());
1711 };
1712
1713 pub const UserValue = union(Tag) {
1714 flag,
1715 scalar: String,
1716 list: StringList,
1717 map: Map.Index,
1718 lazy_path: LazyPath.Index,
1719 lazy_path_list: Storage.LengthPrefixedList(LazyPath.Index),
1720
1721 pub const Standalone = struct {
1722 flags: Flags,
1723 value: Storage.FlagUnion(.flags, .tag, UserValue),
1724
1725 pub const Flags = packed struct(u32) {
1726 tag: UserValue.Tag,
1727 _: u29 = 0,
1728 };
1729
1730 pub const Index = IndexType(@This());
1731 };
1732
1733 pub const Tag = enum(u3) {
1734 flag,
1735 scalar,
1736 list,
1737 map,
1738 lazy_path,
1739 lazy_path_list,
1740
1741 pub fn init(uv: @typeInfo(std.Build.UserValue).@"union".tag_type.?) @This() {
1742 return switch (uv) {
1743 inline else => |tag| @field(@This(), @tagName(tag)),
1744 };
1745 }
1746 };
1747
1748 pub const Map = struct {
1749 keys: StringList,
1750 values: Storage.LengthPrefixedList(UserValue.Standalone.Index),
1751
1752 pub const Index = IndexType(@This());
1753 };
1754 };
1755
1756 pub const Index = enum(u32) {
1757 root,
1758 _,
1759
1760 pub fn ptr(this: @This(), c: *const Configuration) *const PackageInstance {
1761 return &c.package_instances[@backingInt(this)];
1762 }
1763
1764 pub fn package(this: @This(), c: *const Configuration) Package.Index {
1765 return this.ptr(c).package;
1766 }
1767 };
1768
1769 pub const OptionalIndex = enum(u32) {
1770 root,
1771 none = max_u32,
1772 _,
1773
1774 pub fn init(i: Index) OptionalIndex {
1775 const result: OptionalIndex = @fromBackingInt(@intCast(@backingInt(i)));
1776 assert(result != .none);
1777 return result;
1778 }
1779
1780 pub fn unwrap(this: @This()) ?Index {
1781 return switch (this) {
1782 .none => null,
1783 .root => .root,
1784 _ => @fromBackingInt(@intCast(@backingInt(this))),
1785 };
1786 }
1787 };
1788};
1789
1668pub const Module = struct {1790pub const Module = struct {
1669 flags: Flags,1791 flags: Flags,
1670 flags2: Flags2,1792 flags2: Flags2,
1671 import_table: ImportTable.Index,1793 import_table: ImportTable.Index,
1672 owner: Package.Index,1794 owner: PackageInstance.Index,
1673 root_source_file: LazyPath.OptionalIndex,1795 root_source_file: LazyPath.OptionalIndex,
1674 resolved_target: ResolvedTarget.OptionalIndex,1796 resolved_target: ResolvedTarget.OptionalIndex,
1675 c_macros: Storage.FlagLengthPrefixedList(.flags, .c_macros, String),1797 c_macros: Storage.FlagLengthPrefixedList(.flags, .c_macros, String),
...@@ -1896,7 +2018,7 @@ pub const OptionalStringList = enum(u32) {...@@ -1896,7 +2018,7 @@ pub const OptionalStringList = enum(u32) {
1896pub const PathDep = extern struct {2018pub const PathDep = extern struct {
1897 flags: Flags,2019 flags: Flags,
1898 sub: String,2020 sub: String,
1899 pkg: Package.OptionalIndex,2021 pkg: PackageInstance.OptionalIndex,
19002022
1901 pub const Flags = packed struct(u32) {2023 pub const Flags = packed struct(u32) {
1902 mode: Mode,2024 mode: Mode,
...@@ -3162,6 +3284,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {...@@ -3162,6 +3284,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
3162 .available_options = try arena.alloc(AvailableOption, header.available_options_len),3284 .available_options = try arena.alloc(AvailableOption, header.available_options_len),
3163 .search_prefixes = try arena.alloc(String, header.search_prefixes_len),3285 .search_prefixes = try arena.alloc(String, header.search_prefixes_len),
3164 .packages = try arena.alloc(Package, header.packages_len),3286 .packages = try arena.alloc(Package, header.packages_len),
3287 .package_instances = try arena.alloc(PackageInstance, header.package_instances_len),
3165 .extra = try arena.alloc(u32, header.extra_len),3288 .extra = try arena.alloc(u32, header.extra_len),
3166 .default_step = header.default_step,3289 .default_step = header.default_step,
3167 .generated_files_len = header.generated_files_len,3290 .generated_files_len = header.generated_files_len,
...@@ -3176,6 +3299,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {...@@ -3176,6 +3299,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
3176 @ptrCast(result.available_options),3299 @ptrCast(result.available_options),
3177 @ptrCast(result.search_prefixes),3300 @ptrCast(result.search_prefixes),
3178 @ptrCast(result.packages),3301 @ptrCast(result.packages),
3302 @ptrCast(result.package_instances),
3179 @ptrCast(result.extra),3303 @ptrCast(result.extra),
3180 };3304 };
3181 try reader.readVecAll(&vecs);3305 try reader.readVecAll(&vecs);
lib/std/Build/Serialize.zig+96-10
...@@ -12,6 +12,8 @@ wc: *Configuration.Wip,...@@ -12,6 +12,8 @@ wc: *Configuration.Wip,
12module_map: std.array_hash_map.Auto(*std.Build.Module, Configuration.Module.Index) = .empty,12module_map: std.array_hash_map.Auto(*std.Build.Module, Configuration.Module.Index) = .empty,
13/// Keyed by package hash. Index + 1 corresponds to `Configuration.packages` index.13/// Keyed by package hash. Index + 1 corresponds to `Configuration.packages` index.
14package_map: std.array_hash_map.String(void) = .empty,14package_map: std.array_hash_map.String(void) = .empty,
15/// Index corresponds to `Configuration.package_instances` index.
16package_instance_map: std.array_hash_map.Auto(*std.Build, void) = .empty,
15/// Index corresponds to `Configuration.steps` index.17/// Index corresponds to `Configuration.steps` index.
16step_map: std.array_hash_map.Auto(*Step, void) = .empty,18step_map: std.array_hash_map.Auto(*Step, void) = .empty,
1719
...@@ -22,9 +24,15 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -22,9 +24,15 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
2224
23 var s: Serialize = .{ .wc = wc, .arena = arena };25 var s: Serialize = .{ .wc = wc, .arena = arena };
2426
25 // Serialize all of the packages first to seed the package_map, which is27 // Seed the package_map, which is later used when serializing package
26 // later used in calls to packageFromHash.28 // instances.
27 try s.addRootPackage(b);29 try s.traversePackages(b);
30
31 // Seed the package_instance_map, which is later used in calls to
32 // packageInstanceFromBuilder.
33 try s.addPackageInstance(b);
34 var iter = b.graph.dependency_cache.valueIterator();
35 while (iter.next()) |dep| try s.addPackageInstance(dep.*.builder);
2836
29 try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len);37 try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len);
30 for (38 for (
...@@ -49,10 +57,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -49,10 +57,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
49 .relative => |r| try wc.addString(r.sub_path),57 .relative => |r| try wc.addString(r.sub_path),
50 },58 },
51 .pkg = switch (src.lazy_path) {59 .pkg = switch (src.lazy_path) {
52 .src_path => |sp| .init(s.packageFromHash(sp.owner.pkg_hash)),60 .src_path => |sp| .init(s.packageInstanceFromBuilder(sp.owner)),
53 .generated => unreachable,61 .generated => unreachable,
54 .cwd_relative, .relative => .none,62 .cwd_relative, .relative => .none,
55 .dependency => |d| .init(s.packageFromHash(d.dependency.builder.pkg_hash)),63 .dependency => |d| .init(s.packageInstanceFromBuilder(d.dependency.builder)),
56 },64 },
57 };65 };
58 }66 }
...@@ -89,7 +97,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -89,7 +97,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
89 try wc.steps.ensureTotalCapacity(gpa, s.step_map.entries.capacity);97 try wc.steps.ensureTotalCapacity(gpa, s.step_map.entries.capacity);
90 wc.steps.appendAssumeCapacity(.{98 wc.steps.appendAssumeCapacity(.{
91 .name = try wc.addString(step.name),99 .name = try wc.addString(step.name),
92 .owner = s.packageFromHash(step.owner.pkg_hash),100 .owner = s.packageInstanceFromBuilder(step.owner),
93 .deps = deps,101 .deps = deps,
94 .max_rss = .fromBytes(step.max_rss),102 .max_rss = .fromBytes(step.max_rss),
95 .extended = @fromBackingInt(@intCast(switch (step.tag) {103 .extended = @fromBackingInt(@intCast(switch (step.tag) {
...@@ -727,7 +735,7 @@ pub fn packageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!voi...@@ -727,7 +735,7 @@ pub fn packageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!voi
727 }735 }
728}736}
729737
730fn addRootPackage(s: *Serialize, b: *std.Build) Allocator.Error!void {738fn traversePackages(s: *Serialize, b: *std.Build) Allocator.Error!void {
731 const arena = s.arena;739 const arena = s.arena;
732 const wc = s.wc;740 const wc = s.wc;
733741
...@@ -787,13 +795,91 @@ fn packageFromHash(s: *Serialize, pkg_hash: []const u8) Configuration.Package.In...@@ -787,13 +795,91 @@ fn packageFromHash(s: *Serialize, pkg_hash: []const u8) Configuration.Package.In
787 return @fromBackingInt(@intCast(s.package_map.getIndex(pkg_hash).? + 1));795 return @fromBackingInt(@intCast(s.package_map.getIndex(pkg_hash).? + 1));
788}796}
789797
798fn addPackageInstance(s: *Serialize, b: *std.Build) Allocator.Error!void {
799 const arena = s.arena;
800 const wc = s.wc;
801
802 const options = try arena.alloc(
803 Configuration.PackageInstance.UserInputOption.Index,
804 b.user_input_options.count(),
805 );
806
807 var i: usize = 0;
808 var iter = b.user_input_options.valueIterator();
809 while (iter.next()) |option| : (i += 1) {
810 options[i] = try wc.addExtra(Configuration.PackageInstance.UserInputOption, .{
811 .flags = .{
812 .tag = .init(option.value),
813 .used = option.used,
814 },
815 .name = try wc.addString(option.name),
816 .value = .{ .u = try s.makeUserValue(&option.value) },
817 });
818 }
819
820 try wc.package_instances.append(wc.gpa, .{
821 .package = s.packageFromHash(b.pkg_hash),
822 .user_input_options = try wc.addDeduped(Configuration.PackageInstance.UserInputOption.List, .{
823 .options = .{ .slice = options },
824 }),
825 });
826
827 try s.package_instance_map.put(arena, b, {});
828}
829
830fn makeUserValue(s: *Serialize, user_value: *const std.Build.UserValue) Allocator.Error!Configuration.PackageInstance.UserValue {
831 const arena = s.arena;
832 const wc = s.wc;
833
834 return switch (user_value.*) {
835 .flag => .flag,
836 .scalar => |str| .{ .scalar = try wc.addString(str) },
837 .list => |list| .{ .list = try wc.addStringList(list.items) },
838 .map => |map| add: {
839 const keys = try arena.alloc([]const u8, map.count());
840 const values = try arena.alloc(Configuration.PackageInstance.UserValue.Standalone.Index, map.count());
841
842 var i: usize = 0;
843 var iter = map.iterator();
844 while (iter.next()) |entry| : (i += 1) {
845 const value = try s.makeUserValue(entry.value_ptr.*);
846
847 keys[i] = entry.key_ptr.*;
848 values[i] = try wc.addDeduped(
849 Configuration.PackageInstance.UserValue.Standalone,
850 .{ .flags = .{ .tag = value }, .value = .{ .u = value } },
851 );
852 }
853
854 break :add .{ .map = try wc.addDeduped(
855 Configuration.PackageInstance.UserValue.Map,
856 .{
857 .keys = try wc.addStringList(keys),
858 .values = .{ .slice = values },
859 },
860 ) };
861 },
862 .lazy_path => |lp| .{ .lazy_path = try s.addLazyPath(lp) },
863 .lazy_path_list => |lp_list| add: {
864 const paths = try arena.alloc(Configuration.LazyPath.Index, lp_list.items.len);
865 for (paths, lp_list.items) |*dest, src| dest.* = try s.addLazyPath(src);
866 break :add .{ .lazy_path_list = .{ .slice = paths } };
867 },
868 };
869}
870
871fn packageInstanceFromBuilder(s: *Serialize, b: *std.Build) Configuration.PackageInstance.Index {
872 if (b.pkg_hash.len == 0) return .root;
873 return @fromBackingInt(@intCast(s.package_instance_map.getIndex(b).?));
874}
875
790fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex {876fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex {
791 const wc = s.wc;877 const wc = s.wc;
792 return @fromBackingInt(@intCast(switch (lp orelse return .none) {878 return @fromBackingInt(@intCast(switch (lp orelse return .none) {
793 .src_path => |src_path| i: {879 .src_path => |src_path| i: {
794 const sub_path = try wc.addString(src_path.sub_path);880 const sub_path = try wc.addString(src_path.sub_path);
795 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{881 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{
796 .owner = s.packageFromHash(src_path.owner.pkg_hash),882 .owner = s.packageInstanceFromBuilder(src_path.owner),
797 .sub_path = sub_path,883 .sub_path = sub_path,
798 });884 });
799 },885 },
...@@ -821,7 +907,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio...@@ -821,7 +907,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio
821 .dependency => |dependency| i: {907 .dependency => |dependency| i: {
822 const sub_path = try wc.addString(dependency.sub_path);908 const sub_path = try wc.addString(dependency.sub_path);
823 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{909 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{
824 .owner = s.packageFromHash(dependency.dependency.builder.pkg_hash),910 .owner = s.packageInstanceFromBuilder(dependency.dependency.builder),
825 .sub_path = sub_path,911 .sub_path = sub_path,
826 });912 });
827 },913 },
...@@ -1281,7 +1367,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {...@@ -1281,7 +1367,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
1281 .link_libcpp = .init(m.link_libcpp),1367 .link_libcpp = .init(m.link_libcpp),
1282 .no_builtin = .init(m.no_builtin),1368 .no_builtin = .init(m.no_builtin),
1283 },1369 },
1284 .owner = s.packageFromHash(m.owner.pkg_hash),1370 .owner = s.packageInstanceFromBuilder(m.owner),
1285 .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),1371 .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),
1286 .import_table = .invalid,1372 .import_table = .invalid,
1287 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),1373 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),