refactor(desktop): find vswhere through hermes_platform

Review (#141651): _msvc_identity hand-wrote the vswhere.exe install path,
which is the known-path table the hermes_platform rule keeps in one place.
Add visual_studio_installer_dirs() to resolver/known_dirs.py and locate
vswhere with locate_command (PATH first, then the installer directory).

Return None explicitly when vswhere reports no installations, before selecting
the newest instance.

Warn on stderr with the reason whenever MSVC identity detection returns None:
missing vswhere, no matching installations, or a failed probe/version read.
This commit is contained in:
ethernet committed 2026-10-20 15:50:30 -04:00
1 parent 5d8bf6eaf0
commit ec64d1440e
3 files changed
+28 -6

No files matched your search

+5
View File
@@ -85,6 +85,11 @@ def windows_user_program_dirs() -> tuple[str, ...]:
)
def visual_studio_installer_dirs() -> tuple[str, ...]:
"""Where the Visual Studio installer puts vswhere.exe; it is never on PATH."""
return ("%ProgramFiles(x86)%/Microsoft Visual Studio/Installer",) if _WIN else ()
def mac_application_dirs() -> tuple[str, ...]:
return ("/Applications", "~/Applications") if sys.platform == "darwin" else ()
+16 -5
View File
@@ -127,18 +127,29 @@ def prepare_tools(source: Path, work: Path, cache: Path,
def _msvc_identity() -> dict[str, str] | None:
"""The newest VC toolset vswhere reports, with its default tools version."""
vswhere = Path(os.environ.get("ProgramFiles(x86)", r"C:\Program Files (x86)"),
"Microsoft Visual Studio/Installer/vswhere.exe")
from hermes_platform.resolver import locate_command
from hermes_platform.resolver.known_dirs import visual_studio_installer_dirs
vswhere = locate_command("vswhere.exe", known_dirs=visual_studio_installer_dirs())
if not vswhere.found:
print("warning: MSVC cache identity unavailable: vswhere.exe was not found", file=sys.stderr, flush=True)
return None
try:
result = subprocess.run([str(vswhere), "-latest", "-products", "*", "-requires",
result = subprocess.run([*vswhere.command, "-latest", "-products", "*", "-requires",
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-format", "json"],
capture_output=True, text=True, encoding="utf-8", errors="replace",
timeout=30, stdin=subprocess.DEVNULL, check=False)
instance = json.loads(result.stdout or "[]")[0]
instances = json.loads(result.stdout or "[]")
if not instances:
print("warning: MSVC cache identity unavailable: vswhere found no matching installations",
file=sys.stderr, flush=True)
return None
instance = instances[0]
tools = Path(instance["installationPath"], "VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt")
return {"installationVersion": instance["installationVersion"],
"VCToolsVersion": tools.read_text(encoding="utf-8").strip()}
except (OSError, subprocess.TimeoutExpired, ValueError, IndexError, KeyError):
except (OSError, subprocess.TimeoutExpired, ValueError, IndexError, KeyError) as error:
print(f"warning: MSVC cache identity unavailable: {error}", file=sys.stderr, flush=True)
return None
+7 -1
View File
@@ -308,9 +308,15 @@ def test_native_cache_is_stable_without_a_developer_environment(tmp_path, monkey
version_file.parent.mkdir(parents=True)
version_file.write_text("14.44.35207\n", encoding="utf-8")
vswhere = json.dumps([{"installationPath": str(install), "installationVersion": "17.14.1"}])
# vswhere is never on PATH; hermes_platform finds it in the installer directory.
installer = tmp_path / "Program Files (x86)/Microsoft Visual Studio/Installer"
installer.mkdir(parents=True)
(installer / "vswhere.exe").write_bytes(b"")
monkeypatch.setenv("ProgramFiles(x86)", str(tmp_path / "Program Files (x86)"))
monkeypatch.setenv("PATH", "")
def probe(command, **kwargs):
stdout = vswhere if command[0].endswith("vswhere.exe") else "rustc 1.98.0"
stdout = vswhere if command[0] == str(installer / "vswhere.exe") else "rustc 1.98.0"
return SimpleNamespace(returncode=0, stdout=stdout, stderr="")
desktop_toolchain.platform.platform()