diff --git a/configure b/configure index 31d682575e7a0d..bcfc5d924efc12 100755 --- a/configure +++ b/configure @@ -995,6 +995,11 @@ def configure_static(o): if options.enable_asan: o['libraries'] += ['-static-libasan'] +def config_vs2017(o): + if os.environ['GYP_MSVS_VERSION'] != '2017': return + o['msbuild_toolset'] = os.environ['PLATFORM_TOOLSET'] + o['msvs_windows_target_platform_version'] = os.environ['SDK2017'] + def write(filename, data): filename = os.path.join(root_dir, filename) @@ -1316,6 +1321,7 @@ configure_openssl(output) configure_intl(output) configure_static(output) configure_inspector(output) +config_vs2017(output) # variables should be a root level element, # move everything else to target_defaults diff --git a/tools/gyp/pylib/gyp/MSVSUtil.py b/tools/gyp/pylib/gyp/MSVSUtil.py index 0b32e911807844..96dea6c2c9d27f 100644 --- a/tools/gyp/pylib/gyp/MSVSUtil.py +++ b/tools/gyp/pylib/gyp/MSVSUtil.py @@ -14,6 +14,7 @@ 'loadable_module': 'dll', 'shared_library': 'dll', 'static_library': 'lib', + 'windows_driver': 'sys', } @@ -110,7 +111,7 @@ def ShardTargets(target_list, target_dicts): else: new_target_dicts[t] = target_dicts[t] # Shard dependencies. - for t in new_target_dicts: + for t in sorted(new_target_dicts): for deptype in ('dependencies', 'dependencies_original'): dependencies = copy.copy(new_target_dicts[t].get(deptype, [])) new_dependencies = [] diff --git a/tools/gyp/pylib/gyp/MSVSVersion.py b/tools/gyp/pylib/gyp/MSVSVersion.py index d9bfa684fa30c2..094f34a0d22d1e 100644 --- a/tools/gyp/pylib/gyp/MSVSVersion.py +++ b/tools/gyp/pylib/gyp/MSVSVersion.py @@ -18,7 +18,7 @@ class VisualStudioVersion(object): def __init__(self, short_name, description, solution_version, project_version, flat_sln, uses_vcxproj, - path, sdk_based, default_toolset=None): + path, sdk_based, default_toolset=None, compatible_sdks=list()): self.short_name = short_name self.description = description self.solution_version = solution_version @@ -28,6 +28,8 @@ def __init__(self, short_name, description, self.path = path self.sdk_based = sdk_based self.default_toolset = default_toolset + compatible_sdks.sort(key=lambda v: float(v.replace('v', '')), reverse=True) + self.compatible_sdks = compatible_sdks def ShortName(self): return self.short_name @@ -68,17 +70,19 @@ def DefaultToolset(self): of a user override.""" return self.default_toolset - def SetupScript(self, target_arch): + def _SetupScriptInternal(self, target_arch): """Returns a command (with arguments) to be used to set up the environment.""" - # Check if we are running in the SDK command line environment and use - # the setup script from the SDK if so. |target_arch| should be either - # 'x86' or 'x64'. + # If WindowsSDKDir is set and SetEnv.Cmd exists then we are using the + # depot_tools build tools and should run SetEnv.Cmd to set up the + # environment. The check for WindowsSDKDir alone is not sufficient because + # this is set by running vcvarsall.bat. assert target_arch in ('x86', 'x64') sdk_dir = os.environ.get('WindowsSDKDir') - if self.sdk_based and sdk_dir: - return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')), - '/' + target_arch] + if sdk_dir: + setup_path = os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')) + if self.sdk_based and sdk_dir and os.path.exists(setup_path): + return [setup_path, '/' + target_arch] else: # We don't use VC/vcvarsall.bat for x86 because vcvarsall calls # vcvars32, which it can only find if VS??COMNTOOLS is set, which it @@ -106,6 +110,14 @@ def SetupScript(self, target_arch): return [os.path.normpath( os.path.join(self.path, 'VC/vcvarsall.bat')), arg] + def SetupScript(self, target_arch): + script_data = self._SetupScriptInternal(target_arch) + script_path = script_data[0] + if not os.path.exists(script_path): + raise Exception('%s is missing - make sure VC++ tools are installed.' % + script_path) + return script_data + def _RegistryQueryBase(sysdir, key, value): """Use reg.exe to read a particular key. @@ -226,6 +238,16 @@ def _CreateVersion(name, path, sdk_based=False): if path: path = os.path.normpath(path) versions = { + '2017': VisualStudioVersion('2017', + 'Visual Studio 2017', + solution_version='12.00', + project_version='15.0', + flat_sln=False, + uses_vcxproj=True, + path=path, + sdk_based=sdk_based, + default_toolset='v141', + compatible_sdks=['v8.1', 'v10.0']), '2015': VisualStudioVersion('2015', 'Visual Studio 2015', solution_version='12.00', @@ -338,7 +360,6 @@ def _DetectVisualStudioVersions(versions_to_check, force_express): A list of visual studio versions installed in descending order of usage preference. Base this on the registry and a quick check if devenv.exe exists. - Only versions 8-10 are considered. Possibilities are: 2005(e) - Visual Studio 2005 (8) 2008(e) - Visual Studio 2008 (9) @@ -346,6 +367,7 @@ def _DetectVisualStudioVersions(versions_to_check, force_express): 2012(e) - Visual Studio 2012 (11) 2013(e) - Visual Studio 2013 (12) 2015 - Visual Studio 2015 (14) + 2017 - Visual Studio 2017 (15) Where (e) is e for express editions of MSVS and blank otherwise. """ version_to_year = { @@ -355,6 +377,7 @@ def _DetectVisualStudioVersions(versions_to_check, force_express): '11.0': '2012', '12.0': '2013', '14.0': '2015', + '15.0': '2017' } versions = [] for version in versions_to_check: @@ -385,13 +408,18 @@ def _DetectVisualStudioVersions(versions_to_check, force_express): # The old method above does not work when only SDK is installed. keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7', - r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7'] + r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7', + r'HKLM\Software\Microsoft\VisualStudio\SxS\VS7', + r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VS7'] for index in range(len(keys)): path = _RegistryGetValue(keys[index], version) if not path: continue path = _ConvertToCygpath(path) - if version != '14.0': # There is no Express edition for 2015. + if version == '15.0': + if os.path.exists(path): + versions.append(_CreateVersion('2017', path)) + elif version != '14.0': # There is no Express edition for 2015. versions.append(_CreateVersion(version_to_year[version] + 'e', os.path.join(path, '..'), sdk_based=True)) @@ -410,7 +438,7 @@ def SelectVisualStudioVersion(version='auto', allow_fallback=True): if version == 'auto': version = os.environ.get('GYP_MSVS_VERSION', 'auto') version_map = { - 'auto': ('14.0', '12.0', '10.0', '9.0', '8.0', '11.0'), + 'auto': ('15.0', '14.0', '12.0', '10.0', '9.0', '8.0', '11.0'), '2005': ('8.0',), '2005e': ('8.0',), '2008': ('9.0',), @@ -422,6 +450,7 @@ def SelectVisualStudioVersion(version='auto', allow_fallback=True): '2013': ('12.0',), '2013e': ('12.0',), '2015': ('14.0',), + '2017': ('15.0',), } override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH') if override_path: diff --git a/tools/gyp/pylib/gyp/generator/msvs.py b/tools/gyp/pylib/gyp/generator/msvs.py index 44cc1304a2e8ed..e6c096732c6322 100644 --- a/tools/gyp/pylib/gyp/generator/msvs.py +++ b/tools/gyp/pylib/gyp/generator/msvs.py @@ -46,6 +46,8 @@ def _import_OrderedDict(): generator_default_variables = { + 'DRIVER_PREFIX': '', + 'DRIVER_SUFFIX': '.sys', 'EXECUTABLE_PREFIX': '', 'EXECUTABLE_SUFFIX': '.exe', 'STATIC_LIB_PREFIX': '', @@ -91,6 +93,7 @@ def _import_OrderedDict(): 'msvs_target_platform_minversion', ] +generator_filelist_paths = None # List of precompiled header related keys. precomp_keys = [ @@ -256,6 +259,8 @@ def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False): if not tools.get(tool_name): tools[tool_name] = dict() tool = tools[tool_name] + if 'CompileAsWinRT' == setting: + return if tool.get(setting): if only_if_unset: return if type(tool[setting]) == list and type(value) == list: @@ -269,6 +274,10 @@ def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False): tool[setting] = value +def _ConfigTargetVersion(config_data): + return config_data.get('msvs_target_version', 'Windows7') + + def _ConfigPlatform(config_data): return config_data.get('msvs_configuration_platform', 'Win32') @@ -285,6 +294,23 @@ def _ConfigFullName(config_name, config_data): return '%s|%s' % (_ConfigBaseName(config_name, platform_name), platform_name) +def _ConfigWindowsTargetPlatformVersion(config_data, version): + config_ver = config_data.get('msvs_windows_sdk_version') + vers = [config_ver] if config_ver else version.compatible_sdks + for ver in vers: + for key in [ + r'HKLM\Software\Microsoft\Microsoft SDKs\Windows\%s', + r'HKLM\Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows\%s']: + sdk_dir = MSVSVersion._RegistryGetValue(key % ver, 'InstallationFolder') + if not sdk_dir: + continue + version = MSVSVersion._RegistryGetValue(key % ver, 'ProductVersion') or '' + # Find a matching entry in sdk_dir\include. + names = sorted([x for x in os.listdir(r'%s\include' % sdk_dir) + if x.startswith(version)], reverse=True) + return names[0] + + def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, quote_cmd, do_setup_env): @@ -338,6 +364,8 @@ def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, command = ['type'] else: command = [cmd[0].replace('/', '\\')] + if quote_cmd: + command = ['"%s"' % c for c in command] # Add call before command to ensure that commands can be tied together one # after the other without aborting in Incredibuild, since IB makes a bat # file out of the raw command string, and some commands (like python) are @@ -901,6 +929,8 @@ def _GetMsbuildToolsetOfProject(proj_path, spec, version): toolset = default_config.get('msbuild_toolset') if not toolset and version.DefaultToolset(): toolset = version.DefaultToolset() + if spec['type'] == 'windows_driver': + toolset = 'WindowsKernelModeDriver10.0' return toolset @@ -1084,6 +1114,7 @@ def _GetMSVSConfigurationType(spec, build_file): 'shared_library': '2', # .dll 'loadable_module': '2', # .dll 'static_library': '4', # .lib + 'windows_driver': '5', # .sys 'none': '10', # Utility type }[spec['type']] except KeyError: @@ -1268,6 +1299,7 @@ def _GetOutputFilePathAndTool(spec, msbuild): 'executable': ('VCLinkerTool', 'Link', '$(OutDir)', '.exe'), 'shared_library': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'), 'loadable_module': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'), + 'windows_driver': ('VCLinkerTool', 'Link', '$(OutDir)', '.sys'), 'static_library': ('VCLibrarianTool', 'Lib', '$(OutDir)lib\\', '.lib'), } output_file_props = output_file_map.get(spec['type']) @@ -1330,7 +1362,8 @@ def _GetDisabledWarnings(config): def _GetModuleDefinition(spec): def_file = '' - if spec['type'] in ['shared_library', 'loadable_module', 'executable']: + if spec['type'] in ['shared_library', 'loadable_module', 'executable', + 'windows_driver']: def_files = [s for s in spec.get('sources', []) if s.endswith('.def')] if len(def_files) == 1: def_file = _FixPath(def_files[0]) @@ -1937,6 +1970,19 @@ def PerformBuild(data, configurations, params): rtn = subprocess.check_call(arguments) +def CalculateGeneratorInputInfo(params): + if params.get('flavor') == 'ninja': + toplevel = params['options'].toplevel_dir + qualified_out_dir = os.path.normpath(os.path.join( + toplevel, ninja_generator.ComputeOutputDir(params), + 'gypfiles-msvs-ninja')) + + global generator_filelist_paths + generator_filelist_paths = { + 'toplevel': toplevel, + 'qualified_out_dir': qualified_out_dir, + } + def GenerateOutput(target_list, target_dicts, data, params): """Generate .sln and .vcproj files. @@ -2622,7 +2668,7 @@ def _GetMSBuildProjectConfigurations(configurations): return [group] -def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name): +def _GetMSBuildGlobalProperties(spec, version, guid, gyp_file_name): namespace = os.path.splitext(gyp_file_name)[0] properties = [ ['PropertyGroup', {'Label': 'Globals'}, @@ -2637,6 +2683,18 @@ def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name): os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64': properties[0].append(['PreferredToolArchitecture', 'x64']) + if spec.get('msvs_target_platform_version'): + target_platform_version = spec.get('msvs_target_platform_version') + properties[0].append(['WindowsTargetPlatformVersion', + target_platform_version]) + if spec.get('msvs_target_platform_minversion'): + target_platform_minversion = spec.get('msvs_target_platform_minversion') + properties[0].append(['WindowsTargetPlatformMinVersion', + target_platform_minversion]) + else: + properties[0].append(['WindowsTargetPlatformMinVersion', + target_platform_version]) + if spec.get('msvs_enable_winrt'): properties[0].append(['DefaultLanguage', 'en-US']) properties[0].append(['AppContainerApplication', 'true']) @@ -2645,33 +2703,47 @@ def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name): properties[0].append(['ApplicationTypeRevision', app_type_revision]) else: properties[0].append(['ApplicationTypeRevision', '8.1']) - - if spec.get('msvs_target_platform_version'): - target_platform_version = spec.get('msvs_target_platform_version') - properties[0].append(['WindowsTargetPlatformVersion', - target_platform_version]) - if spec.get('msvs_target_platform_minversion'): - target_platform_minversion = spec.get('msvs_target_platform_minversion') - properties[0].append(['WindowsTargetPlatformMinVersion', - target_platform_minversion]) - else: - properties[0].append(['WindowsTargetPlatformMinVersion', - target_platform_version]) if spec.get('msvs_enable_winphone'): properties[0].append(['ApplicationType', 'Windows Phone']) else: properties[0].append(['ApplicationType', 'Windows Store']) + platform_name = None + msvs_windows_sdk_version = None + for configuration in spec['configurations'].itervalues(): + platform_name = platform_name or _ConfigPlatform(configuration) + msvs_windows_sdk_version = ( + msvs_windows_sdk_version or + _ConfigWindowsTargetPlatformVersion(configuration, version) + ) + if platform_name and msvs_windows_sdk_version: + break + if msvs_windows_sdk_version: + properties[0].append(['WindowsTargetPlatformVersion', + str(msvs_windows_sdk_version)]) + elif version.compatible_sdks: + raise GypError('%s requires any SDK of %o version, but non were found' % + (version.description, version.compatible_sdks)) + + if platform_name == 'ARM': + properties[0].append(['WindowsSDKDesktopARMSupport', 'true']) + return properties + def _GetMSBuildConfigurationDetails(spec, build_file): properties = {} for name, settings in spec['configurations'].iteritems(): msbuild_attributes = _GetMSBuildAttributes(spec, settings, build_file) condition = _GetConfigurationCondition(name, settings) character_set = msbuild_attributes.get('CharacterSet') + config_type = msbuild_attributes.get('ConfigurationType') _AddConditionalProperty(properties, condition, 'ConfigurationType', - msbuild_attributes['ConfigurationType']) + config_type) + if config_type == 'Driver': + _AddConditionalProperty(properties, condition, 'DriverType', 'WDM') + _AddConditionalProperty(properties, condition, 'TargetVersion', + _ConfigTargetVersion(settings)) if character_set: if 'msvs_enable_winrt' not in spec : _AddConditionalProperty(properties, condition, 'CharacterSet', @@ -2770,6 +2842,7 @@ def _ConvertMSVSConfigurationType(config_type): '1': 'Application', '2': 'DynamicLibrary', '4': 'StaticLibrary', + '5': 'Driver', '10': 'Utility' }[config_type] return config_type @@ -2798,6 +2871,9 @@ def _GetMSBuildAttributes(spec, config, build_file): product_name = spec.get('product_name', '$(ProjectName)') target_name = prefix + product_name msbuild_attributes['TargetName'] = target_name + if 'TargetExt' not in msbuild_attributes and 'product_extension' in spec: + ext = spec.get('product_extension') + msbuild_attributes['TargetExt'] = '.' + ext if spec.get('msvs_external_builder'): external_out_dir = spec.get('msvs_external_builder_out_dir', '.') @@ -2809,6 +2885,7 @@ def _GetMSBuildAttributes(spec, config, build_file): 'executable': 'Link', 'shared_library': 'Link', 'loadable_module': 'Link', + 'windows_driver': 'Link', 'static_library': 'Lib', } msbuild_tool = msbuild_tool_map.get(spec['type']) @@ -2851,6 +2928,9 @@ def _GetMSBuildConfigurationGlobalProperties(spec, configurations, build_file): attributes['OutputDirectory']) _AddConditionalProperty(properties, condition, 'TargetName', attributes['TargetName']) + if 'TargetExt' in attributes: + _AddConditionalProperty(properties, condition, 'TargetExt', + attributes['TargetExt']) if attributes.get('TargetPath'): _AddConditionalProperty(properties, condition, 'TargetPath', @@ -3203,6 +3283,9 @@ def _GetMSBuildProjectReferences(project): ['ReferenceOutputAssembly', 'false'] ] for config in dependency.spec.get('configurations', {}).itervalues(): + if config.get('msvs_use_library_dependency_inputs', 0): + project_ref.append(['UseLibraryDependencyInputs', 'true']) + break # If it's disabled in any config, turn it off in the reference. if config.get('msvs_2010_disable_uldi_when_referenced', 0): project_ref.append(['UseLibraryDependencyInputs', 'false']) @@ -3295,7 +3378,8 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): }] content += _GetMSBuildProjectConfigurations(configurations) - content += _GetMSBuildGlobalProperties(spec, project.guid, project_file_name) + content += _GetMSBuildGlobalProperties(spec, version, project.guid, + project_file_name) content += import_default_section content += _GetMSBuildConfigurationDetails(spec, project.build_file) if spec.get('msvs_enable_winphone'): diff --git a/tools/gyp/pylib/gyp/win_tool.py b/tools/gyp/pylib/gyp/win_tool.py index bb6f1ea436f258..1c843a0b6cf528 100755 --- a/tools/gyp/pylib/gyp/win_tool.py +++ b/tools/gyp/pylib/gyp/win_tool.py @@ -116,11 +116,19 @@ def ExecLinkWrapper(self, arch, use_separate_mspdbsrv, *args): env = self._GetEnv(arch) if use_separate_mspdbsrv == 'True': self._UseSeparateMspdbsrv(env, args) - link = subprocess.Popen([args[0].replace('/', '\\')] + list(args[1:]), - shell=True, - env=env, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + if sys.platform == 'win32': + args = list(args) # *args is a tuple by default, which is read-only. + args[0] = args[0].replace('/', '\\') + # https://docs.python.org/2/library/subprocess.html: + # "On Unix with shell=True [...] if args is a sequence, the first item + # specifies the command string, and any additional items will be treated as + # additional arguments to the shell itself. That is to say, Popen does the + # equivalent of: + # Popen(['/bin/sh', '-c', args[0], args[1], ...])" + # For that reason, since going through the shell doesn't seem necessary on + # non-Windows don't do that there. + link = subprocess.Popen(args, shell=sys.platform == 'win32', env=env, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, _ = link.communicate() for line in out.splitlines(): if (not line.startswith(' Creating library ') and diff --git a/tools/vc141helper/GetCLPath.ps1 b/tools/vc141helper/GetCLPath.ps1 new file mode 100644 index 00000000000000..891c229bd4f567 --- /dev/null +++ b/tools/vc141helper/GetCLPath.ps1 @@ -0,0 +1,17 @@ +# Copyright 2017 - Refael Ackermann +# Distributed under MIT style license +# See accompanying file LICENSE at https://github.com/node4good/windows-autoconf + +if (-NOT (Test-Path 'Registry::HKEY_CLASSES_ROOT\CLSID\{177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D}')) { Exit 1 } +$jsonFile = '.tmp.json' +Invoke-Expression 'powershell -NoProfile -ExecutionPolicy Unrestricted -Command "&{ Add-Type -Path GetVS2017Configuration.cs; [VisualStudioConfiguration.Main]::Query()}"' > $jsonFile +$instPath = (Get-Content $jsonFile | ? {$_ -like "*InstallationPath*"}) -split '"' -replace '\\\\', '\' | Select-Object -skip 3 -first 1 +$SDK = (Get-Content $jsonFile | ? {$_ -like '*"SDK"*'}) -split '"' -replace '\\\\', '\' | Select-Object -skip 3 -first 1 +$MSBuildToolsPath = (Get-Content $jsonFile | ? {$_ -like '*MSBuildToolsPath*'}) -split '"' -replace '\\\\', '\' | Select-Object -skip 3 -first 1 +if ($args[0] -eq 'InstallationPath') { echo $instPath; exit } +if ($args[0] -eq 'SDK') { echo $SDK; exit } +if ($args[0] -eq 'MSBuildToolsPath') { echo $MSBuildToolsPath; exit } +if ($env:PROCESSOR_ARCHITEW6432 -ne $null) {$filt = '*64\x64*'} else {$filt = '*86\x86*'} +$cls = get-childitem $instPath -Include cl.exe -Recurse | ? { $_.Directory -like '*Host*' } +$cl = $cls | ? { $_.Directory -like $filt } +if ($cl -ne $null) {echo $cl.FullName} else {echo $cls[0].FullName} diff --git a/tools/vc141helper/GetVS2017Configuration.cs b/tools/vc141helper/GetVS2017Configuration.cs new file mode 100644 index 00000000000000..3cd92395ddec99 --- /dev/null +++ b/tools/vc141helper/GetVS2017Configuration.cs @@ -0,0 +1,273 @@ +// Copyright 2017 - Refael Ackermann +// Distributed under MIT style license +// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf + +// Usage: +// powershell -ExecutionPolicy Unrestricted -Version "2.0" -Command "&{ Add-Type -Path GetVS2017Configuration.cs; [VisualStudioConfiguration.Main]::Query()}" +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace VisualStudioConfiguration +{ + [Flags] + public enum InstanceState : uint + { + None = 0, + Local = 1, + Registered = 2, + NoRebootRequired = 4, + NoErrors = 8, + Complete = 4294967295, + } + + [Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IEnumSetupInstances + { + + void Next([MarshalAs(UnmanagedType.U4), In] int celt, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt, + [MarshalAs(UnmanagedType.U4)] out int pceltFetched); + + void Skip([MarshalAs(UnmanagedType.U4), In] int celt); + + void Reset(); + + [return: MarshalAs(UnmanagedType.Interface)] + IEnumSetupInstances Clone(); + } + + [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupConfiguration + { + } + + [Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupConfiguration2 : ISetupConfiguration + { + + [return: MarshalAs(UnmanagedType.Interface)] + IEnumSetupInstances EnumInstances(); + + [return: MarshalAs(UnmanagedType.Interface)] + ISetupInstance GetInstanceForCurrentProcess(); + + [return: MarshalAs(UnmanagedType.Interface)] + ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path); + + [return: MarshalAs(UnmanagedType.Interface)] + IEnumSetupInstances EnumAllInstances(); + } + + [Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupInstance + { + } + + [Guid("89143C9A-05AF-49B0-B717-72E218A2185C")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupInstance2 : ISetupInstance + { + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstanceId(); + + [return: MarshalAs(UnmanagedType.Struct)] + System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstallationName(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstallationPath(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstallationVersion(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid); + + [return: MarshalAs(UnmanagedType.BStr)] + string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath); + + [return: MarshalAs(UnmanagedType.U4)] + InstanceState GetState(); + + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] + ISetupPackageReference[] GetPackages(); + + ISetupPackageReference GetProduct(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetProductPath(); + + [return: MarshalAs(UnmanagedType.VariantBool)] + bool IsLaunchable(); + + [return: MarshalAs(UnmanagedType.VariantBool)] + bool IsComplete(); + + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] + ISetupPropertyStore GetProperties(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetEnginePath(); + } + + [Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupPackageReference + { + + [return: MarshalAs(UnmanagedType.BStr)] + string GetId(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetVersion(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetChip(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetLanguage(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetBranch(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetType(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetUniqueId(); + + [return: MarshalAs(UnmanagedType.VariantBool)] + bool GetIsExtension(); + } + + [Guid("c601c175-a3be-44bc-91f6-4568d230fc83")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupPropertyStore + { + + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] + string[] GetNames(); + + object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName); + } + + [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] + [CoClass(typeof(SetupConfigurationClass))] + [ComImport] + public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration + { + } + + [Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")] + [ClassInterface(ClassInterfaceType.None)] + [ComImport] + public class SetupConfigurationClass + { + } + + public static class Main + { + + public static void Echo(string tmplt, params Object[] args) + { + string str = (args.Length > 0) ? String.Format(tmplt, args) : tmplt; + Console.Write(" " + str + '\n'); + } + + public static void Query() + { + ISetupConfiguration query = new SetupConfiguration(); + ISetupConfiguration2 query2 = (ISetupConfiguration2) query; + IEnumSetupInstances e = query2.EnumAllInstances(); + ISetupInstance2[] rgelt = new ISetupInstance2[1]; + int pceltFetched; + Echo("["); + e.Next(1, rgelt, out pceltFetched); + while (pceltFetched > 0) + { + PrintInstance(rgelt[0]); + e.Next(1, rgelt, out pceltFetched); + if (pceltFetched > 0) + Echo(","); + } + Echo("]"); + } + + private static void PrintInstance(ISetupInstance2 setupInstance2) + { + Echo("{"); + string[] prodParts = setupInstance2.GetProduct().GetId().Split('.'); + Array.Reverse(prodParts); + string prod = prodParts[0]; + string instPath = setupInstance2.GetInstallationPath().Replace("\\", "\\\\"); + string installationVersion = setupInstance2.GetInstallationVersion(); + bool isComplete = setupInstance2.IsComplete(); + bool isLaunchable = setupInstance2.IsLaunchable(); + Echo("\"Product\": \"{0}\",", prod); + Echo("\"Version\": \"{0}\",", installationVersion); + Echo("\"InstallationPath\": \"{0}\",", instPath); + Echo("\"IsComplete\": \"{0}\",", isComplete ? "true" : "false"); + Echo("\"IsLaunchable\": \"{0}\",", isLaunchable ? "true" : "false"); + String cmd = (instPath + @"\\Common7\\Tools\\VsDevCmd.bat"); + Echo("\"CmdPath\": \"{0}\",", cmd); + + List packs = new List(); + string MSBuild = "false"; + string VCTools = "false"; + string Win8SDK = "0"; + string sdk10Ver = "0"; + foreach (ISetupPackageReference package in setupInstance2.GetPackages()) + { + string id = package.GetId(); + string ver = package.GetVersion(); + string detail = "{\"id\": \"" + id + "\", \"version\":\"" + ver + "\"}"; + packs.Add(" " + detail); + + if (id.Contains("Component.MSBuild")) { + MSBuild = detail; + } else if (id.Contains("VC.Tools")) { + VCTools = detail; + } else if (id.Contains("Microsoft.Windows.81SDK")) { + if (Win8SDK.CompareTo(ver) > 0) continue; + Win8SDK = ver; + } else if (id.Contains("Win10SDK_10")) { + if (sdk10Ver.CompareTo(ver) > 0) continue; + sdk10Ver = ver; + } + } + packs.Sort(); + string[] sdk10Parts = sdk10Ver.Split('.'); + sdk10Parts[sdk10Parts.Length - 1] = "0"; + Echo("\"MSBuild\": {0},", MSBuild); + if (MSBuild != "false") { + string MSBuildToolsPath = instPath + @"\\MSBuild\\15.0\\Bin\\"; + Echo("\"MSBuildToolsPath\": \"{0}\",", MSBuildToolsPath); + Echo("\"MSBuildPath\": \"{0}\",", MSBuildToolsPath + "MSBuild.exe"); + } + Echo("\"VCTools\": {0},", VCTools); + Echo("\"SDK8\": \"{0}\",", Win8SDK); + Echo("\"SDK10\": \"{0}\",", sdk10Ver); + Echo("\"SDK\": \"{0}\",", String.Join(".", sdk10Parts)); + Echo("\"Packages\": [\n {0} \n ]", String.Join(",\n ", packs.ToArray())); + Echo("}"); + } + } + +} diff --git a/tools/vc141helper/cl141_path.cmd b/tools/vc141helper/cl141_path.cmd new file mode 100644 index 00000000000000..d0f6050513dbc3 --- /dev/null +++ b/tools/vc141helper/cl141_path.cmd @@ -0,0 +1,16 @@ +:: Copyright 2017 - Refael Ackermann +:: Distributed under MIT style license +:: See accompanying file LICENSE at https://github.com/node4good/windows-autoconf + +@IF NOT DEFINED DEBUG_GETTER @ECHO OFF +SETLOCAL +PUSHD %~dp0 +SET PROMPT=$G +SET DEBUG_GETTER= +CALL :find_CL %~dp0 %1 +POPD +GOTO :eof + +:find_CL +FOR /F "tokens=*" %%A IN ('powershell -NoProfile -ExecutionPolicy Unrestricted "%1GetCLPath.ps1" %2') DO ECHO %%A& EXIT /B +GOTO :eof \ No newline at end of file diff --git a/vcbuild.bat b/vcbuild.bat index f07c50b0fbfc91..1cbf4a9cc59e53 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -15,7 +15,6 @@ if /i "%1"=="/?" goto help set config=Release set target=Build set target_arch=x64 -set target_env= set noprojgen= set nobuild= set sign= @@ -49,7 +48,6 @@ if /i "%1"=="clean" set target=Clean&goto arg-ok if /i "%1"=="ia32" set target_arch=x86&goto arg-ok if /i "%1"=="x86" set target_arch=x86&goto arg-ok if /i "%1"=="x64" set target_arch=x64&goto arg-ok -if /i "%1"=="vc2015" set target_env=vc2015&goto arg-ok if /i "%1"=="noprojgen" set noprojgen=1&goto arg-ok if /i "%1"=="nobuild" set nobuild=1&goto arg-ok if /i "%1"=="nosign" set "sign="&echo Note: vcbuild no longer signs by default. "nosign" is redundant.&goto arg-ok @@ -137,6 +135,36 @@ if defined noprojgen if defined nobuild if not defined sign if not defined msi g @rem Set environment for msbuild +@rem Look for Visual Studio 2017 +echo Looking for Visual Studio 2017 +SET cl141cmd="%~dp0tools\vc141helper\cl141_path.cmd" +for /F "tokens=*" %%A IN ('cmd /D /S /C "%cl141cmd% InstallationPath"') DO if NOT "_%%A_" == "__" ( + CALL :getSDK + CALL :getMSBUILD + set VCINSTALLDIR=%%A + SET VCVARS_VER=141 + set GYP_MSVS_VERSION=2017 + set PLATFORM_TOOLSET=v141 + goto msbuild-found +) +GOTO :find2015 + +:getSDK +for /F "tokens=*" %%A IN ('cmd /D /S /C "%cl141cmd% SDK"') DO if NOT "_%%A_" == "__" ( + SET SDK2017=%%A + GOTO :eof +) +GOTO :eof + +:getMSBUILD +for /F "tokens=*" %%A IN ('cmd /D /S /C "%cl141cmd% MSBuildToolsPath"') DO if NOT "_%%A_" == "__" ( + SET "Path=%Path%;%%A" + GOTO :eof +) +GOTO :eof + + +:find2015 @rem Look for Visual Studio 2015 echo Looking for Visual Studio 2015 if not defined VS140COMNTOOLS goto msbuild-not-found