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
803 lines
27 KiB
Python
803 lines
27 KiB
Python
# Copyright Advanced Micro Devices, Inc.
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
from __future__ import annotations
|
|
from .find_tools import FindPython, FindMSVC
|
|
from .utils import *
|
|
import platform, re, sys, os
|
|
from pathlib import PureWindowsPath
|
|
import subprocess
|
|
from typing import List
|
|
|
|
|
|
class SystemInfo:
|
|
"""
|
|
Provides system information in a nicely formatted output.
|
|
|
|
Workflow:
|
|
1. Have a function extracting the system information <X> you need
|
|
2. Assign it in SystemInfo.__init__(self)
|
|
3. Provide a property <X>_STATUS(self), that provides a list of strings,
|
|
containing the lines of content stripped of whitespace.
|
|
4. Add it to "states" in summary(self):
|
|
("<X>:", self.<X>_STATUS)
|
|
|
|
Using it:
|
|
summary: Print system info
|
|
python_list: Print python list
|
|
section_bar(<section>): Prints <section> centered with "==" surrounding it
|
|
"""
|
|
|
|
def __init__(self):
|
|
|
|
self._os = platform.system().capitalize()
|
|
|
|
self._device_os_stat = self.device_os_status()
|
|
|
|
# Define CPU configuration.
|
|
self._device_cpu_stat = self.device_cpu_status()
|
|
|
|
# Define GPU configuration list.
|
|
self._device_gpu_list = self.device_gpu_list()
|
|
|
|
# Define Device Memory status.
|
|
self._device_dram_stat = self.device_dram_status()
|
|
|
|
# Define Device Storage status.
|
|
self._device_disk_stat = self.device_disk_status()
|
|
|
|
# Define file system overview.
|
|
self._device_file_system_list = self.device_file_system()
|
|
|
|
# Define ccache status.
|
|
self._device_ccache_stat = self.device_ccache_system()
|
|
|
|
self._py = FindPython()
|
|
|
|
# Define python package list
|
|
self._py_list = self.device_python_list()
|
|
|
|
if self.is_windows:
|
|
self._cl = FindMSVC()
|
|
|
|
# Define the device's system is Windows Operating System (Win32).
|
|
@property
|
|
def is_windows(self):
|
|
return self._os == "Windows"
|
|
|
|
@property
|
|
def is_linux(self):
|
|
return self._os == "Linux"
|
|
|
|
@property
|
|
def OS_NAME(self):
|
|
if self.is_windows:
|
|
return f"{self._device_os_stat[0]} {self._device_os_stat[1]} ({self._device_os_stat[2]}, Build {self._device_os_stat[3]})"
|
|
elif self.is_linux:
|
|
return f"{self._device_os_stat[0]} {self._device_os_stat[1]}"
|
|
|
|
@property
|
|
def OS_KERNEL(self):
|
|
return self._device_os_stat[3]
|
|
|
|
if is_windows:
|
|
|
|
@property
|
|
def is_cygwin(self):
|
|
"""
|
|
Define the system environment is Cygwin.
|
|
"""
|
|
return True if sys.platform == "cygwin" else False
|
|
|
|
@property
|
|
def is_msys2(self):
|
|
"""
|
|
Define the system environment is MSYS2.
|
|
"""
|
|
return True if sys.platform == "msys" else False
|
|
|
|
@property
|
|
def GPU_LIST(self):
|
|
return self._device_gpu_list
|
|
|
|
@property
|
|
def VIRTUAL_MEMORY_AVAIL(self):
|
|
return self._device_dram_stat[-1]
|
|
|
|
if is_linux:
|
|
|
|
@property
|
|
def is_WSL2(self):
|
|
with open("/proc/version", "r") as f:
|
|
_f = f.read()
|
|
return True if "microsoft-standard-WSL2" in _f else False
|
|
|
|
@property
|
|
def SWAP_MEMORY_AVAIL(self):
|
|
return self._device_dram_stat[2]
|
|
|
|
def device_os_status(self):
|
|
"""
|
|
Returns Device's operating system status.
|
|
- Windows: -> `(Windows, 10/11, 2_H_, XXXXX)`
|
|
- Linux: -> `(LINUX_DISTRO_NAME, LINUX_DISTRO_VERSION, "GNU/Linux", LINUX_KERNEL_VERSION)`
|
|
- Others: -> `None`.
|
|
"""
|
|
|
|
if self.is_windows:
|
|
_os_major = platform.release()
|
|
_os_build = platform.version()
|
|
_os_update = get_regedit(
|
|
"HKLM",
|
|
r"SOFTWARE\Microsoft\Windows NT\CurrentVersion",
|
|
"DisplayVersion",
|
|
)
|
|
|
|
return (platform.system(), _os_major, _os_update, _os_build)
|
|
|
|
elif self.is_linux:
|
|
kernel = subprocess.check_output(["uname", "-r"], text=True).strip()
|
|
kernel_version = kernel.split("-")[0]
|
|
|
|
with open("/etc/os-release") as f:
|
|
_f = f.read().splitlines()
|
|
for _line in _f:
|
|
_name_match = re.match(r'^NAME="?(.*?)"?$', _line)
|
|
_version_match = re.match(r'^VERSION_ID="?(.*?)"?$', _line)
|
|
|
|
if _name_match:
|
|
_LINUX_DISTRO_NAME = _name_match.group(1)
|
|
if _version_match:
|
|
_LINUX_DISTRO_VERSION = _version_match.group(1)
|
|
|
|
return (
|
|
_LINUX_DISTRO_NAME,
|
|
_LINUX_DISTRO_VERSION,
|
|
"GNU/Linux",
|
|
kernel_version,
|
|
)
|
|
else:
|
|
pass
|
|
|
|
def device_cpu_status(self):
|
|
"""
|
|
**Warning:** This function may broken in Cluster systems.
|
|
Return CPU status, include its name, architecture, total cpu count.
|
|
-> `(CPU_NAME, CPU_ARCH, CPU_CORES)`
|
|
"""
|
|
|
|
import os, platform, subprocess, re
|
|
|
|
if self.is_windows:
|
|
_cpu_name = get_regedit(
|
|
"HKLM",
|
|
r"HARDWARE\DESCRIPTION\System\CentralProcessor\0",
|
|
"ProcessorNameString",
|
|
)
|
|
_cpu_arch = platform.machine()
|
|
_cpu_core = os.cpu_count()
|
|
|
|
return (_cpu_name, _cpu_core, _cpu_arch)
|
|
|
|
elif self.is_linux:
|
|
_cpu_name = (
|
|
re.search(
|
|
r"^\s*Model name:\s*(.+)$",
|
|
subprocess.run(
|
|
["lscpu"], capture_output=True, text=True, check=True
|
|
).stdout,
|
|
re.MULTILINE,
|
|
)
|
|
.group(1)
|
|
.strip()
|
|
)
|
|
_cpu_arch = platform.machine()
|
|
_cpu_core = os.cpu_count()
|
|
|
|
return (_cpu_name, _cpu_core, _cpu_arch)
|
|
|
|
else:
|
|
# <ADD BSD/Intel_MAC ???>
|
|
...
|
|
pass
|
|
|
|
def device_gpu_list(self):
|
|
"""
|
|
Returns a list contains GPU info tuple on Windows platform.
|
|
If on Linux, we skip test as return `None`.
|
|
- Windows: `[(GPU_NUM, GPU_NAME, GPU_VRAM), (...), ...]` or `None`
|
|
- Linux: `None`
|
|
- Others: `None`
|
|
"""
|
|
if self.is_windows:
|
|
gpu_status_list = []
|
|
|
|
try:
|
|
gpu_result = subprocess.run(
|
|
["wmic", "path", "win32_VideoController", "get", "Name"],
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
)
|
|
gpu_result_lines = [
|
|
line.strip()
|
|
for line in gpu_result.stdout.splitlines()
|
|
if line.strip()
|
|
]
|
|
except FileNotFoundError:
|
|
# wmic not found, try PowerShell fallback
|
|
try:
|
|
ps_cmd = [
|
|
"powershell",
|
|
"-Command",
|
|
"Get-CimInstance Win32_VideoController | Select-Object -ExpandProperty Name",
|
|
]
|
|
gpu_result = subprocess.run(
|
|
ps_cmd,
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
)
|
|
gpu_result_lines = [
|
|
line.strip()
|
|
for line in gpu_result.stdout.splitlines()
|
|
if line.strip()
|
|
]
|
|
except Exception:
|
|
return []
|
|
# Handle optional header from `wmic` output; PowerShell output has no header
|
|
if gpu_result_lines and gpu_result_lines[0].strip().lower() == "name":
|
|
gpu_names = gpu_result_lines[1:]
|
|
else:
|
|
gpu_names = gpu_result_lines
|
|
|
|
gpu_count = len(gpu_names) if gpu_names else 0
|
|
|
|
for i in range(0, gpu_count):
|
|
_GPU_REG_KEY = str(
|
|
r"SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}"
|
|
+ f"\\000{i}\\"
|
|
)
|
|
_GPU_CORE_NAME = RepoInfo.amdgpu_llvm_target(
|
|
get_regedit("HKLM", _GPU_REG_KEY, "DriverDesc")
|
|
)
|
|
if _GPU_CORE_NAME != "Microsoft Basic Display Adapter":
|
|
_GPU_VRAM = get_regedit(
|
|
"HKLM", _GPU_REG_KEY, "HardwareInformation.qwMemorySize"
|
|
)
|
|
|
|
if _GPU_VRAM == None:
|
|
gpu_status_list.append((i, f"{_GPU_VRAM}", None))
|
|
else:
|
|
gpu_status_list.append(
|
|
(i, f"{_GPU_CORE_NAME}", float(_GPU_VRAM / (1024**3)))
|
|
)
|
|
return gpu_status_list
|
|
else:
|
|
return None
|
|
|
|
def device_dram_status(self):
|
|
"""
|
|
Analyze Device's DRAM Status. Both on Windows and Linux returns a tuple.
|
|
- Windows: `(DRAM_PHYS_TOTAL, DRAM_PHYS_AVAIL, DRAM_VITURAL_AVAIL)`
|
|
- Linux: `(MEM_PHYS_TOTAL , MEM_PHYS_AVAIL , MEM_SWAP_AVAIL)`
|
|
- Others: `None`.
|
|
"""
|
|
if self.is_windows:
|
|
import ctypes
|
|
|
|
class memSTAT(ctypes.Structure):
|
|
_fields_ = [
|
|
("dwLength", ctypes.c_ulong),
|
|
("dwMemoryLoad", ctypes.c_ulong),
|
|
("ullTotalPhys", ctypes.c_ulonglong),
|
|
("ullAvailPhys", ctypes.c_ulonglong),
|
|
("ullTotalPageFile", ctypes.c_ulonglong),
|
|
("ullAvailPageFile", ctypes.c_ulonglong),
|
|
("ullTotalVirtual", ctypes.c_ulonglong),
|
|
("ullAvailVirtual", ctypes.c_ulonglong),
|
|
("sullAvailExtendedVirtual", ctypes.c_ulonglong),
|
|
]
|
|
|
|
mem_status = memSTAT()
|
|
mem_status.dwLength = ctypes.sizeof(memSTAT())
|
|
|
|
ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(mem_status))
|
|
|
|
MEM_PHYS_TOTAL, MEM_PHYS_AVAIL, MEM_VITURAL_AVAIL = (
|
|
float(mem_status.ullTotalPhys / (1024**3)),
|
|
float(mem_status.ullAvailPhys / (1024**3)),
|
|
float(mem_status.ullAvailPageFile / (1024**3)),
|
|
)
|
|
|
|
return (MEM_PHYS_TOTAL, MEM_PHYS_AVAIL, MEM_VITURAL_AVAIL)
|
|
elif self.is_linux:
|
|
import re
|
|
|
|
with open("/proc/meminfo", "r") as f:
|
|
_f = f.read().splitlines()
|
|
for line in _f:
|
|
mem_tol = re.search(r"^MemTotal:\s+(\d+)\s+kB$", line)
|
|
mem_avl = re.search(r"^MemAvailable:\s+(\d+)\s+kB$", line)
|
|
mem_swp = re.search(r"^SwapTotal:\s+(\d+)\s+kB$", line)
|
|
|
|
if mem_tol:
|
|
MEM_PHYS_TOTAL = float(mem_tol.group(1)) / (1024**2)
|
|
elif mem_avl:
|
|
MEM_PHYS_AVAIL = float(mem_avl.group(1)) / (1024**2)
|
|
elif mem_swp:
|
|
MEM_SWAP_AVAIL = float(mem_swp.group(1)) / (1024**2)
|
|
|
|
return (MEM_PHYS_TOTAL, MEM_PHYS_AVAIL, MEM_SWAP_AVAIL)
|
|
else:
|
|
return None
|
|
...
|
|
|
|
def device_disk_status(self):
|
|
"""
|
|
Return a tuple with Disk Total/Usage messages.
|
|
`(DISK_DEVICE, DISK_MOUNT_POINT, DISK_TOTAL_SPACE, DISK_USAGE_SPACE, DISK_AVAIL_SPACE, DISK_USAGE_RATIO)`
|
|
- `DISK_DEVICE`: Returns `str`. The device "contains this repo" name and its mounting point.
|
|
- Windows: Returns a Drive Letter. eg `F:/` or `F:`
|
|
- Linux: Returns disk's mounted device name and its mounting point. eg `/dev/sdd at: /`
|
|
- `DISK_REPO_POINT`: Returns `str`. RepoInfo current repo abs path.
|
|
- `DISK_TOTAL_SPACE`: Returns `float`. Current repo stored disk's total space.
|
|
- `DISK_USAGE_SPACE`: Returns `float`. Current repo stored disk's used space.
|
|
- `DISK_AVAIL_SPACE`: Returns `float`. Current repo stored disk's avail space.
|
|
- `DISK_USAGE_RATIO`: Returns `float`. Current repo stored disk's current usage percentage.
|
|
"""
|
|
|
|
import os, subprocess
|
|
from shutil import disk_usage
|
|
|
|
if self.is_windows:
|
|
repo_path = RepoInfo.repo()
|
|
repo_disk = PureWindowsPath(__file__).drive
|
|
|
|
DISK_TOTAL_SPACE, DISK_USAGE_SPACE, DISK_AVAIL_SPACE = disk_usage(repo_disk)
|
|
|
|
DISK_USAGE_RATIO = float(DISK_USAGE_SPACE / DISK_TOTAL_SPACE) * 100.0
|
|
DISK_TOTAL_SPACE = DISK_TOTAL_SPACE / (1024**3)
|
|
DISK_USAGE_SPACE = DISK_USAGE_SPACE / (1024**3)
|
|
DISK_AVAIL_SPACE = DISK_AVAIL_SPACE / (1024**3)
|
|
|
|
return (
|
|
repo_path,
|
|
repo_disk,
|
|
round(DISK_TOTAL_SPACE, 2),
|
|
round(DISK_USAGE_SPACE, 2),
|
|
round(DISK_AVAIL_SPACE, 2),
|
|
round(DISK_USAGE_RATIO, 2),
|
|
)
|
|
|
|
elif self.is_linux:
|
|
repo_path = RepoInfo.repo()
|
|
DISK_STATUS_QUERY = (
|
|
subprocess.run(
|
|
["df", "-h", os.getcwd()],
|
|
capture_output=True,
|
|
check=True,
|
|
text=True,
|
|
)
|
|
.stdout.strip()
|
|
.splitlines()[1]
|
|
.split()
|
|
)
|
|
|
|
DISK_MOUNT_POINT, DISK_MOUNT_DEVICE = (
|
|
DISK_STATUS_QUERY[-1],
|
|
DISK_STATUS_QUERY[0],
|
|
)
|
|
DISK_TOTAL_SPACE, DISK_USAGE_SPACE, DISK_AVAIL_SPACE = disk_usage(
|
|
DISK_MOUNT_POINT
|
|
)
|
|
DISK_USAGE_RATIO = DISK_USAGE_SPACE / DISK_TOTAL_SPACE * 100
|
|
DISK_TOTAL_SPACE = DISK_TOTAL_SPACE / (1024**3)
|
|
DISK_USAGE_SPACE = DISK_USAGE_SPACE / (1024**3)
|
|
DISK_AVAIL_SPACE = DISK_AVAIL_SPACE / (1024**3)
|
|
|
|
return (
|
|
repo_path,
|
|
f"{DISK_MOUNT_DEVICE} at: {DISK_MOUNT_POINT}",
|
|
round(DISK_TOTAL_SPACE, 2),
|
|
round(DISK_USAGE_SPACE, 2),
|
|
round(DISK_AVAIL_SPACE, 2),
|
|
round(DISK_USAGE_RATIO, 2),
|
|
)
|
|
|
|
def device_file_system(self):
|
|
"""
|
|
Return a list of strings containing the output of `df -h`.
|
|
`df -h` shows information about all file systems of the systems, including
|
|
filesystem name, size, available and used storage, and where it is mounted
|
|
"""
|
|
|
|
try:
|
|
proc = subprocess.run(
|
|
["df", "-h"], capture_output=True, text=True, check=True
|
|
)
|
|
except subprocess.CalledProcessError:
|
|
return [cstring(f"[!] Command 'df' not found.", "warn")]
|
|
|
|
return proc.stdout.splitlines()
|
|
|
|
def device_ccache_system(self):
|
|
"""
|
|
Returns a pair of string lists that contain information about the ccache on
|
|
the system. If ccache is not installed, strings stating this are returned.
|
|
|
|
CCACHE_STAT (= [0]) contains general status about ccache
|
|
CCACHE_CONFIG ( = [1]) contains the ccache config
|
|
"""
|
|
|
|
ccache = []
|
|
try:
|
|
proc = subprocess.run(
|
|
["ccache", "-s", "-v"], capture_output=True, text=True, check=True
|
|
)
|
|
|
|
ccache.append([proc.stdout.splitlines()])
|
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
ccache.append(["Ccache not detected!"])
|
|
ccache.append([""])
|
|
return ccache
|
|
|
|
try:
|
|
proc = subprocess.run(
|
|
["ccache", "--show-config"], capture_output=True, text=True, check=True
|
|
)
|
|
ccache.append([proc.stdout.splitlines()])
|
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
ccache.append([""])
|
|
|
|
return ccache
|
|
|
|
def device_python_list(self):
|
|
# Try pip first
|
|
try:
|
|
proc = subprocess.run(
|
|
["pip", "list", "--format=freeze"],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
return proc.stdout.splitlines()
|
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
# Fallback to importlib.metadata if pip not found
|
|
try:
|
|
from importlib.metadata import distributions
|
|
|
|
packages = []
|
|
for dist in distributions():
|
|
packages.append(f"{dist.metadata['Name']}=={dist.version}")
|
|
return sorted(packages)
|
|
except Exception:
|
|
return [
|
|
"Unable to detect Python packages (neither pip nor importlib.metadata available)"
|
|
]
|
|
|
|
@property
|
|
def CCACHE_STAT(self):
|
|
return self._device_ccache_stat[0]
|
|
|
|
@property
|
|
def CCACHE_CONFIG(self):
|
|
return self._device_ccache_stat[1]
|
|
|
|
@property
|
|
def python(self):
|
|
return self._py
|
|
|
|
@property
|
|
def CPU_NAME(self):
|
|
return self._device_cpu_stat[0]
|
|
|
|
@property
|
|
def CPU_CORE(self):
|
|
return self._device_cpu_stat[1]
|
|
|
|
@property
|
|
def CPU_ARCH(self):
|
|
return self._device_cpu_stat[2]
|
|
|
|
if is_windows:
|
|
|
|
@property
|
|
def cl(self):
|
|
return self._cl
|
|
|
|
@property
|
|
def VSVER(self):
|
|
"""
|
|
Define Visual Studio version.
|
|
"""
|
|
_VSVER_NUM = os.getenv("VisualStudioVersion")
|
|
return (
|
|
None if (_VSVER_NUM is None or _VSVER_NUM == "") else float(_VSVER_NUM)
|
|
)
|
|
|
|
@property
|
|
def VS20XX(self):
|
|
"""
|
|
Define Visual Studio yearly version.
|
|
"""
|
|
if self.VSVER is not None:
|
|
match self.VSVER:
|
|
case 17.0:
|
|
return "VS2022"
|
|
case 16.0:
|
|
return "VS2019"
|
|
case 15.0:
|
|
return "VS2017"
|
|
case 14.0:
|
|
return "VS2015"
|
|
case _:
|
|
return "Legacy"
|
|
else:
|
|
return False
|
|
|
|
@property
|
|
def VC_VER(self):
|
|
"""Define MSVC build is v14X version."""
|
|
_cl = self.cl.exe
|
|
_vc_ver = os.getenv("VCToolsVersion")
|
|
|
|
if _vc_ver == "14.43.34808":
|
|
return "v143"
|
|
elif _vc_ver == "14.29.30133":
|
|
return "v142"
|
|
elif _vc_ver == "14.16.27023":
|
|
return "v141"
|
|
elif (
|
|
_cl
|
|
== r"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\cl.exe"
|
|
):
|
|
return "v140"
|
|
else:
|
|
return None
|
|
|
|
@property
|
|
def VS20XX_INSTALL_DIR(self):
|
|
"""Find Environment Variable `VSINSTALLDIR` to show the current installed VS20XX location."""
|
|
_dir = os.getenv("VSINSTALLDIR")
|
|
return _dir if _dir is not None else None
|
|
|
|
@property
|
|
def VC_SDK(self):
|
|
"""Define Visual Studio current used Windows SDK version."""
|
|
_sdk = os.getenv("WindowsSDKVersion")
|
|
return _sdk.replace("\\", "") if _sdk is not None else None
|
|
|
|
@property
|
|
def VC_HOST(self):
|
|
"""Find VC++ compiler host environment."""
|
|
_host = os.getenv("VSCMD_ARG_HOST_ARCH")
|
|
return _host if _host is not None else None
|
|
|
|
@property
|
|
def VC_TARGET(self):
|
|
"""Find VC++ compiler target environment."""
|
|
_target = os.getenv("VSCMD_ARG_TGT_ARCH")
|
|
return _target if _target is not None else None
|
|
|
|
@property
|
|
def MAX_PATH_LENGTH(self):
|
|
"""Find if Windows machine enabled Long PATHs."""
|
|
if self.is_windows:
|
|
_long_path = get_regedit(
|
|
"HKLM",
|
|
r"SYSTEM\CurrentControlSet\Control\FileSystem",
|
|
key="LongPathsEnabled",
|
|
)
|
|
return True if _long_path == 1 else False
|
|
else:
|
|
return None
|
|
|
|
@property
|
|
def ROCM_HOME(self):
|
|
return os.getenv("ROCM_HOME")
|
|
|
|
@property
|
|
def HIP_PATH(self):
|
|
return os.getenv("HIP_PATH")
|
|
|
|
#
|
|
# All _STATUS should return List[str]
|
|
#
|
|
|
|
# Define OS configuration.
|
|
@property
|
|
def OS_STATUS(self):
|
|
if self.is_windows:
|
|
return [self.OS_NAME]
|
|
elif self.is_linux:
|
|
return (
|
|
[f"{self.OS_NAME}, GNU/Linux {self.OS_KERNEL} (WSL2)"]
|
|
if self.is_WSL2
|
|
else [f"{self.OS_NAME}, GNU/Linux {self.OS_KERNEL}"]
|
|
)
|
|
else:
|
|
pass
|
|
|
|
# Define CPU status.
|
|
@property
|
|
def CPU_STATUS(self):
|
|
return [f"{self.CPU_NAME} ({self.CPU_ARCH})", f"Logical cores: {self.CPU_CORE}"]
|
|
|
|
# Define GPU list status.
|
|
@property
|
|
def GPU_STATUS(self):
|
|
if self._device_gpu_list is not None:
|
|
_gpulist = []
|
|
for _gpu_info in self._device_gpu_list:
|
|
_gpu_num, _gpu_name, _gpu_vram = _gpu_info
|
|
if _gpu_vram == None:
|
|
_gpulist += [f"GPU {_gpu_num}: \t{_gpu_name}"]
|
|
else:
|
|
_gpulist += [
|
|
f"GPU {_gpu_num}: \t{_gpu_name} ({_gpu_vram:.2f}GB VRAM)"
|
|
]
|
|
return _gpulist
|
|
|
|
elif self.is_linux:
|
|
return [cstring(f"[!] Skip GPU detection on Linux.", "warn")]
|
|
|
|
# Define Memory Device status.
|
|
@property
|
|
def MEM_STATUS(self):
|
|
if self.is_windows:
|
|
return [
|
|
f"Total Physical Memory: {self._device_dram_stat[0]:.2f} GB",
|
|
f"Avail Physical Memory: {self._device_dram_stat[1]:.2f} GB",
|
|
f"Avail Virtual Memory: {self._device_dram_stat[2]:.2f} GB",
|
|
]
|
|
elif self.is_linux:
|
|
return [
|
|
f"Total Physical Memory: {self._device_dram_stat[0]:.2f} GB",
|
|
f"Avail Physical Memory: {self._device_dram_stat[1]:.2f} GB",
|
|
f"Avail Swap Memory: {self._device_dram_stat[2]:.2f} GB",
|
|
]
|
|
else:
|
|
pass
|
|
|
|
# Define Disk Device status.
|
|
@property
|
|
def DISK_STATUS(self):
|
|
return [
|
|
f"Disk Total Space: {self._device_disk_stat[2]} GB",
|
|
f"Disk Avail Space: {self._device_disk_stat[4]} GB",
|
|
f"Disk Used Space: {self._device_disk_stat[3]} GB",
|
|
f"Disk Usage: {self._device_disk_stat[5]} %",
|
|
f"Current Repo path: {self._device_disk_stat[0]}, Disk Device: {self._device_disk_stat[1]}",
|
|
]
|
|
|
|
@property
|
|
def FILE_SYSTEM_STATUS(self):
|
|
return self._device_file_system_list
|
|
|
|
@property
|
|
def ENV_STATUS(self):
|
|
if self.is_windows:
|
|
return [
|
|
f"Python ENV: {self.python.exe} ({self.python.ENV_TYPE})",
|
|
f"Visual Studio: {self.VS20XX}",
|
|
f"Cygwin: {self.is_cygwin}",
|
|
f"MSYS2: {self.is_msys2}",
|
|
]
|
|
elif self.is_linux:
|
|
return [
|
|
f"Python3 VENV: {self.python.exe} ({self.python.ENV_TYPE}) | WSL2: {self.is_WSL2}"
|
|
]
|
|
else:
|
|
return [f"Python3 VENV: {self.python.exe} ({self.python.ENV_TYPE}) "]
|
|
|
|
@property
|
|
def SDK_STATUS(self):
|
|
if self.is_windows:
|
|
|
|
_vs20xx_stat = self.VS20XX if self.VS20XX else "Not Detected"
|
|
_vs20xx_sdk = self.VC_SDK if self.VC_SDK else "Not Detected"
|
|
|
|
_hipcc_stat = self.HIP_PATH if self.HIP_PATH else "Not Detected"
|
|
_rocm_stat = self.ROCM_HOME if self.ROCM_HOME else "Not Detected"
|
|
|
|
return [
|
|
f"Visual Studio: {_vs20xx_stat} | Host/Target: {self.VC_HOST} --> {self.VC_TARGET}",
|
|
f"VC++ Compiler: {self.cl.version}",
|
|
f"VC++ UCRT: {_vs20xx_sdk}",
|
|
f"AMD HIP SDK: {_hipcc_stat}",
|
|
f"AMD ROCm: {_rocm_stat}",
|
|
]
|
|
|
|
@property
|
|
def CCACHE_STATUS(self):
|
|
ccache_stats_cfg_list = [
|
|
*self.CCACHE_STAT[0],
|
|
f"-------------",
|
|
f"Config:",
|
|
f"-------------",
|
|
*self.CCACHE_CONFIG[0],
|
|
]
|
|
return ccache_stats_cfg_list
|
|
|
|
@property
|
|
def PYTHON_LIST(self):
|
|
return self._py_list
|
|
|
|
def format_status(self, title: str, content: List[str], longest_status=14) -> str:
|
|
indent_title = lambda x: f"{' ':8}" + x.ljust(longest_status + 1)
|
|
|
|
indent_str = ""
|
|
|
|
for idx, line in enumerate(content):
|
|
if idx == 0:
|
|
indent_str += indent_title(title) + f"{line}\n"
|
|
else:
|
|
indent_str += indent_title("") + f"{line}\n"
|
|
|
|
return indent_str
|
|
|
|
def section_bar(self, title: str):
|
|
longest_word = "TheRock build pre-diagnosis script completed in xxxx seconds"
|
|
tabs = 3 * 4 # original amount of tabs in the center section
|
|
|
|
# colored font needs extra treatement as len() returns length including ansi chars
|
|
uncolored_string = cstring_strip_color(title)
|
|
tabs += len(title) - len(uncolored_string)
|
|
|
|
return (
|
|
f"{' ':8}==================="
|
|
+ f"{title}".center(len(longest_word) + tabs)
|
|
+ "==================="
|
|
)
|
|
|
|
@property
|
|
def summary(self):
|
|
states = [
|
|
("OS:", self.OS_STATUS),
|
|
("CPU:", self.CPU_STATUS),
|
|
("GPU:", self.GPU_STATUS),
|
|
("RAM:", self.MEM_STATUS),
|
|
("STORAGE:", self.DISK_STATUS),
|
|
("FILE SYSTEM:", self.FILE_SYSTEM_STATUS),
|
|
]
|
|
|
|
if self.is_windows:
|
|
states_win = [
|
|
("ENV:", self.ENV_STATUS),
|
|
("SDK:", self.SDK_STATUS),
|
|
("MAX_PATH_ENABLED:", ["True"] if self.MAX_PATH_LENGTH else ["False"]),
|
|
]
|
|
|
|
states += states_win
|
|
|
|
# have ccache at the end as it has many lines of output
|
|
states += [("CCACHE:", self.CCACHE_STATUS)]
|
|
|
|
print(self.section_bar("Build Environment Summary"))
|
|
print("")
|
|
|
|
longest_state = 0
|
|
|
|
for state, content in states:
|
|
if len(state) > longest_state:
|
|
longest_state = len(state)
|
|
|
|
for state, content in states:
|
|
line_end = "\n"
|
|
if state == "OS:" or state == "GPU:":
|
|
line_end = ""
|
|
|
|
print(
|
|
self.format_status(state, content, longest_status=longest_state),
|
|
end=line_end,
|
|
)
|
|
|
|
@property
|
|
def python_list(self):
|
|
print(self.section_bar("Python List"))
|
|
print()
|
|
print(self.format_status("", self.PYTHON_LIST, longest_status=-1))
|
|
print()
|
|
print(self.section_bar("End Python List"))
|