| ... | ... | @@ -1727,20 +1727,47 @@ pub fn fmt(b: *Build, comptime format: []const u8, args: anytype) []u8 { |
| 1727 | 1727 | return std.fmt.allocPrint(b.allocator, format, args) catch @panic("OOM"); |
| 1728 | 1728 | } |
| 1729 | 1729 | |
| 1730 | fn supportedWindowsProgramExtension(ext: []const u8) bool { |
| 1731 | inline for (@typeInfo(std.process.Child.WindowsExtension).Enum.fields) |field| { |
| 1732 | if (std.ascii.eqlIgnoreCase(ext, "." ++ field.name)) return true; |
| 1733 | } |
| 1734 | return false; |
| 1735 | } |
| 1736 | |
| 1737 | fn tryFindProgram(b: *Build, full_path: []const u8) ?[]const u8 { |
| 1738 | if (fs.realpathAlloc(b.allocator, full_path)) |p| { |
| 1739 | return p; |
| 1740 | } else |err| switch (err) { |
| 1741 | error.OutOfMemory => @panic("OOM"), |
| 1742 | else => {}, |
| 1743 | } |
| 1744 | |
| 1745 | if (builtin.os.tag == .windows) { |
| 1746 | if (b.graph.env_map.get("PATHEXT")) |PATHEXT| { |
| 1747 | var it = mem.tokenizeScalar(u8, PATHEXT, fs.path.delimiter); |
| 1748 | |
| 1749 | while (it.next()) |ext| { |
| 1750 | if (!supportedWindowsProgramExtension(ext)) continue; |
| 1751 | |
| 1752 | return fs.realpathAlloc(b.allocator, b.fmt("{s}{s}", .{ full_path, ext })) catch |err| switch (err) { |
| 1753 | error.OutOfMemory => @panic("OOM"), |
| 1754 | else => continue, |
| 1755 | }; |
| 1756 | } |
| 1757 | } |
| 1758 | } |
| 1759 | |
| 1760 | return null; |
| 1761 | } |
| 1762 | |
| 1730 | 1763 | pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const u8) ![]const u8 { |
| 1731 | 1764 | // TODO report error for ambiguous situations |
| 1732 | | const exe_extension = b.graph.host.result.exeFileExt(); |
| 1733 | 1765 | for (b.search_prefixes.items) |search_prefix| { |
| 1734 | 1766 | for (names) |name| { |
| 1735 | 1767 | if (fs.path.isAbsolute(name)) { |
| 1736 | 1768 | return name; |
| 1737 | 1769 | } |
| 1738 | | const full_path = b.pathJoin(&.{ |
| 1739 | | search_prefix, |
| 1740 | | "bin", |
| 1741 | | b.fmt("{s}{s}", .{ name, exe_extension }), |
| 1742 | | }); |
| 1743 | | return fs.realpathAlloc(b.allocator, full_path) catch continue; |
| 1770 | return tryFindProgram(b, b.pathJoin(&.{ search_prefix, "bin", name })) orelse continue; |
| 1744 | 1771 | } |
| 1745 | 1772 | } |
| 1746 | 1773 | if (b.graph.env_map.get("PATH")) |PATH| { |
| ... | ... | @@ -1750,10 +1777,7 @@ pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const |
| 1750 | 1777 | } |
| 1751 | 1778 | var it = mem.tokenizeScalar(u8, PATH, fs.path.delimiter); |
| 1752 | 1779 | while (it.next()) |p| { |
| 1753 | | const full_path = b.pathJoin(&.{ |
| 1754 | | p, b.fmt("{s}{s}", .{ name, exe_extension }), |
| 1755 | | }); |
| 1756 | | return fs.realpathAlloc(b.allocator, full_path) catch continue; |
| 1780 | return tryFindProgram(b, b.pathJoin(&.{ p, name })) orelse continue; |
| 1757 | 1781 | } |
| 1758 | 1782 | } |
| 1759 | 1783 | } |
| ... | ... | @@ -1762,10 +1786,7 @@ pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const |
| 1762 | 1786 | return name; |
| 1763 | 1787 | } |
| 1764 | 1788 | for (paths) |p| { |
| 1765 | | const full_path = b.pathJoin(&.{ |
| 1766 | | p, b.fmt("{s}{s}", .{ name, exe_extension }), |
| 1767 | | }); |
| 1768 | | return fs.realpathAlloc(b.allocator, full_path) catch continue; |
| 1789 | return tryFindProgram(b, b.pathJoin(&.{ p, name })) orelse continue; |
| 1769 | 1790 | } |
| 1770 | 1791 | } |
| 1771 | 1792 | return error.FileNotFound; |