Skip to content

Commit

Permalink
MSVC: support version preference with search
Browse files Browse the repository at this point in the history
Extend the logic for the WinSDK and UCRT handling to prefer a user
specified version of the VisualC++ tools and Windows SDK.  This allows
us to now perform the regular search for the installation but select the
exact version of the SDK or VC++ tools to override the latest version.
Similar to the other flags controlling this behaviour, if the user
specifies a value, we will not perform validation on the input and will
attempt to prefer that, particularly in the case of VisualC++ tools
where no fallback occurs.

Reviewed by: hans
Differential Revision: https://reviews.llvm.org/D145517
  • Loading branch information
compnerd committed Mar 13, 2023
1 parent 2170067 commit af5f468
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 17 deletions.
19 changes: 17 additions & 2 deletions clang/lib/Driver/ToolChains/MSVC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,8 +440,8 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
WinSysRoot, VCToolChainPath, VSLayout) ||
llvm::findVCToolChainViaEnvironment(getVFS(), VCToolChainPath,
VSLayout) ||
llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath,
VSLayout) ||
llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolsVersion,
VCToolChainPath, VSLayout) ||
llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
}

Expand Down Expand Up @@ -546,6 +546,10 @@ bool MSVCToolChain::getWindowsSDKLibraryPath(const ArgList &Args,

llvm::SmallString<128> libPath(sdkPath);
llvm::sys::path::append(libPath, "Lib");
if (sdkMajor >= 10)
if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) &&
WinSdkVersion.has_value())
windowsSDKLibVersion = *WinSdkVersion;
if (sdkMajor >= 8)
llvm::sys::path::append(libPath, windowsSDKLibVersion, "um");
return llvm::appendArchToWindowsSDKLibPath(sdkMajor, libPath, getArch(),
Expand All @@ -567,6 +571,10 @@ bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
UCRTVersion))
return false;

if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) &&
WinSdkVersion.has_value())
UCRTVersion = *WinSdkVersion;

StringRef ArchName = llvm::archToWindowsSDKArch(getArch());
if (ArchName.empty())
return false;
Expand Down Expand Up @@ -696,6 +704,9 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
WinSysRoot, UniversalCRTSdkPath,
UCRTVersion)) {
if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) &&
WinSdkVersion.has_value())
UCRTVersion = *WinSdkVersion;
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
"Include", UCRTVersion, "ucrt");
}
Expand All @@ -708,6 +719,10 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
WindowsSDKDir, major, windowsSDKIncludeVersion,
windowsSDKLibVersion)) {
if (major >= 10)
if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) &&
WinSdkVersion.has_value())
windowsSDKIncludeVersion = windowsSDKLibVersion = *WinSdkVersion;
if (major >= 8) {
// Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
// Anyway, llvm::sys::path::append is able to manage it.
Expand Down
2 changes: 1 addition & 1 deletion lld/COFF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ void LinkerDriver::detectWinSysRoot(const opt::InputArgList &Args) {
WinSysRoot, vcToolChainPath, vsLayout) &&
(Args.hasArg(OPT_lldignoreenv) ||
!findVCToolChainViaEnvironment(*VFS, vcToolChainPath, vsLayout)) &&
!findVCToolChainViaSetupConfig(*VFS, vcToolChainPath, vsLayout) &&
!findVCToolChainViaSetupConfig(*VFS, {}, vcToolChainPath, vsLayout) &&
!findVCToolChainViaRegistry(vcToolChainPath, vsLayout))
return;

Expand Down
10 changes: 7 additions & 3 deletions llvm/include/llvm/WindowsDriver/MSVCPaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,15 @@ bool findVCToolChainViaEnvironment(vfs::FileSystem &VFS, std::string &Path,
ToolsetLayout &VSLayout);

// Query the Setup Config server for installs, then pick the newest version
// and find its default VC toolchain.
// and find its default VC toolchain. If `VCToolsVersion` is specified, that
// version is preferred over the latest version.
//
// This is the preferred way to discover new Visual Studios, as they're no
// longer listed in the registry.
bool findVCToolChainViaSetupConfig(vfs::FileSystem &VFS, std::string &Path,
ToolsetLayout &VSLayout);
bool
findVCToolChainViaSetupConfig(vfs::FileSystem &VFS,
std::optional<llvm::StringRef> VCToolsVersion,
std::string &Path, ToolsetLayout &VSLayout);

// Look in the registry for Visual Studio installs, and use that to get
// a toolchain path. VS2017 and newer don't get added to the registry.
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ COFFVCRuntimeBootstrapper::getMSVCToolchainPath() {
if (!findVCToolChainViaCommandLine(*VFS, std::nullopt, std::nullopt,
std::nullopt, VCToolChainPath, VSLayout) &&
!findVCToolChainViaEnvironment(*VFS, VCToolChainPath, VSLayout) &&
!findVCToolChainViaSetupConfig(*VFS, VCToolChainPath, VSLayout) &&
!findVCToolChainViaSetupConfig(*VFS, {}, VCToolChainPath, VSLayout) &&
!findVCToolChainViaRegistry(VCToolChainPath, VSLayout))
return make_error<StringError>("Couldn't find msvc toolchain.",
inconvertibleErrorCode());
Expand Down
28 changes: 18 additions & 10 deletions llvm/lib/WindowsDriver/MSVCPaths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,8 +609,9 @@ bool findVCToolChainViaEnvironment(vfs::FileSystem &VFS, std::string &Path,
return false;
}

bool findVCToolChainViaSetupConfig(vfs::FileSystem &VFS, std::string &Path,
ToolsetLayout &VSLayout) {
bool findVCToolChainViaSetupConfig(vfs::FileSystem &VFS,
std::optional<StringRef> VCToolsVersion,
std::string &Path, ToolsetLayout &VSLayout) {
#if !defined(USE_MSVC_SETUP_API)
return false;
#else
Expand Down Expand Up @@ -677,17 +678,24 @@ bool findVCToolChainViaSetupConfig(vfs::FileSystem &VFS, std::string &Path,
std::string VCRootPath;
convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);

SmallString<256> ToolsVersionFilePath(VCRootPath);
sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
"Microsoft.VCToolsVersion.default.txt");
std::string ToolsVersion;
if (VCToolsVersion.has_value()) {
ToolsVersion = *VCToolsVersion;
} else {
SmallString<256> ToolsVersionFilePath(VCRootPath);
sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
"Microsoft.VCToolsVersion.default.txt");

auto ToolsVersionFile = MemoryBuffer::getFile(ToolsVersionFilePath);
if (!ToolsVersionFile)
return false;

ToolsVersion = ToolsVersionFile->get()->getBuffer().rtrim();
}

auto ToolsVersionFile = MemoryBuffer::getFile(ToolsVersionFilePath);
if (!ToolsVersionFile)
return false;

SmallString<256> ToolchainPath(VCRootPath);
sys::path::append(ToolchainPath, "Tools", "MSVC",
ToolsVersionFile->get()->getBuffer().rtrim());
sys::path::append(ToolchainPath, "Tools", "MSVC", ToolsVersion);
auto Status = VFS.status(ToolchainPath);
if (!Status || !Status->isDirectory())
return false;
Expand Down

0 comments on commit af5f468

Please sign in to comment.