Skip to content
67 changes: 66 additions & 1 deletion build_tools/build_python_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,64 @@ def run(args: argparse.Namespace):
params.filter_artifacts(
core_artifact_filter,
# TODO: The base package is shoving CMake redirects into lib.
excludes=["**/cmake/**"],
excludes=[
"**/cmake/**",
# profiler binaries
"bin/rocprof-*",
# rocprofiler-systems payload
"include/rocprofiler-systems/**",
"lib/librocprof-sys*",
"lib/python/site-packages/rocprofsys/**",
"lib/rocprofiler-systems/**",
"libexec/rocprofiler-systems/**",
"share/**/rocprofiler-systems/**",
],
),
)

profiler = PopulatedDistPackage(params, logical_name="profiler")
profiler.rpath_dep(core, "lib")
profiler.rpath_dep(core, "lib/llvm/lib")
profiler.populate_runtime_files(
params.filter_artifacts(
profiler_artifact_filter,
includes=[
# rocprofiler-systems
"bin/rocprof-sys-*",
"include/rocprofiler-systems/**",
"lib/librocprof-sys*",
"lib/python/site-packages/rocprofsys/**",
"lib/rocprofiler-systems/**",
"libexec/rocprofiler-systems/**",
"share/**/rocprofiler-systems/**",
# rocprofiler-compute
"bin/rocprof-*",
"libexec/rocprofiler-compute/**",
# rocprofiler-systems sysdeps
"lib/rocm_sysdeps/lib/librocm_sysdeps_dw.so*",
"lib/rocm_sysdeps/lib/librocm_sysdeps_elf.so*",
"lib/rocm_sysdeps/lib/librocm_sysdeps_z.so*",
"lib/rocm_sysdeps/lib/librocm_sysdeps_zstd.so*",
"lib/rocm_sysdeps/lib/librocm_sysdeps_liblzma.so*",
"lib/rocm_sysdeps/lib/librocm_sysdeps_bz2.so*",
Comment thread
erman-gurses marked this conversation as resolved.
Outdated
],
),
)

# The rocprofiler-compute artifact installs the launcher as a symlink:
# bin/rocprof-compute -> ../libexec/rocprofiler-compute/rocprof-compute
# However, populate_runtime_files() does not preserve symlinks and only
# materializes the real file under libexec/. Recreate the expected bin/
# entry here so CLI entrypoints (_exec("bin/rocprof-compute")) continue to work.
compute_target = (
profiler.platform_dir / "libexec" / "rocprofiler-compute" / "rocprof-compute"
)
compute_link = profiler.platform_dir / "bin" / "rocprof-compute"

if compute_target.exists() and not compute_link.exists():
compute_link.parent.mkdir(parents=True, exist_ok=True)
compute_link.symlink_to("../libexec/rocprofiler-compute/rocprof-compute")

if kpack_split:
_run_kpack_split(args, params, core)
else:
Expand Down Expand Up @@ -304,6 +358,17 @@ def libraries_artifact_filter(target_family: str, an: ArtifactName) -> bool:
return libraries


def profiler_artifact_filter(an: ArtifactName) -> bool:
return (
an.name
in [
"rocprofiler-compute",
"rocprofiler-systems",
]
and an.component in ["lib", "run"]
) or (an.name == "sysdeps" and an.component == "lib")


def device_artifact_filter(target: str, an: ArtifactName) -> bool:
"""Selects per-ISA library artifacts for a specific GFX target.

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
recursive-include src *.py
recursive-include platform/* *
22 changes: 19 additions & 3 deletions build_tools/packaging/python/templates/rocm-profiler/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import os
from pathlib import Path
import platform
import sysconfig

from setuptools import find_packages, setup

Expand All @@ -31,9 +32,14 @@ def _load_local_dist_info():
return module


dist_info = _load_local_dist_info()
my_package = dist_info.ALL_PACKAGES["profiler"]
packages = find_packages(where="./src")
platform_package_name = my_package.get_py_package_name()
packages.append(platform_package_name)

version = os.environ.get("ROCM_SDK_VERSION")
if version is None:
dist_info = _load_local_dist_info()
version = dist_info.__version__

if version == "DEFAULT":
Expand All @@ -44,10 +50,20 @@ def _load_local_dist_info():
name="rocm-profiler",
version=version,
description="ROCm profiler applications (rocprofiler-systems and rocprofiler-compute)",
packages=find_packages(where="src"),
package_dir={"": "src"},
packages=packages,
package_dir={
"": "src",
platform_package_name: f"platform/{platform_package_name}",
},
include_package_data=True,
zip_safe=False,
options={
"bdist_wheel": {
"plat_name": os.getenv(
"ROCM_SDK_WHEEL_PLATFORM_TAG", sysconfig.get_platform()
),
},
},
entry_points={
"console_scripts": (
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,62 +6,53 @@

from __future__ import annotations

import importlib
import os
import sys
from pathlib import Path
import platform

from ._dist_info import ALL_PACKAGES

def _find_platform_root() -> Path:
"""
Locate the packaged ROCm platform root inside this wheel.

Phase 3 will populate runtime files into a subdirectory that contains `bin/`.
This function finds it dynamically to avoid hard-coding the exact platform tag.
"""
pkg_dir = Path(__file__).resolve().parent
children = list(pkg_dir.iterdir())
direct_candidates: list[Path] = [
child for child in children if child.is_dir() and (child / "bin").is_dir()
]
if len(direct_candidates) == 1:
return direct_candidates[0]
if len(direct_candidates) > 1:
raise RuntimeError(
"Ambiguous packaged ROCm profiler binaries: found multiple direct "
f"candidates with bin/: {sorted(str(p) for p in direct_candidates)}"
)

nested_candidates: list[Path] = []
for child in children:
if not child.is_dir():
continue
for grand in child.iterdir():
if grand.is_dir() and (grand / "bin").is_dir():
nested_candidates.append(grand)

if len(nested_candidates) == 1:
return nested_candidates[0]
if len(nested_candidates) > 1:
raise RuntimeError(
"Ambiguous packaged ROCm profiler binaries: found multiple nested "
f"candidates with bin/: {sorted(str(p) for p in nested_candidates)}"
)

raise FileNotFoundError(
"Could not locate packaged ROCm profiler binaries. "
"Expected a directory containing `bin/` under the installed "
"rocm_profiler package."
)

PROFILER_PACKAGE = ALL_PACKAGES["profiler"]
PROFILER_PY_PACKAGE_NAME = PROFILER_PACKAGE.get_py_package_name()

def _exec(relpath: str) -> None:

def _extend_ld_library_path() -> None:
if platform.system() == "Windows":
return

try:
sdk_module = importlib.import_module("_rocm_sdk_core")
except ModuleNotFoundError:
return

sdk_path = Path(sdk_module.__file__).parent
sysdeps_path = sdk_path / "lib" / "rocm_sysdeps" / "lib"
if not sysdeps_path.exists():
return

existing = os.environ.get("LD_LIBRARY_PATH", "")
existing_parts = [p for p in existing.split(":") if p]
sysdeps_str = str(sysdeps_path)

if sysdeps_str not in existing_parts:
os.environ["LD_LIBRARY_PATH"] = ":".join([sysdeps_str, *existing_parts])


def _get_profiler_module_path() -> Path:
profiler_module = importlib.import_module(PROFILER_PY_PACKAGE_NAME)
return Path(profiler_module.__file__).parent


def _exec(relpath: str) -> None:
if platform.system() == "Windows":
raise RuntimeError("rocm-profiler is not supported on Windows.")

root = _find_platform_root()
full_path = root / relpath
_extend_ld_library_path()

full_path = _get_profiler_module_path() / relpath
if not full_path.exists():
raise FileNotFoundError(f"Profiler tool not found: {full_path}")
os.execv(str(full_path), [str(full_path)] + sys.argv[1:])
Expand Down
Loading