CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
603 lines
18 KiB
Python
603 lines
18 KiB
Python
# Copyright Advanced Micro Devices, Inc.
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
from __future__ import annotations
|
|
import subprocess
|
|
import os, re, sys, shutil
|
|
from pathlib import Path
|
|
from abc import ABC
|
|
|
|
|
|
class FindProgram(ABC):
|
|
"""
|
|
# class FindProgram
|
|
|
|
Generally, this class stores programs's version, location.
|
|
|
|
## methods
|
|
- `run_query`: Using a subprocess executes the program's version output (possiably `self.exe --version`).
|
|
- `get_version`: Analyze the version info inputs from `run_query()` or overriden by rules(like Python and MSVC).
|
|
|
|
## Property
|
|
- `exe`: Programs PATH.
|
|
- `version`: Programs version number `<Major>.<Minor>.<Patch>`.
|
|
- `MAJOR_VERSION`: Programs major version number `<Major>`.
|
|
- `MINOR_VERSION`: Programs minor version number `<Minor>`.
|
|
- `PATCH_VERSION`: Programs patch version number `<Patch>`.
|
|
|
|
## General programs
|
|
Nothing special. Programs like `cmake` or `git` with it's version number fits `<Major>.<Minor>.<Patch>` are same.
|
|
|
|
## GCC Binutils
|
|
Binutils (`ar`, `as`, `ld`) comes with version number from `<Major>.<Minor>` to `<Major>.<Minor>.0`.
|
|
|
|
## Python 3
|
|
Python use its self libraries like sys, platform etc. Additional Properties:
|
|
- `is_VENV`: `True` if Shell environment in Python VENV, Astral uv VENV, or Conda ENV. Otherwise (Global Env, pipx, poetry, pyenv etc.) False.
|
|
- `ENV_TYPE`: Print VENV type. Supports `Global Env`, `Python VENV`, `Astral UV`, `Conda ENV`.
|
|
- `Free_Threaded`: If this Python 3 program is Free Threaded version.
|
|
- `no_gil`: If this Python 3 program have no Global Interpreter Lock(GIL). Value same as `Free_Threaded`.
|
|
- `interpreter`: Check Python interpreter is CPython, PyPy, Jython or anything else.
|
|
|
|
## MSVC
|
|
MSVC program's version number is bonded with different version naming conventions and meanings.
|
|
|
|
So, `MAJOR_VERSION`, `MINOR_VERSION`, `PATCH_VERSION` are None, `version` will saying to MSVC build version numbers, with a analyze of `v14X`.
|
|
|
|
Resource Compiler comes with Windows SDK, it's version num will be the version of Windows SDK.
|
|
|
|
Other Microsoft Visual Studio compoments as same to special cases.
|
|
"""
|
|
|
|
def __init__(self):
|
|
self._major_version = None
|
|
self._minor_version = None
|
|
self._patch_version = None
|
|
self._version = None
|
|
self.name = ""
|
|
|
|
@property
|
|
def exe(self):
|
|
_exe = shutil.which(self.name)
|
|
if _exe:
|
|
return _exe.replace("\\", "/").replace("EXE", "exe").replace("BIN", "bin")
|
|
else:
|
|
return None
|
|
|
|
def get_version(self):
|
|
if self.exe is None:
|
|
self._version = None
|
|
else:
|
|
query = re.search(
|
|
r"(\d+)\.(\d+)(?:\.(\d+))?", self.run_query([self.exe, "--version"])
|
|
).groups()
|
|
if query:
|
|
major, minor, patch = query
|
|
self._major_version = int(major)
|
|
self._minor_version = int(minor)
|
|
self._patch_version = int(patch) if patch else 0
|
|
self._version = (
|
|
f"{self._major_version}.{self._minor_version}.{self._patch_version}"
|
|
)
|
|
|
|
def run_query(self, cmd) -> str:
|
|
try:
|
|
return subprocess.run(
|
|
cmd, text=True, capture_output=True, check=True
|
|
).stdout.strip()
|
|
except Exception as e:
|
|
return None
|
|
|
|
@property
|
|
def MAJOR_VERSION(self):
|
|
return self._major_version
|
|
|
|
@property
|
|
def MINOR_VERSION(self):
|
|
return self._minor_version
|
|
|
|
@property
|
|
def PATCH_VERSION(self):
|
|
return self._patch_version
|
|
|
|
@property
|
|
def version(self):
|
|
return self._version
|
|
|
|
|
|
# Find Programs.
|
|
|
|
|
|
class FindPython(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.get_version()
|
|
self._py_env()
|
|
|
|
@property
|
|
def exe(self):
|
|
return (
|
|
sys.executable.replace("\\", "/")
|
|
.replace("EXE", "exe")
|
|
.replace("BIN", "bin")
|
|
)
|
|
|
|
def get_version(self):
|
|
self._major_version = sys.version_info.major
|
|
self._minor_version = sys.version_info.minor
|
|
self._patch_version = sys.version_info.micro
|
|
self._relse_version = sys.version_info.releaselevel
|
|
self._version = (
|
|
f"{self._major_version}.{self._minor_version}.{self._patch_version}"
|
|
)
|
|
|
|
def _py_env(self):
|
|
if os.getenv("CONDA_PREFIX") is not None:
|
|
return True, "Conda ENV"
|
|
elif sys.prefix == sys.base_prefix:
|
|
return False, "Global ENV"
|
|
elif os.getenv("VIRTUAL_ENV") is not None:
|
|
with open(Path(f"{sys.prefix}/pyvenv.cfg").resolve(), "r") as file:
|
|
_conf = file.read()
|
|
_env_type = "uv VENV" if "uv" in _conf else "Python VENV"
|
|
return True, _env_type
|
|
else:
|
|
return False, "Unknown ENV"
|
|
|
|
@property
|
|
def is_VENV(self):
|
|
return self._py_env()[0]
|
|
|
|
@property
|
|
def ENV_TYPE(self):
|
|
return self._py_env()[1]
|
|
|
|
@property
|
|
def Free_Threaded(self):
|
|
if self.MINOR_VERSION <= 12:
|
|
return False
|
|
elif self.MINOR_VERSION >= 13 and sys._is_gil_enabled():
|
|
return False
|
|
elif self.MINOR_VERSION >= 13 and not sys._is_gil_enabled():
|
|
return True
|
|
|
|
@property
|
|
def no_gil(self):
|
|
return self.Free_Threaded
|
|
|
|
@property
|
|
def interpreter(self):
|
|
return sys.implementation.name
|
|
|
|
|
|
class FindGit(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "git"
|
|
self.get_version()
|
|
|
|
|
|
class FindUV(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "uv"
|
|
self.get_version()
|
|
|
|
|
|
class FindCMake(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "cmake"
|
|
self.get_version()
|
|
|
|
|
|
class FindCCache(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "ccache"
|
|
self.get_version()
|
|
|
|
|
|
class FindNinja(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "ninja"
|
|
self.get_version()
|
|
|
|
|
|
# MSVC
|
|
|
|
|
|
class FindMSVC(FindProgram):
|
|
"""
|
|
MSVC have serval properties to check:
|
|
- `cl.exe` versions.
|
|
- Host Triple. MSVC toolchain will define host compiler like `Hostx86` or `Hostx64`.
|
|
- Target Triple. MSVC toolchain targeting machine architectures.
|
|
|
|
Same as `FindML64()`.
|
|
"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "cl"
|
|
self.get_version()
|
|
|
|
def get_version(self):
|
|
if shutil.which("cl.exe"):
|
|
_msg = subprocess.run(
|
|
[self.name],
|
|
text=True,
|
|
shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
).stdout
|
|
_match = re.search(
|
|
r"Version (\d+\.\d+\.\d+) for (\w+)", _msg
|
|
) # MSVC v141, v142, v143
|
|
if _match is None:
|
|
_match = re.search(
|
|
r"Version (\d+\.\d+\.\d+\.\d+) for (\w+)", _msg
|
|
) # MSVC v140
|
|
|
|
_vc_ver = _match.group(1)
|
|
_vc_ver_split = tuple(map(int, _vc_ver.split(".")))
|
|
|
|
if os.getenv("VisualStudioVersion") == "14.0":
|
|
_ver14 = f"v140"
|
|
elif _vc_ver_split >= (14, 30, 00000):
|
|
_ver14 = f"v143"
|
|
elif _vc_ver_split <= (14, 29, 30133):
|
|
_ver14 = f"v142"
|
|
elif _vc_ver_split <= (14, 16, 27023):
|
|
_ver14 = f"v141"
|
|
|
|
self._version = f"{_vc_ver} ({_ver14})"
|
|
self._target = _match.group(2)
|
|
|
|
if os.getenv("VSCMD_ARG_HOST_ARCH"):
|
|
self._host = os.getenv(
|
|
"VSCMD_ARG_HOST_ARCH"
|
|
) # MSVC v141/v142/v143 cases
|
|
elif ( # MSVC v140 cases
|
|
self.exe
|
|
== r"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/BIN/cl.exe"
|
|
):
|
|
self._host = "x86"
|
|
elif (
|
|
self.exe
|
|
== r"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/BIN/amd64/cl.exe"
|
|
):
|
|
self._host = "x64"
|
|
elif (
|
|
self.exe
|
|
== r"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/BIN/arm/cl.exe"
|
|
):
|
|
self._host = "ARM"
|
|
else:
|
|
self._host = os.getenv("VSCMD_ARG_HOST_ARCH")
|
|
|
|
else:
|
|
self._version = None
|
|
self._target = None
|
|
|
|
@property
|
|
def target(self):
|
|
return self._target
|
|
|
|
@property
|
|
def host(self):
|
|
return self._host
|
|
|
|
@property
|
|
def version(self):
|
|
return self._version
|
|
|
|
|
|
class FindML64(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "ml64"
|
|
self.get_version()
|
|
|
|
def get_version(self):
|
|
if shutil.which(self.name):
|
|
_msg = subprocess.run(
|
|
[self.name],
|
|
text=True,
|
|
shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
).stdout
|
|
_match = re.search(r"Version (\d+\.\d+\.\d+)", _msg)
|
|
_vc_ver = _match.group(1)
|
|
_vc_ver_split = tuple(map(int, _vc_ver.split(".")))
|
|
|
|
if os.getenv("VisualStudioVersion") == "14.0":
|
|
_ver14 = f"v140"
|
|
elif _vc_ver_split >= (14, 30, 00000):
|
|
_ver14 = f"v143"
|
|
elif _vc_ver_split <= (14, 29, 30133):
|
|
_ver14 = f"v142"
|
|
elif _vc_ver_split <= (14, 16, 27023):
|
|
_ver14 = f"v141"
|
|
|
|
self._version = f"{_vc_ver} ({_ver14})"
|
|
|
|
else:
|
|
self._version = None
|
|
|
|
|
|
class FindLIB(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "lib"
|
|
self.get_version()
|
|
|
|
def get_version(self):
|
|
try:
|
|
_msg = subprocess.run(
|
|
[self.name],
|
|
text=True,
|
|
shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
).stdout
|
|
_match = re.search(r"Version (\d+\.\d+\.\d+)", _msg)
|
|
if _match is None:
|
|
_match = re.search(r"Version (\d+\.\d+\.\d+\.\d+)", _msg)
|
|
else:
|
|
_vc_ver = _match.group(1)
|
|
_vc_ver_split = tuple(map(int, _vc_ver.split(".")))
|
|
|
|
if os.getenv("VisualStudioVersion") == "14.0":
|
|
_ver14 = f"v140"
|
|
elif _vc_ver_split >= (14, 30, 00000):
|
|
_ver14 = f"v143"
|
|
elif _vc_ver_split <= (14, 29, 30133):
|
|
_ver14 = f"v142"
|
|
elif _vc_ver_split <= (14, 16, 27023):
|
|
_ver14 = f"v141"
|
|
|
|
self._version = f"{_vc_ver} ({_ver14})"
|
|
except FileNotFoundError:
|
|
self._version = None
|
|
|
|
|
|
class FindLINK(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "link"
|
|
self.get_version()
|
|
|
|
def get_version(self):
|
|
try:
|
|
_msg = subprocess.run(
|
|
[self.name],
|
|
text=True,
|
|
shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
).stdout
|
|
_match = re.search(r"Version (\d+\.\d+\.\d+)", _msg)
|
|
if _match is None:
|
|
_match = re.search(r"Version (\d+\.\d+\.\d+\.\d+)", _msg)
|
|
else:
|
|
_vc_ver = _match.group(1)
|
|
_vc_ver_split = tuple(map(int, _vc_ver.split(".")))
|
|
|
|
if os.getenv("VisualStudioVersion") == "14.0":
|
|
_ver14 = f"v140"
|
|
elif _vc_ver_split >= (14, 30, 00000):
|
|
_ver14 = f"v143"
|
|
elif _vc_ver_split <= (14, 29, 30133):
|
|
_ver14 = f"v142"
|
|
elif _vc_ver_split <= (14, 16, 27023):
|
|
_ver14 = f"v141"
|
|
|
|
self._version = f"{_vc_ver} ({_ver14})"
|
|
except FileNotFoundError:
|
|
self._version = None
|
|
|
|
|
|
class FindRC(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "rc"
|
|
self.get_version()
|
|
|
|
def get_version(self):
|
|
if os.getenv("WindowsSDKVersion"):
|
|
return os.getenv("WindowsSDKVersion").replace("\\", "")
|
|
else:
|
|
return None
|
|
|
|
|
|
class FindGCC(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "gcc"
|
|
self.get_version()
|
|
|
|
@property
|
|
def target(self):
|
|
_target_name = subprocess.run(
|
|
[self.name, "-dumpmachine"], capture_output=True, text=True, check=True
|
|
).stdout.strip()
|
|
if self.exe is None:
|
|
_target_name = None
|
|
|
|
match _target_name:
|
|
case "x86_64-linux-gnu":
|
|
return "x64"
|
|
case "x86_64-redhat-linux":
|
|
return "x64"
|
|
case "x86_64-w64-mingw32":
|
|
return "MinGW-x64"
|
|
case "i686-w64-mingw32":
|
|
return "MinGW-x32"
|
|
case "arm-linux-gnueabi":
|
|
return "ARM"
|
|
case "aarch64-linux-gnu":
|
|
return "ARM64"
|
|
case "riscv64-linux-gnu":
|
|
return "RISC-V 64"
|
|
case "riscv32-linux-gnu":
|
|
return "RISC-V 32"
|
|
case "mips64-linux-gnuabi64":
|
|
return "MIPS64"
|
|
case "mips-linux-gnu":
|
|
return "MIPS"
|
|
case "powerpc64-linux-gnu":
|
|
return "PowerPC 64"
|
|
case "powerpc-linux-gnu":
|
|
return "PowerPC"
|
|
case "sparc64-linux-gnu":
|
|
return "SPARC64"
|
|
case _:
|
|
return "Unknown"
|
|
|
|
|
|
class FindGXX(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "g++"
|
|
self.get_version()
|
|
|
|
@property
|
|
def target(self):
|
|
_target_name = subprocess.run(
|
|
[self.name, "-dumpmachine"], capture_output=True, text=True, check=True
|
|
).stdout.strip()
|
|
if self.exe is None:
|
|
_target_name = None
|
|
|
|
match _target_name:
|
|
case "x86_64-linux-gnu":
|
|
return "x64"
|
|
case "x86_64-redhat-linux":
|
|
return "x64"
|
|
case "x86_64-w64-mingw32":
|
|
return "MinGW-x64"
|
|
case "i686-w64-mingw32":
|
|
return "MinGW-x32"
|
|
case "arm-linux-gnueabi":
|
|
return "ARM"
|
|
case "aarch64-linux-gnu":
|
|
return "ARM64"
|
|
case "riscv64-linux-gnu":
|
|
return "RISC-V 64"
|
|
case "riscv32-linux-gnu":
|
|
return "RISC-V 32"
|
|
case "mips64-linux-gnuabi64":
|
|
return "MIPS64"
|
|
case "mips-linux-gnu":
|
|
return "MIPS"
|
|
case "powerpc64-linux-gnu":
|
|
return "PowerPC 64"
|
|
case "powerpc-linux-gnu":
|
|
return "PowerPC"
|
|
case "sparc64-linux-gnu":
|
|
return "SPARC64"
|
|
case _:
|
|
return "Unknown"
|
|
|
|
|
|
class FindGFortran(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "gfortran"
|
|
self.get_version()
|
|
|
|
@property
|
|
def target(self):
|
|
_target_name = subprocess.run(
|
|
[self.name, "-dumpmachine"], capture_output=True, text=True, check=True
|
|
).stdout.strip()
|
|
if self.exe is None:
|
|
_target_name = None
|
|
match _target_name:
|
|
case "x86_64-linux-gnu":
|
|
return "x64"
|
|
case "x86_64-redhat-linux":
|
|
return "x64"
|
|
case "x86_64-w64-mingw32":
|
|
return "MinGW-x64"
|
|
case "i686-w64-mingw32":
|
|
return "MinGW-x32"
|
|
case "arm-linux-gnueabi":
|
|
return "ARM"
|
|
case "aarch64-linux-gnu":
|
|
return "ARM64"
|
|
case "riscv64-linux-gnu":
|
|
return "RISC-V 64"
|
|
case "riscv32-linux-gnu":
|
|
return "RISC-V 32"
|
|
case "mips64-linux-gnuabi64":
|
|
return "MIPS64"
|
|
case "mips-linux-gnu":
|
|
return "MIPS"
|
|
case "powerpc64-linux-gnu":
|
|
return "PowerPC 64"
|
|
case "powerpc-linux-gnu":
|
|
return "PowerPC"
|
|
case "sparc64-linux-gnu":
|
|
return "SPARC64"
|
|
case _:
|
|
return "Unknown"
|
|
|
|
|
|
class FindLD(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "ld"
|
|
self.get_version()
|
|
|
|
|
|
class FindGCC_AR(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "ar"
|
|
self.get_version()
|
|
|
|
|
|
class FindGCC_AS(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "as"
|
|
self.get_version()
|
|
|
|
|
|
# Find SDKs.
|
|
class FindVS20XX(FindProgram):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "Visual Studio"
|
|
self.get_version()
|
|
|
|
def get_version(self) -> str:
|
|
_vs_ver = os.getenv("VisualStudioVersion")
|
|
if _vs_ver is None:
|
|
return None
|
|
else:
|
|
_vs_ver = float(os.getenv("VisualStudioVersion"))
|
|
match _vs_ver:
|
|
case 17.0:
|
|
return "VS2022"
|
|
case 16.0:
|
|
return "VS2019"
|
|
case 15.0:
|
|
return "VS2017"
|
|
case 14.0:
|
|
return "VS2015"
|
|
case _:
|
|
return None
|
|
|
|
|
|
# TODO: Complete AMD ROCM/HIP SDK and amd-llvm detection.
|
|
# AMD ROCm/HIP SDKs.
|
|
# Find_ROCM/HIP ...
|
|
#
|
|
# AMD HIPCC and LLVM compiler.
|
|
# Find_HIPCC/Clang/Clang++/Flang/LLD/LLVM-AR/LLVM-AS/LLVM-MN/ ...
|