blob: 65887a7f418be8aaa8b5431fb0b5f3531b4c8fc9 [file] [log] [blame]
Chandler Carruth79cbbdc2011-12-17 23:10:01 +00001//===--- 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"
Jordan Rose3f6f51e2013-02-08 22:30:41 +000011#include "clang/Basic/CharInfo.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000012#include "clang/Basic/Version.h"
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000013#include "clang/Driver/Compilation.h"
14#include "clang/Driver/Driver.h"
Rafael Espindola29511872013-03-24 15:06:53 +000015#include "clang/Driver/DriverDiagnostic.h"
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000016#include "clang/Driver/Options.h"
Reid Klecknerb1e25a12013-06-14 17:17:23 +000017#include "llvm/Option/Arg.h"
18#include "llvm/Option/ArgList.h"
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000019#include "llvm/Support/ErrorHandling.h"
20#include "llvm/Support/Path.h"
21
22// Include the necessary headers to interface with the Windows registry and
23// environment.
24#ifdef _MSC_VER
25 #define WIN32_LEAN_AND_MEAN
26 #define NOGDI
27 #define NOMINMAX
28 #include <Windows.h>
29#endif
30
31using namespace clang::driver;
32using namespace clang::driver::toolchains;
33using namespace clang;
Reid Klecknerb1e25a12013-06-14 17:17:23 +000034using namespace llvm::opt;
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000035
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000036// FIXME: This probably should goto to some platform utils place.
37#ifdef _MSC_VER
38
39/// \brief Read registry string.
40/// This also supports a means to look for high-versioned keys by use
41/// of a $VERSION placeholder in the key path.
42/// $VERSION in the key path is a placeholder for the version number,
43/// causing the highest value path to be searched for and used.
44/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
45/// There can be additional characters in the component. Only the numberic
46/// characters are compared.
47static bool getSystemRegistryString(const char *keyPath, const char *valueName,
48 char *value, size_t maxLength) {
49 HKEY hRootKey = NULL;
50 HKEY hKey = NULL;
51 const char* subKey = NULL;
52 DWORD valueType;
53 DWORD valueSize = maxLength - 1;
54 long lResult;
55 bool returnValue = false;
56
57 if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
58 hRootKey = HKEY_CLASSES_ROOT;
59 subKey = keyPath + 18;
60 } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
61 hRootKey = HKEY_USERS;
62 subKey = keyPath + 11;
63 } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
64 hRootKey = HKEY_LOCAL_MACHINE;
65 subKey = keyPath + 19;
66 } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
67 hRootKey = HKEY_CURRENT_USER;
68 subKey = keyPath + 18;
69 } else {
70 return false;
71 }
72
73 const char *placeHolder = strstr(subKey, "$VERSION");
74 char bestName[256];
75 bestName[0] = '\0';
76 // If we have a $VERSION placeholder, do the highest-version search.
77 if (placeHolder) {
78 const char *keyEnd = placeHolder - 1;
79 const char *nextKey = placeHolder;
80 // Find end of previous key.
81 while ((keyEnd > subKey) && (*keyEnd != '\\'))
82 keyEnd--;
83 // Find end of key containing $VERSION.
84 while (*nextKey && (*nextKey != '\\'))
85 nextKey++;
86 size_t partialKeyLength = keyEnd - subKey;
87 char partialKey[256];
88 if (partialKeyLength > sizeof(partialKey))
89 partialKeyLength = sizeof(partialKey);
90 strncpy(partialKey, subKey, partialKeyLength);
91 partialKey[partialKeyLength] = '\0';
92 HKEY hTopKey = NULL;
93 lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
94 if (lResult == ERROR_SUCCESS) {
95 char keyName[256];
96 int bestIndex = -1;
97 double bestValue = 0.0;
98 DWORD index, size = sizeof(keyName) - 1;
99 for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
100 NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
101 const char *sp = keyName;
Jordan Rose3f6f51e2013-02-08 22:30:41 +0000102 while (*sp && !isDigit(*sp))
Chandler Carruth79cbbdc2011-12-17 23:10:01 +0000103 sp++;
104 if (!*sp)
105 continue;
106 const char *ep = sp + 1;
Jordan Rose3f6f51e2013-02-08 22:30:41 +0000107 while (*ep && (isDigit(*ep) || (*ep == '.')))
Chandler Carruth79cbbdc2011-12-17 23:10:01 +0000108 ep++;
109 char numBuf[32];
110 strncpy(numBuf, sp, sizeof(numBuf) - 1);
111 numBuf[sizeof(numBuf) - 1] = '\0';
112 double value = strtod(numBuf, NULL);
113 if (value > bestValue) {
114 bestIndex = (int)index;
115 bestValue = value;
116 strcpy(bestName, keyName);
117 }
118 size = sizeof(keyName) - 1;
119 }
120 // If we found the highest versioned key, open the key and get the value.
121 if (bestIndex != -1) {
122 // Append rest of key.
123 strncat(bestName, nextKey, sizeof(bestName) - 1);
124 bestName[sizeof(bestName) - 1] = '\0';
125 // Open the chosen key path remainder.
126 lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
127 if (lResult == ERROR_SUCCESS) {
128 lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
129 (LPBYTE)value, &valueSize);
130 if (lResult == ERROR_SUCCESS)
131 returnValue = true;
132 RegCloseKey(hKey);
133 }
134 }
135 RegCloseKey(hTopKey);
136 }
137 } else {
138 lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
139 if (lResult == ERROR_SUCCESS) {
140 lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
141 (LPBYTE)value, &valueSize);
142 if (lResult == ERROR_SUCCESS)
143 returnValue = true;
144 RegCloseKey(hKey);
145 }
146 }
147 return returnValue;
148}
149
150/// \brief Get Windows SDK installation directory.
151static bool getWindowsSDKDir(std::string &path) {
152 char windowsSDKInstallDir[256];
153 // Try the Windows registry.
154 bool hasSDKDir = getSystemRegistryString(
155 "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
156 "InstallationFolder",
157 windowsSDKInstallDir,
158 sizeof(windowsSDKInstallDir) - 1);
159 // If we have both vc80 and vc90, pick version we were compiled with.
160 if (hasSDKDir && windowsSDKInstallDir[0]) {
161 path = windowsSDKInstallDir;
162 return true;
163 }
164 return false;
165}
166
Hans Wennborg09c24542013-08-16 03:15:10 +0000167// Get Visual Studio installation directory.
Chandler Carruth79cbbdc2011-12-17 23:10:01 +0000168static bool getVisualStudioDir(std::string &path) {
169 // First check the environment variables that vsvars32.bat sets.
170 const char* vcinstalldir = getenv("VCINSTALLDIR");
171 if (vcinstalldir) {
172 char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
173 if (p)
174 *p = '\0';
175 path = vcinstalldir;
176 return true;
177 }
178
179 char vsIDEInstallDir[256];
180 char vsExpressIDEInstallDir[256];
181 // Then try the windows registry.
182 bool hasVCDir = getSystemRegistryString(
183 "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
184 "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
185 bool hasVCExpressDir = getSystemRegistryString(
186 "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
187 "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
188 // If we have both vc80 and vc90, pick version we were compiled with.
189 if (hasVCDir && vsIDEInstallDir[0]) {
190 char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
191 if (p)
192 *p = '\0';
193 path = vsIDEInstallDir;
194 return true;
195 }
196
197 if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
198 char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
199 if (p)
200 *p = '\0';
201 path = vsExpressIDEInstallDir;
202 return true;
203 }
204
205 // Try the environment.
206 const char *vs100comntools = getenv("VS100COMNTOOLS");
207 const char *vs90comntools = getenv("VS90COMNTOOLS");
208 const char *vs80comntools = getenv("VS80COMNTOOLS");
209 const char *vscomntools = NULL;
210
211 // Try to find the version that we were compiled with
212 if(false) {}
213 #if (_MSC_VER >= 1600) // VC100
214 else if(vs100comntools) {
215 vscomntools = vs100comntools;
216 }
217 #elif (_MSC_VER == 1500) // VC80
218 else if(vs90comntools) {
219 vscomntools = vs90comntools;
220 }
221 #elif (_MSC_VER == 1400) // VC80
222 else if(vs80comntools) {
223 vscomntools = vs80comntools;
224 }
225 #endif
226 // Otherwise find any version we can
227 else if (vs100comntools)
228 vscomntools = vs100comntools;
229 else if (vs90comntools)
230 vscomntools = vs90comntools;
231 else if (vs80comntools)
232 vscomntools = vs80comntools;
233
234 if (vscomntools && *vscomntools) {
235 const char *p = strstr(vscomntools, "\\Common7\\Tools");
236 path = p ? std::string(vscomntools, p) : vscomntools;
237 return true;
238 }
239 return false;
240}
241
242#endif // _MSC_VER
243
Hans Wennborg09c24542013-08-16 03:15:10 +0000244Windows::Windows(const Driver &D, const llvm::Triple& Triple,
245 const ArgList &Args)
246 : ToolChain(D, Triple, Args) {
247#ifdef _MSC_VER
248 std::string VSDir;
249 if (getVisualStudioDir(VSDir))
250 getProgramPaths().push_back(VSDir + "\\VC\\bin");
251#endif
252}
253
254Tool *Windows::buildLinker() const {
255 return new tools::visualstudio::Link(*this);
256}
257
258Tool *Windows::buildAssembler() const {
259 if (getTriple().getEnvironment() == llvm::Triple::MachO)
260 return new tools::darwin::Assemble(*this);
261 getDriver().Diag(clang::diag::err_no_external_windows_assembler);
262 return NULL;
263}
264
265bool Windows::IsIntegratedAssemblerDefault() const {
266 return true;
267}
268
269bool Windows::IsUnwindTablesDefault() const {
270 return getArch() == llvm::Triple::x86_64;
271}
272
273bool Windows::isPICDefault() const {
274 return getArch() == llvm::Triple::x86_64;
275}
276
277bool Windows::isPIEDefault() const {
278 return false;
279}
280
281bool Windows::isPICDefaultForced() const {
282 return getArch() == llvm::Triple::x86_64;
283}
284
Chandler Carruth79cbbdc2011-12-17 23:10:01 +0000285void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
286 ArgStringList &CC1Args) const {
287 if (DriverArgs.hasArg(options::OPT_nostdinc))
288 return;
289
290 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
Rafael Espindolada6d1df2013-06-26 03:39:10 +0000291 SmallString<128> P(getDriver().ResourceDir);
292 llvm::sys::path::append(P, "include");
Chandler Carruth79cbbdc2011-12-17 23:10:01 +0000293 addSystemInclude(DriverArgs, CC1Args, P.str());
294 }
295
296 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
297 return;
298
Joao Matos5d9cb1b2012-09-04 17:29:52 +0000299#ifdef _MSC_VER
300 // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
301 if (const char *cl_include_dir = getenv("INCLUDE")) {
302 SmallVector<StringRef, 8> Dirs;
303 StringRef(cl_include_dir).split(Dirs, ";");
304 int n = 0;
305 for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end();
306 I != E; ++I) {
307 StringRef d = *I;
308 if (d.size() == 0)
309 continue;
310 ++n;
311 addSystemInclude(DriverArgs, CC1Args, d);
312 }
313 if (n) return;
314 }
315
316 std::string VSDir;
317 std::string WindowsSDKDir;
318
319 // When built with access to the proper Windows APIs, try to actually find
320 // the correct include paths first.
321 if (getVisualStudioDir(VSDir)) {
322 addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include");
323 if (getWindowsSDKDir(WindowsSDKDir))
324 addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include");
325 else
326 addSystemInclude(DriverArgs, CC1Args,
327 VSDir + "\\VC\\PlatformSDK\\Include");
328 return;
329 }
330#endif // _MSC_VER
331
332 // As a fallback, select default install paths.
333 const StringRef Paths[] = {
334 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
335 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
336 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
337 "C:/Program Files/Microsoft Visual Studio 8/VC/include",
338 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
339 };
340 addSystemIncludes(DriverArgs, CC1Args, Paths);
Chandler Carruth79cbbdc2011-12-17 23:10:01 +0000341}
342
343void Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
344 ArgStringList &CC1Args) const {
345 // FIXME: There should probably be logic here to find libc++ on Windows.
346}