-
-
Notifications
You must be signed in to change notification settings - Fork 324
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
Add support for multiple MSVC platform toolsets for a single Visual Studio installation #4149
Conversation
…tudio installation
Waiting for the experts to weigh in (@jcbrill ?) but it seems like looking for more-than-one-VC as those patterns do could cause confusion about what you actually get. |
Quite right. Some (really) quick thoughts... There is a bit of a terminology problem involved. The proposed implementation is really the "build tools" rather than a "toolset". The build tools are usually referred to as something like "v143" while a fully specified toolset is referred to as "14.32.31326". The The order of the results from a vswhere query are "unpredictable". At one point, I believed that the order returned may have been in reverse order of installation (LIFO). I'm not sure what happens when the vswhere version range is expanded as then there are multiple installations that could be the first returned. This could potentially be exacerbated by the implementation of preview versions if there is a "don't care" option (i.e., return preview or release). There is no guarantee that the first installation returned by the vswhere query supports the desired build tools, and by extension, toolset. For example, when requesting build tools v141 with vs2022 and vs2017 installed, there is no requirement that build tools v141 are installed in vs2022. I believe it is possible that the first instance returned by vswhere could be vs2022. Without a v141 toolset, the build will likely fail due to a msvc script error. At present, this becomes difficult to diagnose as the msvc batch output, while written to stdout, is effectively unavailable via SCons. Even if the first selected installation supports the build tools selected, a user may have a reason for wanting a specific installation of msvs due to ancillary tools that could be installed. In the example above, if the v141 build tools are installed in both vs2022 and vs2017, the product returned by vswhere may not necessarily be the product the user wants to use. VS2022 could be returned but there may be other reasons the user wants to use VS2017. Another potential problem is that the selected product could change based on the products installed and/or removed over time. Depending on the toolsets installed this could change the toolset version. Whether this matters or not probably can't be determined a priori. Although to be fair, this happens now with msvs updates. To date, while SCons uses #4106 discusses three msvc script enhancements:
In the short term, I was planning on implementing For example:
This would not change the selection behavior for existing users. Implementation of This might also close a couple of outstanding issues on the msvc bug scrub list as well. As someone who has implemented toolset support inside SCons once and outside of SCons twice, first-class support for toolsets in SCons is possible but requires a non-trivial expansion of data structures and logic. Feel free to point out any factual errors and errors of omission. As always, I could be wrong... |
P.S.: To date, it has been my experience that an implementation that takes a user version request (e.g., |
You are definitely right about the potential problem that arises when a user has installed both Visual Studio 2017 and Visual Studio 2022 (without the build tools for v141). The naming thing is also quite strange to me, it seems like even Micrsoft doesn't really know what means what, since the Visual Studio installer clearly speaks of "platform toolsets" rather than "build tools" for these options. The thing I wanted to accomplish was that a user with a simple installation of Visual Studio and multiple build tools, can actually compile projects made for all of the installed build tools. I was very confused when it happened to me that I couldn't compile v142 projects using SCons anymore after upgrading from Visual Studio 2019 to Visual Studio 2022, especially since I could still compile v140 projects without any issues. Your issue is definitely something that would need fixing before this PR could ever be merged, but I also believe that perhaps the "edge-case" handling of the automatic detection shouldn't go too far. In my mind, it should "just work" and for 99% of the cases you just want either a v140, v141, v142 or v142 build without actually caring too much about the subversions being used. How about something like this:
That way, there is a system that "just works" for the regular user and does the job 99% of the time exactly right. If for any reason a user has specific needs for special subversions or something similar, then I agree that the solution with the extra environment entries works very well. However, I believe that's not the majority of people but I could be wrong of course. |
Correct me if I'm wrong, but we are actually returning the correct compiler version as requested by the user (hence MSVC and not MSVS as in earlier versions of SCons). This compiler is the exact same as the one provided with the "correct" product version, so it makes perfect sense in my mind at least. Also, this approach already works for the vc140 build tools even in the current SCons version, so it's just an extension of existing functionality / a bugfix if we consider this vc140 thing a feature. I have been using this existing 'feature' for a few months already extensively. |
It is confusing. A given toolset for VS2022 might be In the proposed implementation, only the first 3 digits are used (e.g., "14.3") due to the current restriction on Users with many versions of VS installed could experience unpredictable side effects due to the vswhere selection of the first visual studio instance in the returned list. For example, I have VS2022 Community Preview, VS2022 BuildTools Preview, VS2022 Community, VS2022 BuildTools, VS2019 Community, VS2019 BuildTools, VS2017 Community, VS2017 BuildTools, VS2017 Express, and VS2015 Community installed. A query for '14.1' will return VS2022, VS2019, or VS2017. I have no idea what order they would be returned and whether or not installation order matters.
I am not saying you are wrong because I have made the same argument myself :) The problem is that it implicitly changes the definition of MSVC_VERSION from a "product" (2015 and earlier) to a "build tool/toolset" via a single variable. It is still possible to use Despite being deprecated, there remains a notion that MSVS_VERSION is equivalent to MSVC_VERSION. In fact, MSVS_VERSION is set to MSVC_VERSION which would be incorrect with a build tools/toolset interpretation. It is possible to achieve the end result of what you are asking for but in a different manner that does not affect existing users at all. Unfortunately, such an implementation requires fairly non-trivial updates to the existing code base.
vc140 works differently than the rest of the toolsets. It is a special case which just happens to work in SCons because of the manner in which visual studio is installed. You will notice that the 140 toolsets are not actually in the VS2017/2019/2022 folder with the rest of the toolsets. When the 140 toolset is installed, the 14.0 keys giving the installation location for vs2015 are in the registry. SCons finds the 14.0 (2015) installation via the registry as does msvc. The msvc 2017-2022 batch files find 14.0 via the registry (see
I once proposed exactly what you described. It did not go well :( This requires building a data structure based on all of the results returned from vswhere and walking the vs installation folder to detect which toolset versions are actually installed. By its very nature, this requires implementing a completely new data structure. However, once implemented, there is an opportunity for enhancements to the existing behavior. It is likely better to introduce one or more new variable(s) that does not carry any existing baggage by 're-interpreting" existing variables and won't change the behavior for existing users while allowing for enhanced functionality. I have written a detection implementation outside of SCons that allows me to test ideas and see what works and what doesn't in the context of SCons. My own work outside of SCons uses a function that returns a dictionary that is used by SCons via either Some examples taken from an older test script (some names may have changed):
The first two examples demonstrate the difference without affecting existing users.
Unfortunately, validation and consistency checks become much more involved as more variables are introduced. |
basically.. what @jcbrill said. If we make changes in what MSVC_VERSION means, we need to go through a deprecation cycle (read PITA). |
It seems like Some edge cases need to be defined, probably:
When implementing |
Some food for thought.. Terminology used later:
VS2017, and newer, are effectively containers for multiple build tools and by extension multiple toolsets. Each toolset has multiple tools. VS2015, and earlier, effectively have one toolset with multiple tools (amd64, x86_amd64, x86_arm, etc).
I'm not sure that I agree. For example, on my development box, toolset version '14.16.27023' is available in 9 installed instances:
There is no guarantee that each toolset has the desired target architecture tool installed. For example, maybe the There will be users that want the ability to specify exactly which product/channel/component/toolset is used possibly due to other "features" that are installed and/or corporate policy. In addition to the compiler proper, there are other things placed in the environment path based on VS installation options. Even compiler features (e.g., MFC/ATL, spectre libraries, etc) are based on a user's install preference and may not necessary be installed in every version of Visual Studio let alone by toolset. For those of us that have multiple versions installed, it is handy to able to target a specific product/channel/component/toolset for testing compatibility without having to setup a virtual machine and installing Visual Studio just because the desired combination is not directly selectable. It can be demonstrated that if the internal data structures provide the ability to perform selection of an individual msvc tool then any other functionality can be provided via additional ranked search lists. A visual studio instance can be uniquely identified by
Aside: In my own work, there is a fourth "attribute" (Sequence Number) that applies to VS2015 and earlier and would just muddy the discussion. An msvc tool can be uniquely identified by:
VS2015 and earlier can be handled in the same way as modern toolsets simply by expanding the version number to a toolset version.
A single vswhere query with json output is the way to go. The prototype in the branch to support preview versions does this. The visual studio workloads/components are available in the vswhere output. A ranking hierarchy is easy enough. Dealing with VS2015, and earlier, is a bit trickier. One approach is to reduce the components to a limited set of possibilities: 'Dev' (devenv.com exists), 'Exp' which can be determined directly from the registry, 'Cmd' command-line tools (devenv.com does not exist nor does wdexpress.com/vcexpress.com), 'Py' for Visual C++ for Python. For example:
There is no guarantee that the selected toolset supports the necessary target architectures for a build. Without the ability to uniquely select an msvc tool. There will be users that are unhappy with the policy.
These options are not mutually exlusive if the underlying data structure can be queried in different ways.
Inside of SCons, there was an abandoned effort that implemented the two-stage query you suggested earlier. It is woefully out of date, as the SCons internals have been under renovation. I keep it around as there was the occasional good idea. Repository: Relevant code fragments: Outside of SCons, there exists a script that does everything you are asking for and more. I have finally uploaded it to github but have not made the repository public yet. There is a non-trivial amount of code that is not enabled and a ton of comments taken directly from the msvc batch files that probably should be excised. The script can be used with SCons by placing it in a I will provide a link to the implementation soon. I am curious if it provides everything you want (with the obvious exception of being native SCons). Although, with an appropriate adapter/bridge it probably could be used in one's own hacked version of SCons. The Sconstruct fragment below is used to exercise SCons:
Manual inspection of the cache file confirmed that the toolsets are being correctly individually selected. SConstruct fragment for stress testing SCons:
I am not trying to discourage your efforts. I'm just on about the third or fourth iteration of where you are starting and just trying to hopefully point out some of the things you are bound to run into down the road. |
Closing in favor of #4174 |
Visual Studio versions starting from 2017 support multiple "platform toolsets" for a single Visual Studio installation. SCons seems to only support the matching toolset version for the currently installed Visual Studio version (for example vc143 when Visual Studio 2022 is installed). The vc140 toolset is a notable exception since it can be detected with the older method of reading registry entries (as used by SCons already). Basically, before this pull requests the following combinations would not work correctly (without adding
MSVC_USE_SCRIPT
andMSVC_USE_SCRIPT_ARGS
to the environment):I have tested my (very small) changes on a clean Windows 11 installation (in a virtual machine) with all of the following configurations without any problems:
A small note I have to make: the warning message differs a little bit when you don't have a Visual Studio version installed at all versus when only the specific toolset is not available, although I believe the messages make sense in a way. Two example situations with their corresponding warning that SCons throws:
scons: warning: VC version 14.2 not installed. C/C++ compilers are most likely not set correctly.
scons: warning: Could not find MSVC compiler 'cl'. It may need to be installed separately with Visual Studio.
Contributor Checklist:
CHANGES.txt
(and read theREADME.rst
)