Files
derek.holloway 7502bf64a4
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
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

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]