[Driver] Add support for Windows 10 SDK

Summary:
With Windows 10 SDK, Include and Lib directories now contain an additional subfolder with the name that corresponds to the full version of the SDK, for example:
  - C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\um
  - C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\um\x64


Reviewers: ruiu, rnk

Subscribers: majnemer, cfe-commits

Differential Revision: http://reviews.llvm.org/D12832

llvm-svn: 248463
This commit is contained in:
Igor Kudrin 2015-09-24 05:16:36 +00:00
parent 49655f806f
commit f2e7524356
2 changed files with 102 additions and 68 deletions

View File

@ -220,27 +220,88 @@ static StringRef getWindowsSDKArch(llvm::Triple::ArchType Arch) {
} }
} }
// Find the most recent version of Universal CRT or Windows 10 SDK.
// vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
// directory by name and uses the last one of the list.
// So we compare entry names lexicographically to find the greatest one.
static bool getWindows10SDKVersion(const std::string &SDKPath,
std::string &SDKVersion) {
SDKVersion.clear();
std::error_code EC;
llvm::SmallString<128> IncludePath(SDKPath);
llvm::sys::path::append(IncludePath, "Include");
for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
DirIt != DirEnd && !EC; DirIt.increment(EC)) {
if (!llvm::sys::fs::is_directory(DirIt->path()))
continue;
StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
// If WDK is installed, there could be subfolders like "wdf" in the
// "Include" directory.
// Allow only directories which names start with "10.".
if (!CandidateName.startswith("10."))
continue;
if (CandidateName > SDKVersion)
SDKVersion = CandidateName;
}
return !SDKVersion.empty();
}
/// \brief Get Windows SDK installation directory. /// \brief Get Windows SDK installation directory.
bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major, bool MSVCToolChain::getWindowsSDKDir(std::string &Path, int &Major,
int &minor) const { std::string &WindowsSDKIncludeVersion,
std::string sdkVersion; std::string &WindowsSDKLibVersion) const {
std::string RegistrySDKVersion;
// Try the Windows registry. // Try the Windows registry.
bool hasSDKDir = getSystemRegistryString( if (!getSystemRegistryString(
"SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
"InstallationFolder", path, &sdkVersion); "InstallationFolder", Path, &RegistrySDKVersion))
if (!sdkVersion.empty()) return false;
std::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor); if (Path.empty() || RegistrySDKVersion.empty())
return hasSDKDir && !path.empty(); return false;
WindowsSDKIncludeVersion.clear();
WindowsSDKLibVersion.clear();
Major = 0;
std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
if (Major <= 7)
return true;
if (Major == 8) {
// Windows SDK 8.x installs libraries in a folder whose names depend on the
// version of the OS you're targeting. By default choose the newest, which
// usually corresponds to the version of the OS you've installed the SDK on.
const char *Tests[] = {"winv6.3", "win8", "win7"};
for (const char *Test : Tests) {
llvm::SmallString<128> TestPath(Path);
llvm::sys::path::append(TestPath, "Lib", Test);
if (llvm::sys::fs::exists(TestPath.c_str())) {
WindowsSDKLibVersion = Test;
break;
}
}
return !WindowsSDKLibVersion.empty();
}
if (Major == 10) {
if (!getWindows10SDKVersion(Path, WindowsSDKIncludeVersion))
return false;
WindowsSDKLibVersion = WindowsSDKIncludeVersion;
return true;
}
// Unsupported SDK version
return false;
} }
// Gets the library path required to link against the Windows SDK. // Gets the library path required to link against the Windows SDK.
bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const { bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
std::string sdkPath; std::string sdkPath;
int sdkMajor = 0; int sdkMajor = 0;
int sdkMinor = 0; std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
path.clear(); path.clear();
if (!getWindowsSDKDir(sdkPath, sdkMajor, sdkMinor)) if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
windowsSDKLibVersion))
return false; return false;
llvm::SmallString<128> libPath(sdkPath); llvm::SmallString<128> libPath(sdkPath);
@ -260,28 +321,10 @@ bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
return false; return false;
} }
} else { } else {
// Windows SDK 8.x installs libraries in a folder whose names depend on the
// version of the OS you're targeting. By default choose the newest, which
// usually corresponds to the version of the OS you've installed the SDK on.
const char *tests[] = {"winv6.3", "win8", "win7"};
bool found = false;
for (const char *test : tests) {
llvm::SmallString<128> testPath(libPath);
llvm::sys::path::append(testPath, test);
if (llvm::sys::fs::exists(testPath.c_str())) {
libPath = testPath;
found = true;
break;
}
}
if (!found)
return false;
const StringRef archName = getWindowsSDKArch(getArch()); const StringRef archName = getWindowsSDKArch(getArch());
if (archName.empty()) if (archName.empty())
return false; return false;
llvm::sys::path::append(libPath, "um", archName); llvm::sys::path::append(libPath, windowsSDKLibVersion, "um", archName);
} }
path = libPath.str(); path = libPath.str();
@ -307,25 +350,7 @@ bool MSVCToolChain::getUniversalCRTSdkDir(std::string &Path,
Path, nullptr)) Path, nullptr))
return false; return false;
UCRTVersion.clear(); return getWindows10SDKVersion(Path, UCRTVersion);
// Find the most recent version of Universal CRT.
// vcvarsqueryregistry.bat sorts entries in the include directory by names and
// uses the last one of the list.
// So we compare entry names lexicographically to find the greatest one.
std::error_code EC;
llvm::SmallString<128> IncludePath(Path);
llvm::sys::path::append(IncludePath, "Include");
for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
DirIt != DirEnd && !EC; DirIt.increment(EC)) {
if (!llvm::sys::fs::is_directory(DirIt->path()))
continue;
StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
if (CandidateName > UCRTVersion)
UCRTVersion = CandidateName;
}
return !UCRTVersion.empty();
} }
bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const { bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
@ -483,12 +508,12 @@ bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
return false; return false;
} }
void MSVCToolChain::AddSystemIncludeWithSubfolder(const ArgList &DriverArgs, void MSVCToolChain::AddSystemIncludeWithSubfolder(
ArgStringList &CC1Args, const ArgList &DriverArgs, ArgStringList &CC1Args,
const std::string &folder, const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
const char *subfolder) const { const Twine &subfolder3) const {
llvm::SmallString<128> path(folder); llvm::SmallString<128> path(folder);
llvm::sys::path::append(path, subfolder); llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
addSystemInclude(DriverArgs, CC1Args, path); addSystemInclude(DriverArgs, CC1Args, path);
} }
@ -498,9 +523,8 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return; return;
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> P(getDriver().ResourceDir); AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
llvm::sys::path::append(P, "include"); "include");
addSystemInclude(DriverArgs, CC1Args, P);
} }
if (DriverArgs.hasArg(options::OPT_nostdlibinc)) if (DriverArgs.hasArg(options::OPT_nostdlibinc))
@ -528,23 +552,29 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
std::string UniversalCRTSdkPath; std::string UniversalCRTSdkPath;
std::string UCRTVersion; std::string UCRTVersion;
if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) { if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
llvm::SmallString<128> UCRTIncludePath(UniversalCRTSdkPath); AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
llvm::sys::path::append(UCRTIncludePath, "Include", UCRTVersion, "Include", UCRTVersion, "ucrt");
"ucrt");
addSystemInclude(DriverArgs, CC1Args, UCRTIncludePath);
} }
} }
std::string WindowsSDKDir; std::string WindowsSDKDir;
int major, minor; int major;
if (getWindowsSDKDir(WindowsSDKDir, major, minor)) { std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
if (getWindowsSDKDir(WindowsSDKDir, major, windowsSDKIncludeVersion,
windowsSDKLibVersion)) {
if (major >= 8) { if (major >= 8) {
// Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
// Anyway, llvm::sys::path::append is able to manage it.
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"include\\shared"); "include", windowsSDKIncludeVersion,
"shared");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"include\\um"); "include", windowsSDKIncludeVersion,
"um");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"include\\winrt"); "include", windowsSDKIncludeVersion,
"winrt");
} else { } else {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"include"); "include");

View File

@ -871,7 +871,9 @@ public:
const llvm::opt::ArgList &DriverArgs, const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override; llvm::opt::ArgStringList &CC1Args) const override;
bool getWindowsSDKDir(std::string &path, int &major, int &minor) const; bool getWindowsSDKDir(std::string &path, int &major,
std::string &windowsSDKIncludeVersion,
std::string &windowsSDKLibVersion) const;
bool getWindowsSDKLibraryPath(std::string &path) const; bool getWindowsSDKLibraryPath(std::string &path) const;
/// \brief Check if Universal CRT should be used if available /// \brief Check if Universal CRT should be used if available
bool useUniversalCRT(std::string &visualStudioDir) const; bool useUniversalCRT(std::string &visualStudioDir) const;
@ -889,7 +891,9 @@ protected:
void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs, void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args, llvm::opt::ArgStringList &CC1Args,
const std::string &folder, const std::string &folder,
const char *subfolder) const; const Twine &subfolder1,
const Twine &subfolder2 = "",
const Twine &subfolder3 = "") const;
Tool *buildLinker() const override; Tool *buildLinker() const override;
Tool *buildAssembler() const override; Tool *buildAssembler() const override;