authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-30 11:39:28-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:35-07:00
log0d95b44a1c9e483beb82f7b70515185159d79bdc
treee9755eaff750cefd0d9ba388f3d59cf130f437c3
parenta23050bf733793c40428bb77a8cd08bd1781306e

build system: implement cli positionals


6 files changed, 69 insertions(+), 27 deletions(-)

BRANCH_TODO+23-10
......@@ -1,21 +1,21 @@
1* make more stuff use IndexType
2* make addExtra return Index using reflection
31* remove Cache from configurer
42* implement the build options
5* get zig init template working
63* finish migrating the rest of the build steps
4* inspect b4ffb402c082605c4b324e88120306fc8fb3cf32 diff and apply changes as needed (merge conflict)
75* make zig-pkg path root configurable in maker (make sure --system still works)
86* eliminate calls to getPath, getPath2, getPath3
7* [build system compile step data races with getGraph function](https://codeberg.org/ziglang/zig/issues/31397)
98* solve the TODOs added in this branch
109* get zig tests passing
1110* test a bunch of third party projects / help people migrate
12* refactor with DefaultingEnum
13* inspect b4ffb402c082605c4b324e88120306fc8fb3cf32 diff and apply changes as needed (merge conflict)
14* https://codeberg.org/ziglang/zig/issues/31397
15* restore the generated_compiler_rt_dyn_lib hack?
16* run args
17* https://codeberg.org/ziglang/zig/pulls/30762
11
1812* get the target from the parent process instead
13* [handle missing cache hits when chaining two run steps](https://codeberg.org/ziglang/zig/pulls/30762)
14* [Absolute and cwd-relative paths in build cache](https://codeberg.org/ziglang/zig/issues/32097)
15
16* make more stuff use IndexType
17* make addExtra return Index using reflection
18* refactor with DefaultingEnum
1919
2020## Followup Issues
2121* reduce the size of Maker.Step.Extended (make Run smaller) probably by using an arena per make
......@@ -28,4 +28,17 @@
2828
2929
3030## Release Notes
31* run args are all together now, not observable in configure phase whether run args are provided
31
32run args are all together now, not observable in configure phase whether run args are provided.
33
34```zig
35if (b.args) |args| {
36 run_cmd.addArgs(args);
37}
38```
39
40⬇️
41
42```zig
43run_cmd.addBuildPositionals();
44```
lib/compiler/Maker/Step/Run.zig+13-10
......@@ -72,6 +72,7 @@ pub fn make(
7272
7373 var any_dep_files = false;
7474 var any_output_args = false;
75 var any_cli_positionals = false;
7576
7677 for (conf_run.args.slice) |arg_index| {
7778 const arg = arg_index.get(conf);
......@@ -176,10 +177,11 @@ pub fn make(
176177 });
177178 argv_list.items.len += 1;
178179 },
179 .cli_rest_positionals => {
180 .cli_positionals => {
181 any_cli_positionals = true;
180182 if (maker.run_args) |run_args| {
181183 try argv_list.appendSlice(gpa, run_args);
182 for (run_args) |s| man.hash.addBytes(s);
184 man.hash.addListOfBytes(run_args);
183185 }
184186 },
185187 }
......@@ -236,13 +238,14 @@ pub fn make(
236238 }
237239
238240 // Whether the Run step has side effects *other than* updating the output arguments.
239 const has_side_effects = conf_run.flags.has_side_effects or switch (conf_run.flags.stdio) {
240 .infer_from_args => !any_output_args and
241 conf_run.captured_stdout.value == null and
242 conf_run.captured_stderr.value == null,
243 .inherit => true,
244 .check, .zig_test => false,
245 };
241 const has_side_effects = conf_run.flags.has_side_effects or any_cli_positionals or
242 switch (conf_run.flags.stdio) {
243 .infer_from_args => !any_output_args and
244 conf_run.captured_stdout.value == null and
245 conf_run.captured_stderr.value == null,
246 .inherit => true,
247 .check, .zig_test => false,
248 };
246249
247250 if (!has_side_effects and try step.cacheHitAndWatch(maker, &man)) {
248251 // Cache hit; skip running command.
......@@ -1596,7 +1599,7 @@ pub fn rerunInFuzzMode(
15961599 },
15971600 .output_file => unreachable,
15981601 .output_directory => unreachable,
1599 .cli_rest_positionals => unreachable,
1602 .cli_positionals => unreachable,
16001603 }
16011604 }
16021605
lib/compiler/configurer.zig+2-2
......@@ -492,9 +492,9 @@ const Serialize = struct {
492492 .producer = .{ .value = null },
493493 .generated = .{ .value = a.generated_file },
494494 },
495 .cli_rest_positionals => .{
495 .cli_positionals => .{
496496 .flags = .{
497 .tag = .cli_rest_positionals,
497 .tag = .cli_positionals,
498498 .prefix = false,
499499 .suffix = false,
500500 .basename = false,
lib/init/build.zig+1-3
......@@ -111,9 +111,7 @@ pub fn build(b: *std.Build) void {
111111
112112 // This allows the user to pass arguments to the application in the build
113113 // command itself, like this: `zig build run -- arg1 arg2 etc`
114 if (b.args) |args| {
115 run_cmd.addArgs(args);
116 }
114 run_cmd.addCliPositionals();
117115
118116 // Creates an executable that will run `test` blocks from the provided module.
119117 // Here `mod` needs to define a target, which is why earlier we made sure to
lib/std/Build/Configuration.zig+1-1
......@@ -567,7 +567,7 @@ pub const Step = extern struct {
567567 file_content,
568568 output_file,
569569 output_directory,
570 cli_rest_positionals,
570 cli_positionals,
571571 };
572572
573573 pub const Index = IndexType(@This());
lib/std/Build/Step/Run.zig+29-1
......@@ -142,7 +142,7 @@ pub const Arg = union(enum) {
142142 output_file_dep: *Output,
143143 output_directory: *Output,
144144 /// The arguments passed after "--" on the "zig build" CLI.
145 cli_rest_positionals,
145 cli_positionals,
146146};
147147
148148pub const PrefixedArtifact = struct {
......@@ -491,16 +491,44 @@ pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []co
491491 return .{ .generated = .{ .index = dep_file.generated_file } };
492492}
493493
494/// Appends the contents of `arg`, verbatim, to the command line that will be
495/// passed to the process being run.
496///
497/// If `arg` is an input file, `addFileInput` (or related function) must be
498/// used instead to ensure correct cache behavior.
499///
500/// If `arg` is an output file, `addOutputFileArg` (or related function) must
501/// be used instead to ensure correct cache behavior.
494502pub fn addArg(run: *Run, arg: []const u8) void {
495503 const graph = run.step.owner.graph;
496504 const arena = graph.arena;
497505 run.argv.append(arena, .{ .bytes = graph.dupeString(arg) }) catch @panic("OOM");
498506}
499507
508/// Appends each of `args`, verbatim, to the command line that will be passed
509/// to the process being run.
510///
511/// If any element of `args` is an input file, `addFileInput` must be used
512/// instead to ensure correct cache behavior.
513///
514/// If any element of `args` is an output file, `addOutputFileArg` (or related
515/// function) must be used instead to ensure correct cache behavior.
500516pub fn addArgs(run: *Run, args: []const []const u8) void {
501517 for (args) |arg| run.addArg(arg);
502518}
503519
520/// Any extra positional args are provided to the `zig build` command, they are
521/// appended here. This causes the step to be considered to have side effects,
522/// disabling caching.
523///
524/// In the example command `zig build run -- arg1 arg2`, "arg1" and "arg2" will
525/// be passed to the process being run.
526pub fn addCliPositionals(run: *Run) void {
527 const graph = run.step.owner.graph;
528 const arena = graph.arena;
529 run.argv.append(arena, .cli_positionals) catch @panic("OOM");
530}
531
504532pub fn setStdIn(run: *Run, stdin: StdIn) void {
505533 switch (stdin) {
506534 .lazy_path => |lazy_path| lazy_path.addStepDependencies(&run.step),