diff --git a/CHANGES.txt b/CHANGES.txt index 9b6f0236b..51c4b97e2 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -15,6 +15,19 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From John Doe: - Whatever John Doe did. + From Joseph Brill: + - MSVS: Fix a significant MSVC/MSVC tool initialization slowdown when + vcpkg has been installed and the PSModulePath is not initialized + or propagated from the user's shell environment. To resolve this + The default Windows Powershell 7 path is added before the default + Windows Powershell 5 path in the carefully constructed + environment in which the MSVC batch files are run. The shell + environment variables and values for VCPKG_DISABLE_METRICS and + VCPKG_ROOT are added to the limited MSVC environment when defined. + At present, the VCPKG_DISABLE_METRICS and VCPKG_ROOT variables and + values are not propagated to the SCons environment after running + the MSVC batch files. + From Bill Prendergast: - Fixed SCons.Variables.PackageVariable to correctly test the default setting against both enable & disable strings. (Fixes #4702) diff --git a/RELEASE.txt b/RELEASE.txt index 3c7bff54c..59a6dbca5 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -35,11 +35,17 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY one from PEP 308 introduced in Python 2.5 (2006). The idiom being replaced (using and/or) is regarded as error prone. +- MSVS: The default Windows powershell 7 path is added before the default + Windows powershell 5 path in the limited environment in which the + MSVC batch files are run. + FIXES ----- - Fixed SCons.Variables.PackageVariable to correctly test the default setting against both enable & disable strings. (Fixes #4702) +- MSVS: Fix significant slowdown initializing MSVC tools when vcpkg has + been installed on the system. IMPROVEMENTS ------------ diff --git a/SCons/Tool/MSCommon/common.py b/SCons/Tool/MSCommon/common.py index 5f011052b..effc5cf2d 100644 --- a/SCons/Tool/MSCommon/common.py +++ b/SCons/Tool/MSCommon/common.py @@ -38,6 +38,40 @@ import SCons.Util import SCons.Warnings + +# TODO: Hard-coded list of the variables that (may) need to be +# imported from os.environ[] for the chain of development batch +# files to execute correctly. One call to vcvars*.bat may +# end up running a dozen or more scripts, changes not only with +# each release but with what is installed at the time. We think +# in modern installations most are set along the way and don't +# need to be picked from the env, but include these for safety's sake. +# Any VSCMD variables definitely are picked from the env and +# control execution in interesting ways. +# Note these really should be unified - either controlled by vs.py, +# or synced with the the common_tools_var # settings in vs.py. +VS_VC_VARS = [ + 'COMSPEC', # path to "shell" + 'OS', # name of OS family: Windows_NT or undefined (95/98/ME) + 'VS170COMNTOOLS', # path to common tools for given version + 'VS160COMNTOOLS', + 'VS150COMNTOOLS', + 'VS140COMNTOOLS', + 'VS120COMNTOOLS', + 'VS110COMNTOOLS', + 'VS100COMNTOOLS', + 'VS90COMNTOOLS', + 'VS80COMNTOOLS', + 'VS71COMNTOOLS', + 'VSCOMNTOOLS', + 'MSDevDir', + 'VSCMD_DEBUG', # enable logging and other debug aids + 'VSCMD_SKIP_SENDTELEMETRY', + 'windir', # windows directory (SystemRoot not available in 95/98/ME) + 'VCPKG_DISABLE_METRICS', + 'VCPKG_ROOT', +] + class MSVCCacheInvalidWarning(SCons.Warnings.WarningOnByDefault): pass @@ -325,6 +359,9 @@ def normalize_env(env, keys, force: bool=False): for k in keys: if k in os.environ and (force or k not in normenv): normenv[k] = os.environ[k] + debug("keys: normenv[%s]=%s", k, normenv[k]) + else: + debug("keys: skipped[%s]", k) # add some things to PATH to prevent problems: # Shouldn't be necessary to add system32, since the default environment @@ -342,6 +379,18 @@ def normalize_env(env, keys, force: bool=False): if sys32_wbem_dir not in normenv['PATH']: normenv['PATH'] = normenv['PATH'] + os.pathsep + sys32_wbem_dir + # ProgramFiles for PowerShell 7 Path and PSModulePath + progfiles_dir = os.environ.get("ProgramFiles") + if not progfiles_dir: + sysroot_drive, _ = os.path.splitdrive(sys32_dir) + sysroot_path = sysroot_drive + os.sep + progfiles_dir = os.path.join(sysroot_path, "Program Files") + + # Powershell 7 + progfiles_ps_dir = os.path.join(progfiles_dir, "PowerShell", "7") + if progfiles_ps_dir not in normenv["PATH"]: + normenv["PATH"] = normenv["PATH"] + os.pathsep + progfiles_ps_dir + # Without Powershell in PATH, an internal call to a telemetry # function (starting with a VS2019 update) can fail # Note can also set VSCMD_SKIP_SENDTELEMETRY to avoid this. @@ -353,6 +402,8 @@ def normalize_env(env, keys, force: bool=False): return normenv + + def get_output(vcbat, args=None, env=None, skip_sendtelemetry=False): """Parse the output of given bat file, with given args.""" @@ -360,41 +411,13 @@ def get_output(vcbat, args=None, env=None, skip_sendtelemetry=False): # Create a blank environment, for use in launching the tools env = SCons.Environment.Environment(tools=[]) - # TODO: Hard-coded list of the variables that (may) need to be - # imported from os.environ[] for the chain of development batch - # files to execute correctly. One call to vcvars*.bat may - # end up running a dozen or more scripts, changes not only with - # each release but with what is installed at the time. We think - # in modern installations most are set along the way and don't - # need to be picked from the env, but include these for safety's sake. - # Any VSCMD variables definitely are picked from the env and - # control execution in interesting ways. - # Note these really should be unified - either controlled by vs.py, - # or synced with the the common_tools_var # settings in vs.py. - vs_vc_vars = [ - 'COMSPEC', # path to "shell" - 'OS', # name of OS family: Windows_NT or undefined (95/98/ME) - 'VS170COMNTOOLS', # path to common tools for given version - 'VS160COMNTOOLS', - 'VS150COMNTOOLS', - 'VS140COMNTOOLS', - 'VS120COMNTOOLS', - 'VS110COMNTOOLS', - 'VS100COMNTOOLS', - 'VS90COMNTOOLS', - 'VS80COMNTOOLS', - 'VS71COMNTOOLS', - 'VSCOMNTOOLS', - 'MSDevDir', - 'VSCMD_DEBUG', # enable logging and other debug aids - 'VSCMD_SKIP_SENDTELEMETRY', - 'windir', # windows directory (SystemRoot not available in 95/98/ME) - ] - env['ENV'] = normalize_env(env['ENV'], vs_vc_vars, force=False) + env['ENV'] = normalize_env(env['ENV'], VS_VC_VARS, force=False) if skip_sendtelemetry: _force_vscmd_skip_sendtelemetry(env) + # debug("ENV=%r", env['ENV']) + if args: debug("Calling '%s %s'", vcbat, args) cmd_str = '"%s" %s & set' % (vcbat, args) @@ -460,6 +483,7 @@ def add_env(rmatch, key, dkeep=dkeep) -> None: # it. path = path.strip('"') dkeep[key].append(str(path)) + debug("dkeep[%s].append(%r)", key, path) for line in output.splitlines(): for k, value in rdk.items():