From 36d41ceff8f6955c1f69350ecd2d57316a203a18 Mon Sep 17 00:00:00 2001 From: Chris Blume Date: Thu, 24 Feb 2022 01:26:14 +0000 Subject: [PATCH] Support multiple VS installations Currently, package_from_installed.py assumes only one version of VS is installed. It takes the path of the first installation. This could be incorrect in several ways: - Maybe both 2017 and 2019 (the supported versions) are installed and although the user specified using 2019, the 2017 path comes first. - Maybe 2019 and 2022 are installed, and the 2022 path is used even though it isn't supported. This CL fixes that issue by parsing the vswhere.exe output to confirm the VS version matches what the user specified, using its corresponding path. Change-Id: I2029a4f7126d0a45b5370ad58ab257df55571b3b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/3458722 Reviewed-by: Gavin Mak Reviewed-by: Chris Blume Commit-Queue: Chris Blume Auto-Submit: Chris Blume --- win_toolchain/package_from_installed.py | 36 ++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/win_toolchain/package_from_installed.py b/win_toolchain/package_from_installed.py index fe8ac29ea..40301d21a 100644 --- a/win_toolchain/package_from_installed.py +++ b/win_toolchain/package_from_installed.py @@ -52,6 +52,7 @@ _vs_version = None _win_version = None _vc_tools = None SUPPORTED_VS_VERSIONS = ['2017', '2019'] +_allow_multiple_vs_installs = False def GetVSPath(): @@ -60,12 +61,34 @@ def GetVSPath(): # version is installed. command = (r'C:\Program Files (x86)\Microsoft Visual Studio\Installer' r'\vswhere.exe -prerelease') - marker = 'installationPath: ' + vs_version_marker = 'catalog_productLineVersion: ' + vs_path_marker = 'installationPath: ' output = subprocess.check_output(command, universal_newlines=True) + vs_path = None + vs_installs_count = 0 + matching_vs_path = None for line in output.splitlines(): - if line.startswith(marker): - return line[len(marker):] - raise Exception('VS %s path not found in vswhere output' % (_vs_version)) + if line.startswith(vs_path_marker): + # The path information comes first + vs_path = line[len(vs_path_marker):] + vs_installs_count += 1 + if line.startswith(vs_version_marker): + # The version for that path comes later + if line[len(vs_version_marker):] == VS_VERSION: + matching_vs_path = vs_path + + if vs_installs_count == 0: + raise Exception('VS %s path not found in vswhere output' % (VS_VERSION)) + if vs_installs_count > 1: + if not _allow_multiple_vs_installs: + raise Exception('Multiple VS installs detected. This is unsupported. ' + 'It is recommended that packaging be done on a clean VM ' + 'with just one version installed. To proceed anyway add ' + 'the --allow_multiple_vs_installs flag to this script') + else: + print('Multiple VS installs were detected. This is unsupported. ' + 'Proceeding anyway') + return matching_vs_path def ExpandWildcards(root, sub_dir): @@ -477,6 +500,9 @@ def main(): parser.add_option('--repackage', action='store', type='string', dest='repackage_dir', default=None, help='Specify raw directory to be packaged, for hot fixes.') + parser.add_option('--allow_multiple_vs_installs', action='store_true', + default=False, dest='allow_multiple_vs_installs', + help='Specify if multiple VS installs are allowed.') (options, args) = parser.parse_args() if options.repackage_dir: @@ -499,6 +525,8 @@ def main(): global _win_version _win_version = options.winver global _vc_tools + global _allow_multiple_vs_installs + _allow_multiple_vs_installs = options.allow_multiple_vs_installs vs_path = GetVSPath() temp_tools_path = ExpandWildcards(vs_path, 'VC/Tools/MSVC/14.*.*') # Strip off the leading vs_path characters and switch back to / separators.