zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 642d017fea531d1347b8ade16c33065389a20192 (tree)
parent 9b6dd7ee5c4137942f7fbbdd27d8e06f6ce7c7b1
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Sat, 23 May 2026 15:34:31 -0700

Maker: fix resolveLazyPath accidental mutation

Diffstat:
Mlib/compiler/Maker.zig | 6++++--
Mlib/std/Build/Step/Run.zig | 26++++++++++++++++----------
Mtest/standalone/dirname/build.zig | 16++++++----------
Mtest/standalone/dirname/touch.zig | 19+++++++++----------
4 files changed, 35 insertions(+), 32 deletions(-)

diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig @@ -1708,12 +1708,14 @@ pub fn resolveLazyPath( .source_path => |sp| try packagePath(maker, arena, sp.owner, sp.sub_path.slice(c)), .relative => |relative| relativePath(maker, relative), .generated => |gen| { - const base = generatedPath(maker, gen.index); + const base = generatedPath(maker, gen.index).*; var file_path = base; for (0..gen.flags.up) |_| { file_path.sub_path = Dir.path.dirname(file_path.sub_path) orelse { const s = stepByIndex(maker, asking_step_index); - return s.fail(maker, "invalid LazyPath traversal: up {d} times from {f}", .{ gen.flags.up, base }); + return s.fail(maker, "invalid LazyPath traversal: up {d} times from {f}", .{ + gen.flags.up, base, + }); }; } return file_path.join(arena, gen.sub_path.slice(c)); diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig @@ -242,21 +242,23 @@ pub fn addPrefixedArtifactArg(run: *Run, prefix: []const u8, artifact: *Step.Com /// Returns a `std.Build.LazyPath` which can be used as inputs to other APIs /// throughout the build system. /// +/// `sub_path` is the name of the generated output file which may have zero or +/// more path components. +/// /// Related: /// * `addPrefixedOutputFileArg` - same thing but prepends a string to the argument /// * `addFileArg` - for input files given to the child process -pub fn addOutputFileArg(run: *Run, basename: []const u8) std.Build.LazyPath { - return run.addPrefixedOutputFileArg("", basename); +pub fn addOutputFileArg(run: *Run, sub_path: []const u8) std.Build.LazyPath { + return run.addPrefixedOutputFileArg("", sub_path); } /// Provides a file path as a command line argument to the command being run. -/// Asserts `basename` is not empty. /// -/// For example, a prefix of "-o" and basename of "output.txt" will result in +/// For example, a prefix of "-o" and `sub_path` of "output.txt" will result in /// the child process seeing something like this: "-ozig-cache/.../output.txt" /// /// The child process will see a single argument, regardless of whether the -/// prefix or basename have spaces. +/// prefix or `sub_path` have spaces. /// /// The returned `std.Build.LazyPath` can be used as inputs to other APIs /// throughout the build system. @@ -267,23 +269,27 @@ pub fn addOutputFileArg(run: *Run, basename: []const u8) std.Build.LazyPath { pub fn addPrefixedOutputFileArg( run: *Run, prefix: []const u8, - basename: []const u8, + /// The name of the generated output file which may have zero or more path + /// components. + /// + /// Asserted to be non-empty. + sub_path: []const u8, ) std.Build.LazyPath { const b = run.step.owner; const graph = b.graph; const arena = graph.arena; - if (basename.len == 0) @panic("basename must not be empty"); + assert(sub_path.len != 0); - const output = arena.create(Output) catch @panic("OOM"); + const output = graph.create(Output); output.* = .{ .prefix = graph.dupeString(prefix), - .basename = graph.dupeString(basename), + .basename = graph.dupeString(sub_path), .generated_file = graph.addGeneratedFile(&run.step), }; run.argv.append(arena, .{ .output_file = output }) catch @panic("OOM"); if (run.rename_step_with_output_arg) { - run.setName(b.fmt("{s} ({s})", .{ run.step.name, basename })); + run.setName(b.fmt("{s} ({s})", .{ run.step.name, sub_path })); } return .{ .generated = .{ .index = output.generated_file } }; diff --git a/test/standalone/dirname/build.zig b/test/standalone/dirname/build.zig @@ -27,22 +27,16 @@ pub fn build(b: *std.Build) void { }), }); - // Known path: - addTestRun(test_step, exists_in, touch_src.dirname(), &.{"touch.zig"}); - - // Generated file: - addTestRun(test_step, exists_in, generated.dirname(), &.{"generated.txt"}); - - // Generated file multiple levels: - addTestRun(test_step, exists_in, generated.dirname().dirname(), &.{ + addTestRun(test_step, exists_in, "run exists_in (known path)", touch_src.dirname(), &.{"touch.zig"}); + addTestRun(test_step, exists_in, "run exists_in (generated file)", generated.dirname(), &.{"generated.txt"}); + addTestRun(test_step, exists_in, "run exists_in (generated file multi level)", generated.dirname().dirname(), &.{ "subdir" ++ std.fs.path.sep_str ++ "generated.txt", }); - // Absolute path: const write_files = b.addWriteFiles(); _ = write_files.add("foo.txt", ""); const abs_path = write_files.getDirectory(); - addTestRun(test_step, exists_in, abs_path, &.{"foo.txt"}); + addTestRun(test_step, exists_in, "run exists_in (absolute path)", abs_path, &.{"foo.txt"}); } // Runs exe with the parameters [dirname, args...]. @@ -50,10 +44,12 @@ pub fn build(b: *std.Build) void { fn addTestRun( test_step: *std.Build.Step, exe: *std.Build.Step.Compile, + step_name: []const u8, dirname: std.Build.LazyPath, args: []const []const u8, ) void { const run = test_step.owner.addRunArtifact(exe); + run.setName(step_name); run.addDirectoryArg(dirname); run.addArgs(args); run.expectExitCode(0); diff --git a/test/standalone/dirname/touch.zig b/test/standalone/dirname/touch.zig @@ -7,27 +7,26 @@ //! Path must be absolute. const std = @import("std"); +const Io = std.Io; pub fn main(init: std.process.Init) !void { + const io = init.io; + var args = try init.minimal.args.iterateAllocator(init.gpa); defer args.deinit(); - _ = args.next() orelse unreachable; // skip binary name + _ = args.next().?; // skip binary name const path = args.next() orelse { std.log.err("missing <path> argument", .{}); return error.BadUsage; }; - const dir_path = std.Io.Dir.path.dirname(path) orelse unreachable; - const basename = std.Io.Dir.path.basename(path); - - const io = std.Io.Threaded.global_single_threaded.io(); + const dir_path = Io.Dir.path.dirname(path).?; + const basename = Io.Dir.path.basename(path); - var dir = try std.Io.Dir.cwd().openDir(io, dir_path, .{}); + var dir = try Io.Dir.cwd().openDir(io, dir_path, .{}); defer dir.close(io); - _ = dir.statFile(io, basename, .{}) catch { - var file = try dir.createFile(io, basename, .{}); - file.close(io); - }; + var file = try dir.createFile(io, basename, .{ .truncate = false }); + file.close(io); }