scons icon indicating copy to clipboard operation
scons copied to clipboard

On 64-bit Win7, MSVC_VERSION="XXX" does not report available MS Visual C/C++ versions

Open bdbaddog opened this issue 7 years ago • 4 comments

This issue was originally created at: 2010-07-24 00:59:55. This issue was reported by: carstenf. carstenf said at 2010-07-24 00:59:55

According to the man page about MSVC_VERSION: "Set it to an unexpected value (e.g. "XXX") to see the valid values on your system." This works on the 32-bit Windows that I used to far, but on 64-bit Windows 7 with VC9 (full, not Express) I get: >[ Note: Using env=Environment() for normal operation works as expected. ]

C:\Users\Carsten\Desktop\test-scons>scons -v
SCons by Steven Knight et al.:
        engine: v2.0.0.final.0.r5023, 2010/06/14 22:05:46, by scons on scons-dev
Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The
SCons Foundation
 
C:\Users\Carsten\Desktop\test-scons>type SConstruct
env=Environment(MSVC_VERSION="XXX");
 
env.Program("test", "test.cpp")
env.Tool('mssdk')
 
print env.Dump()
 
C:\Users\Carsten\Desktop\test-scons>scons -Q
ValueError: Unrecognized version XXX ():
  File "C:\Users\Carsten\Desktop\test-scons\SConstruct", line 1:
    env=Environment(MSVC_VERSION="XXX");
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Environment.py", line 991:
    apply_tools(self, tools, toolpath)
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Environment.py", line 105:
    env.Tool(tool)
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Environment.py", line 1692:
    tool(self)
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Tool\__init__.py", line 180:
    self.generate(env, *args, **kw)
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Tool\default.py", line 41:
    SCons.Tool.Tool(t)(env)
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Tool\__init__.py", line 180:
    self.generate(env, *args, **kw)
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Tool\mslink.py", line 242:
    msvc_setup_env_once(env)
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Tool\MSCommon\vc.py", line 343:
    msvc_setup_env(env)
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Tool\MSCommon\vc.py", line 436:
    d = msvc_find_valid_batch_script(env,version)
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Tool\MSCommon\vc.py", line 366:
    if not is_host_target_supported(host_target, version):
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Tool\MSCommon\vc.py", line 184:
    maj, min = msvc_version_to_maj_min(msvc_version)
  File "C:\Python26\Scripts\..\Lib\site-packages\scons-2.0.0.final.0\SCons\Tool\MSCommon\vc.py", line 157:
    raise ValueError("Unrecognized version %s (%s)" %
(msvc_version,msvc_version_numeric))

gregnoel said at 2010-08-08 12:54:20

Bug party triage.

garyo said at 2012-09-01 10:01:49

Bumping all old issues targeted for past releases to 2.x.

bdbaddog avatar Jan 02 '18 14:01 bdbaddog

Just came across this issue. Many years later, the behavior is the same, but there is nothing in the documentation now that says setting to an invalid value will show you what was available.

How to proceed? Among other things, seems to me an invalid version should be a UserError, because we can recognize it as an error in an sconscript file, even if it's also a ValueError in the sense that there's no such value.

mwichmann avatar Oct 30 '21 17:10 mwichmann

As always, there are a couple of things going on here.

The current method of decomposing the msvc version goes back to 2.0.0.final.0 and earlier.

How to proceed? Among other things, seems to me an invalid version should be a UserError, because we can recognize it as an error in an sconscript file, even if it's also a ValueError in the sense that there's no such value.

It may be helpful to distinguish between malformed (user error) versus not implemented/detected.

Checking the user-defined MSVC_VERSION value is deferred based on the code path. I believe that when using a user-defined script (i.e., MSVC_USE_SCRIPT), the MSVC_VERSION may not be checked at all in vc.py but may be in the requisite tools when generating the appropriate arguments and formats.

When the MSVC_VERSION is malformed, an exception is raised when the MSVC_VERSION is attempted to be parsed. The MSVC_VERSION is expected to be a floating point version (e.g., 9.0) optionally followed by an component suffix (e.g., Exp). In this issue, the literal text 'XXX' or an integer '9' fails to meet the parsing requirements and a ValueError is raised. In this case it is surely a UserError.

A well-formed version number may not necessarily be supported by scons. This is useful when passing to a user-defined script AND no other versions are installed to get around the early-exit when there are no detected versions and the MSVC_VERSION is not specified.

If an end-user wants to see the versions that are installed, the best method is to pass a floating point version that is known to greater than what is currently configured as the code paths for the registry and vswhere may differ in potential errors and/or warnings.

Something like '99.9' seems to work as the OP expected (see below).

Test results for each range of versions handled specially in the vc code:

  • 'XXX':

    ValueError: Unrecognized version XXX ()
    
  • '9':

    ValueError: Unrecognized version 9 (9)
    
  • '0.0':

    scons: warning: host, target = ('amd64', 'amd64') not supported for MSVC version 0.0
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 0.0 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: host, target = ('amd64', 'x86_amd64') not supported for MSVC version 0.0
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 0.0 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 0.0 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    
  • '6.8':

    scons: warning: host, target = ('amd64', 'amd64') not supported for MSVC version 6.8
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 6.8 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: host, target = ('amd64', 'x86_amd64') not supported for MSVC version 6.8
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 6.8 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 6.8 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    
  • '13.9':

    scons: warning: VC version 13.9 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 13.9 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 13.9 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    
  • '14.9':

    scons: warning: VC version 14.9 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 14.9 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 14.9 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    
  • '99.9':

    scons: warning: VC version 99.9 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 99.9 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    File "..\scons-master\scripts\scons.py", line 98, in <module>
    
    scons: warning: VC version 99.9 not installed.  C/C++ compilers are most likely not set correctly.
    Installed versions are: ['14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '8.0', '7.1', '7.0', '6.0']
    

Whether or not it is worth documenting is an executive decision.

jcbrill avatar Apr 10 '22 16:04 jcbrill

@bdbaddog any thoughts here? Close, because the docs don't currently claim this, or add a doc note that a certain kind of value (numeric, too big) will come back with a list of installed versions?

Also, should bogus values like the first two be ValueError or UserError? (assuming it's not complicated to enforce the latter - if it is, just forget about it, not worth much effort).

mwichmann avatar Jun 06 '22 17:06 mwichmann

Close, because the docs don't currently claim this, or add a doc note that a certain kind of value (numeric, too big) will come back with a list of installed versions?

Another possibility is to add and document a "public, user-callable function" without any arguments that returns the installed vcs list. Something like:

def get_installed_vcs(env=None):
    ...

def some_user_callable_installed_vcs_function():
   return get_installed_vcs()

jcbrill avatar Jun 06 '22 17:06 jcbrill

Okay, I think we should just close this. I can see tweaking the https://scons.org/doc/production/HTML/scons-man.html#cv-MSVC_VERSION wording a bit further. I don't know that I think it's worth further validating the value passed, in particular making it more clear it needs to be a string representing a numeric value (which would make "XXX" illegal).

With MSVC_VER=137

it fails with the possibly surprising:

scons: Reading SConscript files ...
TypeError: 'int' object is not iterable:
... long traceback

With MSVC_VER="137"

scons: Reading SConscript files ...

scons: warning: MSVC version '137' was not found.
  Visual Studio C/C++ compilers may not be set correctly.
  Installed versions are: ['14.3', '14.2', '14.1']
... long traceback

With an actual valid value, but not as a string (MSVC_VER=14.3) we get:

scons: Reading SConscript files ...
TypeError: 'float' object is not iterable:

And with MSVC_VER="XXX"

scons: Reading SConscript files ...
ValueError: could not convert string to float: '':

So if you give something that's vaguely valid-looking (a string that looks like a number) you at least get the report, though it's in the form of a warning, not a build abort at that point. If you use something else, you get kind of weird errors which abort SCons, but as noted before, it's not documented that you should get anything particularly useful if you chose to use, say "XXX", the "set to unexpected value" thing the original bugreport was about is not present in the docs these days.

mwichmann avatar Nov 22 '23 15:11 mwichmann

All for closing.

So if you give something that's vaguely valid-looking (a string that looks like a number) you at least get the report, though it's in the form of a warning, not a build abort at that point.

One could argue that MSVC version requests that not fruitful should raise an exception that could be caught by a user.

Unfortunately, that would require reworking and/or special handling for the default compiler selection on windows when there are no compilers installed. Also, it likely "breaks" a non-trivial number of the MSVC/MSVS tests.

jcbrill avatar Nov 22 '23 16:11 jcbrill

Okay, closing with this resolution:

  1. 64-bit Windows is not less/more broken in this regard.
  2. It is not documented (any longer) that an absurd value will yield any particular kind of outcome.

Will propose some small doc updates to maybe clarify a few details.

mwichmann avatar Nov 22 '23 16:11 mwichmann

Seems like a better error message should be output when an invalid value is entered..

bdbaddog avatar Nov 24 '23 22:11 bdbaddog

Seems like a better error message should be output when an invalid value is entered..

Yes... though see comment a few back that this might be tricky to implement.

mwichmann avatar Nov 25 '23 16:11 mwichmann

Perhaps judiciously placed type checks (e.g., Util.is_String) for MSVC_VERSION and MSVS_VERSION and possibly malformed (i.e., isn't a supported/expected format) could be helpful.

Moving forward, some of the existing code that initially evaluates the versions may have to be re-arranged and/or deferred when selecting a msvc instance/toolset/tool which likely will change the code execution order.

I can take a look in the next couple of days to see if there is an "easy" solution.

jcbrill avatar Nov 25 '23 17:11 jcbrill

What follows is a simple demonstration of what might be possible.

The example below adds a simple verification check to the get_default_version method that retrieves the MSVC_VERSION and MSVS_VERSION variables from the environment. This method does not appear in all of the code paths that would need verification but would handle the most common case.

Verification (value type and version format) checks:

def get_default_version(env):
    msvc_version = env.get('MSVC_VERSION')
    msvs_version = env.get('MSVS_VERSION')
    debug('msvc_version:%s msvs_version:%s', msvc_version, msvs_version)

    MSVC.Validate.verify_msvc_version(msvc_version, symbol='MSVC_VERSION')
    MSVC.Validate.verify_msvc_version(msvs_version, symbol='MSVS_VERSION')
    
    ...

What follows are the examples from above and an additional case (MSVC_VERSION="1.0") to generate the installed versions.

With MSVC_VERSION=137

scons: Reading SConscript files ...

MSVCArgumentError: Value type error: MSVC_VERSION=137 (expected type 'str', received type 'int'):
  ... long traceback

With MSVC_VERSION="137"

scons: Reading SConscript files ...

MSVCArgumentError: Unrecognized msvc version format: MSVC_VERSION='137':
  ... long traceback

With an actual valid value, but not as a string (MSVC_VERSION=14.3) we get:

scons: Reading SConscript files ...

MSVCArgumentError: Value type error: MSVC_VERSION=14.3 (expected type 'str', received type 'float'):
  ... long traceback

With MSVC_VERSION="XXX"

scons: Reading SConscript files ...

MSVCArgumentError: Unrecognized msvc version format: MSVC_VERSION='XXX':
  ... long traceback

With a correct type and format but an unsupported version (MSVC_VERSION="1.0") we get:

scons: Reading SConscript files ...

MSVCVersionUnsupported: Unrecognized msvc version: MSVC_VERSION='1.0'
  Valid msvc versions are: '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':
  ... long traceback

jcbrill avatar Nov 26 '23 14:11 jcbrill

Noodling a bit... we may want to make this an instance of UserError because that gets special handling - useful when we know there's an error in an SConscript, it trims the traceback so you don't get ... long traceback. It doesn't look like MSVUserError is a UserError. Something to chew on, someday.

mwichmann avatar Nov 26 '23 15:11 mwichmann

It doesn't look like MSVUserError is a UserError. Something to chew on, someday.

Probably a good idea.

It should not be that difficult to either replace or extend the msvc base exception types:

class VisualCException(Exception):
    pass

# base error types

class MSVCInternalError(VisualCException):
    pass

class MSVCUserError(VisualCException):
    pass

class MSVCRuntimeError(VisualCException):
    pass

jcbrill avatar Nov 26 '23 16:11 jcbrill

Examples with MSVCUserError inheriting from VisualCException and UserError. Minor adjustments to error messages.

Better?

With MSVC_VERSION=137

scons: Reading SConscript files ...

scons: *** Type error (expected 'str', received 'int'): MSVC_VERSION (137)
File "S:\SCons\jbrill-msvc-channel\scripts\..\SCons\Tool\MSCommon\MSVC\Validate.py", line 70, in checktype_string

With MSVC_VERSION="137"

scons: Reading SConscript files ...

scons: *** Unsupported msvc version format: MSVC_VERSION ('137')
File "S:\SCons\jbrill-msvc-channel\scripts\..\SCons\Tool\MSCommon\MSVC\Validate.py", line 85, in verify_legacy_version

With an actual valid value, but not as a string (MSVC_VERSION=14.3) we get:

scons: Reading SConscript files ...

scons: *** Type error (expected 'str', received 'float'): MSVC_VERSION (14.3)
File "S:\SCons\jbrill-msvc-channel\scripts\..\SCons\Tool\MSCommon\MSVC\Validate.py", line 70, in checktype_string

With MSVC_VERSION="XXX"

scons: Reading SConscript files ...

scons: *** Unsupported msvc version format: MSVC_VERSION ('XXX')
File "S:\SCons\jbrill-msvc-channel\scripts\..\SCons\Tool\MSCommon\MSVC\Validate.py", line 85, in verify_legacy_version

With a correct type and format but an unsupported version (MSVC_VERSION="1.0") we get:

scons: Reading SConscript files ...

scons: *** Version number '1.0' is not supported: MSVC_VERSION ('1.0')
  Valid values are: '14.3', '14.2', '14.1', '14.0', '12.0', '11.0', '10.0', '9.0', '8.0', '7.1', '7.0', '6.0'
File "S:\SCons\jbrill-msvc-channel\scripts\..\SCons\Tool\MSCommon\MSVC\Validate.py", line 113, in validate_legacy_version

With a corect type and format but an unsupported component (MSVC_VERSION="14.3Arg") we get:

scons: Reading SConscript files ...

scons: *** Component type 'Arg' is not supported: MSVC_VERSION ('14.3Arg')
  Valid values are: 'Exp'
File "S:\SCons\jbrill-msvc-channel\scripts\..\SCons\Tool\MSCommon\MSVC\Validate.py", line 124, in validate_legacy_version

Research:

  • The version list for "1.0" does not include the express versions (i.e., version number vs entire specification).

jcbrill avatar Nov 28 '23 11:11 jcbrill