diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2025-06-18 16:07:20 +0100 |
|---|---|---|
| committer | Matthew Lugg <mlugg@mlugg.co.uk> | 2025-06-18 22:45:05 +0100 |
| commit | 36499c251c592d10a8258b1562bee22e5fb7899a (patch) | |
| tree | fa03fda7f222e30607b62a6e2c25d193f6e96c43 /lib/std/Build | |
| parent | f3940ad858937cc4bb2e1b99828183e070f40bf9 (diff) | |
| download | zig-36499c251c592d10a8258b1562bee22e5fb7899a.tar.gz zig-36499c251c592d10a8258b1562bee22e5fb7899a.zip | |
std.Build.Step.Run: prefix relative path arguments with './'
This is necessary in two cases:
* On POSIX, the exe path (`argv[0]`) must contain a path separator
* Some programs might treat a file named e.g. `-foo` as a flag, which
can be avoided by passing `./-foo`
Rather than detecting these two cases, just always include the prefix;
there's no harm in it.
Also, if the cwd is specified, include it in the manifest. If the user
has set the cwd of a Run step, it is clearly because this affects the
behavior of the executable somehow, so that cwd path should be a part of
the step's manifest.
Resolves: #24216
Diffstat (limited to 'lib/std/Build')
| -rw-r--r-- | lib/std/Build/Step/Run.zig | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index ca5525eff4..eb5ea1c607 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -629,9 +629,22 @@ fn checksContainStderr(checks: []const StdIo.Check) bool { fn convertPathArg(run: *Run, path: Build.Cache.Path) []const u8 { const b = run.step.owner; const path_str = path.toString(b.graph.arena) catch @panic("OOM"); - const child_lazy_cwd = run.cwd orelse return path_str; - const child_cwd = child_lazy_cwd.getPath3(b, &run.step).toString(b.graph.arena) catch @panic("OOM"); - return std.fs.path.relative(b.graph.arena, child_cwd, path_str) catch @panic("OOM"); + if (std.fs.path.isAbsolute(path_str)) { + // Absolute paths don't need changing. + return path_str; + } + const child_cwd_rel: []const u8 = rel: { + const child_lazy_cwd = run.cwd orelse break :rel path_str; + const child_cwd = child_lazy_cwd.getPath3(b, &run.step).toString(b.graph.arena) catch @panic("OOM"); + // Convert it from relative to *our* cwd, to relative to the *child's* cwd. + break :rel std.fs.path.relative(b.graph.arena, child_cwd, path_str) catch @panic("OOM"); + }; + assert(!std.fs.path.isAbsolute(child_cwd_rel)); + // We're not done yet. In some cases this path must be prefixed with './': + // * On POSIX, the executable name cannot be a single component like 'foo' + // * Some executables might treat a leading '-' like a flag, which we must avoid + // There's no harm in it, so just *always* apply this prefix. + return std.fs.path.join(b.graph.arena, &.{ ".", child_cwd_rel }) catch @panic("OOM"); } const IndexedOutput = struct { @@ -756,6 +769,11 @@ fn make(step: *Step, options: Step.MakeOptions) !void { _ = try man.addFile(lazy_path.getPath2(b, step), null); } + if (run.cwd) |cwd| { + const cwd_path = cwd.getPath3(b, step); + _ = man.hash.addBytes(try cwd_path.toString(arena)); + } + if (!has_side_effects and try step.cacheHitAndWatch(&man)) { // cache hit, skip running command const digest = man.final(); |
