Index: lib/Driver/MSVCToolChain.cpp =================================================================== --- lib/Driver/MSVCToolChain.cpp +++ lib/Driver/MSVCToolChain.cpp @@ -205,6 +205,21 @@ #endif // USE_WIN32 } +// Convert LLVM's ArchType +// to the corresponding name of Windows SDK libraries subfolder +static StringRef getWindowsSDKArch(llvm::Triple::ArchType arch) { + switch (arch) { + case llvm::Triple::x86: + return "x86"; + case llvm::Triple::x86_64: + return "x64"; + case llvm::Triple::arm: + return "arm"; + default: + return ""; + } +} + /// \brief Get Windows SDK installation directory. bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major, int &minor) const { @@ -263,22 +278,77 @@ if (!found) return false; - llvm::sys::path::append(libPath, "um"); - switch (getArch()) { - case llvm::Triple::x86: - llvm::sys::path::append(libPath, "x86"); - break; - case llvm::Triple::x86_64: - llvm::sys::path::append(libPath, "x64"); - break; - case llvm::Triple::arm: - llvm::sys::path::append(libPath, "arm"); - break; - default: + const StringRef archName = getWindowsSDKArch(getArch()); + if (archName.empty()) return false; - } + llvm::sys::path::append(libPath, "um", archName); + } + + path = libPath.str(); + return true; +} + +// Check if the Include path of a chosen version of Visual Studio contains +// specific header files. If not, they are probably shipped with Universal CRT. +bool clang::driver::toolchains::MSVCToolChain::useUniversalCRT() const +{ + std::string VSDir; + if (!getVisualStudioInstallDir(VSDir)) + return false; + + llvm::SmallString<128> testPath(VSDir); + llvm::sys::path::append(testPath, "VC\\include\\stdlib.h"); + + return !llvm::sys::fs::exists(testPath); +} + +bool MSVCToolChain::getUniversalCRTSdkDir(std::string &path, + std::string &ucrtVersion) const +{ + // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry + // for the specific key "KitsRoot10". So do we. + if (!getSystemRegistryString( + "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", + "KitsRoot10", path, nullptr)) + return false; + + ucrtVersion.clear(); + + // 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 name = llvm::sys::path::filename(dirIt->path()); + if (name > ucrtVersion) + ucrtVersion = name; } + return !ucrtVersion.empty(); +} + +bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &path) const +{ + std::string universalCRTSdkPath; + std::string ucrtVersion; + + path.clear(); + if (!getUniversalCRTSdkDir(universalCRTSdkPath, ucrtVersion)) + return false; + + StringRef archName = getWindowsSDKArch(getArch()); + if (archName.empty()) + return false; + + llvm::SmallString<128> libPath(universalCRTSdkPath); + llvm::sys::path::append(libPath, "Lib", ucrtVersion, "ucrt", archName); + path = libPath.str(); return true; } @@ -460,6 +530,17 @@ if (getVisualStudioInstallDir(VSDir)) { AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include"); + if (useUniversalCRT()) { + std::string universalCRTSdkPath; + std::string ucrtVersion; + if (getUniversalCRTSdkDir(universalCRTSdkPath, ucrtVersion)) { + llvm::SmallString<128> ucrtIncludePath(universalCRTSdkPath); + llvm::sys::path::append(ucrtIncludePath, + "Include", ucrtVersion, "ucrt"); + addSystemInclude(DriverArgs, CC1Args, ucrtIncludePath); + } + } + std::string WindowsSDKDir; int major, minor; if (getWindowsSDKDir(WindowsSDKDir, major, minor)) { Index: lib/Driver/ToolChains.h =================================================================== --- lib/Driver/ToolChains.h +++ lib/Driver/ToolChains.h @@ -840,6 +840,11 @@ bool getWindowsSDKDir(std::string &path, int &major, int &minor) const; bool getWindowsSDKLibraryPath(std::string &path) const; + /// \brief Check if Universal CRT should be used if available + bool useUniversalCRT() const; + bool getUniversalCRTSdkDir(std::string &path, + std::string &ucrtVersion) const; + bool getUniversalCRTLibraryPath(std::string &path) const; bool getVisualStudioInstallDir(std::string &path) const; bool getVisualStudioBinariesFolder(const char *clangProgramPath, std::string &path) const; Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -8953,6 +8953,13 @@ Args.MakeArgString(std::string("-libpath:") + LibDir.c_str())); } + if (MSVC.useUniversalCRT()) { + std::string UniversalCRTLibPath; + if (MSVC.getUniversalCRTLibraryPath(UniversalCRTLibPath)) + CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + + UniversalCRTLibPath.c_str())); + } + std::string WindowsSdkLibPath; if (MSVC.getWindowsSDKLibraryPath(WindowsSdkLibPath)) CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +