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
153 lines
5.3 KiB
Python
153 lines
5.3 KiB
Python
# Copyright Advanced Micro Devices, Inc.
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
"""Parses AMDGPU target and family definitions from cmake/therock_amdgpu_targets.cmake.
|
|
|
|
Provides a Python-accessible mapping of family names to constituent gfx targets,
|
|
derived from the authoritative CMake source of truth.
|
|
"""
|
|
|
|
import re
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
|
|
_DEFAULT_CMAKE_PATH = (
|
|
Path(__file__).resolve().parent.parent.parent
|
|
/ "cmake"
|
|
/ "therock_amdgpu_targets.cmake"
|
|
)
|
|
|
|
_family_to_targets_cache: dict[Path, dict[str, list[str]]] = {}
|
|
|
|
|
|
@dataclass
|
|
class AmdgpuTargetInfo:
|
|
gfx_target: str
|
|
product_name: str
|
|
families: list[str] = field(default_factory=list)
|
|
|
|
|
|
def parse_amdgpu_targets_cmake(cmake_path: Path) -> list[AmdgpuTargetInfo]:
|
|
"""Parse therock_add_amdgpu_target() calls from a cmake file.
|
|
|
|
Returns one AmdgpuTargetInfo per call. The families list contains only the
|
|
explicit FAMILY arguments; the implicit self-family (each target is its own
|
|
family) is NOT included here - see build_family_to_targets().
|
|
"""
|
|
if not cmake_path.exists():
|
|
raise FileNotFoundError(
|
|
f"AMDGPU targets cmake file not found: {cmake_path}\n"
|
|
"Expected at cmake/therock_amdgpu_targets.cmake relative to repo root."
|
|
)
|
|
|
|
content = cmake_path.read_text()
|
|
results: list[AmdgpuTargetInfo] = []
|
|
|
|
# Each therock_add_amdgpu_target() call has the form:
|
|
# therock_add_amdgpu_target(gfx900 "Vega 10 / MI25" FAMILY dgpu-all gfx900-dgpu)
|
|
# Parsing extracts:
|
|
# tokens[0] -> gfx target (e.g. "gfx900")
|
|
# tokens[1] -> product name (e.g. "Vega 10 / MI25")
|
|
# tokens after FAMILY keyword -> families list (e.g. ["dgpu-all", "gfx900-dgpu"])
|
|
for call_body in re.findall(
|
|
r"therock_add_amdgpu_target\((.*?)\)", content, re.DOTALL
|
|
):
|
|
tokens = _tokenize_cmake(call_body)
|
|
if len(tokens) < 2:
|
|
continue
|
|
|
|
gfx_target = tokens[0]
|
|
product_name = tokens[1]
|
|
|
|
families: list[str] = []
|
|
if "FAMILY" in tokens:
|
|
family_start = tokens.index("FAMILY") + 1
|
|
# Collect until the next cmake keyword or end of tokens.
|
|
cmake_keywords = {"EXCLUDE_TARGET_PROJECTS"}
|
|
for tok in tokens[family_start:]:
|
|
if tok in cmake_keywords:
|
|
break
|
|
families.append(tok)
|
|
|
|
results.append(AmdgpuTargetInfo(gfx_target, product_name, families))
|
|
|
|
return results
|
|
|
|
|
|
def build_family_to_targets(infos: list[AmdgpuTargetInfo]) -> dict[str, list[str]]:
|
|
"""Build a mapping of family name -> list of gfx targets.
|
|
|
|
Includes the implicit self-family: each target is always its own family,
|
|
matching the CMake behaviour in therock_add_amdgpu_target().
|
|
"""
|
|
result: dict[str, list[str]] = {}
|
|
for info in infos:
|
|
# The target is its own family plus all explicit FAMILY entries.
|
|
for family in [info.gfx_target] + info.families:
|
|
result.setdefault(family, [])
|
|
if info.gfx_target not in result[family]:
|
|
result[family].append(info.gfx_target)
|
|
return result
|
|
|
|
|
|
def amdgpu_family_map(
|
|
cmake_path: Path | None = None,
|
|
) -> dict[str, list[str]]:
|
|
"""Return the family → gfx targets map, parsing the CMake file once.
|
|
|
|
Uses `cmake/therock_amdgpu_targets.cmake` at the repo root by default.
|
|
Results are cached per resolved path so repeated calls are free.
|
|
"""
|
|
resolved = (cmake_path or _DEFAULT_CMAKE_PATH).resolve()
|
|
cached = _family_to_targets_cache.get(resolved)
|
|
if cached is None:
|
|
cached = build_family_to_targets(parse_amdgpu_targets_cmake(resolved))
|
|
_family_to_targets_cache[resolved] = cached
|
|
return cached
|
|
|
|
|
|
def expand_families(
|
|
families: list[str],
|
|
family_map: dict[str, list[str]],
|
|
*,
|
|
strict: bool = True,
|
|
) -> list[str]:
|
|
"""Expand a list of family names to the union of their gfx targets.
|
|
|
|
Preserves input order; de-duplicates. When `strict` (the default),
|
|
raises ValueError if any family is not present in `family_map`. With
|
|
`strict=False`, unknown families are silently skipped.
|
|
"""
|
|
if strict:
|
|
unknown = [f for f in families if f not in family_map]
|
|
if unknown:
|
|
known = ", ".join(sorted(family_map.keys()))
|
|
raise ValueError(
|
|
f"Unknown AMD GPU families: {unknown}. Known families: {known}"
|
|
)
|
|
|
|
targets: list[str] = []
|
|
seen: set[str] = set()
|
|
for family in families:
|
|
for target in family_map.get(family, []):
|
|
if target not in seen:
|
|
seen.add(target)
|
|
targets.append(target)
|
|
return targets
|
|
|
|
|
|
def _tokenize_cmake(text: str) -> list[str]:
|
|
"""Tokenize a cmake argument list, stripping comments and handling quotes."""
|
|
# Strip inline comments (# to end of line).
|
|
lines = []
|
|
for line in text.splitlines():
|
|
comment_pos = line.find("#")
|
|
if comment_pos >= 0:
|
|
line = line[:comment_pos]
|
|
lines.append(line)
|
|
|
|
# Tokenize: quoted strings or sequences of non-whitespace non-quote chars.
|
|
tokens = re.findall(r'"[^"]*"|[^\s"]+', " ".join(lines))
|
|
# Strip surrounding quotes from quoted tokens.
|
|
return [t[1:-1] if t.startswith('"') else t for t in tokens]
|