mirror of
https://github.com/ziglang/zig.git
synced 2024-11-30 09:02:32 +00:00
std.Build.findProgram(): Try with and without the Windows executable extensions.
I renamed std.process.Child.CreateProcessSupportedExtension to WindowsExtension and made it public to avoid duplicating the list of extensions. While here, I also improved it to not misreport OOM from std.fs.realpathAlloc() as a generic failure to find the program, but instead panic like the rest of the build system does for OOM. Closes #20314.
This commit is contained in:
parent
451550e86a
commit
9be9b8ca90
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user