Commit 9be9b8ca90
lib/std/process/Child.zig
@@ -1103,7 +1103,7 @@ fn windowsCreateProcessPathExt(
}
var io_status: windows.IO_STATUS_BLOCK = undefined;
- const num_supported_pathext = @typeInfo(CreateProcessSupportedExtension).Enum.fields.len;
+ const num_supported_pathext = @typeInfo(WindowsExtension).Enum.fields.len;
var pathext_seen = [_]bool{false} ** num_supported_pathext;
var any_pathext_seen = false;
var unappended_exists = false;
@@ -1389,8 +1389,9 @@ fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *cons
var pipe_name_counter = std.atomic.Value(u32).init(1);
-// Should be kept in sync with `windowsCreateProcessSupportsExtension`
-const CreateProcessSupportedExtension = enum {
+/// File name extensions supported natively by `CreateProcess()` on Windows.
+// Should be kept in sync with `windowsCreateProcessSupportsExtension`.
+pub const WindowsExtension = enum {
bat,
cmd,
com,
@@ -1398,7 +1399,7 @@ const CreateProcessSupportedExtension = enum {
};
/// Case-insensitive WTF-16 lookup
-fn windowsCreateProcessSupportsExtension(ext: []const u16) ?CreateProcessSupportedExtension {
+fn windowsCreateProcessSupportsExtension(ext: []const u16) ?WindowsExtension {
if (ext.len != 4) return null;
const State = enum {
start,
@@ -1457,7 +1458,7 @@ fn windowsCreateProcessSupportsExtension(ext: []const u16) ?CreateProcessSupport
}
test windowsCreateProcessSupportsExtension {
- try std.testing.expectEqual(CreateProcessSupportedExtension.exe, windowsCreateProcessSupportsExtension(&[_]u16{ '.', 'e', 'X', 'e' }).?);
+ try std.testing.expectEqual(WindowsExtension.exe, windowsCreateProcessSupportsExtension(&[_]u16{ '.', 'e', 'X', 'e' }).?);
try std.testing.expect(windowsCreateProcessSupportsExtension(&[_]u16{ '.', 'e', 'X', 'e', 'c' }) == null);
}
lib/std/Build.zig
@@ -1727,20 +1727,47 @@ pub fn fmt(b: *Build, comptime format: []const u8, args: anytype) []u8 {
return std.fmt.allocPrint(b.allocator, format, args) catch @panic("OOM");
}
+fn supportedWindowsProgramExtension(ext: []const u8) bool {
+ inline for (@typeInfo(std.process.Child.WindowsExtension).Enum.fields) |field| {
+ if (std.ascii.eqlIgnoreCase(ext, "." ++ field.name)) return true;
+ }
+ return false;
+}
+
+fn tryFindProgram(b: *Build, full_path: []const u8) ?[]const u8 {
+ if (fs.realpathAlloc(b.allocator, full_path)) |p| {
+ return p;
+ } else |err| switch (err) {
+ error.OutOfMemory => @panic("OOM"),
+ else => {},
+ }
+
+ if (builtin.os.tag == .windows) {
+ if (b.graph.env_map.get("PATHEXT")) |PATHEXT| {
+ var it = mem.tokenizeScalar(u8, PATHEXT, fs.path.delimiter);
+
+ while (it.next()) |ext| {
+ if (!supportedWindowsProgramExtension(ext)) continue;
+
+ return fs.realpathAlloc(b.allocator, b.fmt("{s}{s}", .{ full_path, ext })) catch |err| switch (err) {
+ error.OutOfMemory => @panic("OOM"),
+ else => continue,
+ };
+ }
+ }
+ }
+
+ return null;
+}
+
pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const u8) ![]const u8 {
// TODO report error for ambiguous situations
- const exe_extension = b.graph.host.result.exeFileExt();
for (b.search_prefixes.items) |search_prefix| {
for (names) |name| {
if (fs.path.isAbsolute(name)) {
return name;
}
- const full_path = b.pathJoin(&.{
- search_prefix,
- "bin",
- b.fmt("{s}{s}", .{ name, exe_extension }),
- });
- return fs.realpathAlloc(b.allocator, full_path) catch continue;
+ return tryFindProgram(b, b.pathJoin(&.{ search_prefix, "bin", name })) orelse continue;
}
}
if (b.graph.env_map.get("PATH")) |PATH| {
@@ -1750,10 +1777,7 @@ pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const
}
var it = mem.tokenizeScalar(u8, PATH, fs.path.delimiter);
while (it.next()) |p| {
- const full_path = b.pathJoin(&.{
- p, b.fmt("{s}{s}", .{ name, exe_extension }),
- });
- return fs.realpathAlloc(b.allocator, full_path) catch continue;
+ return tryFindProgram(b, b.pathJoin(&.{ p, name })) orelse continue;
}
}
}
@@ -1762,10 +1786,7 @@ pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const
return name;
}
for (paths) |p| {
- const full_path = b.pathJoin(&.{
- p, b.fmt("{s}{s}", .{ name, exe_extension }),
- });
- return fs.realpathAlloc(b.allocator, full_path) catch continue;
+ return tryFindProgram(b, b.pathJoin(&.{ p, name })) orelse continue;
}
}
return error.FileNotFound;