@@ -15,6 +15,7 @@ version (Windows):
15
15
import core.stdc.ctype ;
16
16
import core.stdc.stdlib ;
17
17
import core.stdc.string ;
18
+ import core.stdc.wchar_ ;
18
19
import core.sys.windows.winbase ;
19
20
import core.sys.windows.windef ;
20
21
import core.sys.windows.winreg ;
@@ -25,7 +26,16 @@ import dmd.root.filename;
25
26
import dmd.root.outbuffer;
26
27
import dmd.root.rmem;
27
28
28
- struct VSOptions
29
+ version (IN_LLVM)
30
+ {
31
+ enum supportedPre2017Versions = [" 14.0" .ptr];
32
+ }
33
+ else
34
+ {
35
+ enum supportedPre2017Versions = [" 14.0" .ptr, " 12.0" , " 11.0" , " 10.0" , " 9.0" ];
36
+ }
37
+
38
+ extern (C++ ) struct VSOptions
29
39
{
30
40
// evaluated once at startup, reflecting the result of vcvarsall.bat
31
41
// from the current environment or the latest Visual Studio installation
@@ -238,14 +248,20 @@ private:
238
248
if (VSInstallDir is null )
239
249
VSInstallDir = getenv(" VSINSTALLDIR" );
240
250
251
+ version (IN_LLVM)
252
+ {
253
+ if (VSInstallDir is null )
254
+ VSInstallDir = getenv(" LDC_VSDIR" );
255
+ }
256
+
241
257
if (VSInstallDir is null )
242
258
VSInstallDir = detectVSInstallDirViaCOM();
243
259
244
260
if (VSInstallDir is null )
245
261
VSInstallDir = GetRegistryString(r " Microsoft\VisualStudio\SxS\VS7" , " 15.0" ); // VS2017
246
262
247
263
if (VSInstallDir is null )
248
- foreach (const (char )* ver; [ " 14.0 " .ptr, " 12.0 " , " 11.0 " , " 10.0 " , " 9.0 " ] )
264
+ foreach (const (char )* ver; supportedPre2017Versions )
249
265
{
250
266
VSInstallDir = GetRegistryString(FileName.combine(r " Microsoft\VisualStudio" , ver), " InstallDir" );
251
267
if (VSInstallDir)
@@ -267,7 +283,7 @@ private:
267
283
268
284
// detect from registry (build tools?)
269
285
if (VCInstallDir is null )
270
- foreach (const (char )* ver; [ " 14.0 " .ptr, " 12.0 " , " 11.0 " , " 10.0 " , " 9.0 " ] )
286
+ foreach (const (char )* ver; supportedPre2017Versions )
271
287
{
272
288
auto regPath = FileName.buildPath(r " Microsoft\VisualStudio" , ver, r " Setup\VC" );
273
289
VCInstallDir = GetRegistryString(regPath, " ProductDir" );
@@ -311,6 +327,7 @@ private:
311
327
}
312
328
}
313
329
330
+ public :
314
331
/**
315
332
* get Visual C bin folder
316
333
* Params:
@@ -325,7 +342,7 @@ private:
325
342
* Note: differences for the linker binaries are small, they all
326
343
* allow cross compilation
327
344
*/
328
- const (char )* getVCBinDir (bool x64, out const (char )* addpath)
345
+ const (char )* getVCBinDir (bool x64, out const (char )* addpath) const
329
346
{
330
347
static const (char )* linkExists (const (char )* p)
331
348
{
@@ -406,7 +423,7 @@ private:
406
423
* Returns:
407
424
* folder containing the the VC runtime libraries
408
425
*/
409
- const (char )* getVCLibDir (bool x64)
426
+ const (char )* getVCLibDir (bool x64) const
410
427
{
411
428
if (VCToolsInstallDir ! is null )
412
429
return FileName.combine(VCToolsInstallDir, x64 ? r " lib\x64" : r " lib\x86" );
@@ -422,7 +439,7 @@ private:
422
439
* Returns:
423
440
* folder containing the universal CRT libraries
424
441
*/
425
- const (char )* getUCRTLibPath (bool x64)
442
+ const (char )* getUCRTLibPath (bool x64) const
426
443
{
427
444
if (UCRTSdkDir && UCRTVersion)
428
445
return FileName.buildPath(UCRTSdkDir, " Lib" , UCRTVersion, x64 ? r " ucrt\x64" : r " ucrt\x86" );
@@ -436,7 +453,7 @@ private:
436
453
* Returns:
437
454
* folder containing the Windows SDK libraries
438
455
*/
439
- const (char )* getSDKLibPath (bool x64)
456
+ const (char )* getSDKLibPath (bool x64) const
440
457
{
441
458
if (WindowsSdkDir)
442
459
{
@@ -455,13 +472,20 @@ private:
455
472
return sdk;
456
473
}
457
474
475
+ version (IN_LLVM) {}
476
+ else
477
+ {
458
478
// try mingw fallback relative to phobos library folder that's part of LIB
459
479
if (auto p = FileName.searchPath(getenv(" LIB" ), r " mingw\kernel32.lib" [], false ))
460
480
return FileName.path(p).ptr;
481
+ }
461
482
462
483
return null ;
463
484
}
464
485
486
+ private :
487
+ extern (D ):
488
+
465
489
// iterate through subdirectories named by SDK version in baseDir and return the
466
490
// one with the largest version that also contains the test file
467
491
static const (char )* findLatestSDKDir (const (char )* baseDir, const (char )* testfile)
@@ -500,7 +524,7 @@ private:
500
524
* Returns:
501
525
* the registry value if it exists and has string type
502
526
*/
503
- const (char )* GetRegistryString (const (char )* softwareKeyPath, const (char )* valueName)
527
+ const (char )* GetRegistryString (const (char )* softwareKeyPath, const (char )* valueName) const
504
528
{
505
529
enum x64hive = false ; // VS registry entries always in 32-bit hive
506
530
@@ -527,6 +551,7 @@ private:
527
551
char [260 ] buf = void ;
528
552
DWORD cnt = buf.length * char .sizeof;
529
553
DWORD type;
554
+ // TODO: wide API
530
555
int hr = RegQueryValueExA(key, valueName, null , &type, cast (ubyte * ) buf.ptr, &cnt);
531
556
if (hr == 0 && cnt > 0 )
532
557
return buf.dup .ptr;
@@ -579,6 +604,8 @@ import core.sys.windows.oleauto : SysFreeString;
579
604
pragma (lib, " ole32.lib" );
580
605
pragma (lib, " oleaut32.lib" );
581
606
607
+ extern (C ) int _waccess(const (wchar )* _FileName, int _AccessMode);
608
+
582
609
interface ISetupInstance : IUnknown
583
610
{
584
611
// static const GUID iid = uuid("B41463C3-8866-43B5-BC33-2B0676F7F42E");
@@ -635,18 +662,54 @@ const(char)* detectVSInstallDirViaCOM()
635
662
return null ;
636
663
scope (exit) instances.Release();
637
664
665
+ BSTR versionString;
666
+ BSTR installDir;
667
+ scope (exit) SysFreeString (versionString);
668
+ scope (exit) SysFreeString (installDir);
669
+
638
670
while (instances.Next(1 , &instance, &fetched) == S_OK && fetched)
639
671
{
640
- BSTR bstrInstallDir;
641
- if (instance.GetInstallationPath(&bstrInstallDir) != S_OK )
672
+ BSTR thisVersionString;
673
+ if (instance.GetInstallationVersion(&thisVersionString) != S_OK )
674
+ continue ;
675
+ scope (exit) SysFreeString (thisVersionString);
676
+
677
+ BSTR thisInstallDir;
678
+ if (instance.GetInstallationPath(&thisInstallDir) != S_OK )
642
679
continue ;
680
+ scope (exit) SysFreeString (thisInstallDir);
681
+
682
+ if (versionString && wcscmp(thisVersionString, versionString) <= 0 )
683
+ continue ; // not a newer version, skip
684
+
685
+ const installDirLength = wcslen(thisInstallDir);
686
+ const vcInstallDirLength = installDirLength + 4 ;
687
+ auto vcInstallDir = (cast (wchar * ) mem.xmalloc_noscan(vcInstallDirLength * wchar .sizeof))[0 .. vcInstallDirLength];
688
+ scope (exit) mem.xfree(vcInstallDir.ptr);
689
+ vcInstallDir[0 .. installDirLength] = thisInstallDir[0 .. installDirLength];
690
+ vcInstallDir[installDirLength .. $] = " \\ VC\0 " w;
691
+ if (_waccess(vcInstallDir.ptr, 0 ) != 0 )
692
+ continue ; // Visual C++ not included, skip
643
693
644
- char [260 ] path;
645
- int len = WideCharToMultiByte(CP_UTF8 , 0 , bstrInstallDir, - 1 , path.ptr, 260 , null , null );
646
- SysFreeString(bstrInstallDir);
694
+ if (versionString)
695
+ {
696
+ SysFreeString(versionString);
697
+ SysFreeString(installDir);
698
+ }
699
+ version String = thisVersionString;
700
+ installDir = thisInstallDir;
701
+ thisVersionString = null ;
702
+ thisInstallDir = null ;
703
+ }
647
704
648
- if (len > 0 )
649
- return path[0 .. len].idup.ptr;
705
+ if (installDir)
706
+ {
707
+ char [260 ] path = void ;
708
+ int len = WideCharToMultiByte(CP_UTF8 , 0 , installDir, - 1 , path.ptr, path.length, null , null );
709
+ assert (len);
710
+
711
+ return path[0 .. len].idup.ptr;
650
712
}
713
+
651
714
return null ;
652
715
}
0 commit comments