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