@ -5,8 +5,6 @@ using System.IO;
@@ -5,8 +5,6 @@ using System.IO;
using System.Linq ;
using System.Text.RegularExpressions ;
using Microsoft.Win32 ;
using Microsoft.VisualStudio.Setup.Configuration ;
using System.Runtime.InteropServices ;
namespace CppSharp
{
@ -51,35 +49,6 @@ namespace CppSharp
@@ -51,35 +49,6 @@ namespace CppSharp
public static class MSVCToolchain
{
/// <summary>Dumps the detected SDK versions.</summary>
public static void DumpSdks ( )
{
List < ToolchainVersion > vsSdks = GetVisualStudioSdks ( ) ;
DumpSdks ( "Visual Studio" , vsSdks ) ;
List < ToolchainVersion > windowsSdks = GetWindowsSdks ( ) ;
DumpSdks ( "Windows" , windowsSdks ) ;
List < ToolchainVersion > windowsKitsSdks = GetWindowsKitsSdks ( ) ;
DumpSdks ( "Windows Kits" , windowsKitsSdks ) ;
List < ToolchainVersion > netFrameworkSdks = GetNetFrameworkSdks ( ) ;
DumpSdks ( ".NET Framework" , netFrameworkSdks ) ;
List < ToolchainVersion > msbuildSdks = GetMSBuildSdks ( ) ;
DumpSdks ( "MSBuild" , msbuildSdks ) ;
}
/// <summary>Dumps include directories for selected toolchain.</summary>
/// <param name="vsVersion">The version of Visual Studio to dump the SDK-s of.</param>
public static void DumpSdkIncludes ( VisualStudioVersion vsVersion =
VisualStudioVersion . Latest )
{
Console . WriteLine ( "\nInclude search path (VS: {0}):" , vsVersion ) ;
foreach ( var include in MSVCToolchain . GetSystemIncludes ( vsVersion ) )
Console . WriteLine ( $"\t{include}" ) ;
}
public static Version GetCLVersion ( VisualStudioVersion vsVersion )
{
Version clVersion ;
@ -108,91 +77,6 @@ namespace CppSharp
@@ -108,91 +77,6 @@ namespace CppSharp
return clVersion ;
}
public static ToolchainVersion GetVSToolchain ( VisualStudioVersion vsVersion )
{
if ( VSSdks . Value . Count = = 0 )
throw new Exception ( "Could not find a valid Visual Studio toolchain" ) ;
return ( vsVersion = = VisualStudioVersion . Latest )
? VSSdks . Value . Last ( )
: VSSdks . Value . Find ( version = >
( int ) version . Version = = GetVisualStudioVersion ( vsVersion ) ) ;
}
public static ToolchainVersion GetWindowsKitsToolchain ( VisualStudioVersion vsVersion ,
out int windowsSdkMajorVer )
{
var vsSdk = GetVSToolchain ( vsVersion ) ;
var vsDir = vsSdk . Directory ;
vsDir = vsDir . Substring ( 0 , vsDir . LastIndexOf ( @"\Common7\IDE" ,
StringComparison . Ordinal ) ) ;
// Check VCVarsQueryRegistry.bat to see which Windows SDK version
// is supposed to be used with this VS version.
var vcVarsPath = Path . Combine ( vsDir , @"Common7\Tools\VCVarsQueryRegistry.bat" ) ;
windowsSdkMajorVer = 0 ;
string kitsRootKey = string . Empty ;
var vcVarsFile = File . ReadAllText ( vcVarsPath ) ;
var match = Regex . Match ( vcVarsFile , @"Windows\\v([1-9][0-9]*)\.?([0-9]*)" ) ;
if ( match . Success )
windowsSdkMajorVer = int . Parse ( match . Groups [ 1 ] . Value ) ;
match = Regex . Match ( vcVarsFile , "KitsRoot([1-9][0-9]*)" ) ;
if ( match . Success )
kitsRootKey = match . Groups [ 0 ] . Value ;
List < ToolchainVersion > windowsKitsSdks = GetWindowsKitsSdks ( ) ;
var windowsKitSdk = ( ! string . IsNullOrWhiteSpace ( kitsRootKey ) )
? windowsKitsSdks . Find ( version = > version . Value = = kitsRootKey )
: windowsKitsSdks . Last ( ) ;
// If for some reason we cannot find the SDK version reported by VS
// in the system, then fallback to the latest version found.
if ( windowsKitSdk . Value = = null )
windowsKitSdk = windowsKitsSdks . Last ( ) ;
return windowsKitSdk ;
}
public static VisualStudioVersion FindVSVersion ( VisualStudioVersion vsVersion )
{
if ( vsVersion ! = VisualStudioVersion . Latest )
{
var vsSdk = GetVSToolchain ( vsVersion ) ;
if ( vsSdk . IsValid )
return vsVersion ;
}
// we don't know what "latest" is on a given machine
// so start from the latest specified version and loop until a match is found
for ( var i = VisualStudioVersion . Latest - 1 ; i > = VisualStudioVersion . VS2012 ; i - - )
{
vsVersion = FindVSVersion ( i ) ;
if ( vsVersion ! = VisualStudioVersion . Latest )
return vsVersion ;
}
return VisualStudioVersion . Latest ;
}
/// <summary>Gets the system include folders for the given Visual Studio version.</summary>
/// <param name="vsVersion">The version of Visual Studio to get
/// system includes from.</param>
public static List < string > GetSystemIncludes ( VisualStudioVersion vsVersion )
{
var vsSdk = GetVSToolchain ( vsVersion ) ;
var vsDir = vsSdk . Directory ;
if ( Path . GetFileName ( vsDir ) = = "IDE" )
{
string secondToLastDirPath = Path . GetDirectoryName ( vsDir ) ;
if ( Path . GetFileName ( secondToLastDirPath ) = = "Common7" )
vsDir = Path . GetDirectoryName ( secondToLastDirPath ) ;
}
return GetSystemIncludes ( vsVersion , vsDir ) ;
}
private static void DumpSdks ( string sku , IEnumerable < ToolchainVersion > sdks )
{
Console . WriteLine ( "\n{0} SDKs:" , sku ) ;
@ -220,33 +104,6 @@ namespace CppSharp
@@ -220,33 +104,6 @@ namespace CppSharp
}
}
private static List < string > GetSystemIncludes ( VisualStudioVersion vsVersion , string vsDir )
{
if ( vsVersion = = VisualStudioVersion . VS2017 )
return GetSystemIncludesVS2017 ( vsDir ) ;
int windowsSdkMajorVer ;
var windowsKitSdk = GetWindowsKitsToolchain ( vsVersion , out windowsSdkMajorVer ) ;
List < ToolchainVersion > windowsSdks = GetWindowsSdks ( ) ;
var includes = new List < string > { Path . Combine ( vsDir , @"VC\include" ) } ;
// Older Visual Studio versions provide their own Windows SDK.
if ( windowsSdks . Count = = 0 )
{
includes . Add ( Path . Combine ( vsDir , @"\VC\PlatformSDK\Include" ) ) ;
}
else
{
includes . AddRange ( GetIncludeDirsFromWindowsSdks ( windowsSdkMajorVer , windowsSdks ) ) ;
}
includes . AddRange (
CollectUniversalCRuntimeIncludeDirs ( vsDir , windowsKitSdk , windowsSdkMajorVer ) ) ;
return includes ;
}
private static IEnumerable < string > GetIncludeDirsFromWindowsSdks (
int windowsSdkMajorVer , List < ToolchainVersion > windowsSdks )
{
@ -412,38 +269,6 @@ namespace CppSharp
@@ -412,38 +269,6 @@ namespace CppSharp
return versions ;
}
/// <summary>
/// Gets Visual Studio installation directories.
/// </summary>
/// <param name="versions">Collection holding information about available Visual Studio instances</param>
/// <returns>Success of the operation</returns>
public static List < ToolchainVersion > GetVisualStudioSdks ( )
{
var versions = GetToolchainsFromSystemRegistry (
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio" ,
"InstallDir" , RegistryView . Registry32 ) ;
if ( versions . Count = = 0 & & Environment . Is64BitProcess )
versions . AddRange ( GetToolchainsFromSystemRegistry (
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio" ,
"InstallDir" , RegistryView . Registry64 ) ) ;
versions . AddRange ( GetToolchainsFromSystemRegistry (
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress" ,
"InstallDir" , RegistryView . Registry32 ) ) ;
if ( versions . Count = = 0 & & Environment . Is64BitProcess )
versions . AddRange ( GetToolchainsFromSystemRegistry (
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress" ,
"InstallDir" , RegistryView . Registry64 ) ) ;
//Check for VS 2017
GetVs2017Instances ( versions ) ;
versions . Sort ( ( v1 , v2 ) = > ( int ) ( v1 . Version - v2 . Version ) ) ;
return versions ;
}
/// <summary>
/// Read registry strings looking for matching values.
/// </summary>
@ -597,165 +422,5 @@ namespace CppSharp
@@ -597,165 +422,5 @@ namespace CppSharp
return hive ;
}
private static Lazy < List < ToolchainVersion > > VSSdks =
new Lazy < List < ToolchainVersion > > ( GetVisualStudioSdks , true ) ;
#region VS2017
/// <summary>
/// Returns all system includes of the installed VS 2017 instance.
/// </summary>
/// <param name="vsDir">Path to the visual studio installation (for identifying the correct instance)</param>
/// <returns>The system includes</returns>
private static List < string > GetSystemIncludesVS2017 ( string vsDir )
{
List < string > includes = new List < string > ( ) ;
//They includes are in a different folder
const int REGDB_E_CLASSNOTREG = unchecked ( ( int ) 0x80040154 ) ;
try
{
var query = new SetupConfiguration ( ) ;
var query2 = ( ISetupConfiguration2 ) query ;
var e = query2 . EnumAllInstances ( ) ;
int fetched ;
var instances = new ISetupInstance [ 1 ] ;
var regexWinSDK10Version = new Regex ( @"Windows10SDK\.(\d+)\.?" ) ;
do
{
e . Next ( 1 , instances , out fetched ) ;
if ( fetched > 0 )
{
var instance = ( ISetupInstance2 ) instances [ 0 ] ;
if ( instance . GetInstallationPath ( ) ! = vsDir ) continue ;
var packages = instance . GetPackages ( ) ;
var vc_tools = from package in packages
where package . GetId ( ) . Contains ( "Microsoft.VisualStudio.Component.VC.Tools" )
orderby package . GetId ( )
select package ;
if ( vc_tools . Any ( ) )
{ // Tools found, get path
var path = instance . GetInstallationPath ( ) ;
var versionFilePath = path + @"\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" ;
var version = System . IO . File . ReadLines ( versionFilePath ) . ElementAt ( 0 ) . Trim ( ) ;
includes . Add ( path + @"\VC\Tools\MSVC\" + version + @"\include" ) ;
includes . Add ( path + @"\VC\Tools\MSVC\" + version + @"\atlmfc\include" ) ;
}
var sdks = from package in packages
where package . GetId ( ) . Contains ( "Windows10SDK" ) | |
package . GetId ( ) . Contains ( "Windows81SDK" ) | |
package . GetId ( ) . Contains ( "Win10SDK_10" )
select package ;
var win10sdks = from sdk in sdks
where regexWinSDK10Version . Match ( sdk . GetId ( ) ) . Success
orderby sdk . GetId ( )
select sdk ;
var win8sdks = from sdk in sdks
where sdk . GetId ( ) . Contains ( "Windows81SDK" )
select sdk ;
if ( win10sdks . Any ( ) )
{
var sdk = win10sdks . Last ( ) ;
var matchVersion = regexWinSDK10Version . Match ( sdk . GetId ( ) ) ;
string path ;
if ( matchVersion . Success )
{
Environment . SpecialFolder specialFolder = Environment . Is64BitOperatingSystem ?
Environment . SpecialFolder . ProgramFilesX86 : Environment . SpecialFolder . ProgramFiles ;
var programFiles = Environment . GetFolderPath ( specialFolder ) ;
path = Path . Combine ( programFiles , "Windows Kits" , "10" , "include" ,
$"10.0.{matchVersion.Groups[1].Value}.0" ) ;
}
else
{
throw new Exception ( "Windows10SDK should not have been detected, something is terribly wrong" ) ;
}
var shared = Path . Combine ( path , "shared" ) ;
var um = Path . Combine ( path , "um" ) ;
var winrt = Path . Combine ( path , "winrt" ) ;
var ucrt = Path . Combine ( path , "ucrt" ) ;
if ( Directory . Exists ( shared ) & &
Directory . Exists ( um ) & &
Directory . Exists ( winrt ) & &
Directory . Exists ( ucrt ) )
{
includes . Add ( shared ) ;
includes . Add ( um ) ;
includes . Add ( winrt ) ;
includes . Add ( ucrt ) ;
}
}
else if ( win8sdks . Any ( ) )
{
includes . Add ( @"C:\Program Files (x86)\Windows Kits\8.1\include\shared" ) ;
includes . Add ( @"C:\Program Files (x86)\Windows Kits\8.1\include\um" ) ;
includes . Add ( @"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" ) ;
}
return includes ; //We've collected all information.
}
}
while ( fetched > 0 ) ;
}
// a COM exception means the VS 2017 COM API (therefore VS itself) is not installed, ignore
catch ( COMException ex ) when ( ex . HResult = = REGDB_E_CLASSNOTREG )
{
}
catch ( Exception ex )
{
Console . Error . WriteLine ( $"Error 0x{ex.HResult:x8}: {ex.Message}" ) ;
}
return includes ;
}
/// <summary>
/// Tries to get all vs 2017 instances.
/// </summary>
/// <param name="versions">Collection holding available visual studio instances</param>
/// <returns>Success of the operation</returns>
private static bool GetVs2017Instances ( ICollection < ToolchainVersion > versions )
{
const int REGDB_E_CLASSNOTREG = unchecked ( ( int ) 0x80040154 ) ;
try
{
var query = new SetupConfiguration ( ) ;
var query2 = ( ISetupConfiguration2 ) query ;
var e = query2 . EnumAllInstances ( ) ;
int fetched ;
var instances = new ISetupInstance [ 1 ] ;
do
{
e . Next ( 1 , instances , out fetched ) ;
if ( fetched > 0 )
{
var instance = ( ISetupInstance2 ) instances [ 0 ] ;
var toolchain = new ToolchainVersion
{
Directory = instance . GetInstallationPath ( ) + @"\Common7\IDE" ,
Version = float . Parse ( instance . GetInstallationVersion ( ) . Remove ( 2 ) ) ,
Value = null // Not used currently
} ;
versions . Add ( toolchain ) ;
}
}
while ( fetched > 0 ) ;
}
// a COM exception means the VS 2017 COM API (therefore VS itself) is not installed, ignore
catch ( COMException ex ) when ( ex . HResult = = REGDB_E_CLASSNOTREG )
{
return false ;
}
catch ( Exception ex )
{
Console . Error . WriteLine ( $"Error 0x{ex.HResult:x8}: {ex.Message}" ) ;
return false ;
}
return true ;
}
#endregion
}
}