Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for MSVC 2022 series #4030

Merged
merged 8 commits into from
Oct 16, 2021
5 changes: 4 additions & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions RELEASE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion SCons/Tool/MSCommon/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
32 changes: 29 additions & 3 deletions SCons/Tool/MSCommon/vc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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': [
Expand All @@ -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': [
Expand Down
12 changes: 12 additions & 0 deletions SCons/Tool/MSCommon/vs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
1 change: 1 addition & 0 deletions SCons/Tool/msvc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ constructor; setting it later has no effect.

<para>
Valid values for Windows are
<literal>14.3</literal>,
<literal>14.2</literal>,
<literal>14.1</literal>,
<literal>14.1Exp</literal>,
Expand Down
10 changes: 8 additions & 2 deletions SCons/Tool/msvs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
24 changes: 21 additions & 3 deletions test/MSVC/MSVC_UWP_APP.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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()
Expand Down
115 changes: 115 additions & 0 deletions test/MSVS/vs-14.3-exec.py
Original file line number Diff line number Diff line change
@@ -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 "<foo.c>" > output.txt'})
env.Program('foo.c')
""" % locals())

test.write(['sub dir', 'foo.c'], r"""
#include <stdio.h>
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:
1 change: 1 addition & 0 deletions test/MSVS/vs-6.0-exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
Visual Studio 6 project (.dsp) and solution (.dsw) files.
"""

import os
import sys

import TestSConsMSVS
Expand Down
1 change: 1 addition & 0 deletions test/MSVS/vs-7.0-exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
Visual Studio 7.0 project (.vcproj) and solution (.sln) files.
"""

import os
import sys

import TestSConsMSVS
Expand Down
1 change: 1 addition & 0 deletions test/MSVS/vs-7.1-exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
Visual Studio 7.1 project (.vcproj) and solution (.sln) files
"""

import os
import sys

import TestSConsMSVS
Expand Down
5 changes: 4 additions & 1 deletion testing/framework/TestSConsMSVS.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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)

Expand Down