authorgravatar for hemisputnik@proton.mehemisputnik <hemisputnik@proton.me> 2026-08-05 06:50:26+03:00
committergravatar for hemisputnik@proton.mehemisputnik <hemisputnik@proton.me> 2026-08-08 09:02:31+03:00
log0f332fd536aee4fcff4d0875d1d7136ba5b6f01b
treeca6c0c7fb119087c1604477a3a35e033636f7b01
parent800fc5d25a5ed386910dc36c81ae200a19a1d01b
signaturebadge-check Signed by SSH key SHA256:iUK/EffQPyeXTXChJNV0UrxsscinNLxnk+0pu4OGU7Q

std.Build.Configuration: serialize packages and their dependencies

The serializer now traverses the builder's available_deps and their dependencies recursively, and serializes them into Configuration.packages.

5 files changed, 136 insertions(+), 33 deletions(-)

lib/compiler/Maker.zig+5-3
......@@ -3312,17 +3312,19 @@ pub fn packagePath(
33123312) Allocator.Error!Path {
33133313 const c = &maker.scanned_config.configuration;
33143314 const graph = maker.graph;
3315 const package = package_index.get(c) orelse return .{
3315
3316 if (package_index == .root) return .{
33163317 .root_dir = graph.build_root_directory,
33173318 .sub_path = sub_path,
33183319 };
3320
33193321 // Currently, neither configurer nor Maker is aware of the standard zig
33203322 // package path, and the root path is stored as a bare string rather than
33213323 // relative to a known base directory. Without changing that, we must
33223324 // construct a cwd relative path here.
33233325 return .{
33243326 .root_dir = .cwd(),
3325 .sub_path = try Dir.path.join(arena, &.{ package.root_path.slice(c), sub_path }),
3327 .sub_path = try Dir.path.join(arena, &.{ package_index.ptr(c).root_path.slice(c), sub_path }),
33263328 };
33273329}
33283330
......@@ -3952,7 +3954,7 @@ fn confPathDepToCachePath(
39523954 .root_dir = graph.build_root_directory,
39533955 .sub_path = switch (path_dep.pkg.unwrap().?) {
39543956 .root => sub_path,
3955 else => |index| try Dir.path.join(arena, &.{ index.get(c).?.root_path.slice(c), sub_path }),
3957 else => |index| try Dir.path.join(arena, &.{ index.ptr(c).root_path.slice(c), sub_path }),
39563958 },
39573959 },
39583960 .zig_lib => .{
lib/compiler/Maker/ScannedConfig.zig+21
......@@ -83,6 +83,27 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
8383 try tf.end();
8484 }
8585
86 {
87 var tf = try s.beginTupleField("packages", .{});
88 for (c.packages) |package| {
89 var sf = try tf.beginStructField(.{});
90 try sf.field("dep_prefix", package.dep_prefix.slice(c), .{});
91 try sf.field("hash", package.hash.slice(c), .{});
92 try sf.field("root_path", package.root_path.slice(c), .{});
93
94 var dtf = try sf.beginTupleField("deps", .{});
95 for (package.deps.slice(c)) |dep| {
96 var dsf = try dtf.beginStructField(.{});
97 try sc.printStruct(&dsf, Configuration.Package.Dep, dep);
98 try dsf.end();
99 }
100 try dtf.end();
101
102 try sf.end();
103 }
104 try tf.end();
105 }
106
86107 try s.end();
87108}
88109
lib/std/Build.zig+3-2
......@@ -2160,7 +2160,7 @@ pub fn dependencyLazy(b: *Build, name: []const u8, args: anytype) error{LazyDepe
21602160 return dependencyResolved(b, name, entry, userInputOptionsFromArgs(b.graph.arena, args));
21612161}
21622162
2163const PackageEntry = struct {
2163pub const PackageEntry = struct {
21642164 hash: []const u8,
21652165 available: bool,
21662166 build_root: []const u8,
......@@ -2168,7 +2168,8 @@ const PackageEntry = struct {
21682168 run_build: ?*const fn (*Build) void,
21692169};
21702170
2171const package_map: std.StaticStringMap(PackageEntry) = blk: {
2171/// Build system implementation detail.
2172pub const package_map: std.StaticStringMap(PackageEntry) = blk: {
21722173 const deps = @import("root").dependencies;
21732174 const decl_names = @typeInfo(deps.packages).@"struct".decl_names;
21742175 var kvs: [decl_names.len]struct { []const u8, PackageEntry } = undefined;
lib/std/Build/Configuration.zig+39-10
......@@ -15,6 +15,8 @@ unlazy_deps: []String,
1515system_integrations: []SystemIntegration,
1616available_options: []AvailableOption,
1717search_prefixes: []String,
18/// Index 0 always exists and is the root package.
19packages: []Package,
1820extra: []u32,
1921default_step: Step.Index,
2022generated_files_len: u32,
......@@ -30,6 +32,7 @@ pub const Header = extern struct {
3032 system_integrations_len: u32,
3133 available_options_len: u32,
3234 search_prefixes_len: u32,
35 packages_len: u32,
3336 extra_len: u32,
3437
3538 default_step: Step.Index,
......@@ -58,6 +61,7 @@ pub const Wip = struct {
5861 steps: std.ArrayList(Step) = .empty,
5962 path_deps: std.ArrayList(PathDep) = .empty,
6063 search_prefixes: std.ArrayList(String) = .empty,
64 packages: std.ArrayList(Package) = .empty,
6165 extra: std.ArrayList(u32) = .empty,
6266 next_generated_file_index: u32 = 0,
6367 cache_poison: bool = false,
......@@ -139,6 +143,7 @@ pub const Wip = struct {
139143 wip.steps.deinit(gpa);
140144 wip.path_deps.deinit(gpa);
141145 wip.search_prefixes.deinit(gpa);
146 wip.packages.deinit(gpa);
142147 wip.extra.deinit(gpa);
143148 wip.* = undefined;
144149 }
......@@ -158,6 +163,7 @@ pub const Wip = struct {
158163 .system_integrations_len = @intCast(wip.system_integrations.items.len),
159164 .available_options_len = @intCast(wip.available_options.items.len),
160165 .search_prefixes_len = @intCast(wip.search_prefixes.items.len),
166 .packages_len = @intCast(wip.packages.items.len),
161167 .extra_len = @intCast(wip.extra.items.len),
162168
163169 .default_step = static.default_step,
......@@ -175,6 +181,7 @@ pub const Wip = struct {
175181 @ptrCast(wip.system_integrations.items),
176182 @ptrCast(wip.available_options.items),
177183 @ptrCast(wip.search_prefixes.items),
184 @ptrCast(wip.packages.items),
178185 @ptrCast(wip.extra.items),
179186 };
180187 try w.writeVecAll(&buffers);
......@@ -1596,30 +1603,28 @@ pub const OptionalGeneratedFileIndex = enum(u32) {
15961603 }
15971604};
15981605
1599pub const Package = struct {
1606pub const Package = extern struct {
16001607 dep_prefix: String,
16011608 hash: String,
16021609 root_path: String,
1610 deps: Dep.List.Index,
16031611
16041612 pub const Index = enum(u32) {
1605 root = max_u32,
1613 root,
16061614 _,
16071615
1608 /// Returns `null` for root package.
1609 pub fn get(i: @This(), c: *const Configuration) ?Package {
1610 if (i == .root) return null;
1611 return extraData(c, Package, @backingInt(i));
1616 pub fn ptr(i: @This(), c: *const Configuration) *const Package {
1617 return &c.packages[@backingInt(i)];
16121618 }
16131619
16141620 pub fn depPrefixSlice(i: @This(), c: *const Configuration) [:0]const u8 {
1615 const package = get(i, c) orelse return "";
1616 return package.dep_prefix.slice(c);
1621 return ptr(i, c).dep_prefix.slice(c);
16171622 }
16181623 };
16191624
16201625 pub const OptionalIndex = enum(u32) {
1621 none = max_u32 - 1,
1622 root = max_u32,
1626 root,
1627 none = max_u32,
16231628 _,
16241629
16251630 pub fn init(i: Index) OptionalIndex {
......@@ -1636,6 +1641,28 @@ pub const Package = struct {
16361641 };
16371642 }
16381643 };
1644
1645 pub const Dep = extern struct {
1646 name: String,
1647 /// Must not be `.root`.
1648 package: Package.Index,
1649
1650 pub const List = struct {
1651 deps: Storage.LengthPrefixedList(Dep),
1652
1653 pub const Index = enum(u32) {
1654 _,
1655
1656 pub fn get(this: @This(), c: *const Configuration) List {
1657 return extraData(c, List, @backingInt(this));
1658 }
1659
1660 pub fn slice(this: @This(), c: *const Configuration) []const Dep {
1661 return get(this, c).deps.slice;
1662 }
1663 };
1664 };
1665 };
16391666};
16401667
16411668pub const Module = struct {
......@@ -3170,6 +3197,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
31703197 .system_integrations = try arena.alloc(SystemIntegration, header.system_integrations_len),
31713198 .available_options = try arena.alloc(AvailableOption, header.available_options_len),
31723199 .search_prefixes = try arena.alloc(String, header.search_prefixes_len),
3200 .packages = try arena.alloc(Package, header.packages_len),
31733201 .extra = try arena.alloc(u32, header.extra_len),
31743202 .default_step = header.default_step,
31753203 .generated_files_len = header.generated_files_len,
......@@ -3183,6 +3211,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
31833211 @ptrCast(result.system_integrations),
31843212 @ptrCast(result.available_options),
31853213 @ptrCast(result.search_prefixes),
3214 @ptrCast(result.packages),
31863215 @ptrCast(result.extra),
31873216 };
31883217 try reader.readVecAll(&vecs);
lib/std/Build/Serialize.zig+68-18
......@@ -10,7 +10,8 @@ const log = std.log;
1010arena: Allocator,
1111wc: *Configuration.Wip,
1212module_map: std.array_hash_map.Auto(*std.Build.Module, Configuration.Module.Index) = .empty,
13package_map: std.array_hash_map.Auto(*std.Build, Configuration.Package.Index) = .empty,
13/// Keyed by package hash.
14package_map: std.array_hash_map.String(Configuration.Package.Index) = .empty,
1415/// Index corresponds to `Configuration.steps` index.
1516step_map: std.array_hash_map.Auto(*Step, void) = .empty,
1617
......@@ -21,6 +22,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
2122
2223 var s: Serialize = .{ .wc = wc, .arena = arena };
2324
25 // Serialize all of the packages first to seed the package_map, which is
26 // later used in calls to packageFromHash.
27 try s.addRootPackage(b);
28
2429 try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len);
2530 for (
2631 graph.configure_dependencies.items,
......@@ -44,10 +49,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
4449 .relative => |r| try wc.addString(r.sub_path),
4550 },
4651 .pkg = switch (src.lazy_path) {
47 .src_path => |sp| .init(try s.builderToPackage(sp.owner)),
52 .src_path => |sp| .init(s.packageFromHash(sp.owner.pkg_hash)),
4853 .generated => unreachable,
4954 .cwd_relative, .relative => .none,
50 .dependency => |d| .init(try s.builderToPackage(d.dependency.builder)),
55 .dependency => |d| .init(s.packageFromHash(d.dependency.builder.pkg_hash)),
5156 },
5257 };
5358 }
......@@ -84,7 +89,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
8489 try wc.steps.ensureTotalCapacity(gpa, s.step_map.entries.capacity);
8590 wc.steps.appendAssumeCapacity(.{
8691 .name = try wc.addString(step.name),
87 .owner = try s.builderToPackage(step.owner),
92 .owner = s.packageFromHash(step.owner.pkg_hash),
8893 .deps = deps,
8994 .max_rss = .fromBytes(step.max_rss),
9095 .extended = @fromBackingInt(@intCast(switch (step.tag) {
......@@ -724,19 +729,64 @@ pub fn packageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!voi
724729 }
725730}
726731
727fn builderToPackage(s: *Serialize, b: *std.Build) !Configuration.Package.Index {
728 if (b.pkg_hash.len == 0) return .root;
732fn addRootPackage(s: *Serialize, b: *std.Build) Allocator.Error!void {
729733 const arena = s.arena;
730734 const wc = s.wc;
731 const gop = try s.package_map.getOrPut(arena, b);
732 if (!gop.found_existing) {
733 gop.value_ptr.* = try wc.addExtra(Configuration.Package, .{
734 .hash = try wc.addString(b.pkg_hash),
735 .dep_prefix = try wc.addString(b.dep_prefix),
736 .root_path = try wc.addString(try b.root.toString(arena)),
737 });
738 }
739 return gop.value_ptr.*;
735
736 try wc.packages.append(wc.gpa, .{
737 .dep_prefix = .empty,
738 .hash = .empty,
739 .root_path = try wc.addString(try b.root.toString(arena)),
740 .deps = undefined,
741 });
742
743 const deps = try arena.alloc(Configuration.Package.Dep, b.available_deps.len);
744 for (deps, b.available_deps) |*dest, src| dest.* = try s.makePackageDep("", src[0], src[1]);
745
746 wc.packages.items[0].deps = try wc.addExtra(Configuration.Package.Dep.List, .{
747 .deps = .{ .slice = deps },
748 });
749}
750
751fn makePackageDep(s: *Serialize, parent_dep_prefix: []const u8, name: []const u8, hash: []const u8) Allocator.Error!Configuration.Package.Dep {
752 const arena = s.arena;
753 const wc = s.wc;
754
755 if (s.package_map.get(hash)) |index| return .{
756 .name = try wc.addString(name),
757 .package = index,
758 };
759
760 const entry = std.Build.package_map.get(hash) orelse unreachable;
761
762 const dep_prefix = try arena.print("{s}{s}.", .{ parent_dep_prefix, name });
763
764 const index: Configuration.Package.Index = @fromBackingInt(@intCast(wc.packages.items.len));
765 try s.package_map.put(arena, hash, index);
766
767 try wc.packages.append(wc.gpa, .{
768 .dep_prefix = try wc.addString(dep_prefix),
769 .hash = try wc.addString(hash),
770 .root_path = try wc.addString(entry.build_root),
771 .deps = undefined,
772 });
773
774 const deps = try arena.alloc(Configuration.Package.Dep, entry.deps.len);
775 for (deps, entry.deps) |*dest, src| dest.* = try s.makePackageDep(dep_prefix, src[0], src[1]);
776
777 wc.packages.items[@backingInt(index)].deps = try wc.addExtra(Configuration.Package.Dep.List, .{
778 .deps = .{ .slice = deps },
779 });
780
781 return .{
782 .name = try wc.addString(name),
783 .package = index,
784 };
785}
786
787fn packageFromHash(s: *Serialize, pkg_hash: []const u8) Configuration.Package.Index {
788 if (pkg_hash.len == 0) return .root;
789 return s.package_map.get(pkg_hash) orelse std.debug.panic("unrecognized package hash: {q}", .{pkg_hash});
740790}
741791
742792fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex {
......@@ -745,7 +795,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio
745795 .src_path => |src_path| i: {
746796 const sub_path = try wc.addString(src_path.sub_path);
747797 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{
748 .owner = try s.builderToPackage(src_path.owner),
798 .owner = s.packageFromHash(src_path.owner.pkg_hash),
749799 .sub_path = sub_path,
750800 });
751801 },
......@@ -773,7 +823,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio
773823 .dependency => |dependency| i: {
774824 const sub_path = try wc.addString(dependency.sub_path);
775825 break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{
776 .owner = try s.builderToPackage(dependency.dependency.builder),
826 .owner = s.packageFromHash(dependency.dependency.builder.pkg_hash),
777827 .sub_path = sub_path,
778828 });
779829 },
......@@ -1138,7 +1188,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
11381188 .link_libcpp = .init(m.link_libcpp),
11391189 .no_builtin = .init(m.no_builtin),
11401190 },
1141 .owner = try s.builderToPackage(m.owner),
1191 .owner = s.packageFromHash(m.owner.pkg_hash),
11421192 .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),
11431193 .import_table = .invalid,
11441194 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),