Skip to content

Commit ba37a43

Browse files
committed
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.
1 parent 1f95e3d commit ba37a43

File tree

3 files changed

+25
-26
lines changed

3 files changed

+25
-26
lines changed

lib/std/zig/LibCInstallation.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation {
182182
});
183183
return self;
184184
} 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) {
186186
error.NotFound => return error.WindowsSdkNotFound,
187187
error.PathTooLong => return error.WindowsSdkNotFound,
188188
error.OutOfMemory => return error.OutOfMemory,

lib/std/zig/WindowsSdk.zig

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const product_version_max_length = version_major_minor_max_length + ".65535".len
1919
/// Find path and version of Windows 10 SDK and Windows 8.1 SDK, and find path to MSVC's `lib/` directory.
2020
/// Caller owns the result's fields.
2121
/// After finishing work, call `free(allocator)`.
22-
pub fn find(allocator: std.mem.Allocator) error{ OutOfMemory, NotFound, PathTooLong }!WindowsSdk {
22+
pub fn find(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, NotFound, PathTooLong }!WindowsSdk {
2323
if (builtin.os.tag != .windows) return error.NotFound;
2424

2525
//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
4444
};
4545
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) {
4848
error.MsvcLibDirNotFound => null,
4949
error.OutOfMemory => return error.OutOfMemory,
5050
};
@@ -742,7 +742,7 @@ const MsvcLibDir = struct {
742742
///
743743
/// The logic in this function is intended to match what ISetupConfiguration does
744744
/// 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 {
746746
// Typically `%PROGRAMDATA%\Microsoft\VisualStudio\Packages\_Instances`
747747
// This will contain directories with names of instance IDs like 80a758ca,
748748
// which will contain `state.json` files that have the version and
@@ -786,7 +786,7 @@ const MsvcLibDir = struct {
786786
const installation_path = parsed.value.object.get("installationPath") orelse continue;
787787
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) {
790790
error.OutOfMemory => |e| return e,
791791
error.PathNotFound => continue,
792792
};
@@ -801,7 +801,7 @@ const MsvcLibDir = struct {
801801
return latest_version_lib_dir.toOwnedSlice(allocator);
802802
}
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 {
805805
var lib_dir_buf = try std.ArrayList(u8).initCapacity(allocator, installation_path.len + 64);
806806
errdefer lib_dir_buf.deinit();
807807

@@ -823,14 +823,14 @@ const MsvcLibDir = struct {
823823
lib_dir_buf.shrinkRetainingCapacity(installation_path_with_trailing_sep_len);
824824
try lib_dir_buf.appendSlice("VC\\Tools\\MSVC\\");
825825
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) {
827828
.thumb => "arm",
828829
.aarch64 => "arm64",
829830
.x86 => "x86",
830831
.x86_64 => "x64",
831-
else => |tag| @compileError("MSVC lib dir cannot be detected on architecture " ++ tag),
832-
};
833-
try lib_dir_buf.appendSlice(folder_with_arch);
832+
else => unreachable,
833+
});
834834

835835
if (!verifyLibDir(lib_dir_buf.items)) {
836836
return error.PathNotFound;
@@ -840,7 +840,7 @@ const MsvcLibDir = struct {
840840
}
841841

842842
// 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

845845
// %localappdata%\Microsoft\VisualStudio\
846846
// %appdata%\Local\Microsoft\VisualStudio\
@@ -908,15 +908,14 @@ const MsvcLibDir = struct {
908908
msvc_dir.shrinkRetainingCapacity(msvc_dir.items.len - "\\include".len);
909909
}
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) {
912913
.thumb => "arm",
913914
.aarch64 => "arm64",
914915
.x86 => "x86",
915916
.x86_64 => "x64",
916-
else => |tag| @compileError("MSVC lib dir cannot be detected on architecture " ++ tag),
917-
};
918-
919-
try msvc_dir.appendSlice(folder_with_arch);
917+
else => unreachable,
918+
});
920919
const msvc_dir_with_arch = try msvc_dir.toOwnedSlice();
921920
break :msvc_dir msvc_dir_with_arch;
922921
};
@@ -929,7 +928,7 @@ const MsvcLibDir = struct {
929928
return msvc_dir;
930929
}
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 {
933932
var base_path: std.ArrayList(u8) = base_path: {
934933
try_env: {
935934
var env_map = std.process.getEnvMap(allocator) catch |err| switch (err) {
@@ -976,14 +975,14 @@ const MsvcLibDir = struct {
976975
};
977976
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) {
980980
.thumb => "arm",
981981
.aarch64 => "arm64",
982982
.x86 => "", //x86 is in the root of the Lib folder
983983
.x86_64 => "amd64",
984-
else => |tag| @compileError("MSVC lib dir cannot be detected on architecture " ++ tag),
985-
};
986-
try base_path.appendSlice(folder_with_arch);
984+
else => unreachable,
985+
});
987986

988987
if (!verifyLibDir(base_path.items)) {
989988
return error.PathNotFound;
@@ -1008,12 +1007,12 @@ const MsvcLibDir = struct {
10081007

10091008
/// Find path to MSVC's `lib/` directory.
10101009
/// Caller owns the result.
1011-
pub fn find(allocator: std.mem.Allocator) error{ OutOfMemory, MsvcLibDirNotFound }![]const u8 {
1012-
const full_path = MsvcLibDir.findViaCOM(allocator) catch |err1| switch (err1) {
1010+
pub fn find(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, MsvcLibDirNotFound }![]const u8 {
1011+
const full_path = MsvcLibDir.findViaCOM(allocator, arch) catch |err1| switch (err1) {
10131012
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) {
10151014
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) {
10171016
error.OutOfMemory => return error.OutOfMemory,
10181017
error.PathNotFound => return error.MsvcLibDirNotFound,
10191018
},

test/standalone/windows_argv/build.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub fn build(b: *std.Build) !void {
5959

6060
// Only target the MSVC ABI if MSVC/Windows SDK is available
6161
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) {
6363
error.OutOfMemory => @panic("oom"),
6464
else => break :has_msvc false,
6565
};

0 commit comments

Comments
 (0)