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

fix: detect preview versions of msvs #269

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 44 additions & 16 deletions cpython-windows/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,35 +224,63 @@ def find_vswhere():


def find_vs_path(path, msvc_version):
"""
Attempts to find 'path' by invoking vswhere to identify where the
given msvc_version is installed.

vswhere is akin to things like 'pkg-config', it's an executable
that can be invoked to retrieve parameters of visual studio code
installations on the host machine.
"""
vswhere = find_vswhere()

# vswhere uses a math-like range expression for specifying the
# major release numbers.
# 16 = Visual Studio 2019,
# 17 = Visual Studio 2022,
if msvc_version == "2019":
version = "[16,17)"
elif msvc_version == "2022":
version = "[17,18)"
else:
raise ValueError(f"unsupported Visual Studio version: {msvc_version}")

p = subprocess.check_output(
[
str(vswhere),
# Visual Studio 2019.
"-version",
version,
"-property",
"installationPath",
"-products",
"*",
]
)
# Assemble the command line into an argv list for a subprocess
# call, so if the command fails we can tell the user what command
# we tried and enable them to potentially investigate further.
cmdline = [
str(vswhere),
"-version",
version,
"-property",
"installationPath",
"-prerelease",
"-products",
"*",
]
p = subprocess.check_output(cmdline)
if not p:
# add quotes around any of the terms with spaces in them, so that
# the user can copy-and-paste the command.
cmdline = ['"%s"' % term if " " in term else term for term in cmdline]
print("could not find visual studio (using '%s')" % cmdline)
sys.exit(1)

# Strictly speaking the output may not be UTF-8.
p = pathlib.Path(p.strip().decode("utf-8"))

p = p / path
p = p.strip().decode("utf-8")

# vswhere can potentially report multiple installed versions,
# one per line. The above 'strip' will have removed any
# trailing newlines, so if there is still a newline, there
# is more than one option.
if "\n" in p: # more than one line
print("found multiple matching instances of visual studio %s:" % msvc_version)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is like: you have 2022 and the 2022 pre-release installed? Should we just... pick one? (If you know) are they ordered?

Copy link
Author

@kfsone kfsone Jun 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two options:

  -latest        Return only the newest version and last installed.
  -sort          Sorts the instances from newest version and last installed to oldest.
                 When used with "find", first instances are sorted then files are sorted lexigraphically.

outputs (removing the -version so it shows both my installs; not quite sure I trust ms's installer enough to risk installing vs2022 proper with 19 tools and 22 preview at the same time)

E:\>"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -property installationPath -prerelease -products *
C:\Program Files\Microsoft Visual Studio\2022\Preview
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools

E:\>"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -property installationPath -prerelease -products * -sort
C:\Program Files\Microsoft Visual Studio\2022\Preview
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools

E:\>"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -property installationPath -prerelease -products * -latest
C:\Program Files\Microsoft Visual Studio\2022\Preview

ergo we could use '-latest', but that's not really solving the problem, just another python-related booby trap for the poor SOB who got the "make it work on windows" ticket...

It would be nice if running this from a devshell could just use the current environmented visual studio, but I lost that fight several times trying to do something similar with our studio's python-based cmake wrapper and haven't had the courage to revisit it since finding using powershell was a sufficient workaround =/

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, can you clarify why using -latest isn't really solving the problem?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I've been building time-and-again with C++X language features only available in the Preview edition and then it suddenly fails on me because it transparently switched to using the latest update of the Build Tools release, that's going to be a head scratcher, especially if it was an automatic update nobody manually triggered.

If they have multiple installs of the same edition, I'm sure they're expecting to have a switch of some kind for it, but I don't really want to explode this diff into tackling that.

It's not uncommon for canary builders or ci machines to have multiple VS variants of the same edition installed: 1/ VS 2022 Build Tools, 2/ VS 2022 Professional, 3/ VS 2022 Ultimate Preview, or if they have 4/ a Community Edition installed that gives them licensing considerations.

print(p)
sys.exit(1)

p = pathlib.Path(p, path)
if not p.exists():
print("%s does not exist" % p)
print("%s does not exist for vs%s" % (p, msvc_version))
sys.exit(1)

return p
Expand Down