blob: 0909c4c2174b9ffddba9184a80b820bf4f6ebc63 [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/Arg.h"
14#include "clang/Driver/ArgList.h"
15#include "clang/Driver/Compilation.h"
16#include "clang/Driver/Driver.h"
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000017#include "clang/Driver/Options.h"
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000018#include "llvm/Support/ErrorHandling.h"
19#include "llvm/Support/Path.h"
20
21// Include the necessary headers to interface with the Windows registry and
22// environment.
23#ifdef _MSC_VER
24 #define WIN32_LEAN_AND_MEAN
25 #define NOGDI
26 #define NOMINMAX
27 #include <Windows.h>
28#endif
29
30using namespace clang::driver;
31using namespace clang::driver::toolchains;
32using namespace clang;
33
Rafael Espindolaaf370e62013-03-18 18:10:27 +000034Windows::Windows(const Driver &D, const llvm::Triple& Triple,
35 const ArgList &Args)
36 : ToolChain(D, Triple, Args) {
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000037}
38
Rafael Espindola5b222052013-03-18 20:48:54 +000039Tool *Windows::constructTool(Action::ActionClass AC) const {
40 switch (AC) {
Rafael Espindolaf3260562013-03-18 18:50:01 +000041 case Action::InputClass:
42 case Action::BindArchClass:
43 case Action::LipoJobClass:
44 case Action::DsymutilJobClass:
45 case Action::VerifyJobClass:
46 case Action::PreprocessJobClass:
47 case Action::PrecompileJobClass:
48 case Action::AnalyzeJobClass:
49 case Action::MigrateJobClass:
50 case Action::CompileJobClass:
Rafael Espindola5b222052013-03-18 20:48:54 +000051 return new tools::Clang(*this);
Rafael Espindolaf3260562013-03-18 18:50:01 +000052 case Action::AssembleJobClass:
Rafael Espindola8a1115f2013-03-18 23:56:07 +000053 if (getTriple().getEnvironment() == llvm::Triple::MachO)
Rafael Espindola5b222052013-03-18 20:48:54 +000054 return new tools::darwin::Assemble(*this);
Rafael Espindola8a1115f2013-03-18 23:56:07 +000055 llvm_unreachable("We only have the integrated assembler on this TC");
Rafael Espindolaf3260562013-03-18 18:50:01 +000056 break;
57 case Action::LinkJobClass:
Rafael Espindola5b222052013-03-18 20:48:54 +000058 return new tools::visualstudio::Link(*this);
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000059 }
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000060}
61
62bool Windows::IsIntegratedAssemblerDefault() const {
63 return true;
64}
65
66bool Windows::IsUnwindTablesDefault() const {
Rafael Espindolaa4a809e2012-10-07 03:23:40 +000067 return getArch() == llvm::Triple::x86_64;
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000068}
69
Chandler Carruth7ce816a2012-11-19 03:52:03 +000070bool Windows::isPICDefault() const {
71 return getArch() == llvm::Triple::x86_64;
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000072}
73
Chandler Carruth7ce816a2012-11-19 03:52:03 +000074bool Windows::isPICDefaultForced() const {
75 return getArch() == llvm::Triple::x86_64;
Chandler Carruth79cbbdc2011-12-17 23:10:01 +000076}
77
78// FIXME: This probably should goto to some platform utils place.
79#ifdef _MSC_VER
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.
89static bool getSystemRegistryString(const char *keyPath, const char *valueName,
90 char *value, size_t maxLength) {
91 HKEY hRootKey = NULL;
92 HKEY hKey = NULL;
93 const char* subKey = NULL;
94 DWORD valueType;
95 DWORD valueSize = maxLength - 1;
96 long lResult;
97 bool returnValue = false;
98
99 if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
100 hRootKey = HKEY_CLASSES_ROOT;
101 subKey = keyPath + 18;
102 } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
103 hRootKey = HKEY_USERS;
104 subKey = keyPath + 11;
105 } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
106 hRootKey = HKEY_LOCAL_MACHINE;
107 subKey = keyPath + 19;
108 } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
109 hRootKey = HKEY_CURRENT_USER;
110 subKey = keyPath + 18;
111 } else {
112 return false;
113 }
114
115 const char *placeHolder = strstr(subKey, "$VERSION");
116 char bestName[256];
117 bestName[0] = '\0';
118 // If we have a $VERSION placeholder, do the highest-version search.
119 if (placeHolder) {
120 const char *keyEnd = placeHolder - 1;
121 const char *nextKey = placeHolder;
122 // Find end of previous key.
123 while ((keyEnd > subKey) && (*keyEnd != '\\'))
124 keyEnd--;
125 // Find end of key containing $VERSION.
126 while (*nextKey && (*nextKey != '\\'))
127 nextKey++;
128 size_t partialKeyLength = keyEnd - subKey;
129 char partialKey[256];
130 if (partialKeyLength > sizeof(partialKey))
131 partialKeyLength = sizeof(partialKey);
132 strncpy(partialKey, subKey, partialKeyLength);
133 partialKey[partialKeyLength] = '\0';
134 HKEY hTopKey = NULL;
135 lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
136 if (lResult == ERROR_SUCCESS) {
137 char keyName[256];
138 int bestIndex = -1;
139 double bestValue = 0.0;
140 DWORD index, size = sizeof(keyName) - 1;
141 for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
142 NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
143 const char *sp = keyName;
Jordan Rose3f6f51e2013-02-08 22:30:41 +0000144 while (*sp && !isDigit(*sp))
Chandler Carruth79cbbdc2011-12-17 23:10:01 +0000145 sp++;
146 if (!*sp)
147 continue;
148 const char *ep = sp + 1;
Jordan Rose3f6f51e2013-02-08 22:30:41 +0000149 while (*ep && (isDigit(*ep) || (*ep == '.')))
Chandler Carruth79cbbdc2011-12-17 23:10:01 +0000150 ep++;
151 char numBuf[32];
152 strncpy(numBuf, sp, sizeof(numBuf) - 1);
153 numBuf[sizeof(numBuf) - 1] = '\0';
154 double value = strtod(numBuf, NULL);
155 if (value > bestValue) {
156 bestIndex = (int)index;
157 bestValue = value;
158 strcpy(bestName, keyName);
159 }
160 size = sizeof(keyName) - 1;
161 }
162 // If we found the highest versioned key, open the key and get the value.
163 if (bestIndex != -1) {
164 // Append rest of key.
165 strncat(bestName, nextKey, sizeof(bestName) - 1);
166 bestName[sizeof(bestName) - 1] = '\0';
167 // Open the chosen key path remainder.
168 lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
169 if (lResult == ERROR_SUCCESS) {
170 lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
171 (LPBYTE)value, &valueSize);
172 if (lResult == ERROR_SUCCESS)
173 returnValue = true;
174 RegCloseKey(hKey);
175 }
176 }
177 RegCloseKey(hTopKey);
178 }
179 } else {
180 lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
181 if (lResult == ERROR_SUCCESS) {
182 lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
183 (LPBYTE)value, &valueSize);
184 if (lResult == ERROR_SUCCESS)
185 returnValue = true;
186 RegCloseKey(hKey);
187 }
188 }
189 return returnValue;
190}
191
192/// \brief Get Windows SDK installation directory.
193static bool getWindowsSDKDir(std::string &path) {
194 char windowsSDKInstallDir[256];
195 // Try the Windows registry.
196 bool hasSDKDir = getSystemRegistryString(
197 "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
198 "InstallationFolder",
199 windowsSDKInstallDir,
200 sizeof(windowsSDKInstallDir) - 1);
201 // If we have both vc80 and vc90, pick version we were compiled with.
202 if (hasSDKDir && windowsSDKInstallDir[0]) {
203 path = windowsSDKInstallDir;
204 return true;
205 }
206 return false;
207}
208
209 // Get Visual Studio installation directory.
210static bool getVisualStudioDir(std::string &path) {
211 // First check the environment variables that vsvars32.bat sets.
212 const char* vcinstalldir = getenv("VCINSTALLDIR");
213 if (vcinstalldir) {
214 char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
215 if (p)
216 *p = '\0';
217 path = vcinstalldir;
218 return true;
219 }
220
221 char vsIDEInstallDir[256];
222 char vsExpressIDEInstallDir[256];
223 // Then try the windows registry.
224 bool hasVCDir = getSystemRegistryString(
225 "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
226 "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
227 bool hasVCExpressDir = getSystemRegistryString(
228 "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
229 "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
230 // If we have both vc80 and vc90, pick version we were compiled with.
231 if (hasVCDir && vsIDEInstallDir[0]) {
232 char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
233 if (p)
234 *p = '\0';
235 path = vsIDEInstallDir;
236 return true;
237 }
238
239 if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
240 char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
241 if (p)
242 *p = '\0';
243 path = vsExpressIDEInstallDir;
244 return true;
245 }
246
247 // Try the environment.
248 const char *vs100comntools = getenv("VS100COMNTOOLS");
249 const char *vs90comntools = getenv("VS90COMNTOOLS");
250 const char *vs80comntools = getenv("VS80COMNTOOLS");
251 const char *vscomntools = NULL;
252
253 // Try to find the version that we were compiled with
254 if(false) {}
255 #if (_MSC_VER >= 1600) // VC100
256 else if(vs100comntools) {
257 vscomntools = vs100comntools;
258 }
259 #elif (_MSC_VER == 1500) // VC80
260 else if(vs90comntools) {
261 vscomntools = vs90comntools;
262 }
263 #elif (_MSC_VER == 1400) // VC80
264 else if(vs80comntools) {
265 vscomntools = vs80comntools;
266 }
267 #endif
268 // Otherwise find any version we can
269 else if (vs100comntools)
270 vscomntools = vs100comntools;
271 else if (vs90comntools)
272 vscomntools = vs90comntools;
273 else if (vs80comntools)
274 vscomntools = vs80comntools;
275
276 if (vscomntools && *vscomntools) {
277 const char *p = strstr(vscomntools, "\\Common7\\Tools");
278 path = p ? std::string(vscomntools, p) : vscomntools;
279 return true;
280 }
281 return false;
282}
283
284#endif // _MSC_VER
285
286void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
287 ArgStringList &CC1Args) const {
288 if (DriverArgs.hasArg(options::OPT_nostdinc))
289 return;
290
291 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
292 llvm::sys::Path P(getDriver().ResourceDir);
293 P.appendComponent("include");
294 addSystemInclude(DriverArgs, CC1Args, P.str());
295 }
296
297 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
298 return;
299
Joao Matos5d9cb1b2012-09-04 17:29:52 +0000300#ifdef _MSC_VER
301 // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
302 if (const char *cl_include_dir = getenv("INCLUDE")) {
303 SmallVector<StringRef, 8> Dirs;
304 StringRef(cl_include_dir).split(Dirs, ";");
305 int n = 0;
306 for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end();
307 I != E; ++I) {
308 StringRef d = *I;
309 if (d.size() == 0)
310 continue;
311 ++n;
312 addSystemInclude(DriverArgs, CC1Args, d);
313 }
314 if (n) return;
315 }
316
317 std::string VSDir;
318 std::string WindowsSDKDir;
319
320 // When built with access to the proper Windows APIs, try to actually find
321 // the correct include paths first.
322 if (getVisualStudioDir(VSDir)) {
323 addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include");
324 if (getWindowsSDKDir(WindowsSDKDir))
325 addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include");
326 else
327 addSystemInclude(DriverArgs, CC1Args,
328 VSDir + "\\VC\\PlatformSDK\\Include");
329 return;
330 }
331#endif // _MSC_VER
332
333 // As a fallback, select default install paths.
334 const StringRef Paths[] = {
335 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
336 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
337 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
338 "C:/Program Files/Microsoft Visual Studio 8/VC/include",
339 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
340 };
341 addSystemIncludes(DriverArgs, CC1Args, Paths);
Chandler Carruth79cbbdc2011-12-17 23:10:01 +0000342}
343
344void Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
345 ArgStringList &CC1Args) const {
346 // FIXME: There should probably be logic here to find libc++ on Windows.
347}