diff options
Diffstat (limited to 'clang/lib/Driver/WindowsToolChain.cpp')
-rw-r--r-- | clang/lib/Driver/WindowsToolChain.cpp | 189 |
1 files changed, 99 insertions, 90 deletions
diff --git a/clang/lib/Driver/WindowsToolChain.cpp b/clang/lib/Driver/WindowsToolChain.cpp index ca4aa6780b5..117ca2b5d82 100644 --- a/clang/lib/Driver/WindowsToolChain.cpp +++ b/clang/lib/Driver/WindowsToolChain.cpp @@ -18,7 +18,6 @@ #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Path.h" // Include the necessary headers to interface with the Windows registry and // environment. @@ -77,61 +76,65 @@ bool Windows::isPICDefaultForced() const { return getArch() == llvm::Triple::x86_64; } +#ifdef USE_WIN32 +static bool readFullStringValue(HKEY hkey, const char *valueName, + std::string &value) { + // FIXME: We should be using the W versions of the registry functions, but + // doing so requires UTF8 / UTF16 conversions similar to how we handle command + // line arguments. The UTF8 conversion functions are not exposed publicly + // from LLVM though, so in order to do this we will probably need to create + // a registry abstraction in LLVMSupport that is Windows only. + DWORD result = 0; + DWORD valueSize = 0; + DWORD type = 0; + // First just query for the required size. + result = RegQueryValueEx(hkey, valueName, NULL, &type, NULL, &valueSize); + if (result != ERROR_SUCCESS || type != REG_SZ) + return false; + std::vector<BYTE> buffer(valueSize); + result = RegQueryValueEx(hkey, valueName, NULL, NULL, &buffer[0], &valueSize); + if (result == ERROR_SUCCESS) + value.assign(reinterpret_cast<const char *>(buffer.data())); + return result; +} +#endif + /// \brief Read registry string. /// This also supports a means to look for high-versioned keys by use /// of a $VERSION placeholder in the key path. /// $VERSION in the key path is a placeholder for the version number, /// causing the highest value path to be searched for and used. -/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". -/// There can be additional characters in the component. Only the numberic -/// characters are compared. +/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". +/// There can be additional characters in the component. Only the numeric +/// characters are compared. This function only searches HKLM. static bool getSystemRegistryString(const char *keyPath, const char *valueName, - char *value, size_t maxLength) { + std::string &value, std::string *phValue) { #ifndef USE_WIN32 return false; #else - HKEY hRootKey = NULL; + HKEY hRootKey = HKEY_LOCAL_MACHINE; HKEY hKey = NULL; - const char* subKey = NULL; - DWORD valueType; - DWORD valueSize = maxLength - 1; + DWORD valueSize = 0; long lResult; bool returnValue = false; - if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { - hRootKey = HKEY_CLASSES_ROOT; - subKey = keyPath + 18; - } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { - hRootKey = HKEY_USERS; - subKey = keyPath + 11; - } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { - hRootKey = HKEY_LOCAL_MACHINE; - subKey = keyPath + 19; - } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { - hRootKey = HKEY_CURRENT_USER; - subKey = keyPath + 18; - } else { - return false; - } - - const char *placeHolder = strstr(subKey, "$VERSION"); - char bestName[256]; - bestName[0] = '\0'; + const char *placeHolder = strstr(keyPath, "$VERSION"); + std::string bestName; // If we have a $VERSION placeholder, do the highest-version search. if (placeHolder) { const char *keyEnd = placeHolder - 1; const char *nextKey = placeHolder; // Find end of previous key. - while ((keyEnd > subKey) && (*keyEnd != '\\')) + while ((keyEnd > keyPath) && (*keyEnd != '\\')) keyEnd--; // Find end of key containing $VERSION. while (*nextKey && (*nextKey != '\\')) nextKey++; - size_t partialKeyLength = keyEnd - subKey; + size_t partialKeyLength = keyEnd - keyPath; char partialKey[256]; if (partialKeyLength > sizeof(partialKey)) partialKeyLength = sizeof(partialKey); - strncpy(partialKey, subKey, partialKeyLength); + strncpy(partialKey, keyPath, partialKeyLength); partialKey[partialKeyLength] = '\0'; HKEY hTopKey = NULL; lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY, @@ -158,18 +161,18 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName, if (dvalue > bestValue) { // Test that InstallDir is indeed there before keeping this index. // Open the chosen key path remainder. - strcpy(bestName, keyName); + bestName = keyName; // Append rest of key. - strncat(bestName, nextKey, sizeof(bestName) - 1); - bestName[sizeof(bestName) - 1] = '\0'; - lResult = RegOpenKeyEx(hTopKey, bestName, 0, + bestName.append(nextKey); + lResult = RegOpenKeyEx(hTopKey, bestName.c_str(), 0, KEY_READ | KEY_WOW64_32KEY, &hKey); if (lResult == ERROR_SUCCESS) { - lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, - (LPBYTE)value, &valueSize); + lResult = readFullStringValue(hKey, valueName, value); if (lResult == ERROR_SUCCESS) { bestIndex = (int)index; bestValue = dvalue; + if (phValue) + *phValue = bestName; returnValue = true; } RegCloseKey(hKey); @@ -180,13 +183,14 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName, RegCloseKey(hTopKey); } } else { - lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ | KEY_WOW64_32KEY, - &hKey); + lResult = + RegOpenKeyEx(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); if (lResult == ERROR_SUCCESS) { - lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, - (LPBYTE)value, &valueSize); + lResult = readFullStringValue(hKey, valueName, value); if (lResult == ERROR_SUCCESS) returnValue = true; + if (phValue) + phValue->clear(); RegCloseKey(hKey); } } @@ -195,61 +199,50 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName, } /// \brief Get Windows SDK installation directory. -static bool getWindowsSDKDir(std::string &path) { - char windowsSDKInstallDir[256]; +bool Windows::getWindowsSDKDir(std::string &path, int &major, + int &minor) const { + std::string sdkVersion; // Try the Windows registry. bool hasSDKDir = getSystemRegistryString( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", - "InstallationFolder", - windowsSDKInstallDir, - sizeof(windowsSDKInstallDir) - 1); - // If we have both vc80 and vc90, pick version we were compiled with. - if (hasSDKDir && windowsSDKInstallDir[0]) { - path = windowsSDKInstallDir; - return true; - } - return false; + "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", + "InstallationFolder", path, &sdkVersion); + if (!sdkVersion.empty()) + ::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor); + return hasSDKDir && !path.empty(); } // Get Visual Studio installation directory. -static bool getVisualStudioDir(std::string &path) { +bool Windows::getVisualStudioDir(std::string &path) const { // First check the environment variables that vsvars32.bat sets. - const char* vcinstalldir = getenv("VCINSTALLDIR"); + const char *vcinstalldir = getenv("VCINSTALLDIR"); if (vcinstalldir) { - char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC")); - if (p) - *p = '\0'; path = vcinstalldir; + path = path.substr(0, path.find("\\VC")); return true; } - char vsIDEInstallDir[256]; - char vsExpressIDEInstallDir[256]; + std::string vsIDEInstallDir; + std::string vsExpressIDEInstallDir; // Then try the windows registry. - bool hasVCDir = getSystemRegistryString( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", - "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1); - bool hasVCExpressDir = getSystemRegistryString( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION", - "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1); - // If we have both vc80 and vc90, pick version we were compiled with. - if (hasVCDir && vsIDEInstallDir[0]) { - char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); - if (p) - *p = '\0'; - path = vsIDEInstallDir; + bool hasVCDir = + getSystemRegistryString("SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", + "InstallDir", vsIDEInstallDir, nullptr); + if (hasVCDir && !vsIDEInstallDir.empty()) { + path = vsIDEInstallDir.substr(0, vsIDEInstallDir.find("\\Common7\\IDE")); return true; } - if (hasVCExpressDir && vsExpressIDEInstallDir[0]) { - char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE"); - if (p) - *p = '\0'; - path = vsExpressIDEInstallDir; + bool hasVCExpressDir = + getSystemRegistryString("SOFTWARE\\Microsoft\\VCExpress\\$VERSION", + "InstallDir", vsExpressIDEInstallDir, nullptr); + if (hasVCExpressDir && !vsExpressIDEInstallDir.empty()) { + path = vsExpressIDEInstallDir.substr( + 0, vsIDEInstallDir.find("\\Common7\\IDE")); return true; } // Try the environment. + const char *vs120comntools = getenv("VS120COMNTOOLS"); const char *vs100comntools = getenv("VS100COMNTOOLS"); const char *vs90comntools = getenv("VS90COMNTOOLS"); const char *vs80comntools = getenv("VS80COMNTOOLS"); @@ -257,7 +250,9 @@ static bool getVisualStudioDir(std::string &path) { const char *vscomntools = nullptr; // Find any version we can - if (vs100comntools) + if (vs120comntools) + vscomntools = vs120comntools; + else if (vs100comntools) vscomntools = vs100comntools; else if (vs90comntools) vscomntools = vs90comntools; @@ -272,6 +267,15 @@ static bool getVisualStudioDir(std::string &path) { return false; } +void Windows::AddSystemIncludeWithSubfolder(const ArgList &DriverArgs, + ArgStringList &CC1Args, + const std::string &folder, + const char *subfolder) const { + llvm::SmallString<128> path(folder); + llvm::sys::path::append(path, subfolder); + addSystemInclude(DriverArgs, CC1Args, path.str()); +} + void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { if (DriverArgs.hasArg(options::OPT_nostdinc)) @@ -298,23 +302,28 @@ void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs, } std::string VSDir; - std::string WindowsSDKDir; // When built with access to the proper Windows APIs, try to actually find // the correct include paths first. if (getVisualStudioDir(VSDir)) { - SmallString<128> P; - P = VSDir; - llvm::sys::path::append(P, "VC\\include"); - addSystemInclude(DriverArgs, CC1Args, P.str()); - if (getWindowsSDKDir(WindowsSDKDir)) { - P = WindowsSDKDir; - llvm::sys::path::append(P, "include"); - addSystemInclude(DriverArgs, CC1Args, P.str()); + AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include"); + + std::string WindowsSDKDir; + int major, minor; + if (getWindowsSDKDir(WindowsSDKDir, major, minor)) { + if (major >= 8) { + AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, + "include\\shared"); + AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, + "include\\um"); + AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, + "include\\winrt"); + } else { + AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, + "include"); + } } else { - P = VSDir; - llvm::sys::path::append(P, "VC\\PlatformSDK\\Include"); - addSystemInclude(DriverArgs, CC1Args, P.str()); + addSystemInclude(DriverArgs, CC1Args, VSDir); } return; } |