| ... | @@ -1727,20 +1727,47 @@ pub fn fmt(b: *Build, comptime format: []const u8, args: anytype) []u8 { | ... | @@ -1727,20 +1727,47 @@ pub fn fmt(b: *Build, comptime format: []const u8, args: anytype) []u8 { |
| 1727 | return std.fmt.allocPrint(b.allocator, format, args) catch @panic("OOM"); | 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 | pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const u8) ![]const u8 { | 1763 | pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const u8) ![]const u8 { |
| 1731 | // TODO report error for ambiguous situations | 1764 | // TODO report error for ambiguous situations |
| 1732 | const exe_extension = b.graph.host.result.exeFileExt(); | | |
| 1733 | for (b.search_prefixes.items) |search_prefix| { | 1765 | for (b.search_prefixes.items) |search_prefix| { |
| 1734 | for (names) |name| { | 1766 | for (names) |name| { |
| 1735 | if (fs.path.isAbsolute(name)) { | 1767 | if (fs.path.isAbsolute(name)) { |
| 1736 | return name; | 1768 | return name; |
| 1737 | } | 1769 | } |
| 1738 | const full_path = b.pathJoin(&.{ | 1770 | return tryFindProgram(b, b.pathJoin(&.{ search_prefix, "bin", name })) orelse continue; |
| 1739 | search_prefix, | | |
| 1740 | "bin", | | |
| 1741 | b.fmt("{s}{s}", .{ name, exe_extension }), | | |
| 1742 | }); | | |
| 1743 | return fs.realpathAlloc(b.allocator, full_path) catch continue; | | |
| 1744 | } | 1771 | } |
| 1745 | } | 1772 | } |
| 1746 | if (b.graph.env_map.get("PATH")) |PATH| { | 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,10 +1777,7 @@ pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const |
| 1750 | } | 1777 | } |
| 1751 | var it = mem.tokenizeScalar(u8, PATH, fs.path.delimiter); | 1778 | var it = mem.tokenizeScalar(u8, PATH, fs.path.delimiter); |
| 1752 | while (it.next()) |p| { | 1779 | while (it.next()) |p| { |
| 1753 | const full_path = b.pathJoin(&.{ | 1780 | return tryFindProgram(b, b.pathJoin(&.{ p, name })) orelse continue; |
| 1754 | p, b.fmt("{s}{s}", .{ name, exe_extension }), | | |
| 1755 | }); | | |
| 1756 | return fs.realpathAlloc(b.allocator, full_path) catch continue; | | |
| 1757 | } | 1781 | } |
| 1758 | } | 1782 | } |
| 1759 | } | 1783 | } |
| ... | @@ -1762,10 +1786,7 @@ pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const | ... | @@ -1762,10 +1786,7 @@ pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const |
| 1762 | return name; | 1786 | return name; |
| 1763 | } | 1787 | } |
| 1764 | for (paths) |p| { | 1788 | for (paths) |p| { |
| 1765 | const full_path = b.pathJoin(&.{ | 1789 | return tryFindProgram(b, b.pathJoin(&.{ p, name })) orelse continue; |
| 1766 | p, b.fmt("{s}{s}", .{ name, exe_extension }), | | |
| 1767 | }); | | |
| 1768 | return fs.realpathAlloc(b.allocator, full_path) catch continue; | | |
| 1769 | } | 1790 | } |
| 1770 | } | 1791 | } |
| 1771 | return error.FileNotFound; | 1792 | return error.FileNotFound; |