diff --git a/CHANGES.txt b/CHANGES.txt index 413bc0768f..ff7aa5c347 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -9,7 +9,10 @@ NOTE: The 4.2.0 Release of SCons will deprecate Python 3.5 Support. Python 3.5 s RELEASE VERSION/DATE TO BE FILLED IN LATER - + From Joseph Brill: + - Fix MSVS tests (vs-N.N-exec.py) for MSVS 6.0, 7.0, and 7.1 (import missing module). + - Add support for Visual Studio 2022 (release and prerelease). + From William Deegan: - Fix reproducible builds. Restore logic respecting SOURCE_DATE_EPOCH when set. - Fix version tests to work with updated scons --version output. (Date format changed) diff --git a/RELEASE.txt b/RELEASE.txt index 075a766d84..95ee4eb6c6 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -9,6 +9,8 @@ Here is a summary of the changes since 4.2.0: NEW FUNCTIONALITY ----------------- +- Add support for Visual Studio 2022. +- Add support for pre-release versions of Visual Studio 2022 via an environment variable. - Added ninja API 'NINJA_FORCE_SCONS_BUILD' to force a node to callback to scons. DEPRECATED FUNCTIONALITY @@ -39,6 +41,7 @@ FIXES - Fix PCH not being evaluated by subst() where necessary. - Fix issue #4021. Change the way subst() is used in Textfile() to not evaluate '$$(' -> '$', but instead it should yield '$('. +- Fix MSVS tests (vs-N.N-exec.py) for MSVS 6.0, 7.0, and 7.1 (import missing module). - Fix command line escaping for ninja dollar sign escape. Without escaping ninja properly, the ninja file scons regenerate and callback invocations will lose the $ characters used in the scons command line which ninja uses itself for escaping. For Example: diff --git a/SCons/Tool/MSCommon/common.py b/SCons/Tool/MSCommon/common.py index b477c22789..f5e64ee1ed 100644 --- a/SCons/Tool/MSCommon/common.py +++ b/SCons/Tool/MSCommon/common.py @@ -238,7 +238,8 @@ def get_output(vcbat, args=None, env=None): # or synced with the the common_tools_var # settings in vs.py. vs_vc_vars = [ 'COMSPEC', # path to "shell" - 'VS160COMNTOOLS', # path to common tools for given version + 'VS170COMNTOOLS', # path to common tools for given version + 'VS160COMNTOOLS', 'VS150COMNTOOLS', 'VS140COMNTOOLS', 'VS120COMNTOOLS', diff --git a/SCons/Tool/MSCommon/vc.py b/SCons/Tool/MSCommon/vc.py index 66a081f1b2..129a9b4293 100644 --- a/SCons/Tool/MSCommon/vc.py +++ b/SCons/Tool/MSCommon/vc.py @@ -228,18 +228,42 @@ def get_host_target(env): return (host, target, req_target_platform) +# Enable prerelease version(s) via vswhere query argument. +# When enabled, an installed prerelease version will likely be the default msvc version. +_MSVC_CHECK_PRERELEASE = os.environ.get('MSVC_CHECK_PRERELEASE') in ('1', 'true', 'True') + # If you update this, update SupportedVSList in Tool/MSCommon/vs.py, and the # MSVC_VERSION documentation in Tool/msvc.xml. -_VCVER = ["14.2", "14.1", "14.1Exp", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"] +_VCVER = [ + "14.3", + "14.2", + "14.1", "14.1Exp", + "14.0", "14.0Exp", + "12.0", "12.0Exp", + "11.0", "11.0Exp", + "10.0", "10.0Exp", + "9.0", "9.0Exp", + "8.0", "8.0Exp", + "7.1", + "7.0", + "6.0"] # if using vswhere, configure command line arguments to probe for installed VC editions _VCVER_TO_VSWHERE_VER = { + '14.3': [ + ["-version", "[17.0, 18.0)"], # default: Enterprise, Professional, Community (order unpredictable?) + ["-version", "[17.0, 18.0)", "-products", "Microsoft.VisualStudio.Product.BuildTools"], # BuildTools + ] + [ + # TODO: remove after VS 2022 is released + ["-prerelease", "-version", "[17.0, 18.0)"], # default: Enterprise, Professional, Community (order unpredictable?) + ["-prerelease", "-version", "[17.0, 18.0)", "-products", "Microsoft.VisualStudio.Product.BuildTools"], # BuildTools + ] if _MSVC_CHECK_PRERELEASE else [], '14.2': [ - ["-version", "[16.0, 17.0)", ], # default: Enterprise, Professional, Community (order unpredictable?) + ["-version", "[16.0, 17.0)"], # default: Enterprise, Professional, Community (order unpredictable?) ["-version", "[16.0, 17.0)", "-products", "Microsoft.VisualStudio.Product.BuildTools"], # BuildTools ], '14.1': [ - ["-version", "[15.0, 16.0)", ], # default: Enterprise, Professional, Community (order unpredictable?) + ["-version", "[15.0, 16.0)"], # default: Enterprise, Professional, Community (order unpredictable?) ["-version", "[15.0, 16.0)", "-products", "Microsoft.VisualStudio.Product.BuildTools"], # BuildTools ], '14.1Exp': [ @@ -248,6 +272,8 @@ def get_host_target(env): } _VCVER_TO_PRODUCT_DIR = { + '14.3': [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version '14.2': [ (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version '14.1': [ diff --git a/SCons/Tool/MSCommon/vs.py b/SCons/Tool/MSCommon/vs.py index 7be7049ec4..b6fe282222 100644 --- a/SCons/Tool/MSCommon/vs.py +++ b/SCons/Tool/MSCommon/vs.py @@ -197,6 +197,18 @@ def reset(self): # Tool/MSCommon/vc.py, and the MSVC_VERSION documentation in Tool/msvc.xml. SupportedVSList = [ + # Visual Studio 2022 + VisualStudio('14.3', + vc_version='14.3', + sdk_version='10.0A', + hkeys=[], + common_tools_var='VS170COMNTOOLS', + executable_path=r'Common7\IDE\devenv.com', + # should be a fallback, prefer use vswhere installationPath + batch_file_path=r'Common7\Tools\VsDevCmd.bat', + supported_arch=['x86', 'amd64', "arm"], + ), + # Visual Studio 2019 VisualStudio('14.2', vc_version='14.2', diff --git a/SCons/Tool/msvc.xml b/SCons/Tool/msvc.xml index 7c864562c4..3c6af955ff 100644 --- a/SCons/Tool/msvc.xml +++ b/SCons/Tool/msvc.xml @@ -353,6 +353,7 @@ constructor; setting it later has no effect. Valid values for Windows are +14.3, 14.2, 14.1, 14.1Exp, diff --git a/SCons/Tool/msvs.py b/SCons/Tool/msvs.py index 9fdee65eec..7a827f4a5b 100644 --- a/SCons/Tool/msvs.py +++ b/SCons/Tool/msvs.py @@ -379,7 +379,10 @@ class _GenerateV10User(_UserGenerator): def __init__(self, dspfile, source, env): version_num, suite = msvs_parse_version(env['MSVS_VERSION']) - if version_num >= 14.2: + if version_num >= 14.3: + # Visual Studio 2022 is considered to be version 17. + self.versionstr = '17.0' + elif version_num >= 14.2: # Visual Studio 2019 is considered to be version 16. self.versionstr = '16.0' elif version_num >= 14.1: @@ -1599,7 +1602,10 @@ def Parse(self): def PrintSolution(self): """Writes a solution file""" self.file.write('Microsoft Visual Studio Solution File, Format Version %s\n' % self.versionstr) - if self.version_num >= 14.2: + if self.version_num >= 14.3: + # Visual Studio 2022 is considered to be version 17. + self.file.write('# Visual Studio 17\n') + elif self.version_num >= 14.2: # Visual Studio 2019 is considered to be version 16. self.file.write('# Visual Studio 16\n') elif self.version_num > 14.0: diff --git a/test/MSVC/MSVC_UWP_APP.py b/test/MSVC/MSVC_UWP_APP.py index 4bb2f5c5cf..6ccd1177f1 100644 --- a/test/MSVC/MSVC_UWP_APP.py +++ b/test/MSVC/MSVC_UWP_APP.py @@ -89,8 +89,9 @@ def AreVCStoreLibPathsInLIBPATH(output): msvc_140 = '14.0' in installed_msvc_versions msvc_141 = '14.1' in installed_msvc_versions msvc_142 = '14.2' in installed_msvc_versions +msvc_143 = '14.3' in installed_msvc_versions -if not any((msvc_140, msvc_141, msvc_142)): +if not any((msvc_140, msvc_141, msvc_142, msvc_143)): test.skip_test("Available MSVC doesn't support App store\n") if msvc_140: @@ -128,8 +129,25 @@ def AreVCStoreLibPathsInLIBPATH(output): test.fail_test((vclibstore_path_present is True) or (vclibstorerefs_path_present is True), message='VC Store LIBPATHs present when MSVC_UWP_APP not set (msvc_version=%s)' % msvc_version) -if msvc_141 or msvc_142: - if msvc_142: +if msvc_141 or msvc_142 or msvc_143: + if msvc_143: + test.write('SConstruct', """\ +if ARGUMENTS.get('MSVC_UWP_APP'): + help_vars = Variables() + help_vars.Add(EnumVariable( + 'MSVC_UWP_APP', + 'Build a Universal Windows Platform (UWP) Application', + '0', + allowed_values=('0', '1'))) +else: + help_vars = None +env = Environment(tools=['default', 'msvc'], variables=help_vars, MSVC_VERSION='14.3') +# Print the ENV LIBPATH to stdout +print('env[ENV][LIBPATH]=%s' % env.get('ENV').get('LIBPATH')) +print('env[MSVC_VERSION]=%s' % env.get('MSVC_VERSION')) +print('env[ENV][VSCMD_ARG_app_plat]=%s' % env.get('ENV').get('VSCMD_ARG_app_plat')) +""") + elif msvc_142: test.write('SConstruct', """\ if ARGUMENTS.get('MSVC_UWP_APP'): help_vars = Variables() diff --git a/test/MSVS/vs-14.3-exec.py b/test/MSVS/vs-14.3-exec.py new file mode 100644 index 0000000000..840b4324d5 --- /dev/null +++ b/test/MSVS/vs-14.3-exec.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test that we can actually build a simple program using our generated +Visual Studio 14.0 project (.vcxproj) and solution (.sln) files +using Visual Studio 14.3 +""" + +import os +import sys + +import TestSConsMSVS + +test = TestSConsMSVS.TestSConsMSVS() + +if sys.platform != 'win32': + msg = "Skipping Visual Studio test on non-Windows platform '%s'\n" % sys.platform + test.skip_test(msg) + +msvs_version = '14.3' + +if msvs_version not in test.msvs_versions(): + msg = "Visual Studio %s not installed; skipping test.\n" % msvs_version + test.skip_test(msg) + + + +# Let SCons figure out the Visual Studio environment variables for us and +# print out a statement that we can exec to suck them into our external +# environment so we can execute devenv and really try to build something. + +test.run(arguments = '-n -q -Q -f -', stdin = """\ +env = Environment(tools = ['msvc'], MSVS_VERSION='%(msvs_version)s') +if env.WhereIs('cl'): + print("os.environ.update(%%s)" %% repr(env['ENV'])) +""" % locals()) + +if(test.stdout() == ""): + msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version + test.skip_test(msg) + +exec(test.stdout()) + + + +test.subdir('sub dir') + +test.write(['sub dir', 'SConstruct'], """\ +env=Environment(MSVS_VERSION = '%(msvs_version)s') + +env.MSVSProject(target = 'foo.vcxproj', + srcs = ['foo.c'], + buildtarget = 'foo.exe', + variant = 'Release', + DebugSettings = {'LocalDebuggerCommandArguments':'echo "" > output.txt'}) +env.Program('foo.c') +""" % locals()) + +test.write(['sub dir', 'foo.c'], r""" +#include +int +main(int argc, char *argv) +{ + printf("foo.c\n"); + exit (0); +} +""") + +test.run(chdir='sub dir', arguments='.') + +test.vcproj_sys_path(test.workpath('sub dir', 'foo.vcxproj')) + +import SCons.Platform.win32 +system_dll_path = os.path.join(SCons.Platform.win32.get_system_root(), 'System32') +os.environ['PATH'] = os.environ['PATH'] + os.pathsep + system_dll_path + +test.run(chdir='sub dir', + program=[test.get_msvs_executable(msvs_version)], + arguments=['foo.sln', '/build', 'Release']) + +test.run(program=test.workpath('sub dir', 'foo'), stdout="foo.c\n") +test.validate_msvs_file(test.workpath('sub dir', 'foo.vcxproj.user')) + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/MSVS/vs-6.0-exec.py b/test/MSVS/vs-6.0-exec.py index 40f69c0113..ab708726fd 100644 --- a/test/MSVS/vs-6.0-exec.py +++ b/test/MSVS/vs-6.0-exec.py @@ -29,6 +29,7 @@ Visual Studio 6 project (.dsp) and solution (.dsw) files. """ +import os import sys import TestSConsMSVS diff --git a/test/MSVS/vs-7.0-exec.py b/test/MSVS/vs-7.0-exec.py index a6235a79fa..3c41aa56a3 100644 --- a/test/MSVS/vs-7.0-exec.py +++ b/test/MSVS/vs-7.0-exec.py @@ -29,6 +29,7 @@ Visual Studio 7.0 project (.vcproj) and solution (.sln) files. """ +import os import sys import TestSConsMSVS diff --git a/test/MSVS/vs-7.1-exec.py b/test/MSVS/vs-7.1-exec.py index 7bb3055adb..f66b92d793 100644 --- a/test/MSVS/vs-7.1-exec.py +++ b/test/MSVS/vs-7.1-exec.py @@ -29,6 +29,7 @@ Visual Studio 7.1 project (.vcproj) and solution (.sln) files """ +import os import sys import TestSConsMSVS diff --git a/testing/framework/TestSConsMSVS.py b/testing/framework/TestSConsMSVS.py index 1ab41360ee..fc0a411b1d 100644 --- a/testing/framework/TestSConsMSVS.py +++ b/testing/framework/TestSConsMSVS.py @@ -655,7 +655,7 @@ def get_tested_proj_file_vc_versions(): """ Returns all MSVC versions that we want to test project file creation for. """ - return ['8.0', '9.0', '10.0', '11.0', '12.0', '14.0', '14.1', '14.2'] + return ['8.0', '9.0', '10.0', '11.0', '12.0', '14.0', '14.1', '14.2', '14.3'] class TestSConsMSVS(TestSCons): @@ -879,6 +879,9 @@ def _get_vcxproj_file_tools_version(self, vc_version): elif vc_version == '14.2': # ToolsVersion='16' return '16.0' + elif vc_version == '14.3': + # ToolsVersion='17' + return '17.0' else: raise SCons.Errors.UserError('Received unexpected VC version %s' % vc_version)