From bd4c1e34d28bb7ab88ada31bb0fa01fda6e4b201 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 9 May 2026 19:30:08 -0700 Subject: [PATCH] configurer: add search_prefixes back It is generally best practice to avoid calling this function, instead relying on the user to provide these paths via the standard build system interface. However, when integrating with other build systems, the user may have already provided the information to the other build system, and thus it is desirable to use that same information without requiring the user to provide it again. --- BRANCH_TODO | 23 +++++++++++++++++++++++ lib/compiler/Maker.zig | 3 +++ lib/compiler/Maker/ScannedConfig.zig | 6 ++++++ lib/std/Build.zig | 24 +++++++++++++++--------- lib/std/Build/Configuration.zig | 8 ++++++++ 5 files changed, 55 insertions(+), 9 deletions(-) diff --git a/BRANCH_TODO b/BRANCH_TODO index b54140d4a0..ffc063b7cc 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -77,3 +77,26 @@ closes #31397 * `b.build_root` (Directory) -> `b.root` (Path) * `ConfigHeader.Options`: `include_guard_override` -> `include_guard` + +### Perf Data Point: `zig build -h` (cached) + +``` +Benchmark 1 (34 runs): master/zig build -h + measurement mean ± σ min … max outliers delta + wall_time 150ms ± 5.52ms 145ms … 165ms 4 (12%) 0% + peak_rss 84.8MB ± 275KB 84.2MB … 85.1MB 0 ( 0%) 0% + cpu_cycles 593M ± 4.01M 588M … 608M 2 ( 6%) 0% + instructions 995M ± 52.5K 995M … 995M 0 ( 0%) 0% + cache_references 25.8M ± 165K 25.4M … 26.1M 0 ( 0%) 0% + cache_misses 651K ± 20.1K 619K … 697K 0 ( 0%) 0% + branch_misses 918K ± 7.44K 906K … 935K 0 ( 0%) 0% +Benchmark 2 (348 runs): branch/zig build -h + measurement mean ± σ min … max outliers delta + wall_time 14.3ms ± 744us 13.2ms … 23.3ms 8 ( 2%) ⚡- 90.4% ± 0.4% + peak_rss 78.5MB ± 562KB 77.1MB … 81.4MB 7 ( 2%) ⚡- 7.4% ± 0.2% + cpu_cycles 24.1M ± 821K 22.8M … 27.1M 3 ( 1%) ⚡- 95.9% ± 0.1% + instructions 43.7M ± 23.8K 43.7M … 43.8M 56 (16%) ⚡- 95.6% ± 0.0% + cache_references 1.46M ± 14.6K 1.40M … 1.50M 19 ( 5%) ⚡- 94.3% ± 0.1% + cache_misses 142K ± 4.87K 127K … 157K 2 ( 1%) ⚡- 78.1% ± 0.4% + branch_misses 126K ± 1.37K 120K … 129K 12 ( 3%) ⚡- 86.3% ± 0.1% +``` diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig index 48a7cf785d..d443a6ae4d 100644 --- a/lib/compiler/Maker.zig +++ b/lib/compiler/Maker.zig @@ -446,6 +446,9 @@ pub fn main(init: process.Init.Minimal) !void { else => {}, } } + for (c.search_prefixes) |search_prefix| { + try graph.search_prefixes.append(arena, search_prefix.slice(c)); + } break :sc .{ .configuration = configuration, .top_level_steps = top_level_steps, diff --git a/lib/compiler/Maker/ScannedConfig.zig b/lib/compiler/Maker/ScannedConfig.zig index 7fc7cc9608..5bb3a9871f 100644 --- a/lib/compiler/Maker/ScannedConfig.zig +++ b/lib/compiler/Maker/ScannedConfig.zig @@ -20,6 +20,12 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void { var serializer: Serializer = .{ .writer = w }; var s = try serializer.beginStruct(.{}); + { + var tf = try s.beginTupleField("search_prefixes", .{}); + for (c.search_prefixes) |string| try tf.field(string.slice(c), .{}); + try tf.end(); + } + try s.field("default_step", @intFromEnum(c.default_step), .{}); { var sf = try s.beginStructField("top_level_steps", .{}); diff --git a/lib/std/Build.zig b/lib/std/Build.zig index b5eeefa171..ad87bc2466 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -295,12 +295,12 @@ fn createChild( pkg_deps: AvailableDeps, user_input_options: UserInputOptionsMap, ) error{OutOfMemory}!*Build { - const allocator = parent.allocator; - const child = try allocator.create(Build); + const arena = parent.graph.arena; + const child = try arena.create(Build); child.* = .{ .graph = parent.graph, .root = root, - .allocator = allocator, + .allocator = arena, .install_tls = .{ .step = .init(.{ .tag = .top_level, @@ -334,8 +334,8 @@ fn createChild( .pkg_hash = pkg_hash, .available_deps = pkg_deps, }; - try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls); - try child.top_level_steps.put(allocator, child.uninstall_tls.step.name, &child.uninstall_tls); + try child.top_level_steps.put(arena, child.install_tls.step.name, &child.install_tls); + try child.top_level_steps.put(arena, child.uninstall_tls.step.name, &child.uninstall_tls); child.default_step = &child.install_tls.step; return child; } @@ -1773,10 +1773,16 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 { /// it is desirable to use that same information without requiring the user to /// provide it again. pub fn addSearchPrefix(b: *Build, search_prefix: []const u8) void { - _ = b; - _ = search_prefix; - @panic("TODO"); - //b.search_prefixes.append(b.allocator, b.dupePath(search_prefix)) catch @panic("OOM"); + if (b.isRoot()) { + const graph = b.graph; + const wc = &graph.wip_configuration; + const string = wc.addString(search_prefix) catch @panic("OOM"); + wc.search_prefixes.append(wc.gpa, string) catch @panic("OOM"); + } +} + +pub fn isRoot(b: *const Build) bool { + return b.pkg_hash.len == 0; } pub const Dependency = struct { diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig index b08fb39543..c008dcc90f 100644 --- a/lib/std/Build/Configuration.zig +++ b/lib/std/Build/Configuration.zig @@ -13,6 +13,7 @@ path_deps_sub: []String, unlazy_deps: []String, system_integrations: []SystemIntegration, available_options: []AvailableOption, +search_prefixes: []String, extra: []u32, default_step: Step.Index, generated_files_len: u32, @@ -26,6 +27,7 @@ pub const Header = extern struct { unlazy_deps_len: u32, system_integrations_len: u32, available_options_len: u32, + search_prefixes_len: u32, extra_len: u32, default_step: Step.Index, @@ -47,6 +49,7 @@ pub const Wip = struct { available_options: std.ArrayList(AvailableOption) = .empty, steps: std.ArrayList(Step) = .empty, path_deps: std.MultiArrayList(Path) = .empty, + search_prefixes: std.ArrayList(String) = .empty, extra: std.ArrayList(u32) = .empty, next_generated_file_index: u32 = 0, @@ -126,6 +129,7 @@ pub const Wip = struct { wip.available_options.deinit(gpa); wip.steps.deinit(gpa); wip.path_deps.deinit(gpa); + wip.search_prefixes.deinit(gpa); wip.extra.deinit(gpa); wip.* = undefined; } @@ -143,6 +147,7 @@ pub const Wip = struct { .unlazy_deps_len = @intCast(wip.unlazy_deps.items.len), .system_integrations_len = @intCast(wip.system_integrations.items.len), .available_options_len = @intCast(wip.available_options.items.len), + .search_prefixes_len = @intCast(wip.search_prefixes.items.len), .extra_len = @intCast(wip.extra.items.len), .default_step = static.default_step, @@ -157,6 +162,7 @@ pub const Wip = struct { @ptrCast(wip.unlazy_deps.items), @ptrCast(wip.system_integrations.items), @ptrCast(wip.available_options.items), + @ptrCast(wip.search_prefixes.items), @ptrCast(wip.extra.items), }; try w.writeVecAll(&buffers); @@ -3017,6 +3023,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration { .unlazy_deps = try arena.alloc(String, header.unlazy_deps_len), .system_integrations = try arena.alloc(SystemIntegration, header.system_integrations_len), .available_options = try arena.alloc(AvailableOption, header.available_options_len), + .search_prefixes = try arena.alloc(String, header.search_prefixes_len), .extra = try arena.alloc(u32, header.extra_len), .default_step = header.default_step, .generated_files_len = header.generated_files_len, @@ -3029,6 +3036,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration { @ptrCast(result.unlazy_deps), @ptrCast(result.system_integrations), @ptrCast(result.available_options), + @ptrCast(result.search_prefixes), @ptrCast(result.extra), }; try reader.readVecAll(&vecs);