authorgravatar for bblack@wikimedia.orgBrandon Black <bblack@wikimedia.org> 2026-05-29 13:14:49-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-18 04:31:03+02:00
log5ede6a167eef1835f6fb6c768a82d977269dafe5
tree63caa43d668a66ef5049921f67146127d93b9041
parentaeb55668ba2b23ffc99524ff28b25cec2b0fc356

Build.Step.Options: addOptionPathUntracked

This interface is like `addOptionPath`, but does not assume that the provided `LazyPath` represents a generated file, and does not set up any further dependencies on whatever the path represents. This supports use-cases like setting an `.install_prefix` -based default directory path option for the application to use as a fallback when the user does not provide an override. Example: options.addOptionPathUntracked( "DefaultConfigDir", b.graph.path( .install_prefix, b.pathJoin(&.{ "etc", "myapp" }), ), );

4 files changed, 50 insertions(+), 3 deletions(-)

lib/compiler/Maker/Step/Options.zig+14-2
...@@ -27,8 +27,11 @@ pub fn make(...@@ -27,8 +27,11 @@ pub fn make(
27 const contents = conf_options.contents.slice(conf);27 const contents = conf_options.contents.slice(conf);
2828
29 // This step operates under the assumption that all contents of the29 // This step operates under the assumption that all contents of the
30 // generated zig file are observable by dependant steps, as well as the30 // generated zig file are observable by dependant steps.
31 // contents of files added via Options.Arg.31 // Pathnames added to Options.args are assumed to be generated files whose
32 // contents are also observable, while pathnames added to
33 // Options.args_untracked are treated as pure path string data with no
34 // tracking of the path's state or contents.
3235
33 step.clearWatchInputs(maker);36 step.clearWatchInputs(maker);
3437
...@@ -48,6 +51,15 @@ pub fn make(...@@ -48,6 +51,15 @@ pub fn make(
48 });51 });
49 }52 }
5053
54 for (conf_options.args_untracked.slice) |arg| {
55 const name = arg.name.slice(conf);
56 const lazy_path = arg.path.get(conf);
57 const arg_path = try maker.resolveLazyPath(arena, lazy_path, step_index);
58 try args_bytes.print(arena, "pub const {f}: []const u8 = \"{f}\";\n", .{
59 std.zig.fmtId(name), arg_path.fmtEscapeString(),
60 });
61 }
62
51 man.hash.addBytes(contents);63 man.hash.addBytes(contents);
52 man.hash.addBytes(args_bytes.items);64 man.hash.addBytes(args_bytes.items);
5365
lib/std/Build/Configuration.zig+3-1
...@@ -1379,6 +1379,7 @@ pub const Step = extern struct {...@@ -1379,6 +1379,7 @@ pub const Step = extern struct {
1379 generated_file: GeneratedFileIndex,1379 generated_file: GeneratedFileIndex,
1380 contents: Bytes,1380 contents: Bytes,
1381 args: Storage.FlagLengthPrefixedList(.flags, .args, Arg),1381 args: Storage.FlagLengthPrefixedList(.flags, .args, Arg),
1382 args_untracked: Storage.FlagLengthPrefixedList(.flags, .args_untracked, Arg),
13821383
1383 pub const Arg = extern struct {1384 pub const Arg = extern struct {
1384 name: String,1385 name: String,
...@@ -1388,7 +1389,8 @@ pub const Step = extern struct {...@@ -1388,7 +1389,8 @@ pub const Step = extern struct {
1388 pub const Flags = packed struct(u32) {1389 pub const Flags = packed struct(u32) {
1389 tag: Tag = .options,1390 tag: Tag = .options,
1390 args: bool,1391 args: bool,
1391 _: u26 = 0,1392 args_untracked: bool,
1393 _: u25 = 0,
1392 };1394 };
1393 };1395 };
13941396
lib/std/Build/Serialize.zig+8
...@@ -654,13 +654,21 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi...@@ -654,13 +654,21 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
654 .path = try s.addLazyPath(src.path),654 .path = try s.addLazyPath(src.path),
655 };655 };
656656
657 const args_untracked = try arena.alloc(Configuration.Step.Options.Arg, so.args_untracked.items.len);
658 for (args_untracked, so.args_untracked.items) |*dest, src| dest.* = .{
659 .name = src.name,
660 .path = try s.addLazyPath(src.path),
661 };
662
657 break :e try wc.addExtraErased(Configuration.Step.Options, .{663 break :e try wc.addExtraErased(Configuration.Step.Options, .{
658 .flags = .{664 .flags = .{
659 .args = so.args.items.len != 0,665 .args = so.args.items.len != 0,
666 .args_untracked = so.args_untracked.items.len != 0,
660 },667 },
661 .generated_file = so.generated_file,668 .generated_file = so.generated_file,
662 .contents = try wc.addBytes(so.contents.items),669 .contents = try wc.addBytes(so.contents.items),
663 .args = .{ .slice = args },670 .args = .{ .slice = args },
671 .args_untracked = .{ .slice = args_untracked },
664 });672 });
665 },673 },
666 })),674 })),
lib/std/Build/Step/Options.zig+25
...@@ -13,6 +13,7 @@ step: Step,...@@ -13,6 +13,7 @@ step: Step,
13generated_file: Configuration.GeneratedFileIndex,13generated_file: Configuration.GeneratedFileIndex,
14contents: std.ArrayList(u8) = .empty,14contents: std.ArrayList(u8) = .empty,
15args: std.ArrayList(Arg) = .empty,15args: std.ArrayList(Arg) = .empty,
16args_untracked: std.ArrayList(Arg) = .empty,
16encountered_types: std.StringHashMapUnmanaged(void),17encountered_types: std.StringHashMapUnmanaged(void),
1718
18pub const base_tag: Step.Tag = .options;19pub const base_tag: Step.Tag = .options;
...@@ -421,6 +422,11 @@ fn printStructValue(...@@ -421,6 +422,11 @@ fn printStructValue(
421}422}
422423
423/// The added option has type `[]const u8` and value of the provided path.424/// The added option has type `[]const u8` and value of the provided path.
425/// This interface assumes the provided path is a generated file, and causes a
426/// transitive dependency through Options on the file's contents.
427///
428/// See also:
429/// * `addOptionPathUntracked`
424pub fn addOptionPath(options: *Options, name: []const u8, path: LazyPath) void {430pub fn addOptionPath(options: *Options, name: []const u8, path: LazyPath) void {
425 const graph = options.step.owner.graph;431 const graph = options.step.owner.graph;
426 const arena = graph.arena;432 const arena = graph.arena;
...@@ -433,6 +439,25 @@ pub fn addOptionPath(options: *Options, name: []const u8, path: LazyPath) void {...@@ -433,6 +439,25 @@ pub fn addOptionPath(options: *Options, name: []const u8, path: LazyPath) void {
433 path.addStepDependencies(&options.step);439 path.addStepDependencies(&options.step);
434}440}
435441
442/// The added option has type `[]const u8` and value of the provided path.
443/// This interface treats the resolved path string as pure data, meaning it
444/// does not track anything about the meaning or contents of this path, and
445/// therefore also does not create any related dependencies.
446///
447/// See also:
448/// * `addOptionPath`
449pub fn addOptionPathUntracked(options: *Options, name: []const u8, path: LazyPath) void {
450 const graph = options.step.owner.graph;
451 const arena = graph.arena;
452 const wc = &graph.wip_configuration;
453
454 options.args_untracked.append(arena, .{
455 .name = wc.addString(name) catch @panic("OOM"),
456 .path = path.dupe(options.step.owner.graph),
457 }) catch @panic("OOM");
458 path.addStepDependencies(&options.step);
459}
460
436pub fn createModule(options: *Options) *std.Build.Module {461pub fn createModule(options: *Options) *std.Build.Module {
437 return options.step.owner.createModule(.{462 return options.step.owner.createModule(.{
438 .root_source_file = options.getOutput(),463 .root_source_file = options.getOutput(),