• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "ToolChains.h"
11 #include "clang/Basic/CharInfo.h"
12 #include "clang/Basic/Version.h"
13 #include "clang/Driver/Compilation.h"
14 #include "clang/Driver/Driver.h"
15 #include "clang/Driver/DriverDiagnostic.h"
16 #include "clang/Driver/Options.h"
17 #include "llvm/Config/llvm-config.h"
18 #include "llvm/Option/Arg.h"
19 #include "llvm/Option/ArgList.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/Path.h"
22 
23 // Include the necessary headers to interface with the Windows registry and
24 // environment.
25 #if defined(LLVM_ON_WIN32)
26 #define USE_WIN32
27 #endif
28 
29 #ifdef USE_WIN32
30   #define WIN32_LEAN_AND_MEAN
31   #define NOGDI
32   #define NOMINMAX
33   #include <windows.h>
34 #endif
35 
36 using namespace clang::driver;
37 using namespace clang::driver::toolchains;
38 using namespace clang;
39 using namespace llvm::opt;
40 
Windows(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)41 Windows::Windows(const Driver &D, const llvm::Triple& Triple,
42                  const ArgList &Args)
43   : ToolChain(D, Triple, Args) {
44 }
45 
buildLinker() const46 Tool *Windows::buildLinker() const {
47   return new tools::visualstudio::Link(*this);
48 }
49 
buildAssembler() const50 Tool *Windows::buildAssembler() const {
51   if (getTriple().isOSBinFormatMachO())
52     return new tools::darwin::Assemble(*this);
53   getDriver().Diag(clang::diag::err_no_external_assembler);
54   return nullptr;
55 }
56 
IsIntegratedAssemblerDefault() const57 bool Windows::IsIntegratedAssemblerDefault() const {
58   return true;
59 }
60 
IsUnwindTablesDefault() const61 bool Windows::IsUnwindTablesDefault() const {
62   // FIXME: LLVM's lowering of Win64 data is broken right now.  MSVC's linker
63   // says that our object files provide invalid .pdata contributions.  Until
64   // that is fixed, don't ask for unwind tables.
65   return false;
66   //return getArch() == llvm::Triple::x86_64;
67 }
68 
isPICDefault() const69 bool Windows::isPICDefault() const {
70   return getArch() == llvm::Triple::x86_64;
71 }
72 
isPIEDefault() const73 bool Windows::isPIEDefault() const {
74   return false;
75 }
76 
isPICDefaultForced() const77 bool Windows::isPICDefaultForced() const {
78   return getArch() == llvm::Triple::x86_64;
79 }
80 
81 /// \brief Read registry string.
82 /// This also supports a means to look for high-versioned keys by use
83 /// of a $VERSION placeholder in the key path.
84 /// $VERSION in the key path is a placeholder for the version number,
85 /// causing the highest value path to be searched for and used.
86 /// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
87 /// There can be additional characters in the component.  Only the numberic
88 /// characters are compared.
getSystemRegistryString(const char * keyPath,const char * valueName,char * value,size_t maxLength)89 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
90                                     char *value, size_t maxLength) {
91 #ifndef USE_WIN32
92   return false;
93 #else
94   HKEY hRootKey = NULL;
95   HKEY hKey = NULL;
96   const char* subKey = NULL;
97   DWORD valueType;
98   DWORD valueSize = maxLength - 1;
99   long lResult;
100   bool returnValue = false;
101 
102   if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
103     hRootKey = HKEY_CLASSES_ROOT;
104     subKey = keyPath + 18;
105   } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
106     hRootKey = HKEY_USERS;
107     subKey = keyPath + 11;
108   } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
109     hRootKey = HKEY_LOCAL_MACHINE;
110     subKey = keyPath + 19;
111   } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
112     hRootKey = HKEY_CURRENT_USER;
113     subKey = keyPath + 18;
114   } else {
115     return false;
116   }
117 
118   const char *placeHolder = strstr(subKey, "$VERSION");
119   char bestName[256];
120   bestName[0] = '\0';
121   // If we have a $VERSION placeholder, do the highest-version search.
122   if (placeHolder) {
123     const char *keyEnd = placeHolder - 1;
124     const char *nextKey = placeHolder;
125     // Find end of previous key.
126     while ((keyEnd > subKey) && (*keyEnd != '\\'))
127       keyEnd--;
128     // Find end of key containing $VERSION.
129     while (*nextKey && (*nextKey != '\\'))
130       nextKey++;
131     size_t partialKeyLength = keyEnd - subKey;
132     char partialKey[256];
133     if (partialKeyLength > sizeof(partialKey))
134       partialKeyLength = sizeof(partialKey);
135     strncpy(partialKey, subKey, partialKeyLength);
136     partialKey[partialKeyLength] = '\0';
137     HKEY hTopKey = NULL;
138     lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
139                            &hTopKey);
140     if (lResult == ERROR_SUCCESS) {
141       char keyName[256];
142       int bestIndex = -1;
143       double bestValue = 0.0;
144       DWORD index, size = sizeof(keyName) - 1;
145       for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
146           NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
147         const char *sp = keyName;
148         while (*sp && !isDigit(*sp))
149           sp++;
150         if (!*sp)
151           continue;
152         const char *ep = sp + 1;
153         while (*ep && (isDigit(*ep) || (*ep == '.')))
154           ep++;
155         char numBuf[32];
156         strncpy(numBuf, sp, sizeof(numBuf) - 1);
157         numBuf[sizeof(numBuf) - 1] = '\0';
158         double dvalue = strtod(numBuf, NULL);
159         if (dvalue > bestValue) {
160           // Test that InstallDir is indeed there before keeping this index.
161           // Open the chosen key path remainder.
162           strcpy(bestName, keyName);
163           // Append rest of key.
164           strncat(bestName, nextKey, sizeof(bestName) - 1);
165           bestName[sizeof(bestName) - 1] = '\0';
166           lResult = RegOpenKeyEx(hTopKey, bestName, 0,
167                                  KEY_READ | KEY_WOW64_32KEY, &hKey);
168           if (lResult == ERROR_SUCCESS) {
169             lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
170               (LPBYTE)value, &valueSize);
171             if (lResult == ERROR_SUCCESS) {
172               bestIndex = (int)index;
173               bestValue = dvalue;
174               returnValue = true;
175             }
176             RegCloseKey(hKey);
177           }
178         }
179         size = sizeof(keyName) - 1;
180       }
181       RegCloseKey(hTopKey);
182     }
183   } else {
184     lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ | KEY_WOW64_32KEY,
185                            &hKey);
186     if (lResult == ERROR_SUCCESS) {
187       lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
188         (LPBYTE)value, &valueSize);
189       if (lResult == ERROR_SUCCESS)
190         returnValue = true;
191       RegCloseKey(hKey);
192     }
193   }
194   return returnValue;
195 #endif // USE_WIN32
196 }
197 
198 /// \brief Get Windows SDK installation directory.
getWindowsSDKDir(std::string & path)199 static bool getWindowsSDKDir(std::string &path) {
200   char windowsSDKInstallDir[256];
201   // Try the Windows registry.
202   bool hasSDKDir = getSystemRegistryString(
203    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
204                                            "InstallationFolder",
205                                            windowsSDKInstallDir,
206                                            sizeof(windowsSDKInstallDir) - 1);
207     // If we have both vc80 and vc90, pick version we were compiled with.
208   if (hasSDKDir && windowsSDKInstallDir[0]) {
209     path = windowsSDKInstallDir;
210     return true;
211   }
212   return false;
213 }
214 
215 // Get Visual Studio installation directory.
getVisualStudioDir(std::string & path)216 static bool getVisualStudioDir(std::string &path) {
217   // First check the environment variables that vsvars32.bat sets.
218   const char* vcinstalldir = getenv("VCINSTALLDIR");
219   if (vcinstalldir) {
220     char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
221     if (p)
222       *p = '\0';
223     path = vcinstalldir;
224     return true;
225   }
226 
227   char vsIDEInstallDir[256];
228   char vsExpressIDEInstallDir[256];
229   // Then try the windows registry.
230   bool hasVCDir = getSystemRegistryString(
231     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
232     "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
233   bool hasVCExpressDir = getSystemRegistryString(
234     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
235     "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
236     // If we have both vc80 and vc90, pick version we were compiled with.
237   if (hasVCDir && vsIDEInstallDir[0]) {
238     char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
239     if (p)
240       *p = '\0';
241     path = vsIDEInstallDir;
242     return true;
243   }
244 
245   if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
246     char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
247     if (p)
248       *p = '\0';
249     path = vsExpressIDEInstallDir;
250     return true;
251   }
252 
253   // Try the environment.
254   const char *vs100comntools = getenv("VS100COMNTOOLS");
255   const char *vs90comntools = getenv("VS90COMNTOOLS");
256   const char *vs80comntools = getenv("VS80COMNTOOLS");
257 
258   const char *vscomntools = nullptr;
259 
260   // Find any version we can
261   if (vs100comntools)
262     vscomntools = vs100comntools;
263   else if (vs90comntools)
264     vscomntools = vs90comntools;
265   else if (vs80comntools)
266     vscomntools = vs80comntools;
267 
268   if (vscomntools && *vscomntools) {
269     const char *p = strstr(vscomntools, "\\Common7\\Tools");
270     path = p ? std::string(vscomntools, p) : vscomntools;
271     return true;
272   }
273   return false;
274 }
275 
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const276 void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
277                                         ArgStringList &CC1Args) const {
278   if (DriverArgs.hasArg(options::OPT_nostdinc))
279     return;
280 
281   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
282     SmallString<128> P(getDriver().ResourceDir);
283     llvm::sys::path::append(P, "include");
284     addSystemInclude(DriverArgs, CC1Args, P.str());
285   }
286 
287   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
288     return;
289 
290   // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
291   if (const char *cl_include_dir = getenv("INCLUDE")) {
292     SmallVector<StringRef, 8> Dirs;
293     StringRef(cl_include_dir)
294         .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
295     for (StringRef Dir : Dirs)
296       addSystemInclude(DriverArgs, CC1Args, Dir);
297     if (!Dirs.empty())
298       return;
299   }
300 
301   std::string VSDir;
302   std::string WindowsSDKDir;
303 
304   // When built with access to the proper Windows APIs, try to actually find
305   // the correct include paths first.
306   if (getVisualStudioDir(VSDir)) {
307     SmallString<128> P;
308     P = VSDir;
309     llvm::sys::path::append(P, "VC\\include");
310     addSystemInclude(DriverArgs, CC1Args, P.str());
311     if (getWindowsSDKDir(WindowsSDKDir)) {
312       P = WindowsSDKDir;
313       llvm::sys::path::append(P, "include");
314       addSystemInclude(DriverArgs, CC1Args, P.str());
315     } else {
316       P = VSDir;
317       llvm::sys::path::append(P, "VC\\PlatformSDK\\Include");
318       addSystemInclude(DriverArgs, CC1Args, P.str());
319     }
320     return;
321   }
322 
323   // As a fallback, select default install paths.
324   // FIXME: Don't guess drives and paths like this on Windows.
325   const StringRef Paths[] = {
326     "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
327     "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
328     "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
329     "C:/Program Files/Microsoft Visual Studio 8/VC/include",
330     "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
331   };
332   addSystemIncludes(DriverArgs, CC1Args, Paths);
333 }
334 
AddClangCXXStdlibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const335 void Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
336                                            ArgStringList &CC1Args) const {
337   // FIXME: There should probably be logic here to find libc++ on Windows.
338 }
339