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