authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-12-07 22:44:10+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-12-08 04:53:28+01:00
logba37a4369b936c3fe4ad4f4b1d61bc93d9936018
treeb723787455dd02d813011125696db4add38ce6f7
parent1f95e3d9cd6bdd313536fb35beb46a09b4fd8834

std.zig.WindowsSdk: Support cross-arch SDK lookups.

This makes e.g. cross-compiling for x86-windows-msvc on a x86_64-windows-msvc system work properly. Closes #11926.

3 files changed, 25 insertions(+), 26 deletions(-)

lib/std/zig/LibCInstallation.zig+1-1
...@@ -182,7 +182,7 @@ pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation {...@@ -182,7 +182,7 @@ pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation {
182 });182 });
183 return self;183 return self;
184 } else if (is_windows) {184 } else if (is_windows) {
185 const sdk = std.zig.WindowsSdk.find(args.allocator) catch |err| switch (err) {185 const sdk = std.zig.WindowsSdk.find(args.allocator, args.target.cpu.arch) catch |err| switch (err) {
186 error.NotFound => return error.WindowsSdkNotFound,186 error.NotFound => return error.WindowsSdkNotFound,
187 error.PathTooLong => return error.WindowsSdkNotFound,187 error.PathTooLong => return error.WindowsSdkNotFound,
188 error.OutOfMemory => return error.OutOfMemory,188 error.OutOfMemory => return error.OutOfMemory,
lib/std/zig/WindowsSdk.zig+23-24
...@@ -19,7 +19,7 @@ const product_version_max_length = version_major_minor_max_length + ".65535".len...@@ -19,7 +19,7 @@ const product_version_max_length = version_major_minor_max_length + ".65535".len
19/// Find path and version of Windows 10 SDK and Windows 8.1 SDK, and find path to MSVC's `lib/` directory.19/// Find path and version of Windows 10 SDK and Windows 8.1 SDK, and find path to MSVC's `lib/` directory.
20/// Caller owns the result's fields.20/// Caller owns the result's fields.
21/// After finishing work, call `free(allocator)`.21/// After finishing work, call `free(allocator)`.
22pub fn find(allocator: std.mem.Allocator) error{ OutOfMemory, NotFound, PathTooLong }!WindowsSdk {22pub fn find(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, NotFound, PathTooLong }!WindowsSdk {
23 if (builtin.os.tag != .windows) return error.NotFound;23 if (builtin.os.tag != .windows) return error.NotFound;
2424
25 //note(dimenus): If this key doesn't exist, neither the Win 8 SDK nor the Win 10 SDK is installed25 //note(dimenus): If this key doesn't exist, neither the Win 8 SDK nor the Win 10 SDK is installed
...@@ -44,7 +44,7 @@ pub fn find(allocator: std.mem.Allocator) error{ OutOfMemory, NotFound, PathTooL...@@ -44,7 +44,7 @@ pub fn find(allocator: std.mem.Allocator) error{ OutOfMemory, NotFound, PathTooL
44 };44 };
45 errdefer if (windows81sdk) |*w| w.free(allocator);45 errdefer if (windows81sdk) |*w| w.free(allocator);
4646
47 const msvc_lib_dir: ?[]const u8 = MsvcLibDir.find(allocator) catch |err| switch (err) {47 const msvc_lib_dir: ?[]const u8 = MsvcLibDir.find(allocator, arch) catch |err| switch (err) {
48 error.MsvcLibDirNotFound => null,48 error.MsvcLibDirNotFound => null,
49 error.OutOfMemory => return error.OutOfMemory,49 error.OutOfMemory => return error.OutOfMemory,
50 };50 };
...@@ -742,7 +742,7 @@ const MsvcLibDir = struct {...@@ -742,7 +742,7 @@ const MsvcLibDir = struct {
742 ///742 ///
743 /// The logic in this function is intended to match what ISetupConfiguration does743 /// The logic in this function is intended to match what ISetupConfiguration does
744 /// under-the-hood, as verified using Procmon.744 /// under-the-hood, as verified using Procmon.
745 fn findViaCOM(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }![]const u8 {745 fn findViaCOM(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 {
746 // Typically `%PROGRAMDATA%\Microsoft\VisualStudio\Packages\_Instances`746 // Typically `%PROGRAMDATA%\Microsoft\VisualStudio\Packages\_Instances`
747 // This will contain directories with names of instance IDs like 80a758ca,747 // This will contain directories with names of instance IDs like 80a758ca,
748 // which will contain `state.json` files that have the version and748 // which will contain `state.json` files that have the version and
...@@ -786,7 +786,7 @@ const MsvcLibDir = struct {...@@ -786,7 +786,7 @@ const MsvcLibDir = struct {
786 const installation_path = parsed.value.object.get("installationPath") orelse continue;786 const installation_path = parsed.value.object.get("installationPath") orelse continue;
787 if (installation_path != .string) continue;787 if (installation_path != .string) continue;
788788
789 const lib_dir_path = libDirFromInstallationPath(allocator, installation_path.string) catch |err| switch (err) {789 const lib_dir_path = libDirFromInstallationPath(allocator, installation_path.string, arch) catch |err| switch (err) {
790 error.OutOfMemory => |e| return e,790 error.OutOfMemory => |e| return e,
791 error.PathNotFound => continue,791 error.PathNotFound => continue,
792 };792 };
...@@ -801,7 +801,7 @@ const MsvcLibDir = struct {...@@ -801,7 +801,7 @@ const MsvcLibDir = struct {
801 return latest_version_lib_dir.toOwnedSlice(allocator);801 return latest_version_lib_dir.toOwnedSlice(allocator);
802 }802 }
803803
804 fn libDirFromInstallationPath(allocator: std.mem.Allocator, installation_path: []const u8) error{ OutOfMemory, PathNotFound }![]const u8 {804 fn libDirFromInstallationPath(allocator: std.mem.Allocator, installation_path: []const u8, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 {
805 var lib_dir_buf = try std.ArrayList(u8).initCapacity(allocator, installation_path.len + 64);805 var lib_dir_buf = try std.ArrayList(u8).initCapacity(allocator, installation_path.len + 64);
806 errdefer lib_dir_buf.deinit();806 errdefer lib_dir_buf.deinit();
807807
...@@ -823,14 +823,14 @@ const MsvcLibDir = struct {...@@ -823,14 +823,14 @@ const MsvcLibDir = struct {
823 lib_dir_buf.shrinkRetainingCapacity(installation_path_with_trailing_sep_len);823 lib_dir_buf.shrinkRetainingCapacity(installation_path_with_trailing_sep_len);
824 try lib_dir_buf.appendSlice("VC\\Tools\\MSVC\\");824 try lib_dir_buf.appendSlice("VC\\Tools\\MSVC\\");
825 try lib_dir_buf.appendSlice(default_tools_version);825 try lib_dir_buf.appendSlice(default_tools_version);
826 const folder_with_arch = "\\Lib\\" ++ comptime switch (builtin.target.cpu.arch) {826 try lib_dir_buf.appendSlice("\\Lib\\");
827 try lib_dir_buf.appendSlice(switch (arch) {
827 .thumb => "arm",828 .thumb => "arm",
828 .aarch64 => "arm64",829 .aarch64 => "arm64",
829 .x86 => "x86",830 .x86 => "x86",
830 .x86_64 => "x64",831 .x86_64 => "x64",
831 else => |tag| @compileError("MSVC lib dir cannot be detected on architecture " ++ tag),832 else => unreachable,
832 };833 });
833 try lib_dir_buf.appendSlice(folder_with_arch);
834834
835 if (!verifyLibDir(lib_dir_buf.items)) {835 if (!verifyLibDir(lib_dir_buf.items)) {
836 return error.PathNotFound;836 return error.PathNotFound;
...@@ -840,7 +840,7 @@ const MsvcLibDir = struct {...@@ -840,7 +840,7 @@ const MsvcLibDir = struct {
840 }840 }
841841
842 // https://learn.microsoft.com/en-us/visualstudio/install/tools-for-managing-visual-studio-instances?view=vs-2022#editing-the-registry-for-a-visual-studio-instance842 // https://learn.microsoft.com/en-us/visualstudio/install/tools-for-managing-visual-studio-instances?view=vs-2022#editing-the-registry-for-a-visual-studio-instance
843 fn findViaRegistry(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }![]const u8 {843 fn findViaRegistry(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 {
844844
845 // %localappdata%\Microsoft\VisualStudio\845 // %localappdata%\Microsoft\VisualStudio\
846 // %appdata%\Local\Microsoft\VisualStudio\846 // %appdata%\Local\Microsoft\VisualStudio\
...@@ -908,15 +908,14 @@ const MsvcLibDir = struct {...@@ -908,15 +908,14 @@ const MsvcLibDir = struct {
908 msvc_dir.shrinkRetainingCapacity(msvc_dir.items.len - "\\include".len);908 msvc_dir.shrinkRetainingCapacity(msvc_dir.items.len - "\\include".len);
909 }909 }
910910
911 const folder_with_arch = "\\Lib\\" ++ comptime switch (builtin.target.cpu.arch) {911 try msvc_dir.appendSlice("\\Lib\\");
912 try msvc_dir.appendSlice(switch (arch) {
912 .thumb => "arm",913 .thumb => "arm",
913 .aarch64 => "arm64",914 .aarch64 => "arm64",
914 .x86 => "x86",915 .x86 => "x86",
915 .x86_64 => "x64",916 .x86_64 => "x64",
916 else => |tag| @compileError("MSVC lib dir cannot be detected on architecture " ++ tag),917 else => unreachable,
917 };918 });
918
919 try msvc_dir.appendSlice(folder_with_arch);
920 const msvc_dir_with_arch = try msvc_dir.toOwnedSlice();919 const msvc_dir_with_arch = try msvc_dir.toOwnedSlice();
921 break :msvc_dir msvc_dir_with_arch;920 break :msvc_dir msvc_dir_with_arch;
922 };921 };
...@@ -929,7 +928,7 @@ const MsvcLibDir = struct {...@@ -929,7 +928,7 @@ const MsvcLibDir = struct {
929 return msvc_dir;928 return msvc_dir;
930 }929 }
931930
932 fn findViaVs7Key(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }![]const u8 {931 fn findViaVs7Key(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 {
933 var base_path: std.ArrayList(u8) = base_path: {932 var base_path: std.ArrayList(u8) = base_path: {
934 try_env: {933 try_env: {
935 var env_map = std.process.getEnvMap(allocator) catch |err| switch (err) {934 var env_map = std.process.getEnvMap(allocator) catch |err| switch (err) {
...@@ -976,14 +975,14 @@ const MsvcLibDir = struct {...@@ -976,14 +975,14 @@ const MsvcLibDir = struct {
976 };975 };
977 errdefer base_path.deinit();976 errdefer base_path.deinit();
978977
979 const folder_with_arch = "\\VC\\lib\\" ++ comptime switch (builtin.target.cpu.arch) {978 try base_path.appendSlice("\\VC\\lib\\");
979 try base_path.appendSlice(switch (arch) {
980 .thumb => "arm",980 .thumb => "arm",
981 .aarch64 => "arm64",981 .aarch64 => "arm64",
982 .x86 => "", //x86 is in the root of the Lib folder982 .x86 => "", //x86 is in the root of the Lib folder
983 .x86_64 => "amd64",983 .x86_64 => "amd64",
984 else => |tag| @compileError("MSVC lib dir cannot be detected on architecture " ++ tag),984 else => unreachable,
985 };985 });
986 try base_path.appendSlice(folder_with_arch);
987986
988 if (!verifyLibDir(base_path.items)) {987 if (!verifyLibDir(base_path.items)) {
989 return error.PathNotFound;988 return error.PathNotFound;
...@@ -1008,12 +1007,12 @@ const MsvcLibDir = struct {...@@ -1008,12 +1007,12 @@ const MsvcLibDir = struct {
10081007
1009 /// Find path to MSVC's `lib/` directory.1008 /// Find path to MSVC's `lib/` directory.
1010 /// Caller owns the result.1009 /// Caller owns the result.
1011 pub fn find(allocator: std.mem.Allocator) error{ OutOfMemory, MsvcLibDirNotFound }![]const u8 {1010 pub fn find(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, MsvcLibDirNotFound }![]const u8 {
1012 const full_path = MsvcLibDir.findViaCOM(allocator) catch |err1| switch (err1) {1011 const full_path = MsvcLibDir.findViaCOM(allocator, arch) catch |err1| switch (err1) {
1013 error.OutOfMemory => return error.OutOfMemory,1012 error.OutOfMemory => return error.OutOfMemory,
1014 error.PathNotFound => MsvcLibDir.findViaRegistry(allocator) catch |err2| switch (err2) {1013 error.PathNotFound => MsvcLibDir.findViaRegistry(allocator, arch) catch |err2| switch (err2) {
1015 error.OutOfMemory => return error.OutOfMemory,1014 error.OutOfMemory => return error.OutOfMemory,
1016 error.PathNotFound => MsvcLibDir.findViaVs7Key(allocator) catch |err3| switch (err3) {1015 error.PathNotFound => MsvcLibDir.findViaVs7Key(allocator, arch) catch |err3| switch (err3) {
1017 error.OutOfMemory => return error.OutOfMemory,1016 error.OutOfMemory => return error.OutOfMemory,
1018 error.PathNotFound => return error.MsvcLibDirNotFound,1017 error.PathNotFound => return error.MsvcLibDirNotFound,
1019 },1018 },
test/standalone/windows_argv/build.zig+1-1
...@@ -59,7 +59,7 @@ pub fn build(b: *std.Build) !void {...@@ -59,7 +59,7 @@ pub fn build(b: *std.Build) !void {
5959
60 // Only target the MSVC ABI if MSVC/Windows SDK is available60 // Only target the MSVC ABI if MSVC/Windows SDK is available
61 const has_msvc = has_msvc: {61 const has_msvc = has_msvc: {
62 const sdk = std.zig.WindowsSdk.find(b.allocator) catch |err| switch (err) {62 const sdk = std.zig.WindowsSdk.find(b.allocator, builtin.cpu.arch) catch |err| switch (err) {
63 error.OutOfMemory => @panic("oom"),63 error.OutOfMemory => @panic("oom"),
64 else => break :has_msvc false,64 else => break :has_msvc false,
65 };65 };