LLVM 17.0.0git
MSVCPaths.cpp
Go to the documentation of this file.
1//===-- MSVCPaths.cpp - MSVC path-parsing helpers -------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
12#include "llvm/ADT/StringRef.h"
13#include "llvm/ADT/Triple.h"
14#include "llvm/ADT/Twine.h"
15#include "llvm/Support/Host.h"
16#include "llvm/Support/Path.h"
21#include <optional>
22#include <string>
23
24#ifdef _WIN32
26#endif
27
28#ifdef _WIN32
29#define WIN32_LEAN_AND_MEAN
30#define NOGDI
31#ifndef NOMINMAX
32#define NOMINMAX
33#endif
34#include <windows.h>
35#endif
36
37#ifdef _MSC_VER
38// Don't support SetupApi on MinGW.
39#define USE_MSVC_SETUP_API
40
41// Make sure this comes before MSVCSetupApi.h
42#include <comdef.h>
43
44#include "llvm/Support/COM.h"
45#ifdef __clang__
46#pragma clang diagnostic push
47#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
48#endif
50#ifdef __clang__
51#pragma clang diagnostic pop
52#endif
53_COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
54_COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
55_COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
56_COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
57_COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
58_COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
59#endif
60
61static std::string
63 llvm::StringRef Directory) {
64 std::string Highest;
65 llvm::VersionTuple HighestTuple;
66
67 std::error_code EC;
68 for (llvm::vfs::directory_iterator DirIt = VFS.dir_begin(Directory, EC),
69 DirEnd;
70 !EC && DirIt != DirEnd; DirIt.increment(EC)) {
71 auto Status = VFS.status(DirIt->path());
72 if (!Status || !Status->isDirectory())
73 continue;
74 llvm::StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
76 if (Tuple.tryParse(CandidateName)) // tryParse() returns true on error.
77 continue;
78 if (Tuple > HighestTuple) {
79 HighestTuple = Tuple;
80 Highest = CandidateName.str();
81 }
82 }
83
84 return Highest;
85}
86
88 const std::string &SDKPath,
89 std::string &SDKVersion) {
90 llvm::SmallString<128> IncludePath(SDKPath);
91 llvm::sys::path::append(IncludePath, "Include");
92 SDKVersion = getHighestNumericTupleInDirectory(VFS, IncludePath);
93 return !SDKVersion.empty();
94}
95
97 llvm::vfs::FileSystem &VFS, std::optional<llvm::StringRef> WinSdkDir,
98 std::optional<llvm::StringRef> WinSdkVersion,
99 std::optional<llvm::StringRef> WinSysRoot, std::string &Path, int &Major,
100 std::string &Version) {
101 if (WinSdkDir || WinSysRoot) {
102 // Don't validate the input; trust the value supplied by the user.
103 // The motivation is to prevent unnecessary file and registry access.
104 llvm::VersionTuple SDKVersion;
105 if (WinSdkVersion)
106 SDKVersion.tryParse(*WinSdkVersion);
107
108 if (WinSysRoot) {
109 llvm::SmallString<128> SDKPath(*WinSysRoot);
110 llvm::sys::path::append(SDKPath, "Windows Kits");
111 if (!SDKVersion.empty())
112 llvm::sys::path::append(SDKPath, llvm::Twine(SDKVersion.getMajor()));
113 else
115 SDKPath, getHighestNumericTupleInDirectory(VFS, SDKPath));
116 Path = std::string(SDKPath.str());
117 } else {
118 Path = WinSdkDir->str();
119 }
120
121 if (!SDKVersion.empty()) {
122 Major = SDKVersion.getMajor();
123 Version = SDKVersion.getAsString();
124 } else if (getWindows10SDKVersionFromPath(VFS, Path, Version)) {
125 Major = 10;
126 }
127 return true;
128 }
129 return false;
130}
131
132#ifdef _WIN32
133static bool readFullStringValue(HKEY hkey, const char *valueName,
134 std::string &value) {
135 std::wstring WideValueName;
136 if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
137 return false;
138
139 DWORD result = 0;
140 DWORD valueSize = 0;
141 DWORD type = 0;
142 // First just query for the required size.
143 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
144 &valueSize);
145 if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
146 return false;
147 std::vector<BYTE> buffer(valueSize);
148 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
149 &valueSize);
150 if (result == ERROR_SUCCESS) {
151 std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
152 valueSize / sizeof(wchar_t));
153 if (valueSize && WideValue.back() == L'\0') {
154 WideValue.pop_back();
155 }
156 // The destination buffer must be empty as an invariant of the conversion
157 // function; but this function is sometimes called in a loop that passes in
158 // the same buffer, however. Simply clear it out so we can overwrite it.
159 value.clear();
160 return llvm::convertWideToUTF8(WideValue, value);
161 }
162 return false;
163}
164#endif
165
166/// Read registry string.
167/// This also supports a means to look for high-versioned keys by use
168/// of a $VERSION placeholder in the key path.
169/// $VERSION in the key path is a placeholder for the version number,
170/// causing the highest value path to be searched for and used.
171/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
172/// There can be additional characters in the component. Only the numeric
173/// characters are compared. This function only searches HKLM.
174static bool getSystemRegistryString(const char *keyPath, const char *valueName,
175 std::string &value, std::string *phValue) {
176#ifndef _WIN32
177 return false;
178#else
179 HKEY hRootKey = HKEY_LOCAL_MACHINE;
180 HKEY hKey = NULL;
181 long lResult;
182 bool returnValue = false;
183
184 const char *placeHolder = strstr(keyPath, "$VERSION");
185 std::string bestName;
186 // If we have a $VERSION placeholder, do the highest-version search.
187 if (placeHolder) {
188 const char *keyEnd = placeHolder - 1;
189 const char *nextKey = placeHolder;
190 // Find end of previous key.
191 while ((keyEnd > keyPath) && (*keyEnd != '\\'))
192 keyEnd--;
193 // Find end of key containing $VERSION.
194 while (*nextKey && (*nextKey != '\\'))
195 nextKey++;
196 size_t partialKeyLength = keyEnd - keyPath;
197 char partialKey[256];
198 if (partialKeyLength >= sizeof(partialKey))
199 partialKeyLength = sizeof(partialKey) - 1;
200 strncpy(partialKey, keyPath, partialKeyLength);
201 partialKey[partialKeyLength] = '\0';
202 HKEY hTopKey = NULL;
203 lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
204 &hTopKey);
205 if (lResult == ERROR_SUCCESS) {
206 char keyName[256];
207 double bestValue = 0.0;
208 DWORD index, size = sizeof(keyName) - 1;
209 for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
210 NULL, NULL) == ERROR_SUCCESS;
211 index++) {
212 const char *sp = keyName;
213 while (*sp && !llvm::isDigit(*sp))
214 sp++;
215 if (!*sp)
216 continue;
217 const char *ep = sp + 1;
218 while (*ep && (llvm::isDigit(*ep) || (*ep == '.')))
219 ep++;
220 char numBuf[32];
221 strncpy(numBuf, sp, sizeof(numBuf) - 1);
222 numBuf[sizeof(numBuf) - 1] = '\0';
223 double dvalue = strtod(numBuf, NULL);
224 if (dvalue > bestValue) {
225 // Test that InstallDir is indeed there before keeping this index.
226 // Open the chosen key path remainder.
227 bestName = keyName;
228 // Append rest of key.
229 bestName.append(nextKey);
230 lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
231 KEY_READ | KEY_WOW64_32KEY, &hKey);
232 if (lResult == ERROR_SUCCESS) {
233 if (readFullStringValue(hKey, valueName, value)) {
234 bestValue = dvalue;
235 if (phValue)
236 *phValue = bestName;
237 returnValue = true;
238 }
239 RegCloseKey(hKey);
240 }
241 }
242 size = sizeof(keyName) - 1;
243 }
244 RegCloseKey(hTopKey);
245 }
246 } else {
247 lResult =
248 RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
249 if (lResult == ERROR_SUCCESS) {
250 if (readFullStringValue(hKey, valueName, value))
251 returnValue = true;
252 if (phValue)
253 phValue->clear();
254 RegCloseKey(hKey);
255 }
256 }
257 return returnValue;
258#endif // _WIN32
259}
260
261namespace llvm {
262
264 switch (Arch) {
266 return "x86";
268 return "x64";
270 return "arm";
272 return "arm64";
273 default:
274 return "";
275 }
276}
277
279 switch (Arch) {
281 // x86 is default in legacy VC toolchains.
282 // e.g. x86 libs are directly in /lib as opposed to /lib/x86.
283 return "";
285 return "amd64";
287 return "arm";
289 return "arm64";
290 default:
291 return "";
292 }
293}
294
296 switch (Arch) {
298 return "i386";
300 return "amd64";
302 return "arm";
304 return "arm64";
305 default:
306 return "";
307 }
308}
309
311 Triple::ArchType Arch, std::string &path) {
312 if (SDKMajor >= 8) {
314 } else {
315 switch (Arch) {
316 // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
317 case Triple::x86:
318 break;
319 case Triple::x86_64:
320 sys::path::append(LibPath, "x64");
321 break;
322 case Triple::arm:
323 // It is not necessary to link against Windows SDK 7.x when targeting ARM.
324 return false;
325 default:
326 return false;
327 }
328 }
329
330 path = std::string(LibPath.str());
331 return true;
332}
333
335 const std::string &VCToolChainPath,
336 Triple::ArchType TargetArch,
337 StringRef SubdirParent) {
338 const char *SubdirName;
339 const char *IncludeName;
340 switch (VSLayout) {
342 SubdirName = archToLegacyVCArch(TargetArch);
343 IncludeName = "include";
344 break;
346 SubdirName = archToWindowsSDKArch(TargetArch);
347 IncludeName = "include";
348 break;
350 SubdirName = archToDevDivInternalArch(TargetArch);
351 IncludeName = "inc";
352 break;
353 }
354
355 SmallString<256> Path(VCToolChainPath);
356 if (!SubdirParent.empty())
357 sys::path::append(Path, SubdirParent);
358
359 switch (Type) {
361 if (VSLayout == ToolsetLayout::VS2017OrNewer) {
362 // MSVC ships with two linkers: a 32-bit x86 and 64-bit x86 linker.
363 // On x86, pick the linker that corresponds to the current process.
364 // On ARM64, pick the 32-bit x86 linker; the 64-bit one doesn't run
365 // on Windows 10.
366 //
367 // FIXME: Consider using IsWow64GuestMachineSupported to figure out
368 // if we can invoke the 64-bit linker. It's generally preferable
369 // because it won't run out of address-space.
370 const bool HostIsX64 =
372 const char *const HostName = HostIsX64 ? "Hostx64" : "Hostx86";
373 sys::path::append(Path, "bin", HostName, SubdirName);
374 } else { // OlderVS or DevDivInternal
375 sys::path::append(Path, "bin", SubdirName);
376 }
377 break;
379 sys::path::append(Path, IncludeName);
380 break;
382 sys::path::append(Path, "lib", SubdirName);
383 break;
384 }
385 return std::string(Path.str());
386}
387
388bool useUniversalCRT(ToolsetLayout VSLayout, const std::string &VCToolChainPath,
389 Triple::ArchType TargetArch, vfs::FileSystem &VFS) {
391 SubDirectoryType::Include, VSLayout, VCToolChainPath, TargetArch));
392 sys::path::append(TestPath, "stdlib.h");
393 return !VFS.exists(TestPath);
394}
395
396bool getWindowsSDKDir(vfs::FileSystem &VFS, std::optional<StringRef> WinSdkDir,
397 std::optional<StringRef> WinSdkVersion,
398 std::optional<StringRef> WinSysRoot, std::string &Path,
399 int &Major, std::string &WindowsSDKIncludeVersion,
400 std::string &WindowsSDKLibVersion) {
401 // Trust /winsdkdir and /winsdkversion if present.
402 if (getWindowsSDKDirViaCommandLine(VFS, WinSdkDir, WinSdkVersion, WinSysRoot,
403 Path, Major, WindowsSDKIncludeVersion)) {
404 WindowsSDKLibVersion = WindowsSDKIncludeVersion;
405 return true;
406 }
407
408 // FIXME: Try env vars (%WindowsSdkDir%, %UCRTVersion%) before going to
409 // registry.
410
411 // Try the Windows registry.
412 std::string RegistrySDKVersion;
414 "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
415 "InstallationFolder", Path, &RegistrySDKVersion))
416 return false;
417 if (Path.empty() || RegistrySDKVersion.empty())
418 return false;
419
420 WindowsSDKIncludeVersion.clear();
421 WindowsSDKLibVersion.clear();
422 Major = 0;
423 std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
424 if (Major <= 7)
425 return true;
426 if (Major == 8) {
427 // Windows SDK 8.x installs libraries in a folder whose names depend on the
428 // version of the OS you're targeting. By default choose the newest, which
429 // usually corresponds to the version of the OS you've installed the SDK on.
430 const char *Tests[] = {"winv6.3", "win8", "win7"};
431 for (const char *Test : Tests) {
432 SmallString<128> TestPath(Path);
433 sys::path::append(TestPath, "Lib", Test);
434 if (VFS.exists(TestPath)) {
435 WindowsSDKLibVersion = Test;
436 break;
437 }
438 }
439 return !WindowsSDKLibVersion.empty();
440 }
441 if (Major == 10) {
442 if (!getWindows10SDKVersionFromPath(VFS, Path, WindowsSDKIncludeVersion))
443 return false;
444 WindowsSDKLibVersion = WindowsSDKIncludeVersion;
445 return true;
446 }
447 // Unsupported SDK version
448 return false;
449}
450
452 std::optional<StringRef> WinSdkDir,
453 std::optional<StringRef> WinSdkVersion,
454 std::optional<StringRef> WinSysRoot,
455 std::string &Path, std::string &UCRTVersion) {
456 // If /winsdkdir is passed, use it as location for the UCRT too.
457 // FIXME: Should there be a dedicated /ucrtdir to override /winsdkdir?
458 int Major;
459 if (getWindowsSDKDirViaCommandLine(VFS, WinSdkDir, WinSdkVersion, WinSysRoot,
460 Path, Major, UCRTVersion))
461 return true;
462
463 // FIXME: Try env vars (%UniversalCRTSdkDir%, %UCRTVersion%) before going to
464 // registry.
465
466 // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
467 // for the specific key "KitsRoot10". So do we.
469 "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
470 Path, nullptr))
471 return false;
472
473 return getWindows10SDKVersionFromPath(VFS, Path, UCRTVersion);
474}
475
477 std::optional<StringRef> VCToolsDir,
478 std::optional<StringRef> VCToolsVersion,
479 std::optional<StringRef> WinSysRoot,
480 std::string &Path, ToolsetLayout &VSLayout) {
481 // Don't validate the input; trust the value supplied by the user.
482 // The primary motivation is to prevent unnecessary file and registry access.
483 if (VCToolsDir || WinSysRoot) {
484 if (WinSysRoot) {
485 SmallString<128> ToolsPath(*WinSysRoot);
486 sys::path::append(ToolsPath, "VC", "Tools", "MSVC");
487 std::string ToolsVersion;
488 if (VCToolsVersion)
489 ToolsVersion = VCToolsVersion->str();
490 else
491 ToolsVersion = getHighestNumericTupleInDirectory(VFS, ToolsPath);
492 sys::path::append(ToolsPath, ToolsVersion);
493 Path = std::string(ToolsPath.str());
494 } else {
495 Path = VCToolsDir->str();
496 }
498 return true;
499 }
500 return false;
501}
502
504 ToolsetLayout &VSLayout) {
505 // These variables are typically set by vcvarsall.bat
506 // when launching a developer command prompt.
507 if (std::optional<std::string> VCToolsInstallDir =
508 sys::Process::GetEnv("VCToolsInstallDir")) {
509 // This is only set by newer Visual Studios, and it leads straight to
510 // the toolchain directory.
511 Path = std::move(*VCToolsInstallDir);
513 return true;
514 }
515 if (std::optional<std::string> VCInstallDir =
516 sys::Process::GetEnv("VCINSTALLDIR")) {
517 // If the previous variable isn't set but this one is, then we've found
518 // an older Visual Studio. This variable is set by newer Visual Studios too,
519 // so this check has to appear second.
520 // In older Visual Studios, the VC directory is the toolchain.
521 Path = std::move(*VCInstallDir);
522 VSLayout = ToolsetLayout::OlderVS;
523 return true;
524 }
525
526 // We couldn't find any VC environment variables. Let's walk through PATH and
527 // see if it leads us to a VC toolchain bin directory. If it does, pick the
528 // first one that we find.
529 if (std::optional<std::string> PathEnv = sys::Process::GetEnv("PATH")) {
530 SmallVector<StringRef, 8> PathEntries;
531 StringRef(*PathEnv).split(PathEntries, sys::EnvPathSeparator);
532 for (StringRef PathEntry : PathEntries) {
533 if (PathEntry.empty())
534 continue;
535
536 SmallString<256> ExeTestPath;
537
538 // If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
539 ExeTestPath = PathEntry;
540 sys::path::append(ExeTestPath, "cl.exe");
541 if (!VFS.exists(ExeTestPath))
542 continue;
543
544 // cl.exe existing isn't a conclusive test for a VC toolchain; clang also
545 // has a cl.exe. So let's check for link.exe too.
546 ExeTestPath = PathEntry;
547 sys::path::append(ExeTestPath, "link.exe");
548 if (!VFS.exists(ExeTestPath))
549 continue;
550
551 // whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
552 StringRef TestPath = PathEntry;
553 bool IsBin = sys::path::filename(TestPath).equals_insensitive("bin");
554 if (!IsBin) {
555 // Strip any architecture subdir like "amd64".
556 TestPath = sys::path::parent_path(TestPath);
557 IsBin = sys::path::filename(TestPath).equals_insensitive("bin");
558 }
559 if (IsBin) {
560 StringRef ParentPath = sys::path::parent_path(TestPath);
561 StringRef ParentFilename = sys::path::filename(ParentPath);
562 if (ParentFilename.equals_insensitive("VC")) {
563 Path = std::string(ParentPath);
564 VSLayout = ToolsetLayout::OlderVS;
565 return true;
566 }
567 if (ParentFilename.equals_insensitive("x86ret") ||
568 ParentFilename.equals_insensitive("x86chk") ||
569 ParentFilename.equals_insensitive("amd64ret") ||
570 ParentFilename.equals_insensitive("amd64chk")) {
571 Path = std::string(ParentPath);
573 return true;
574 }
575
576 } else {
577 // This could be a new (>=VS2017) toolchain. If it is, we should find
578 // path components with these prefixes when walking backwards through
579 // the path.
580 // Note: empty strings match anything.
581 StringRef ExpectedPrefixes[] = {"", "Host", "bin", "",
582 "MSVC", "Tools", "VC"};
583
584 auto It = sys::path::rbegin(PathEntry);
585 auto End = sys::path::rend(PathEntry);
586 for (StringRef Prefix : ExpectedPrefixes) {
587 if (It == End)
588 goto NotAToolChain;
589 if (!It->startswith_insensitive(Prefix))
590 goto NotAToolChain;
591 ++It;
592 }
593
594 // We've found a new toolchain!
595 // Back up 3 times (/bin/Host/arch) to get the root path.
596 StringRef ToolChainPath(PathEntry);
597 for (int i = 0; i < 3; ++i)
598 ToolChainPath = sys::path::parent_path(ToolChainPath);
599
600 Path = std::string(ToolChainPath);
602 return true;
603 }
604
605 NotAToolChain:
606 continue;
607 }
608 }
609 return false;
610}
611
613 ToolsetLayout &VSLayout) {
614#if !defined(USE_MSVC_SETUP_API)
615 return false;
616#else
617 // FIXME: This really should be done once in the top-level program's main
618 // function, as it may have already been initialized with a different
619 // threading model otherwise.
621 HRESULT HR;
622
623 // _com_ptr_t will throw a _com_error if a COM calls fail.
624 // The LLVM coding standards forbid exception handling, so we'll have to
625 // stop them from being thrown in the first place.
626 // The destructor will put the regular error handler back when we leave
627 // this scope.
628 struct SuppressCOMErrorsRAII {
629 static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
630
631 SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
632
633 ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
634
635 } COMErrorSuppressor;
636
637 ISetupConfigurationPtr Query;
638 HR = Query.CreateInstance(__uuidof(SetupConfiguration));
639 if (FAILED(HR))
640 return false;
641
642 IEnumSetupInstancesPtr EnumInstances;
643 HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
644 if (FAILED(HR))
645 return false;
646
647 ISetupInstancePtr Instance;
648 HR = EnumInstances->Next(1, &Instance, nullptr);
649 if (HR != S_OK)
650 return false;
651
652 ISetupInstancePtr NewestInstance;
653 std::optional<uint64_t> NewestVersionNum;
654 do {
655 bstr_t VersionString;
656 uint64_t VersionNum;
657 HR = Instance->GetInstallationVersion(VersionString.GetAddress());
658 if (FAILED(HR))
659 continue;
660 HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
661 if (FAILED(HR))
662 continue;
663 if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
664 NewestInstance = Instance;
665 NewestVersionNum = VersionNum;
666 }
667 } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
668
669 if (!NewestInstance)
670 return false;
671
672 bstr_t VCPathWide;
673 HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
674 if (FAILED(HR))
675 return false;
676
677 std::string VCRootPath;
678 convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
679
680 SmallString<256> ToolsVersionFilePath(VCRootPath);
681 sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
682 "Microsoft.VCToolsVersion.default.txt");
683
684 auto ToolsVersionFile = MemoryBuffer::getFile(ToolsVersionFilePath);
685 if (!ToolsVersionFile)
686 return false;
687
688 SmallString<256> ToolchainPath(VCRootPath);
689 sys::path::append(ToolchainPath, "Tools", "MSVC",
690 ToolsVersionFile->get()->getBuffer().rtrim());
691 auto Status = VFS.status(ToolchainPath);
692 if (!Status || !Status->isDirectory())
693 return false;
694
695 Path = std::string(ToolchainPath.str());
697 return true;
698#endif
699}
700
701bool findVCToolChainViaRegistry(std::string &Path, ToolsetLayout &VSLayout) {
702 std::string VSInstallPath;
703 if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
704 "InstallDir", VSInstallPath, nullptr) ||
705 getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
706 "InstallDir", VSInstallPath, nullptr)) {
707 if (!VSInstallPath.empty()) {
708 auto pos = VSInstallPath.find(R"(\Common7\IDE)");
709 if (pos == std::string::npos)
710 return false;
711 SmallString<256> VCPath(StringRef(VSInstallPath.c_str(), pos));
712 sys::path::append(VCPath, "VC");
713
714 Path = std::string(VCPath.str());
715 VSLayout = ToolsetLayout::OlderVS;
716 return true;
717 }
718 }
719 return false;
720}
721
722} // namespace llvm
This header is deprecated in favour of llvm/TargetParser/Triple.h.
Provides a library for accessing COM functionality of the Host OS.
Given that RA is a live value
static bool getSystemRegistryString(const char *keyPath, const char *valueName, std::string &value, std::string *phValue)
Read registry string.
Definition: MSVCPaths.cpp:174
static bool getWindowsSDKDirViaCommandLine(llvm::vfs::FileSystem &VFS, std::optional< llvm::StringRef > WinSdkDir, std::optional< llvm::StringRef > WinSdkVersion, std::optional< llvm::StringRef > WinSysRoot, std::string &Path, int &Major, std::string &Version)
Definition: MSVCPaths.cpp:96
static bool getWindows10SDKVersionFromPath(llvm::vfs::FileSystem &VFS, const std::string &SDKPath, std::string &SDKVersion)
Definition: MSVCPaths.cpp:87
static std::string getHighestNumericTupleInDirectory(llvm::vfs::FileSystem &VFS, llvm::StringRef Directory)
Definition: MSVCPaths.cpp:62
struct ISetupInstance2 ISetupInstance2
Definition: MSVCSetupApi.h:87
struct ISetupInstance ISetupInstance
Definition: MSVCSetupApi.h:82
struct ISetupConfiguration ISetupConfiguration
Definition: MSVCSetupApi.h:97
struct ISetupHelper ISetupHelper
Definition: MSVCSetupApi.h:112
struct ISetupConfiguration2 ISetupConfiguration2
Definition: MSVCSetupApi.h:102
struct IEnumSetupInstances IEnumSetupInstances
Definition: MSVCSetupApi.h:92
return ToRemove size() > 0
Provides a library for accessing information about this process and other processes on the operating ...
This file defines the SmallString class.
This file defines the SmallVector class.
This header is deprecated in favour of llvm/TargetParser/Host.h.
Defines the llvm::VersionTuple class, which represents a version in the form major[....
Defines the virtual file system interface vfs::FileSystem.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:261
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:688
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:222
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition: StringRef.h:170
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition: Triple.h:355
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Represents a version number in the form major[.minor[.subminor[.build]]].
Definition: VersionTuple.h:31
unsigned getMajor() const
Retrieve the major version number.
Definition: VersionTuple.h:73
bool tryParse(StringRef string)
Try to parse the given string as a version number.
std::string getAsString() const
Retrieve a string representation of the version number.
bool empty() const
Determine whether this version information is empty (e.g., all version components are zero).
Definition: VersionTuple.h:68
static std::optional< std::string > GetEnv(StringRef name)
The virtual file system interface.
bool exists(const Twine &Path)
Check whether a file exists. Provided for convenience.
virtual directory_iterator dir_begin(const Twine &Dir, std::error_code &EC)=0
Get a directory_iterator for Dir.
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
An input iterator over the entries in a virtual path, similar to llvm::sys::fs::directory_iterator.
reverse_iterator rend(StringRef path)
Get reverse end iterator over path.
Definition: Path.cpp:306
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:577
reverse_iterator rbegin(StringRef path, Style style=Style::native)
Get reverse begin iterator over path.
Definition: Path.cpp:297
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:467
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:456
const char EnvPathSeparator
This is the OS-specific separator for PATH like environment variables:
Definition: Program.h:32
std::string getProcessTriple()
getProcessTriple() - Return an appropriate target triple for generating code to be loaded into the cu...
Definition: Host.cpp:1880
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
const char * archToWindowsSDKArch(llvm::Triple::ArchType Arch)
Definition: MSVCPaths.cpp:263
bool findVCToolChainViaCommandLine(vfs::FileSystem &VFS, std::optional< llvm::StringRef > VCToolsDir, std::optional< llvm::StringRef > VCToolsVersion, std::optional< llvm::StringRef > WinSysRoot, std::string &Path, ToolsetLayout &VSLayout)
Definition: MSVCPaths.cpp:476
SubDirectoryType
Definition: MSVCPaths.h:24
bool getWindowsSDKDir(vfs::FileSystem &VFS, std::optional< llvm::StringRef > WinSdkDir, std::optional< llvm::StringRef > WinSdkVersion, std::optional< llvm::StringRef > WinSysRoot, std::string &Path, int &Major, std::string &WindowsSDKIncludeVersion, std::string &WindowsSDKLibVersion)
Get Windows SDK installation directory.
Definition: MSVCPaths.cpp:396
bool useUniversalCRT(ToolsetLayout VSLayout, const std::string &VCToolChainPath, llvm::Triple::ArchType TargetArch, llvm::vfs::FileSystem &VFS)
Definition: MSVCPaths.cpp:388
bool findVCToolChainViaEnvironment(vfs::FileSystem &VFS, std::string &Path, ToolsetLayout &VSLayout)
Definition: MSVCPaths.cpp:503
bool convertWideToUTF8(const std::wstring &Source, std::string &Result)
Converts a std::wstring to a UTF-8 encoded std::string.
const char * archToLegacyVCArch(llvm::Triple::ArchType Arch)
Definition: MSVCPaths.cpp:278
bool findVCToolChainViaSetupConfig(vfs::FileSystem &VFS, std::string &Path, ToolsetLayout &VSLayout)
Definition: MSVCPaths.cpp:612
ToolsetLayout
Definition: MSVCPaths.h:30
bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, char *&ResultPtr, const UTF8 *&ErrorPtr)
Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on WideCharWidth.
const char * archToDevDivInternalArch(llvm::Triple::ArchType Arch)
Definition: MSVCPaths.cpp:295
std::string getSubDirectoryPath(SubDirectoryType Type, ToolsetLayout VSLayout, const std::string &VCToolChainPath, llvm::Triple::ArchType TargetArch, llvm::StringRef SubdirParent="")
Definition: MSVCPaths.cpp:334
bool appendArchToWindowsSDKLibPath(int SDKMajor, llvm::SmallString< 128 > LibPath, llvm::Triple::ArchType Arch, std::string &path)
Definition: MSVCPaths.cpp:310
bool findVCToolChainViaRegistry(std::string &Path, ToolsetLayout &VSLayout)
Definition: MSVCPaths.cpp:701
bool getUniversalCRTSdkDir(vfs::FileSystem &VFS, std::optional< llvm::StringRef > WinSdkDir, std::optional< llvm::StringRef > WinSdkVersion, std::optional< llvm::StringRef > WinSysRoot, std::string &Path, std::string &UCRTVersion)
Definition: MSVCPaths.cpp:451