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/ADT/StringExtras.h"
18 #include "llvm/Config/llvm-config.h"
19 #include "llvm/Option/Arg.h"
20 #include "llvm/Option/ArgList.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/FileSystem.h"
23 #include "llvm/Support/Process.h"
24 #include <cstdio>
25 
26 // Include the necessary headers to interface with the Windows registry and
27 // environment.
28 #if defined(LLVM_ON_WIN32)
29 #define USE_WIN32
30 #endif
31 
32 #ifdef USE_WIN32
33   #define WIN32_LEAN_AND_MEAN
34   #define NOGDI
35   #ifndef NOMINMAX
36     #define NOMINMAX
37   #endif
38   #include <windows.h>
39 #endif
40 
41 using namespace clang::driver;
42 using namespace clang::driver::toolchains;
43 using namespace clang;
44 using namespace llvm::opt;
45 
MSVCToolChain(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)46 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple& Triple,
47                              const ArgList &Args)
48   : ToolChain(D, Triple, Args) {
49   getProgramPaths().push_back(getDriver().getInstalledDir());
50   if (getDriver().getInstalledDir() != getDriver().Dir)
51     getProgramPaths().push_back(getDriver().Dir);
52 }
53 
buildLinker() const54 Tool *MSVCToolChain::buildLinker() const {
55   return new tools::visualstudio::Link(*this);
56 }
57 
buildAssembler() const58 Tool *MSVCToolChain::buildAssembler() const {
59   if (getTriple().isOSBinFormatMachO())
60     return new tools::darwin::Assemble(*this);
61   getDriver().Diag(clang::diag::err_no_external_assembler);
62   return nullptr;
63 }
64 
IsIntegratedAssemblerDefault() const65 bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
66   return true;
67 }
68 
IsUnwindTablesDefault() const69 bool MSVCToolChain::IsUnwindTablesDefault() const {
70   // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms
71   // such as ARM and PPC actually require unwind tables, but LLVM doesn't know
72   // how to generate them yet.
73   return getArch() == llvm::Triple::x86_64;
74 }
75 
isPICDefault() const76 bool MSVCToolChain::isPICDefault() const {
77   return getArch() == llvm::Triple::x86_64;
78 }
79 
isPIEDefault() const80 bool MSVCToolChain::isPIEDefault() const {
81   return false;
82 }
83 
isPICDefaultForced() const84 bool MSVCToolChain::isPICDefaultForced() const {
85   return getArch() == llvm::Triple::x86_64;
86 }
87 
88 #ifdef USE_WIN32
readFullStringValue(HKEY hkey,const char * valueName,std::string & value)89 static bool readFullStringValue(HKEY hkey, const char *valueName,
90                                 std::string &value) {
91   // FIXME: We should be using the W versions of the registry functions, but
92   // doing so requires UTF8 / UTF16 conversions similar to how we handle command
93   // line arguments.  The UTF8 conversion functions are not exposed publicly
94   // from LLVM though, so in order to do this we will probably need to create
95   // a registry abstraction in LLVMSupport that is Windows only.
96   DWORD result = 0;
97   DWORD valueSize = 0;
98   DWORD type = 0;
99   // First just query for the required size.
100   result = RegQueryValueEx(hkey, valueName, NULL, &type, NULL, &valueSize);
101   if (result != ERROR_SUCCESS || type != REG_SZ)
102     return false;
103   std::vector<BYTE> buffer(valueSize);
104   result = RegQueryValueEx(hkey, valueName, NULL, NULL, &buffer[0], &valueSize);
105   if (result == ERROR_SUCCESS)
106     value.assign(reinterpret_cast<const char *>(buffer.data()));
107   return result;
108 }
109 #endif
110 
111 /// \brief Read registry string.
112 /// This also supports a means to look for high-versioned keys by use
113 /// of a $VERSION placeholder in the key path.
114 /// $VERSION in the key path is a placeholder for the version number,
115 /// causing the highest value path to be searched for and used.
116 /// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
117 /// There can be additional characters in the component.  Only the numeric
118 /// characters are compared.  This function only searches HKLM.
getSystemRegistryString(const char * keyPath,const char * valueName,std::string & value,std::string * phValue)119 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
120                                     std::string &value, std::string *phValue) {
121 #ifndef USE_WIN32
122   return false;
123 #else
124   HKEY hRootKey = HKEY_LOCAL_MACHINE;
125   HKEY hKey = NULL;
126   long lResult;
127   bool returnValue = false;
128 
129   const char *placeHolder = strstr(keyPath, "$VERSION");
130   std::string bestName;
131   // If we have a $VERSION placeholder, do the highest-version search.
132   if (placeHolder) {
133     const char *keyEnd = placeHolder - 1;
134     const char *nextKey = placeHolder;
135     // Find end of previous key.
136     while ((keyEnd > keyPath) && (*keyEnd != '\\'))
137       keyEnd--;
138     // Find end of key containing $VERSION.
139     while (*nextKey && (*nextKey != '\\'))
140       nextKey++;
141     size_t partialKeyLength = keyEnd - keyPath;
142     char partialKey[256];
143     if (partialKeyLength > sizeof(partialKey))
144       partialKeyLength = sizeof(partialKey);
145     strncpy(partialKey, keyPath, partialKeyLength);
146     partialKey[partialKeyLength] = '\0';
147     HKEY hTopKey = NULL;
148     lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
149                            &hTopKey);
150     if (lResult == ERROR_SUCCESS) {
151       char keyName[256];
152       double bestValue = 0.0;
153       DWORD index, size = sizeof(keyName) - 1;
154       for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
155           NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
156         const char *sp = keyName;
157         while (*sp && !isDigit(*sp))
158           sp++;
159         if (!*sp)
160           continue;
161         const char *ep = sp + 1;
162         while (*ep && (isDigit(*ep) || (*ep == '.')))
163           ep++;
164         char numBuf[32];
165         strncpy(numBuf, sp, sizeof(numBuf) - 1);
166         numBuf[sizeof(numBuf) - 1] = '\0';
167         double dvalue = strtod(numBuf, NULL);
168         if (dvalue > bestValue) {
169           // Test that InstallDir is indeed there before keeping this index.
170           // Open the chosen key path remainder.
171           bestName = keyName;
172           // Append rest of key.
173           bestName.append(nextKey);
174           lResult = RegOpenKeyEx(hTopKey, bestName.c_str(), 0,
175                                  KEY_READ | KEY_WOW64_32KEY, &hKey);
176           if (lResult == ERROR_SUCCESS) {
177             lResult = readFullStringValue(hKey, valueName, value);
178             if (lResult == ERROR_SUCCESS) {
179               bestValue = dvalue;
180               if (phValue)
181                 *phValue = bestName;
182               returnValue = true;
183             }
184             RegCloseKey(hKey);
185           }
186         }
187         size = sizeof(keyName) - 1;
188       }
189       RegCloseKey(hTopKey);
190     }
191   } else {
192     lResult =
193         RegOpenKeyEx(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
194     if (lResult == ERROR_SUCCESS) {
195       lResult = readFullStringValue(hKey, valueName, value);
196       if (lResult == ERROR_SUCCESS)
197         returnValue = true;
198       if (phValue)
199         phValue->clear();
200       RegCloseKey(hKey);
201     }
202   }
203   return returnValue;
204 #endif // USE_WIN32
205 }
206 
207 /// \brief Get Windows SDK installation directory.
getWindowsSDKDir(std::string & path,int & major,int & minor) const208 bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major,
209                                      int &minor) const {
210   std::string sdkVersion;
211   // Try the Windows registry.
212   bool hasSDKDir = getSystemRegistryString(
213       "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
214       "InstallationFolder", path, &sdkVersion);
215   if (!sdkVersion.empty())
216     std::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor);
217   return hasSDKDir && !path.empty();
218 }
219 
220 // Gets the library path required to link against the Windows SDK.
getWindowsSDKLibraryPath(std::string & path) const221 bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
222   std::string sdkPath;
223   int sdkMajor = 0;
224   int sdkMinor = 0;
225 
226   path.clear();
227   if (!getWindowsSDKDir(sdkPath, sdkMajor, sdkMinor))
228     return false;
229 
230   llvm::SmallString<128> libPath(sdkPath);
231   llvm::sys::path::append(libPath, "Lib");
232   if (sdkMajor <= 7) {
233     switch (getArch()) {
234     // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
235     case llvm::Triple::x86:
236       break;
237     case llvm::Triple::x86_64:
238       llvm::sys::path::append(libPath, "x64");
239       break;
240     case llvm::Triple::arm:
241       // It is not necessary to link against Windows SDK 7.x when targeting ARM.
242       return false;
243     default:
244       return false;
245     }
246   } else {
247     // Windows SDK 8.x installs libraries in a folder whose names depend on the
248     // version of the OS you're targeting.  By default choose the newest, which
249     // usually corresponds to the version of the OS you've installed the SDK on.
250     const char *tests[] = {"winv6.3", "win8", "win7"};
251     bool found = false;
252     for (const char *test : tests) {
253       llvm::SmallString<128> testPath(libPath);
254       llvm::sys::path::append(testPath, test);
255       if (llvm::sys::fs::exists(testPath.c_str())) {
256         libPath = testPath;
257         found = true;
258         break;
259       }
260     }
261 
262     if (!found)
263       return false;
264 
265     llvm::sys::path::append(libPath, "um");
266     switch (getArch()) {
267     case llvm::Triple::x86:
268       llvm::sys::path::append(libPath, "x86");
269       break;
270     case llvm::Triple::x86_64:
271       llvm::sys::path::append(libPath, "x64");
272       break;
273     case llvm::Triple::arm:
274       llvm::sys::path::append(libPath, "arm");
275       break;
276     default:
277       return false;
278     }
279   }
280 
281   path = libPath.str();
282   return true;
283 }
284 
285 // Get the location to use for Visual Studio binaries.  The location priority
286 // is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on
287 // system (as reported by the registry).
getVisualStudioBinariesFolder(const char * clangProgramPath,std::string & path) const288 bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath,
289                                                   std::string &path) const {
290   path.clear();
291 
292   SmallString<128> BinDir;
293 
294   // First check the environment variables that vsvars32.bat sets.
295   llvm::Optional<std::string> VcInstallDir =
296       llvm::sys::Process::GetEnv("VCINSTALLDIR");
297   if (VcInstallDir.hasValue()) {
298     BinDir = VcInstallDir.getValue();
299     llvm::sys::path::append(BinDir, "bin");
300   } else {
301     // Next walk the PATH, trying to find a cl.exe in the path.  If we find one,
302     // use that.  However, make sure it's not clang's cl.exe.
303     llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
304     if (OptPath.hasValue()) {
305       const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
306       SmallVector<StringRef, 8> PathSegments;
307       llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
308 
309       for (StringRef PathSegment : PathSegments) {
310         if (PathSegment.empty())
311           continue;
312 
313         SmallString<128> FilePath(PathSegment);
314         llvm::sys::path::append(FilePath, "cl.exe");
315         if (llvm::sys::fs::can_execute(FilePath.c_str()) &&
316             !llvm::sys::fs::equivalent(FilePath.c_str(), clangProgramPath)) {
317           // If we found it on the PATH, use it exactly as is with no
318           // modifications.
319           path = PathSegment;
320           return true;
321         }
322       }
323     }
324 
325     std::string installDir;
326     // With no VCINSTALLDIR and nothing on the PATH, if we can't find it in the
327     // registry then we have no choice but to fail.
328     if (!getVisualStudioInstallDir(installDir))
329       return false;
330 
331     // Regardless of what binary we're ultimately trying to find, we make sure
332     // that this is a Visual Studio directory by checking for cl.exe.  We use
333     // cl.exe instead of other binaries like link.exe because programs such as
334     // GnuWin32 also have a utility called link.exe, so cl.exe is the least
335     // ambiguous.
336     BinDir = installDir;
337     llvm::sys::path::append(BinDir, "VC", "bin");
338     SmallString<128> ClPath(BinDir);
339     llvm::sys::path::append(ClPath, "cl.exe");
340 
341     if (!llvm::sys::fs::can_execute(ClPath.c_str()))
342       return false;
343   }
344 
345   if (BinDir.empty())
346     return false;
347 
348   switch (getArch()) {
349   case llvm::Triple::x86:
350     break;
351   case llvm::Triple::x86_64:
352     llvm::sys::path::append(BinDir, "amd64");
353     break;
354   case llvm::Triple::arm:
355     llvm::sys::path::append(BinDir, "arm");
356     break;
357   default:
358     // Whatever this is, Visual Studio doesn't have a toolchain for it.
359     return false;
360   }
361   path = BinDir.str();
362   return true;
363 }
364 
365 // Get Visual Studio installation directory.
getVisualStudioInstallDir(std::string & path) const366 bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
367   // First check the environment variables that vsvars32.bat sets.
368   const char *vcinstalldir = getenv("VCINSTALLDIR");
369   if (vcinstalldir) {
370     path = vcinstalldir;
371     path = path.substr(0, path.find("\\VC"));
372     return true;
373   }
374 
375   std::string vsIDEInstallDir;
376   std::string vsExpressIDEInstallDir;
377   // Then try the windows registry.
378   bool hasVCDir =
379       getSystemRegistryString("SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
380                               "InstallDir", vsIDEInstallDir, nullptr);
381   if (hasVCDir && !vsIDEInstallDir.empty()) {
382     path = vsIDEInstallDir.substr(0, vsIDEInstallDir.find("\\Common7\\IDE"));
383     return true;
384   }
385 
386   bool hasVCExpressDir =
387       getSystemRegistryString("SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
388                               "InstallDir", vsExpressIDEInstallDir, nullptr);
389   if (hasVCExpressDir && !vsExpressIDEInstallDir.empty()) {
390     path = vsExpressIDEInstallDir.substr(
391         0, vsIDEInstallDir.find("\\Common7\\IDE"));
392     return true;
393   }
394 
395   // Try the environment.
396   const char *vs120comntools = getenv("VS120COMNTOOLS");
397   const char *vs100comntools = getenv("VS100COMNTOOLS");
398   const char *vs90comntools = getenv("VS90COMNTOOLS");
399   const char *vs80comntools = getenv("VS80COMNTOOLS");
400 
401   const char *vscomntools = nullptr;
402 
403   // Find any version we can
404   if (vs120comntools)
405     vscomntools = vs120comntools;
406   else if (vs100comntools)
407     vscomntools = vs100comntools;
408   else if (vs90comntools)
409     vscomntools = vs90comntools;
410   else if (vs80comntools)
411     vscomntools = vs80comntools;
412 
413   if (vscomntools && *vscomntools) {
414     const char *p = strstr(vscomntools, "\\Common7\\Tools");
415     path = p ? std::string(vscomntools, p) : vscomntools;
416     return true;
417   }
418   return false;
419 }
420 
AddSystemIncludeWithSubfolder(const ArgList & DriverArgs,ArgStringList & CC1Args,const std::string & folder,const char * subfolder) const421 void MSVCToolChain::AddSystemIncludeWithSubfolder(const ArgList &DriverArgs,
422                                                   ArgStringList &CC1Args,
423                                                   const std::string &folder,
424                                                   const char *subfolder) const {
425   llvm::SmallString<128> path(folder);
426   llvm::sys::path::append(path, subfolder);
427   addSystemInclude(DriverArgs, CC1Args, path);
428 }
429 
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const430 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
431                                               ArgStringList &CC1Args) const {
432   if (DriverArgs.hasArg(options::OPT_nostdinc))
433     return;
434 
435   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
436     SmallString<128> P(getDriver().ResourceDir);
437     llvm::sys::path::append(P, "include");
438     addSystemInclude(DriverArgs, CC1Args, P);
439   }
440 
441   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
442     return;
443 
444   // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
445   if (const char *cl_include_dir = getenv("INCLUDE")) {
446     SmallVector<StringRef, 8> Dirs;
447     StringRef(cl_include_dir)
448         .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
449     for (StringRef Dir : Dirs)
450       addSystemInclude(DriverArgs, CC1Args, Dir);
451     if (!Dirs.empty())
452       return;
453   }
454 
455   std::string VSDir;
456 
457   // When built with access to the proper Windows APIs, try to actually find
458   // the correct include paths first.
459   if (getVisualStudioInstallDir(VSDir)) {
460     AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include");
461 
462     std::string WindowsSDKDir;
463     int major, minor;
464     if (getWindowsSDKDir(WindowsSDKDir, major, minor)) {
465       if (major >= 8) {
466         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
467                                       "include\\shared");
468         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
469                                       "include\\um");
470         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
471                                       "include\\winrt");
472       } else {
473         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
474                                       "include");
475       }
476     } else {
477       addSystemInclude(DriverArgs, CC1Args, VSDir);
478     }
479     return;
480   }
481 
482   // As a fallback, select default install paths.
483   // FIXME: Don't guess drives and paths like this on Windows.
484   const StringRef Paths[] = {
485     "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
486     "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
487     "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
488     "C:/Program Files/Microsoft Visual Studio 8/VC/include",
489     "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
490   };
491   addSystemIncludes(DriverArgs, CC1Args, Paths);
492 }
493 
AddClangCXXStdlibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const494 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
495                                                  ArgStringList &CC1Args) const {
496   // FIXME: There should probably be logic here to find libc++ on Windows.
497 }
498