-
-
Notifications
You must be signed in to change notification settings - Fork 320
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
[WIP] MSVC: detection fixes and changes #4409
base: master
Are you sure you want to change the base?
Conversation
Changes: * VS/VC roots are classified by their installed features (e.g, devenv.com, vcexpress.com, etc.). This provides for special-case verification of batch file arguments based on the internal classification. * Consistent with earlier behavior, express versions are used for the non-express msvc version symbol for 14.1 and 8.0 when the express version is the only version installed. * There is a strong possibility that 14.0Exp may not have been detected correctly. It appears that registry keys for earlier versions of msvc are not populated. Refined detection of 14.0Exp was added. * Special case handling of VS2015 BuildTools was added. The msvc batch files restrict the arguments available as compared to full versions. The arguments may be accepted and ignored possibly resulting in build failures that are likely not easy to diagnose. * Special case handling og VS2015 Express was added. The msvc batch files restrict the arguments available as compared to full versions. For example, store/UWP build are only available for x86 targets. * Windows/Platform SDK installations of 7.1, 7.0, and 6.1 populate registry keys and installation folders that were detected by scons (versions 10.0 and 9.0). Unfortunately, the generated files are intended to be used via SetEnv.cmd and result in errors. The detection of sdk-only installations was added and the roots are ignored. * The relative imports of the MSCommon module were changed to top-level absolute imports in a number of microsoft tools. Moving any of the tools to the site tools folder failed on import (i.e., the relative paths become invalid when moved). * VS2005 to VS2015 vcvarsall.bat dispatches to a dependent batch file when configuring the msvc environment. In certain installation scenarios, the dependent batch file (e.g., vcvars64.bat) may not exist. The existence of vcvarsall.bat, the dependent batch file, and the compiler executable are now verified. * MSVC configuration data specific to versions VS2005 to VS2008 was added as the dependent batch files have different names than the batch files for VS2010 and later. VC++ For Python is handled as a special case as the dependent batch files: are not used and are in different locations. * When VC++ For Python is installed using the ALLUSERS=1 command-line option, the registry keys written are under HKLM rather than HKCU. VC++ For Python installed for all users is now correctly detected. * The existing detection configuration for vswhere and the registry was refactored to separate the two methods of detection. * The detection of the msvc compiler executable has been modified and no longer considers the os environment. The detection of the msvc compiler executable was modified to provide more detailed warning messages.
[STICKY] More detailed notes:
Suggested changes:
Test Environments
Footnotes:
Kind description:
Express Detection ChangesResults from VMs with only express versions installed.
Stress TestsEnvironments build count and msvc cache entry count by test environment (i.e., combinations of msvc batch file arguments).
|
…c path from json output. Test failures when the vc path from json is normalized. Test failure for AddOption help output.
…where command-line argument
@mwichmann @bdbaddog I need some guidance. Any takers? Providing the ability to specify the vswhere path on the command-line would allow the user-defined path specification to be used when constructing the default environment tools (i.e., the initial detection). This also allows a SetOption from an sconstruct and/or site initialization file to set the value of the option rather than on the command-line proper. Specifying the vswhere path via an Environment likely is not available when the default environment tools are initialized. Since the installed vcs list is cached, if new roots are discovered by the user-defined vswhere path (which is presumably why it is being specified), the installed vcs list needs to be cleared and recomputed. The proposed branch does this. Specifying the vswhere path via the environment makes the implementation more complicated that it would be otherwise. If the vswhere path specification via the environment were deprecated and eventually eliminated, detection of msvc instances can be done once and never again as all requisite information is available at the time of initial detection. I believe there are at least two methods for implementing the vswhere path command-line option. Any and all advice is welcome. Method A - Built-in option in
|
Sigh... I've just been hacking on a complaint about paths, which shows up here: #4410. This still isn't completely fleshed out, but stuff that came tumbling out when I sat down to actually write it. There's an item there about user-supplied paths... And, yes, there's already an issue complaining about the problems of tool modules that optionally add cli arguments: #3455. And, yes, the tests are painfully fragile when they expect specific outputs, but that output is variable based on external factors. Usually it means writing an even more complex regex than the one that was in place before. So all this is known stuff, and I have no answers... |
I realize you have a lot on your plate and am not trying to pile on. #4410 is well written and is kind of depressing. #3455 (and the referenced issue) is more or less what I'm struggling with here. As a middle ground, could internal modules supporting tools (e.g., the MSCommon.vc module supports msvc, mslib, mslink) be added as "built-in"options conditionally based on the platform in script options in the near term? For example, the "--vswhere-path" option would only be added to the parser definitions on The downside is that the help message would vary by platform which may not be the worst thing in the world as the local options would only be added on The upside is that the options are not "local options" so they would be displayed with |
@jcbrill - any --vswhere would need be a separate PR. I'd advocate for |
You'll need to add blurb to CHANGES.txt and RELEASE.txt. |
SCons/Tool/midl.py
Outdated
@@ -37,7 +37,7 @@ | |||
import SCons.Scanner.IDL | |||
import SCons.Util | |||
|
|||
from .MSCommon import msvc_setup_env_tool | |||
from SCons.Tool.MSCommon import msvc_setup_env_tool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why make this change? (and all the similar changes)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MSCommon module import was changed from a relative import to a top-level/absolute import in the following Microsoft tools: midl, mslib, mslink, mssdk, msvc, msvs.
Moving any of the tools using relative imports to the site tools folder would fail on import (i.e., the relative import paths become invalid when moved).
Should just work moving to scons-site folder. Was doing some testing and the imports failed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you'd want moving some part of the msvc logic to site-scons, and not all of it to work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. If one wanted to copy and customize a microsoft tool like mslib.py locally. After copying mslib.py to the tools folder in the site-scons folder and running scons, the copied tool import would fail as the relative imports are no longer valid.
The MSCommon module was the only module in the microsoft tools that was using a relative import. All others were absolute.
This is not something that I'm passionate about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh ok.
I think I misread this previously. So this isn't about moving part of a tool to site-tools, but rather a whole tool, which in this case depends on common logic in SCons.Tool
O.k. Then yes these changes make total sense. Good catch.
I thought I read somewhere that an environment variable was added based on the name. There already exists a VSWHERE construction variable. Thought there might be a conflict. Happy to move to another PR, it was just easier in this one since the handling of vswhere executables has been modified anyway and there is a function to evaluate if a command-line argument was set (which could just be no-op stub returning None). No harm, no foul. |
In general. The smaller more focus each PR has, the easier it is for me to review and merge. The larger it gets, the review time will increase almost exponentially.. |
In both the existing code and the proposed code, the subprocess call for vswhere has the Anyone else OK with that? It might matter if there is an issue with vs installed vswhere.exe which would likely cause the script to fail during default msvc tools initialization. In this case, the user-specified vswhere via the Environment may not get a chance to run which kind of defeats the purpose of being able to set it in the environment (something I would like to see removed). |
…turning None. Change processing of user-specified vswhere path. TODO: * revisit MSVC.Util.process_path due to realpath behavior for some windows specifications (drive specifications, etc).
What would cause this type of failure? Bad command line args to vswhere? |
My understanding is that when I suppose it is possible that bad arguments could cause vswhere.exe to exit with a non-zero code. I have not tried it but it should not be too difficult to test. There might be any number of OS events that could cause vswhere.exe to fail internally. If subprocess.run is passed invalid arguments a ValueError should be raised. |
I'd rather you didn't add any additional features/logic to this PR. It's already very large and will take quite some time to properly review. |
That's fine. There are no more features planned. Are you ok with catching and ignoring CalledProcessError? Like OSError, the error string is logged to the debug file if enabled. Basically, from: except OSError as e:
errmsg = str(e)
debug("%s: %s", type(e).__name__, errmsg)
break to: except (OSError, subprocess.CalledProcessError) as e:
errmsg = str(e)
debug("%s: %s", type(e).__name__, errmsg)
break |
That'd be a logic change. See previous statement.. ;) |
There's a reason there is WIP in the title ;) |
[STICKY] Notes to self for post-review cleanup:
|
That could be an error (on my part). That flag was added after examining linter complaints:
It's quieter now, but... that meant we changed from the default ( |
Changes: * Added MSVC detection priority. * Added VS2015 edition limitations. * Updated SDK batch file known issues. * Added footnotes for MSVC batch file argument limitations. * Added footnote for Windows SDK version numbers (Windows 10 and Windows 11)
Revised |
… prefix handling for debug output to stdout.
Internal changes: * Move command-line option handling to MSVC/Options.py * Move vswhere code to MSVC/VSWhere.py * Move new vs detection code to MSVC/VSDetect.py * Update test suite accordingly.
this is with what gh has named Edit: sorry... operator error, on the VM in question, what I always have set to open up a cmd shell in this case did a powershell. Retrying. |
And, it works to build. Sorry about the false alarm, guess my setup wasn't consistent and I got lazy. That VM has no other install, and the build fails without that argument with the usual 'cl' is not recognized as an internal or external command,
operable program or batch file. So that's good! |
@mwichmann Thank you. The help is appreciated. |
So just to put this out there... this mechanism adds an optional command-line argument to pass arguments to the msvc subsystem. It looks, however, quite different from how another optional feature, ninja, is enabled. To be enable the chance to use ninja, you use a commandline option ( Also, I was trying to figure out if I could enable this without putting on the commandline. You can't run the testsuite with non-standard arguments directly, you'd have to modify every single launch. However, |
Yes. Please use --experimental for this. Adding another env var should be the very last option used. |
Banged out in a hurry, apologies for grammatical errors. If I didn't answer a question, post a gentle reminder.
The environment variable is temporary and is only used for my own development testing. Unlike, the ninja and install sandbox arguments, it is preferable to define the command-line arguments at the file level rather than via a constructed environment. The only reason that it wasn't added without the environment variable is that it causes one of the unit tests to fail. The command-line options end up being local options and the test (I can't recall which one) is matching the options that it added in the test file and is not expecting any other local arguments so the expected matched text fails. The ability to set the channel and the component via the environment. was implemented, tested, and then removed. There is a non-trivial amount of validation that needs to happen so it was easier to take it out for now. The development strategy thus far has been to make sure that without any additional information, the new code behaves identically to the old code.
For a single run, there is an exposed method that can used to set the default channel. It needs to be called before first use in the msvc code. The
The implementation will use the command-line argument first, followed by the value set via the function above, or the initialized value (Release) if neither the command-line argument or the method call were defined. This could be done in a site initialization file or an sconstruct file (subject to the fact that it need to be set before first retrieval, otherwise a warning is issued):
At present, without the command-line option or the method call mentioned above, the code acts as the current master (preview versions are ignored). The reason is that there are issues that still need to be resolved surrounding:
|
@mwichmann If you want to run the test suite with only preview versions, you can change a hard-coded initialization value in SCons/Tool/MSCommon/MSVC/VSDetect.py Change cls.vs_channel_initial from:
to:
|
Unfortunately, it's probably never going to work without modifications. The issue appears to be that the command-line options are registered in the the MSCommon/Tool/MSVC/Options.py module. Any test that does not load the vc.py (MSCommon?) module is going to fail with a The options would have to be defined in SCons/Script/ScriptOptions.py to be considered "first-class" options always known to the parser. |
Hmmm, might need to record that tidbit somewhere. The whole way the options are handled (other than the so-called "built-in options", which are mostly fine) gives lots of headaches. I didn't realize that def _exec_main(parser, values) -> None:
sconsflags = os.environ.get('SCONSFLAGS', '')
all_args = sconsflags.split() + sys.argv[1:]
options, args = parser.parse_args(all_args, values) |
SCONSFLAGS is doing what it is supposed to do. The problem is that there are a lot of tests that don't necessarily load the module which adds the local options.
EDIT: THIS POST IS LIKELY INCORRECT PENDING FURTHER INVESTIGATION. |
I'm not sure the previous post is correct. |
Okay, I get it, now. Yes, there will be issues with this. In fact, many of the tests specifically don't want to load the module, as they intend to test paths through setting and retrieving construction variables. So stuffing an argument into |
I expected this to work:
Where
Of the 79 MSVS+MSVC tests, the following tests fail, I'm not sure why yet and can't look at until later tonight:
|
* Log OSError exception for resolve_path in MSCommon/MSVC/Util.py. * Fix file docstring for VSDetect.py. * Update MSVC action when MSVC_USE_SCRIPT is None and MSVC_USE_SETTINGS is not None (SETTINGS instead of BYPASS). * Replace process_path function with resolve_path and normalize_path functions in MSCommon/MSVC/Util.py. * Replace process_path invocations with normalize_path invocations. * Protect against inadvertent resolve/realpath for windows drive specifications in resolve_path and normalize_path. * Additional options for normalize_path with defaults consistent with process_path.
…t default channel.
@mwichmann A minor tweak was pushed that allows running the test suite with the default msvs channel being set to Preview. TEMPORARY FIX: Instead of using the windows environment variable to enable command-line options, a windows environment variable was added that defines the default channel if the command-line option is not defined. Sample usage:
It is not all rainbows and unicorns though: at a minimum, the This is not particularly surprising as the code has been modified working from the inside out and only the release versions are strictly compatible with all test files. As mentioned above, there are known issues that have not been addressed yet. At this point in the development cycle, I typically only run the MSVS+MSVC tests (approximately 79 tests). Feel free to take it for a spin around the block. |
Manually resolved conflicts: * CHANGES.txt * RELEASE.txt
* Add env_query function to return the value in a mapping associated with the key, invoking subst method when specified and available. Support general mapping in addition to scons Environments. * Add methods that accept env mapping in MSCommon/MSVC/VSDetect.py and MSCommon/MSVC/VSWhere.py.
… installations. Internal changes: * Remove "*" as a channel symbol. * MSVC options: * Use a single environment variable (SCONS_MSVC_OPTIONS). * Add an msvc options parser. * Always add scons options. * Update test/Help.py for msvc local options. * MSVC/MSVS detection: * Update configuration data for MSVS and update registry keys for MSVC/Config.py. * Add msvc exists guard in MSCommon/vcTests.py for sdk list tests in case sdk installed but msvc is not (preview testing). * Rework vs.py for msvs instances and temporarily comment-out existing accessor methods and replace with attributes. * SCons/Tool/msvsTests.py: * Rework DummyExists implementation to accommodate revised msvc/msvs detection. * Handle multiple versions returned for express versions. * test/Help.py * Detect if msvc location options should be present and adjust the expected output accordingly.
Manually resolve conflicts: * SCons/Tool/MSCommon/MSVC/Util.py * SCons/Tool/MSCommon/MSVC/UtilTests.py
@mwichmann All tests appear to pass using preview-only versions with the latest commit (and there was much rejoicing). Previous temporary environment variables were removed and replaced with a single environment variable that is similar to To run the test suite with preview-only versions:
To run the test suite normally:
To run a single script with preview-only versions:
To run a single script normally:
Note:
Windows temporary environment variables Environment variable The msvc local command-line options are always added when the This caused an issue with The current commit was tested locally as follows:
A number of internal sematic issues are still outstanding. |
Changes:
devenv.com
,vcexpress.com
, etc.). This provides for special-case verification of batch file arguments based on the internal classification.14.1
and8.0
when the express version is the only version installed.14.0Exp
may not have been detected correctly. It appears that registry keys for earlier versions of msvc are not populated. Refined detection of14.0Exp
was added.x86
targets.7.1
,7.0
, and6.1
populate registry keys and installation folders that were detected by scons (versions10.0
and9.0
). Unfortunately, the generated files are intended to be used viaSetEnv.cmd
and result in errors. The detection of sdk-only installations was added and the roots are ignored.vcvarsall.bat
) dispatches to a dependent batch file when configuring the msvc environment. In certain installation scenarios, the dependent batch file (e.g.,vcvars64.bat
) may not exist. The existence ofvcvarsall.bat
, the dependent batch file, and the compiler executable are now verified.ALLUSERS=1
command-line option, the registry keys written are underHKLM
rather thanHKCU
. VC++ For Python installed for all users is now correctly detected.Internal code changes:
Contributor Checklist:
CHANGES.txt
(and read theREADME.rst
)