Skip to content

Commit 43d6346

Browse files
committed
dmd.vsoptions: Use latest version, not first VS installation found via COM
Also try to exclude VS installations without Visual C++. Also try to detect a VC++ Build Tools 2017 installation in its default installation directory; that's from LDC, and IIRC, there was no other way to detect it automatically (nothing in the registry).
1 parent 2f6c1d0 commit 43d6346

File tree

1 file changed

+46
-6
lines changed

1 file changed

+46
-6
lines changed

src/dmd/vsoptions.d

+46-6
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,15 @@ private:
250250
if (VSInstallDir is null)
251251
VSInstallDir = GetRegistryString(r"Microsoft\VisualStudio\SxS\VS7", "15.0"w); // VS2017
252252

253+
if (VSInstallDir is null)
254+
{
255+
wchar[260] buffer = void;
256+
// VS Build Tools 2017 (default installation path)
257+
const numWritten = ExpandEnvironmentStringsW(r"%ProgramFiles(x86)%\Microsoft Visual Studio\2017\BuildTools"w.ptr, buffer.ptr, buffer.length);
258+
if (numWritten <= buffer.length && exists(buffer.ptr))
259+
VSInstallDir = toNarrow(buffer.ptr);
260+
}
261+
253262
if (VSInstallDir is null)
254263
foreach (const(char)* ver; supportedPre2017Versions)
255264
{
@@ -760,15 +769,46 @@ const(char)* detectVSInstallDirViaCOM()
760769
return null;
761770
scope(exit) instances.Release();
762771

772+
static struct WrappedBString
773+
{
774+
BSTR ptr;
775+
this(this) @disable;
776+
~this() { SysFreeString(ptr); }
777+
bool opCast(T : bool)() { return ptr !is null; }
778+
size_t length() { return SysStringLen(ptr); }
779+
void moveTo(ref WrappedBString other)
780+
{
781+
SysFreeString(other.ptr);
782+
other.ptr = ptr;
783+
ptr = null;
784+
}
785+
}
786+
787+
WrappedBString versionString, installDir;
788+
763789
while (instances.Next(1, &instance, &fetched) == S_OK && fetched)
764790
{
765-
BSTR bstrInstallDir;
766-
if (instance.GetInstallationPath(&bstrInstallDir) != S_OK)
791+
WrappedBString thisVersionString, thisInstallDir;
792+
if (instance.GetInstallationVersion(&thisVersionString.ptr) != S_OK ||
793+
instance.GetInstallationPath(&thisInstallDir.ptr) != S_OK)
767794
continue;
768-
scope(exit) SysFreeString(bstrInstallDir);
769795

770-
if (SysStringLen(bstrInstallDir))
771-
return toNarrow(bstrInstallDir);
796+
// FIXME: proper version strings comparison
797+
if (versionString && wcscmp(thisVersionString.ptr, versionString.ptr) <= 0)
798+
continue; // not a newer version, skip
799+
800+
const installDirLength = thisInstallDir.length;
801+
const vcInstallDirLength = installDirLength + 4;
802+
auto vcInstallDir = (cast(wchar*) mem.xmalloc_noscan(vcInstallDirLength * wchar.sizeof))[0 .. vcInstallDirLength];
803+
scope(exit) mem.xfree(vcInstallDir.ptr);
804+
vcInstallDir[0 .. installDirLength] = thisInstallDir.ptr[0 .. installDirLength];
805+
vcInstallDir[installDirLength .. $] = "\\VC\0"w;
806+
if (!exists(vcInstallDir.ptr))
807+
continue; // Visual C++ not included, skip
808+
809+
thisVersionString.moveTo(versionString);
810+
thisInstallDir.moveTo(installDir);
772811
}
773-
return null;
812+
813+
return installDir ? toNarrow(installDir.ptr) : null;
774814
}

0 commit comments

Comments
 (0)