LLVM 19.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);
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";
272 return "arm";
274 return "arm64";
275 default:
276 return "";
277 }
278}
279
281 switch (Arch) {
283 // x86 is default in legacy VC toolchains.
284 // e.g. x86 libs are directly in /lib as opposed to /lib/x86.
285 return "";
287 return "amd64";
290 return "arm";
292 return "arm64";
293 default:
294 return "";
295 }
296}
297
299 switch (Arch) {
301 return "i386";
303 return "amd64";
306 return "arm";
308 return "arm64";
309 default:
310 return "";
311 }
312}
313
315 Triple::ArchType Arch, std::string &path) {
316 if (SDKMajor >= 8) {
318 } else {
319 switch (Arch) {
320 // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
321 case Triple::x86:
322 break;
323 case Triple::x86_64:
324 sys::path::append(LibPath, "x64");
325 break;
326 case Triple::arm:
327 case Triple::thumb:
328 // It is not necessary to link against Windows SDK 7.x when targeting ARM.
329 return false;
330 default:
331 return false;
332 }
333 }
334
335 path = std::string(LibPath);
336 return true;
337}
338
340 const std::string &VCToolChainPath,
341 Triple::ArchType TargetArch,
342 StringRef SubdirParent) {
343 const char *SubdirName;
344 const char *IncludeName;
345 switch (VSLayout) {
347 SubdirName = archToLegacyVCArch(TargetArch);
348 IncludeName = "include";
349 break;
351 SubdirName = archToWindowsSDKArch(TargetArch);
352 IncludeName = "include";
353 break;
355 SubdirName = archToDevDivInternalArch(TargetArch);
356 IncludeName = "inc";
357 break;
358 }
359
360 SmallString<256> Path(VCToolChainPath);
361 if (!SubdirParent.empty())
362 sys::path::append(Path, SubdirParent);
363
364 switch (Type) {
366 if (VSLayout == ToolsetLayout::VS2017OrNewer) {
367 // MSVC ships with two linkers: a 32-bit x86 and 64-bit x86 linker.
368 // On x86, pick the linker that corresponds to the current process.
369 // On ARM64, pick the 32-bit x86 linker; the 64-bit one doesn't run
370 // on Windows 10.
371 //
372 // FIXME: Consider using IsWow64GuestMachineSupported to figure out
373 // if we can invoke the 64-bit linker. It's generally preferable
374 // because it won't run out of address-space.
375 const bool HostIsX64 =
377 const char *const HostName = HostIsX64 ? "Hostx64" : "Hostx86";
378 sys::path::append(Path, "bin", HostName, SubdirName);
379 } else { // OlderVS or DevDivInternal
380 sys::path::append(Path, "bin", SubdirName);
381 }
382 break;
384 sys::path::append(Path, IncludeName);
385 break;
387 sys::path::append(Path, "lib", SubdirName);
388 break;
389 }
390 return std::string(Path);
391}
392
393bool useUniversalCRT(ToolsetLayout VSLayout, const std::string &VCToolChainPath,
394 Triple::ArchType TargetArch, vfs::FileSystem &VFS) {
396 SubDirectoryType::Include, VSLayout, VCToolChainPath, TargetArch));
397 sys::path::append(TestPath, "stdlib.h");
398 return !VFS.exists(TestPath);
399}
400
401bool getWindowsSDKDir(vfs::FileSystem &VFS, std::optional<StringRef> WinSdkDir,
402 std::optional<StringRef> WinSdkVersion,
403 std::optional<StringRef> WinSysRoot, std::string &Path,
404 int &Major, std::string &WindowsSDKIncludeVersion,
405 std::string &WindowsSDKLibVersion) {
406 // Trust /winsdkdir and /winsdkversion if present.
407 if (getWindowsSDKDirViaCommandLine(VFS, WinSdkDir, WinSdkVersion, WinSysRoot,
408 Path, Major, WindowsSDKIncludeVersion)) {
409 WindowsSDKLibVersion = WindowsSDKIncludeVersion;
410 return true;
411 }
412
413 // FIXME: Try env vars (%WindowsSdkDir%, %UCRTVersion%) before going to
414 // registry.
415
416 // Try the Windows registry.
417 std::string RegistrySDKVersion;
419 "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
420 "InstallationFolder", Path, &RegistrySDKVersion))
421 return false;
422 if (Path.empty() || RegistrySDKVersion.empty())
423 return false;
424
425 WindowsSDKIncludeVersion.clear();
426 WindowsSDKLibVersion.clear();
427 Major = 0;
428 std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
429 if (Major <= 7)
430 return true;
431 if (Major == 8) {
432 // Windows SDK 8.x installs libraries in a folder whose names depend on the
433 // version of the OS you're targeting. By default choose the newest, which
434 // usually corresponds to the version of the OS you've installed the SDK on.
435 const char *Tests[] = {"winv6.3", "win8", "win7"};
436 for (const char *Test : Tests) {
437 SmallString<128> TestPath(Path);
438 sys::path::append(TestPath, "Lib", Test);
439 if (VFS.exists(TestPath)) {
440 WindowsSDKLibVersion = Test;
441 break;
442 }
443 }
444 return !WindowsSDKLibVersion.empty();
445 }
446 if (Major == 10) {
447 if (!getWindows10SDKVersionFromPath(VFS, Path, WindowsSDKIncludeVersion))
448 return false;
449 WindowsSDKLibVersion = WindowsSDKIncludeVersion;
450 return true;
451 }
452 // Unsupported SDK version
453 return false;
454}
455
457 std::optional<StringRef> WinSdkDir,
458 std::optional<StringRef> WinSdkVersion,
459 std::optional<StringRef> WinSysRoot,
460 std::string &Path, std::string &UCRTVersion) {
461 // If /winsdkdir is passed, use it as location for the UCRT too.
462 // FIXME: Should there be a dedicated /ucrtdir to override /winsdkdir?
463 int Major;
464 if (getWindowsSDKDirViaCommandLine(VFS, WinSdkDir, WinSdkVersion, WinSysRoot,
465 Path, Major, UCRTVersion))
466 return true;
467
468 // FIXME: Try env vars (%UniversalCRTSdkDir%, %UCRTVersion%) before going to
469 // registry.
470
471 // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
472 // for the specific key "KitsRoot10". So do we.
474 "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
475 Path, nullptr))
476 return false;
477
478 return getWindows10SDKVersionFromPath(VFS, Path, UCRTVersion);
479}
480
482 std::optional<StringRef> VCToolsDir,
483 std::optional<StringRef> VCToolsVersion,
484 std::optional<StringRef> WinSysRoot,
485 std::string &Path, ToolsetLayout &VSLayout) {
486 // Don't validate the input; trust the value supplied by the user.
487 // The primary motivation is to prevent unnecessary file and registry access.
488 if (VCToolsDir || WinSysRoot) {
489 if (WinSysRoot) {
490 SmallString<128> ToolsPath(*WinSysRoot);
491 sys::path::append(ToolsPath, "VC", "Tools", "MSVC");
492 std::string ToolsVersion;
493 if (VCToolsVersion)
494 ToolsVersion = VCToolsVersion->str();
495 else
496 ToolsVersion = getHighestNumericTupleInDirectory(VFS, ToolsPath);
497 sys::path::append(ToolsPath, ToolsVersion);
498 Path = std::string(ToolsPath);
499 } else {
500 Path = VCToolsDir->str();
501 }
503 return true;
504 }
505 return false;
506}
507
509 ToolsetLayout &VSLayout) {
510 // These variables are typically set by vcvarsall.bat
511 // when launching a developer command prompt.
512 if (std::optional<std::string> VCToolsInstallDir =
513 sys::Process::GetEnv("VCToolsInstallDir")) {
514 // This is only set by newer Visual Studios, and it leads straight to
515 // the toolchain directory.
516 Path = std::move(*VCToolsInstallDir);
518 return true;
519 }
520 if (std::optional<std::string> VCInstallDir =
521 sys::Process::GetEnv("VCINSTALLDIR")) {
522 // If the previous variable isn't set but this one is, then we've found
523 // an older Visual Studio. This variable is set by newer Visual Studios too,
524 // so this check has to appear second.
525 // In older Visual Studios, the VC directory is the toolchain.
526 Path = std::move(*VCInstallDir);
527 VSLayout = ToolsetLayout::OlderVS;
528 return true;
529 }
530
531 // We couldn't find any VC environment variables. Let's walk through PATH and
532 // see if it leads us to a VC toolchain bin directory. If it does, pick the
533 // first one that we find.
534 if (std::optional<std::string> PathEnv = sys::Process::GetEnv("PATH")) {
535 SmallVector<StringRef, 8> PathEntries;
536 StringRef(*PathEnv).split(PathEntries, sys::EnvPathSeparator);
537 for (StringRef PathEntry : PathEntries) {
538 if (PathEntry.empty())
539 continue;
540
541 SmallString<256> ExeTestPath;
542
543 // If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
544 ExeTestPath = PathEntry;
545 sys::path::append(ExeTestPath, "cl.exe");
546 if (!VFS.exists(ExeTestPath))
547 continue;
548
549 // cl.exe existing isn't a conclusive test for a VC toolchain; clang also
550 // has a cl.exe. So let's check for link.exe too.
551 ExeTestPath = PathEntry;
552 sys::path::append(ExeTestPath, "link.exe");
553 if (!VFS.exists(ExeTestPath))
554 continue;
555
556 // whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
557 StringRef TestPath = PathEntry;
558 bool IsBin = sys::path::filename(TestPath).equals_insensitive("bin");
559 if (!IsBin) {
560 // Strip any architecture subdir like "amd64".
561 TestPath = sys::path::parent_path(TestPath);
562 IsBin = sys::path::filename(TestPath).equals_insensitive("bin");
563 }
564 if (IsBin) {
565 StringRef ParentPath = sys::path::parent_path(TestPath);
566 StringRef ParentFilename = sys::path::filename(ParentPath);
567 if (ParentFilename.equals_insensitive("VC")) {
568 Path = std::string(ParentPath);
569 VSLayout = ToolsetLayout::OlderVS;
570 return true;
571 }
572 if (ParentFilename.equals_insensitive("x86ret") ||
573 ParentFilename.equals_insensitive("x86chk") ||
574 ParentFilename.equals_insensitive("amd64ret") ||
575 ParentFilename.equals_insensitive("amd64chk")) {
576 Path = std::string(ParentPath);
578 return true;
579 }
580
581 } else {
582 // This could be a new (>=VS2017) toolchain. If it is, we should find
583 // path components with these prefixes when walking backwards through
584 // the path.
585 // Note: empty strings match anything.
586 StringRef ExpectedPrefixes[] = {"", "Host", "bin", "",
587 "MSVC", "Tools", "VC"};
588
589 auto It = sys::path::rbegin(PathEntry);
590 auto End = sys::path::rend(PathEntry);
591 for (StringRef Prefix : ExpectedPrefixes) {
592 if (It == End)
593 goto NotAToolChain;
594 if (!It->starts_with_insensitive(Prefix))
595 goto NotAToolChain;
596 ++It;
597 }
598
599 // We've found a new toolchain!
600 // Back up 3 times (/bin/Host/arch) to get the root path.
601 StringRef ToolChainPath(PathEntry);
602 for (int i = 0; i < 3; ++i)
603 ToolChainPath = sys::path::parent_path(ToolChainPath);
604
605 Path = std::string(ToolChainPath);
607 return true;
608 }
609
610 NotAToolChain:
611 continue;
612 }
613 }
614 return false;
615}
616
618 std::optional<StringRef> VCToolsVersion,
619 std::string &Path, ToolsetLayout &VSLayout) {
620#if !defined(USE_MSVC_SETUP_API)
621 return false;
622#else
623 // FIXME: This really should be done once in the top-level program's main
624 // function, as it may have already been initialized with a different
625 // threading model otherwise.
627 HRESULT HR;
628
629 // _com_ptr_t will throw a _com_error if a COM calls fail.
630 // The LLVM coding standards forbid exception handling, so we'll have to
631 // stop them from being thrown in the first place.
632 // The destructor will put the regular error handler back when we leave
633 // this scope.
634 struct SuppressCOMErrorsRAII {
635 static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
636
637 SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
638
639 ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
640
641 } COMErrorSuppressor;
642
643 ISetupConfigurationPtr Query;
644 HR = Query.CreateInstance(__uuidof(SetupConfiguration));
645 if (FAILED(HR))
646 return false;
647
648 IEnumSetupInstancesPtr EnumInstances;
649 HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
650 if (FAILED(HR))
651 return false;
652
653 ISetupInstancePtr Instance;
654 HR = EnumInstances->Next(1, &Instance, nullptr);
655 if (HR != S_OK)
656 return false;
657
658 ISetupInstancePtr NewestInstance;
659 std::optional<uint64_t> NewestVersionNum;
660 do {
661 bstr_t VersionString;
662 uint64_t VersionNum;
663 HR = Instance->GetInstallationVersion(VersionString.GetAddress());
664 if (FAILED(HR))
665 continue;
666 HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
667 if (FAILED(HR))
668 continue;
669 if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
670 NewestInstance = Instance;
671 NewestVersionNum = VersionNum;
672 }
673 } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
674
675 if (!NewestInstance)
676 return false;
677
678 bstr_t VCPathWide;
679 HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
680 if (FAILED(HR))
681 return false;
682
683 std::string VCRootPath;
684 convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
685
686 std::string ToolsVersion;
687 if (VCToolsVersion.has_value()) {
688 ToolsVersion = *VCToolsVersion;
689 } else {
690 SmallString<256> ToolsVersionFilePath(VCRootPath);
691 sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
692 "Microsoft.VCToolsVersion.default.txt");
693
694 auto ToolsVersionFile = MemoryBuffer::getFile(ToolsVersionFilePath);
695 if (!ToolsVersionFile)
696 return false;
697
698 ToolsVersion = ToolsVersionFile->get()->getBuffer().rtrim();
699 }
700
701
702 SmallString<256> ToolchainPath(VCRootPath);
703 sys::path::append(ToolchainPath, "Tools", "MSVC", ToolsVersion);
704 auto Status = VFS.status(ToolchainPath);
705 if (!Status || !Status->isDirectory())
706 return false;
707
708 Path = std::string(ToolchainPath.str());
710 return true;
711#endif
712}
713
714bool findVCToolChainViaRegistry(std::string &Path, ToolsetLayout &VSLayout) {
715 std::string VSInstallPath;
716 if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
717 "InstallDir", VSInstallPath, nullptr) ||
718 getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
719 "InstallDir", VSInstallPath, nullptr)) {
720 if (!VSInstallPath.empty()) {
721 auto pos = VSInstallPath.find(R"(\Common7\IDE)");
722 if (pos == std::string::npos)
723 return false;
724 SmallString<256> VCPath(StringRef(VSInstallPath.c_str(), pos));
725 sys::path::append(VCPath, "VC");
726
727 Path = std::string(VCPath);
728 VSLayout = ToolsetLayout::OlderVS;
729 return true;
730 }
731 }
732 return false;
733}
734
735} // 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:480
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:254
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
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:696
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:361
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:29
unsigned getMajor() const
Retrieve the major version number.
Definition: VersionTuple.h:71
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:66
static std::optional< std::string > GetEnv(StringRef name)
The virtual file system interface.
virtual bool exists(const Twine &Path)
Check whether Path exists.
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:307
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:578
reverse_iterator rbegin(StringRef path, Style style=Style::native)
Get reverse begin iterator over path.
Definition: Path.cpp:298
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:468
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:457
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:2037
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:481
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:401
bool useUniversalCRT(ToolsetLayout VSLayout, const std::string &VCToolChainPath, llvm::Triple::ArchType TargetArch, llvm::vfs::FileSystem &VFS)
Definition: MSVCPaths.cpp:393
bool findVCToolChainViaEnvironment(vfs::FileSystem &VFS, std::string &Path, ToolsetLayout &VSLayout)
Definition: MSVCPaths.cpp:508
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:617
const char * archToLegacyVCArch(llvm::Triple::ArchType Arch)
Definition: MSVCPaths.cpp:280
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:298
std::string getSubDirectoryPath(SubDirectoryType Type, ToolsetLayout VSLayout, const std::string &VCToolChainPath, llvm::Triple::ArchType TargetArch, llvm::StringRef SubdirParent="")
Definition: MSVCPaths.cpp:339
bool appendArchToWindowsSDKLibPath(int SDKMajor, llvm::SmallString< 128 > LibPath, llvm::Triple::ArchType Arch, std::string &path)
Definition: MSVCPaths.cpp:314
bool findVCToolChainViaRegistry(std::string &Path, ToolsetLayout &VSLayout)
Definition: MSVCPaths.cpp:714
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:456