[BE] parse CMake version from cmake -E capabilities instead of cmake --version (#157073)

`cmake -E capabilities` produces a JSON format that is more machine-friendly.

```console
$ cmake --version
cmake version 4.0.3

CMake suite maintained and supported by Kitware (kitware.com/cmake).
$ cmake -E capabilities | jq '.version.string'
"4.0.3"
$ cmake -E capabilities | jq
{
  "debugger": true,
  "fileApi": {
    "requests": [
      {
        "kind": "codemodel",
        "version": [
          {
            "major": 2,
            "minor": 8
          }
        ]
      },
      {
        "kind": "configureLog",
        "version": [
          {
            "major": 1,
            "minor": 0
          }
        ]
      },
      {
        "kind": "cache",
        "version": [
          {
            "major": 2,
            "minor": 0
          }
        ]
      },
      {
        "kind": "cmakeFiles",
        "version": [
          {
            "major": 1,
            "minor": 1
          }
        ]
      },
      {
        "kind": "toolchains",
        "version": [
          {
            "major": 1,
            "minor": 0
          }
        ]
      }
    ]
  },
  "generators": [
    {
      "extraGenerators": [],
      "name": "Watcom WMake",
      "platformSupport": false,
      "toolsetSupport": false
    },
    {
      "extraGenerators": [
        "Kate"
      ],
      "name": "Ninja Multi-Config",
      "platformSupport": false,
      "toolsetSupport": false
    },
    {
      "extraGenerators": [
        "CodeBlocks",
        "CodeLite",
        "Eclipse CDT4",
        "Kate",
        "Sublime Text 2"
      ],
      "name": "Ninja",
      "platformSupport": false,
      "toolsetSupport": false
    },
    {
      "extraGenerators": [],
      "name": "Xcode",
      "platformSupport": false,
      "toolsetSupport": true
    },
    {
      "extraGenerators": [
        "CodeBlocks",
        "CodeLite",
        "Eclipse CDT4",
        "Kate",
        "Sublime Text 2"
      ],
      "name": "Unix Makefiles",
      "platformSupport": false,
      "toolsetSupport": false
    }
  ],
  "serverMode": false,
  "tls": true,
  "version": {
    "isDirty": false,
    "major": 4,
    "minor": 0,
    "patch": 3,
    "string": "4.0.3",
    "suffix": ""
  }
}
```

Pull Request resolved: https://github.com/pytorch/pytorch/pull/157073
Approved by: https://github.com/Skylion007
This commit is contained in:
Xuehai Pan
2025-06-28 23:11:30 +08:00
committed by PyTorch MergeBot
parent 772d590415
commit 90b973a2e2
3 changed files with 39 additions and 14 deletions

View File

@ -18,3 +18,5 @@ start /wait "" python-amd64.exe /quiet InstallAllUsers=1 PrependPath=0 Include_t
if errorlevel 1 exit /b 1
set "PATH=%CD%\Python\Scripts;%CD%\Python;%PATH%"
%PYTHON_EXEC% -m pip install --upgrade pip setuptools packaging wheel
if errorlevel 1 exit /b 1

View File

@ -31,12 +31,13 @@ requires = [
"setuptools>=62.3.0,<80.0",
"wheel",
"astunparse",
"numpy",
"ninja",
"pyyaml",
"cmake",
"typing-extensions>=4.10.0",
"ninja",
"numpy",
"packaging",
"pyyaml",
"requests",
"typing-extensions>=4.10.0",
]
# Use legacy backend to import local packages in setup.py
build-backend = "setuptools.build_meta:__legacy__"

View File

@ -2,21 +2,32 @@
from __future__ import annotations
import json
import multiprocessing
import os
import platform
import sys
import sysconfig
from distutils.version import LooseVersion
from pathlib import Path
from subprocess import CalledProcessError, check_call, check_output
from typing import Any, cast
from subprocess import CalledProcessError, check_call, check_output, DEVNULL
from typing import cast
from . import which
from .cmake_utils import CMakeValue, get_cmake_cache_variables_from_file
from .env import BUILD_DIR, check_negative_env_flag, IS_64BIT, IS_DARWIN, IS_WINDOWS
try:
from packaging.version import Version
except ImportError:
try:
from setuptools.dist import Version # type: ignore[attr-defined,no-redef]
except ImportError:
from distutils.version import ( # type: ignore[assignment,no-redef]
LooseVersion as Version,
)
def _mkdir_p(d: str) -> None:
try:
os.makedirs(d, exist_ok=True)
@ -60,7 +71,7 @@ class CMake:
cmake3_version = CMake._get_version(which("cmake3"))
cmake_version = CMake._get_version(which("cmake"))
_cmake_min_version = LooseVersion("3.27.0")
_cmake_min_version = Version("3.27.0")
if all(
ver is None or ver < _cmake_min_version
for ver in [cmake_version, cmake3_version]
@ -82,15 +93,26 @@ class CMake:
return cmake_command
@staticmethod
def _get_version(cmd: str | None) -> Any:
"Returns cmake version."
def _get_version(cmd: str | None) -> Version | None:
"""Returns cmake version."""
if cmd is None:
return None
for line in check_output([cmd, "--version"]).decode("utf-8").split("\n"):
if "version" in line:
return LooseVersion(line.strip().split(" ")[2])
raise RuntimeError("no version found")
try:
cmake_capabilities = json.loads(
check_output(
[cmd, "-E", "capabilities"],
stderr=DEVNULL,
text=True,
),
)
except (OSError, CalledProcessError, json.JSONDecodeError):
cmake_capabilities = {}
cmake_version = cmake_capabilities.get("version", {}).get("string")
if cmake_version is not None:
return Version(cmake_version)
raise RuntimeError(f"Failed to get CMake version from command: {cmd}")
def run(self, args: list[str], env: dict[str, str]) -> None:
"Executes cmake with arguments and an environment."