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