authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-08-13 00:34:22+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-08-13 00:34:22+02:00
log8e48a5c524f970c4630725e2efe69243d8d79fde
tree5a97e78e8fbde363a127c2de8ac70dbf9d58b1ac
parent2aae46494a82c2d99e509a30d7e686b771737895
parente98205bd17bb39ba501213f9b8ce2b0559b90035

Merge pull request 'std.Build.Configuration: serialize public modules of packages' (#36461) from hemisputnik/zig:work/36388-configuration-package-modules into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36461 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

5 files changed, 344 insertions(+), 83 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+32
...@@ -104,6 +104,38 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {...@@ -104,6 +104,38 @@ 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 var msf = try sf.beginStructField("modules", .{});
128 for (inst.modules.keys.slice(c), inst.modules.values.slice(c)) |key, value| {
129 var msf2 = try msf.beginStructField(key.slice(c), .{});
130 try sc.printStruct(&msf2, Configuration.Module, value.get(c));
131 try msf2.end();
132 }
133 try msf.end();
134
135 try sf.end();
136 }
137 }
138
107 try s.end();139 try s.end();
108}140}
109141
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+158-54
...@@ -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) {
...@@ -1515,13 +1526,7 @@ pub const LazyPath = union(@This().Tag) {...@@ -1515,13 +1526,7 @@ pub const LazyPath = union(@This().Tag) {
1515 };1526 };
15161527
1517 /// An index into `extra`.1528 /// An index into `extra`.
1518 pub const Index = enum(u32) {1529 pub const Index = IndexType(@This());
1519 _,
1520
1521 pub fn get(this: @This(), c: *const Configuration) LazyPath {
1522 return extraData(c, LazyPath, @backingInt(this));
1523 }
1524 };
15251530
1526 /// An index into `extra`, or `null`.1531 /// An index into `extra`, or `null`.
1527 pub const OptionalIndex = enum(u32) {1532 pub const OptionalIndex = enum(u32) {
...@@ -1538,7 +1543,7 @@ pub const LazyPath = union(@This().Tag) {...@@ -1538,7 +1543,7 @@ pub const LazyPath = union(@This().Tag) {
15381543
1539 pub const SourcePath = struct {1544 pub const SourcePath = struct {
1540 flags: @This().Flags = .{},1545 flags: @This().Flags = .{},
1541 owner: Package.Index,1546 owner: PackageInstance.Index,
1542 sub_path: String,1547 sub_path: String,
15431548
1544 pub const Flags = packed struct(u32) {1549 pub const Flags = packed struct(u32) {
...@@ -1671,11 +1676,128 @@ pub const Package = extern struct {...@@ -1671,11 +1676,128 @@ pub const Package = extern struct {
1671 };1676 };
1672};1677};
16731678
1679pub const PackageInstance = extern struct {
1680 package: Package.Index,
1681 user_input_options: UserInputOption.List.Index,
1682 modules: PublicModules,
1683
1684 pub const UserInputOption = struct {
1685 flags: Flags,
1686 name: String,
1687 value: Storage.FlagUnion(.flags, .tag, UserValue),
1688
1689 pub const Flags = packed struct(u32) {
1690 tag: UserValue.Tag,
1691 used: bool,
1692 _: u28 = 0,
1693 };
1694
1695 pub const List = struct {
1696 options: Storage.LengthPrefixedList(UserInputOption.Index),
1697
1698 pub const Index = enum(u32) {
1699 _,
1700
1701 pub fn get(this: @This(), c: *const Configuration) List {
1702 return extraData(c, List, @backingInt(this));
1703 }
1704
1705 pub fn slice(this: @This(), c: *const Configuration) []const UserInputOption.Index {
1706 return this.get(c).options.slice;
1707 }
1708 };
1709 };
1710
1711 pub const Index = IndexType(@This());
1712 };
1713
1714 pub const UserValue = union(Tag) {
1715 flag,
1716 scalar: String,
1717 list: StringList,
1718 map: Map.Index,
1719 lazy_path: LazyPath.Index,
1720 lazy_path_list: Storage.LengthPrefixedList(LazyPath.Index),
1721
1722 pub const Standalone = struct {
1723 flags: Flags,
1724 value: Storage.FlagUnion(.flags, .tag, UserValue),
1725
1726 pub const Flags = packed struct(u32) {
1727 tag: UserValue.Tag,
1728 _: u29 = 0,
1729 };
1730
1731 pub const Index = IndexType(@This());
1732 };
1733
1734 pub const Tag = enum(u3) {
1735 flag,
1736 scalar,
1737 list,
1738 map,
1739 lazy_path,
1740 lazy_path_list,
1741
1742 pub fn init(uv: @typeInfo(std.Build.UserValue).@"union".tag_type.?) @This() {
1743 return switch (uv) {
1744 inline else => |tag| @field(@This(), @tagName(tag)),
1745 };
1746 }
1747 };
1748
1749 pub const Map = struct {
1750 keys: StringList,
1751 values: Storage.LengthPrefixedList(UserValue.Standalone.Index),
1752
1753 pub const Index = IndexType(@This());
1754 };
1755 };
1756
1757 pub const PublicModules = extern struct {
1758 keys: StringList,
1759 values: Module.List.Index,
1760 };
1761
1762 pub const Index = enum(u32) {
1763 root,
1764 _,
1765
1766 pub fn ptr(this: @This(), c: *const Configuration) *const PackageInstance {
1767 return &c.package_instances[@backingInt(this)];
1768 }
1769
1770 pub fn package(this: @This(), c: *const Configuration) Package.Index {
1771 return this.ptr(c).package;
1772 }
1773 };
1774
1775 pub const OptionalIndex = enum(u32) {
1776 root,
1777 none = max_u32,
1778 _,
1779
1780 pub fn init(i: Index) OptionalIndex {
1781 const result: OptionalIndex = @fromBackingInt(@intCast(@backingInt(i)));
1782 assert(result != .none);
1783 return result;
1784 }
1785
1786 pub fn unwrap(this: @This()) ?Index {
1787 return switch (this) {
1788 .none => null,
1789 .root => .root,
1790 _ => @fromBackingInt(@intCast(@backingInt(this))),
1791 };
1792 }
1793 };
1794};
1795
1674pub const Module = struct {1796pub const Module = struct {
1675 flags: Flags,1797 flags: Flags,
1676 flags2: Flags2,1798 flags2: Flags2,
1677 import_table: ImportTable.Index,1799 import_table: ImportTable.Index,
1678 owner: Package.Index,1800 owner: PackageInstance.Index,
1679 root_source_file: LazyPath.OptionalIndex,1801 root_source_file: LazyPath.OptionalIndex,
1680 resolved_target: ResolvedTarget.OptionalIndex,1802 resolved_target: ResolvedTarget.OptionalIndex,
1681 c_macros: Storage.FlagLengthPrefixedList(.flags, .c_macros, String),1803 c_macros: Storage.FlagLengthPrefixedList(.flags, .c_macros, String),
...@@ -1746,14 +1868,6 @@ pub const Module = struct {...@@ -1746,14 +1868,6 @@ pub const Module = struct {
1746 }1868 }
1747 };1869 };
17481870
1749 pub const Index = enum(u32) {
1750 _,
1751
1752 pub fn get(this: @This(), c: *const Configuration) Module {
1753 return extraData(c, Module, @backingInt(this));
1754 }
1755 };
1756
1757 pub const Flags = packed struct(u32) {1871 pub const Flags = packed struct(u32) {
1758 optimize: Optimize,1872 optimize: Optimize,
1759 strip: DefaultingBool,1873 strip: DefaultingBool,
...@@ -1824,6 +1938,24 @@ pub const Module = struct {...@@ -1824,6 +1938,24 @@ pub const Module = struct {
1824 _: u30 = 0,1938 _: u30 = 0,
1825 };1939 };
1826 };1940 };
1941
1942 pub const Index = IndexType(@This());
1943
1944 pub const List = struct {
1945 modules: Storage.LengthPrefixedList(Module.Index),
1946
1947 pub const Index = enum(u32) {
1948 _,
1949
1950 pub fn get(this: @This(), c: *const Configuration) List {
1951 return extraData(c, List, @backingInt(this));
1952 }
1953
1954 pub fn slice(this: @This(), c: *const Configuration) []const Module.Index {
1955 return this.get(c).modules.slice;
1956 }
1957 };
1958 };
1827};1959};
18281960
1829pub const ImportTable = struct {1961pub const ImportTable = struct {
...@@ -1908,7 +2040,7 @@ pub const OptionalStringList = enum(u32) {...@@ -1908,7 +2040,7 @@ pub const OptionalStringList = enum(u32) {
1908pub const PathDep = extern struct {2040pub const PathDep = extern struct {
1909 flags: Flags,2041 flags: Flags,
1910 sub: String,2042 sub: String,
1911 pkg: Package.OptionalIndex,2043 pkg: PackageInstance.OptionalIndex,
19122044
1913 pub const Flags = packed struct(u32) {2045 pub const Flags = packed struct(u32) {
1914 mode: Mode,2046 mode: Mode,
...@@ -2051,13 +2183,7 @@ pub const SystemLib = struct {...@@ -2051,13 +2183,7 @@ pub const SystemLib = struct {
2051 name: String,2183 name: String,
2052 flags: Flags,2184 flags: Flags,
20532185
2054 pub const Index = enum(u32) {2186 pub const Index = IndexType(@This());
2055 _,
2056
2057 pub fn get(this: @This(), c: *const Configuration) SystemLib {
2058 return extraData(c, SystemLib, @backingInt(this));
2059 }
2060 };
20612187
2062 pub const UsePkgConfig = enum(u2) {2188 pub const UsePkgConfig = enum(u2) {
2063 /// Don't use pkg-config, just pass -lfoo where foo is name.2189 /// Don't use pkg-config, just pass -lfoo where foo is name.
...@@ -2090,13 +2216,7 @@ pub const CSourceFiles = struct {...@@ -2090,13 +2216,7 @@ pub const CSourceFiles = struct {
2090 args: Storage.FlagList(.flags, .args_len, String),2216 args: Storage.FlagList(.flags, .args_len, String),
2091 sub_paths: Storage.LengthPrefixedList(String),2217 sub_paths: Storage.LengthPrefixedList(String),
20922218
2093 pub const Index = enum(u32) {2219 pub const Index = IndexType(@This());
2094 _,
2095
2096 pub fn get(this: @This(), c: *const Configuration) CSourceFiles {
2097 return extraData(c, CSourceFiles, @backingInt(this));
2098 }
2099 };
21002220
2101 pub const Flags = packed struct(u32) {2221 pub const Flags = packed struct(u32) {
2102 /// C compiler CLI flags.2222 /// C compiler CLI flags.
...@@ -2110,13 +2230,7 @@ pub const CSourceFile = struct {...@@ -2110,13 +2230,7 @@ pub const CSourceFile = struct {
2110 file: LazyPath.Index,2230 file: LazyPath.Index,
2111 args: Storage.FlagList(.flags, .args_len, String),2231 args: Storage.FlagList(.flags, .args_len, String),
21122232
2113 pub const Index = enum(u32) {2233 pub const Index = IndexType(@This());
2114 _,
2115
2116 pub fn get(this: @This(), c: *const Configuration) CSourceFile {
2117 return extraData(c, CSourceFile, @backingInt(this));
2118 }
2119 };
21202234
2121 pub const Flags = packed struct(u32) {2235 pub const Flags = packed struct(u32) {
2122 /// C compiler CLI flags.2236 /// C compiler CLI flags.
...@@ -2131,13 +2245,7 @@ pub const RcSourceFile = struct {...@@ -2131,13 +2245,7 @@ pub const RcSourceFile = struct {
2131 args: Storage.FlagList(.flags, .args_len, String),2245 args: Storage.FlagList(.flags, .args_len, String),
2132 include_paths: Storage.FlagLengthPrefixedList(.flags, .include_paths, LazyPath.Index),2246 include_paths: Storage.FlagLengthPrefixedList(.flags, .include_paths, LazyPath.Index),
21332247
2134 pub const Index = enum(u32) {2248 pub const Index = IndexType(@This());
2135 _,
2136
2137 pub fn get(this: @This(), c: *const Configuration) RcSourceFile {
2138 return extraData(c, RcSourceFile, @backingInt(this));
2139 }
2140 };
21412249
2142 pub const Flags = packed struct(u32) {2250 pub const Flags = packed struct(u32) {
2143 /// C compiler CLI flags.2251 /// C compiler CLI flags.
...@@ -2176,13 +2284,7 @@ pub const ResolvedTarget = struct {...@@ -2176,13 +2284,7 @@ pub const ResolvedTarget = struct {
2176 /// defaults will be resolved.2284 /// defaults will be resolved.
2177 result: TargetQuery.Index,2285 result: TargetQuery.Index,
21782286
2179 pub const Index = enum(u32) {2287 pub const Index = IndexType(@This());
2180 _,
2181
2182 pub fn get(this: @This(), c: *const Configuration) ResolvedTarget {
2183 return extraData(c, ResolvedTarget, @backingInt(this));
2184 }
2185 };
21862288
2187 pub const OptionalIndex = enum(u32) {2289 pub const OptionalIndex = enum(u32) {
2188 none = max_u32,2290 none = max_u32,
...@@ -3204,6 +3306,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {...@@ -3204,6 +3306,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
3204 .available_options = try arena.alloc(AvailableOption, header.available_options_len),3306 .available_options = try arena.alloc(AvailableOption, header.available_options_len),
3205 .search_prefixes = try arena.alloc(String, header.search_prefixes_len),3307 .search_prefixes = try arena.alloc(String, header.search_prefixes_len),
3206 .packages = try arena.alloc(Package, header.packages_len),3308 .packages = try arena.alloc(Package, header.packages_len),
3309 .package_instances = try arena.alloc(PackageInstance, header.package_instances_len),
3207 .extra = try arena.alloc(u32, header.extra_len),3310 .extra = try arena.alloc(u32, header.extra_len),
3208 .default_step = header.default_step,3311 .default_step = header.default_step,
3209 .generated_files_len = header.generated_files_len,3312 .generated_files_len = header.generated_files_len,
...@@ -3218,6 +3321,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {...@@ -3218,6 +3321,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
3218 @ptrCast(result.available_options),3321 @ptrCast(result.available_options),
3219 @ptrCast(result.search_prefixes),3322 @ptrCast(result.search_prefixes),
3220 @ptrCast(result.packages),3323 @ptrCast(result.packages),
3324 @ptrCast(result.package_instances),
3221 @ptrCast(result.extra),3325 @ptrCast(result.extra),
3222 };3326 };
3223 try reader.readVecAll(&vecs);3327 try reader.readVecAll(&vecs);
lib/std/Build/Serialize.zig+146-21
...@@ -10,8 +10,10 @@ const log = std.log;...@@ -10,8 +10,10 @@ const log = std.log;
10arena: Allocator,10arena: Allocator,
11wc: *Configuration.Wip,11wc: *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.13/// Keyed by package hash. Index + 1 corresponds to `Configuration.packages` index.
14package_map: std.array_hash_map.String(Configuration.Package.Index) = .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,28 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -22,9 +24,28 @@ 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 // Next, seed the package_instance_map, which is later used in calls to
32 // packageInstanceFromBuilder.
33
34 _ = try wc.package_instances.addManyAsSlice(gpa, 1 + b.graph.dependency_cache.count());
35 try s.package_instance_map.ensureTotalCapacity(arena, 1 + b.graph.dependency_cache.count());
36
37 // As serializing package instances also requires serializing the public
38 // modules of each one, we must first allocate an index for each package
39 // instance. Otherwise, addModule may access a package instance that hasn't
40 // been created yet with packageInstanceFromBuilder.
41
42 s.package_instance_map.putAssumeCapacityNoClobber(b, {});
43 var iter = b.graph.dependency_cache.valueIterator();
44 while (iter.next()) |dep| s.package_instance_map.putAssumeCapacityNoClobber(dep.*.builder, {});
45
46 try s.addPackageInstance(b);
47 var iter2 = b.graph.dependency_cache.valueIterator();
48 while (iter2.next()) |dep| try s.addPackageInstance(dep.*.builder);
2849
29 try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len);50 try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len);
30 for (51 for (
...@@ -49,10 +70,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -49,10 +70,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
49 .relative => |r| try wc.addString(r.sub_path),70 .relative => |r| try wc.addString(r.sub_path),
50 },71 },
51 .pkg = switch (src.lazy_path) {72 .pkg = switch (src.lazy_path) {
52 .src_path => |sp| .init(s.packageFromHash(sp.owner.pkg_hash)),73 .src_path => |sp| .init(s.packageInstanceFromBuilder(sp.owner)),
53 .generated => unreachable,74 .generated => unreachable,
54 .cwd_relative, .relative => .none,75 .cwd_relative, .relative => .none,
55 .dependency => |d| .init(s.packageFromHash(d.dependency.builder.pkg_hash)),76 .dependency => |d| .init(s.packageInstanceFromBuilder(d.dependency.builder)),
56 },77 },
57 };78 };
58 }79 }
...@@ -89,7 +110,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -89,7 +110,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);110 try wc.steps.ensureTotalCapacity(gpa, s.step_map.entries.capacity);
90 wc.steps.appendAssumeCapacity(.{111 wc.steps.appendAssumeCapacity(.{
91 .name = try wc.addString(step.name),112 .name = try wc.addString(step.name),
92 .owner = s.packageFromHash(step.owner.pkg_hash),113 .owner = s.packageInstanceFromBuilder(step.owner),
93 .deps = deps,114 .deps = deps,
94 .max_rss = .fromBytes(step.max_rss),115 .max_rss = .fromBytes(step.max_rss),
95 .extended = @fromBackingInt(@intCast(switch (step.tag) {116 .extended = @fromBackingInt(@intCast(switch (step.tag) {
...@@ -727,7 +748,7 @@ pub fn packageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!voi...@@ -727,7 +748,7 @@ pub fn packageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!voi
727 }748 }
728}749}
729750
730fn addRootPackage(s: *Serialize, b: *std.Build) Allocator.Error!void {751fn traversePackages(s: *Serialize, b: *std.Build) Allocator.Error!void {
731 const arena = s.arena;752 const arena = s.arena;
732 const wc = s.wc;753 const wc = s.wc;
733754
...@@ -741,7 +762,7 @@ fn addRootPackage(s: *Serialize, b: *std.Build) Allocator.Error!void {...@@ -741,7 +762,7 @@ fn addRootPackage(s: *Serialize, b: *std.Build) Allocator.Error!void {
741 const deps = try arena.alloc(Configuration.Package.Dep, b.available_deps.len);762 const deps = try arena.alloc(Configuration.Package.Dep, b.available_deps.len);
742 for (deps, b.available_deps) |*dest, src| dest.* = try s.makePackageDep("", src[0], src[1]);763 for (deps, b.available_deps) |*dest, src| dest.* = try s.makePackageDep("", src[0], src[1]);
743764
744 wc.packages.items[0].deps = try wc.addExtra(Configuration.Package.Dep.List, .{765 wc.packages.items[0].deps = try wc.addDeduped(Configuration.Package.Dep.List, .{
745 .deps = .{ .slice = deps },766 .deps = .{ .slice = deps },
746 });767 });
747}768}
...@@ -750,18 +771,18 @@ fn makePackageDep(s: *Serialize, parent_dep_prefix: []const u8, name: []const u8...@@ -750,18 +771,18 @@ fn makePackageDep(s: *Serialize, parent_dep_prefix: []const u8, name: []const u8
750 const arena = s.arena;771 const arena = s.arena;
751 const wc = s.wc;772 const wc = s.wc;
752773
753 if (s.package_map.get(hash)) |index| return .{774 if (s.package_map.getIndex(hash)) |index| return .{
754 .name = try wc.addString(name),775 .name = try wc.addString(name),
755 .package = index,776 .package = @fromBackingInt(@intCast(index + 1)),
756 };777 };
757778
779 const index: Configuration.Package.Index = @fromBackingInt(@intCast(wc.packages.items.len));
780 try s.package_map.put(arena, hash, {});
781
758 const entry = std.Build.package_map.get(hash) orelse unreachable;782 const entry = std.Build.package_map.get(hash) orelse unreachable;
759783
760 const dep_prefix = try arena.print("{s}{s}.", .{ parent_dep_prefix, name });784 const dep_prefix = try arena.print("{s}{s}.", .{ parent_dep_prefix, name });
761785
762 const index: Configuration.Package.Index = @fromBackingInt(@intCast(wc.packages.items.len));
763 try s.package_map.put(arena, hash, index);
764
765 try wc.packages.append(wc.gpa, .{786 try wc.packages.append(wc.gpa, .{
766 .dep_prefix = try wc.addString(dep_prefix),787 .dep_prefix = try wc.addString(dep_prefix),
767 .hash = try wc.addString(hash),788 .hash = try wc.addString(hash),
...@@ -772,7 +793,7 @@ fn makePackageDep(s: *Serialize, parent_dep_prefix: []const u8, name: []const u8...@@ -772,7 +793,7 @@ fn makePackageDep(s: *Serialize, parent_dep_prefix: []const u8, name: []const u8
772 const deps = try arena.alloc(Configuration.Package.Dep, entry.deps.len);793 const deps = try arena.alloc(Configuration.Package.Dep, entry.deps.len);
773 for (deps, entry.deps) |*dest, src| dest.* = try s.makePackageDep(dep_prefix, src[0], src[1]);794 for (deps, entry.deps) |*dest, src| dest.* = try s.makePackageDep(dep_prefix, src[0], src[1]);
774795
775 wc.packages.items[@backingInt(index)].deps = try wc.addExtra(Configuration.Package.Dep.List, .{796 wc.packages.items[@backingInt(index)].deps = try wc.addDeduped(Configuration.Package.Dep.List, .{
776 .deps = .{ .slice = deps },797 .deps = .{ .slice = deps },
777 });798 });
778799
...@@ -784,7 +805,111 @@ fn makePackageDep(s: *Serialize, parent_dep_prefix: []const u8, name: []const u8...@@ -784,7 +805,111 @@ fn makePackageDep(s: *Serialize, parent_dep_prefix: []const u8, name: []const u8
784805
785fn packageFromHash(s: *Serialize, pkg_hash: []const u8) Configuration.Package.Index {806fn packageFromHash(s: *Serialize, pkg_hash: []const u8) Configuration.Package.Index {
786 if (pkg_hash.len == 0) return .root;807 if (pkg_hash.len == 0) return .root;
787 return s.package_map.get(pkg_hash) orelse std.debug.panic("unrecognized package hash: {q}", .{pkg_hash});808 return @fromBackingInt(@intCast(s.package_map.getIndex(pkg_hash).? + 1));
809}
810
811fn addPackageInstance(s: *Serialize, b: *std.Build) Allocator.Error!void {
812 const arena = s.arena;
813 const wc = s.wc;
814
815 const index = s.package_instance_map.getIndex(b).?;
816
817 const options = try arena.alloc(
818 Configuration.PackageInstance.UserInputOption.Index,
819 b.user_input_options.count(),
820 );
821
822 {
823 var i: usize = 0;
824 var iter = b.user_input_options.valueIterator();
825 while (iter.next()) |option| : (i += 1) {
826 options[i] = try wc.addExtra(Configuration.PackageInstance.UserInputOption, .{
827 .flags = .{
828 .tag = .init(option.value),
829 .used = option.used,
830 },
831 .name = try wc.addString(option.name),
832 .value = .{ .u = try s.makeUserValue(&option.value) },
833 });
834 }
835 }
836
837 const modules_keys = try arena.alloc(
838 []const u8,
839 b.modules.count(),
840 );
841 const modules_values = try arena.alloc(
842 Configuration.Module.Index,
843 b.modules.count(),
844 );
845
846 {
847 var i: usize = 0;
848 var iter = b.modules.iterator();
849 while (iter.next()) |entry| : (i += 1) {
850 modules_keys[i] = entry.key_ptr.*;
851 modules_values[i] = try s.addModule(entry.value_ptr.*);
852 }
853 }
854
855 wc.package_instances.items[index] = .{
856 .package = s.packageFromHash(b.pkg_hash),
857 .user_input_options = try wc.addDeduped(Configuration.PackageInstance.UserInputOption.List, .{
858 .options = .{ .slice = options },
859 }),
860 .modules = .{
861 .keys = try wc.addStringList(modules_keys),
862 .values = try wc.addDeduped(Configuration.Module.List, .{
863 .modules = .{ .slice = modules_values },
864 }),
865 },
866 };
867}
868
869fn makeUserValue(s: *Serialize, user_value: *const std.Build.UserValue) Allocator.Error!Configuration.PackageInstance.UserValue {
870 const arena = s.arena;
871 const wc = s.wc;
872
873 return switch (user_value.*) {
874 .flag => .flag,
875 .scalar => |str| .{ .scalar = try wc.addString(str) },
876 .list => |list| .{ .list = try wc.addStringList(list.items) },
877 .map => |map| add: {
878 const keys = try arena.alloc([]const u8, map.count());
879 const values = try arena.alloc(Configuration.PackageInstance.UserValue.Standalone.Index, map.count());
880
881 var i: usize = 0;
882 var iter = map.iterator();
883 while (iter.next()) |entry| : (i += 1) {
884 const value = try s.makeUserValue(entry.value_ptr.*);
885
886 keys[i] = entry.key_ptr.*;
887 values[i] = try wc.addDeduped(
888 Configuration.PackageInstance.UserValue.Standalone,
889 .{ .flags = .{ .tag = value }, .value = .{ .u = value } },
890 );
891 }
892
893 break :add .{ .map = try wc.addDeduped(
894 Configuration.PackageInstance.UserValue.Map,
895 .{
896 .keys = try wc.addStringList(keys),
897 .values = .{ .slice = values },
898 },
899 ) };
900 },
901 .lazy_path => |lp| .{ .lazy_path = try s.addLazyPath(lp) },
902 .lazy_path_list => |lp_list| add: {
903 const paths = try arena.alloc(Configuration.LazyPath.Index, lp_list.items.len);
904 for (paths, lp_list.items) |*dest, src| dest.* = try s.addLazyPath(src);
905 break :add .{ .lazy_path_list = .{ .slice = paths } };
906 },
907 };
908}
909
910fn packageInstanceFromBuilder(s: *Serialize, b: *std.Build) Configuration.PackageInstance.Index {
911 if (b.pkg_hash.len == 0) return .root;
912 return @fromBackingInt(@intCast(s.package_instance_map.getIndex(b).?));
788}913}
789914
790fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex {915fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex {
...@@ -793,7 +918,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio...@@ -793,7 +918,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio
793 .src_path => |src_path| i: {918 .src_path => |src_path| i: {
794 const sub_path = try wc.addString(src_path.sub_path);919 const sub_path = try wc.addString(src_path.sub_path);
795 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{920 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{
796 .owner = s.packageFromHash(src_path.owner.pkg_hash),921 .owner = s.packageInstanceFromBuilder(src_path.owner),
797 .sub_path = sub_path,922 .sub_path = sub_path,
798 });923 });
799 },924 },
...@@ -821,7 +946,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio...@@ -821,7 +946,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio
821 .dependency => |dependency| i: {946 .dependency => |dependency| i: {
822 const sub_path = try wc.addString(dependency.sub_path);947 const sub_path = try wc.addString(dependency.sub_path);
823 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{948 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{
824 .owner = s.packageFromHash(dependency.dependency.builder.pkg_hash),949 .owner = s.packageInstanceFromBuilder(dependency.dependency.builder),
825 .sub_path = sub_path,950 .sub_path = sub_path,
826 });951 });
827 },952 },
...@@ -1250,7 +1375,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {...@@ -1250,7 +1375,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
1250 const c_macros = try initStringList(s, m.c_macros.items);1375 const c_macros = try initStringList(s, m.c_macros.items);
1251 const export_symbol_names = try initStringList(s, m.export_symbol_names);1376 const export_symbol_names = try initStringList(s, m.export_symbol_names);
12521377
1253 const module_index: Configuration.Module.Index = try wc.addExtra(Configuration.Module, .{1378 const module_index: Configuration.Module.Index = try wc.addDeduped(Configuration.Module, .{
1254 .flags = .{1379 .flags = .{
1255 .optimize = .init(m.optimize),1380 .optimize = .init(m.optimize),
1256 .strip = .init(m.strip),1381 .strip = .init(m.strip),
...@@ -1281,7 +1406,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {...@@ -1281,7 +1406,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
1281 .link_libcpp = .init(m.link_libcpp),1406 .link_libcpp = .init(m.link_libcpp),
1282 .no_builtin = .init(m.no_builtin),1407 .no_builtin = .init(m.no_builtin),
1283 },1408 },
1284 .owner = s.packageFromHash(m.owner.pkg_hash),1409 .owner = s.packageInstanceFromBuilder(m.owner),
1285 .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),1410 .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),
1286 .import_table = .invalid,1411 .import_table = .invalid,
1287 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),1412 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),