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
198 lines
6.3 KiB
Python
Executable File
198 lines
6.3 KiB
Python
Executable File
# Copyright Advanced Micro Devices, Inc.
|
||
# SPDX-License-Identifier: MIT
|
||
|
||
from pathlib import Path
|
||
import os
|
||
import platform
|
||
import shutil
|
||
import subprocess
|
||
import sys
|
||
|
||
repo_root = Path(__file__).resolve().parents[4]
|
||
build_tools_path = repo_root / "build_tools"
|
||
sys.path.insert(0, str(build_tools_path))
|
||
from patch_linux_so import relativize_pc_file
|
||
|
||
|
||
def rename_pc_files(pc_file: Path) -> None:
|
||
"""Rename a .pc file by removing the 'rocm_sysdeps_' prefix if present.
|
||
|
||
This function is used when ROCm‑patched pkg‑config files need to be
|
||
restored to their original upstream names. If the filename begins with the
|
||
prefix 'rocm_sysdeps_', the prefix is stripped and the file is renamed in place.
|
||
|
||
Parameters
|
||
----------
|
||
pc_file : Path Path object pointing to the .pc file to be examined and possibly renamed.
|
||
|
||
Returns
|
||
-------
|
||
None The function performs an in‑place rename and does not return a value.
|
||
"""
|
||
prefix = "rocm_sysdeps_"
|
||
if pc_file.name.startswith(prefix):
|
||
new_name = pc_file.name[len(prefix) :]
|
||
new_path = pc_file.with_name(new_name)
|
||
pc_file.rename(new_path)
|
||
|
||
|
||
def symlink_or_copy(existing_path, new_link):
|
||
"""Create symlink if the destination filesystem supports it. Create a copy otherwise.
|
||
Exists to support Windows, where only modern systems might support symlinks.
|
||
"""
|
||
existing_path = Path(existing_path)
|
||
new_link = Path(new_link)
|
||
new_link.parent.mkdir(parents=True, exist_ok=True)
|
||
|
||
if new_link.exists() or new_link.is_symlink():
|
||
if new_link.is_dir() and not new_link.is_symlink():
|
||
shutil.rmtree(new_link)
|
||
else:
|
||
new_link.unlink()
|
||
|
||
try:
|
||
rel_target = os.path.relpath(existing_path, start=new_link.parent)
|
||
new_link.symlink_to(rel_target, target_is_directory=existing_path.is_dir())
|
||
return
|
||
except OSError:
|
||
pass
|
||
|
||
if existing_path.is_dir():
|
||
shutil.copytree(existing_path, new_link)
|
||
else:
|
||
shutil.copy2(existing_path, new_link)
|
||
|
||
|
||
def update_library_links(libfile: Path) -> None:
|
||
"""
|
||
Normalize a shared library so that its real file is named exactly as its ELF SONAME,
|
||
and ensure a canonical linker-visible symlink exists.
|
||
|
||
This function is used when a library has been installed under a prefixed or
|
||
non-standard filename (e.g., librocm_sysdeps_ncursesw.so).
|
||
It performs the following operations:
|
||
- Extracts the library's SONAME using `patchelf --print-soname`.
|
||
- Resolves the underlying real file (following symlinks).
|
||
- Renames the real file to match its SONAME if it does not already.
|
||
- Creates or updates a symlink named `linker_name` pointing to the SONAME file.
|
||
- Removes or renames the original file or symlink as appropriate.
|
||
|
||
Parameters ----------
|
||
libfile : Path
|
||
Path to the library file or symlink to normalize.
|
||
Example: /prefix/lib/librocm_sysdeps_ncursesw.so
|
||
|
||
"""
|
||
# Ensure file exists
|
||
if not libfile.exists():
|
||
raise FileNotFoundError(f"File '{libfile}' not found")
|
||
|
||
dir_path = libfile.parent
|
||
# Get SONAME
|
||
try:
|
||
lib_soname = subprocess.check_output(
|
||
[patchelf_exe, "--print-soname", str(libfile)],
|
||
stderr=subprocess.DEVNULL,
|
||
text=True,
|
||
).strip()
|
||
except subprocess.CalledProcessError:
|
||
print(f"Error: No SONAME found in '{libfile}'", flush=True)
|
||
sys.exit(1)
|
||
|
||
# Resolve real file path
|
||
try:
|
||
realname = libfile.resolve(strict=True)
|
||
except FileNotFoundError:
|
||
print(f"Error: resolve() failed for '{libfile}'", flush=True)
|
||
sys.exit(1)
|
||
|
||
linker_name = libfile.name.replace("librocm_sysdeps_", "lib")
|
||
target_real = dir_path / lib_soname
|
||
symlink_path = dir_path / linker_name
|
||
|
||
if realname != target_real:
|
||
# Move real file to $dir/$soname
|
||
shutil.move(str(realname), str(target_real))
|
||
|
||
# Create/update symlink
|
||
if symlink_path.exists() or symlink_path.is_symlink():
|
||
symlink_path.unlink()
|
||
symlink_path.symlink_to(lib_soname)
|
||
|
||
# Remove the original symlink or file
|
||
if libfile.is_symlink() or libfile.exists():
|
||
libfile.unlink()
|
||
else:
|
||
# Rename symlink in the same directory
|
||
if symlink_path.exists():
|
||
symlink_path.unlink()
|
||
libfile.rename(symlink_path)
|
||
|
||
|
||
def link_header_files_under_dir(source_dir, dest_dir):
|
||
"""Support applications referencing ncurses header through
|
||
both `<ncurses.h>` and `<ncursesw/ncurses.h>` by making
|
||
|
||
"""
|
||
source_dir = Path(source_dir)
|
||
dest_dir = Path(dest_dir)
|
||
if not source_dir.exists():
|
||
return
|
||
dest_dir.mkdir(parents=True, exist_ok=True)
|
||
|
||
for header_path in source_dir.iterdir():
|
||
if header_path.is_file() and header_path.suffix == ".h":
|
||
symlink_or_copy(header_path, dest_dir / header_path.name)
|
||
|
||
|
||
# Fetch an environment variable or exit if it is not found.
|
||
def get_env_or_exit(var_name):
|
||
value = os.environ.get(var_name)
|
||
if value is None:
|
||
print(f"Error: {var_name} not defined")
|
||
sys.exit(1)
|
||
return value
|
||
|
||
|
||
# Validate the install prefix argument.
|
||
if len(sys.argv) < 2:
|
||
print("Error: Expected install prefix argument")
|
||
sys.exit(1)
|
||
|
||
# 1st argument is the installation prefix.
|
||
install_prefix = Path(sys.argv[1])
|
||
|
||
# Required environment variables.
|
||
patchelf_exe = get_env_or_exit("PATCHELF")
|
||
|
||
# Make headers available under <ncursesw/> e.g.
|
||
# `<ncurses.h>` and `<ncursesw/ncurses.h>`
|
||
# This follows Ubuntu and Fedora packaging
|
||
include_dir = Path(install_prefix) / "include"
|
||
ncursesw_dir = include_dir / "ncursesw"
|
||
link_header_files_under_dir(include_dir, ncursesw_dir)
|
||
|
||
if platform.system() == "Linux":
|
||
# Specify the directory
|
||
lib_dir = Path(install_prefix) / "lib"
|
||
|
||
# Remove static libs (*.a) and descriptors (*.la).
|
||
for file_path in lib_dir.iterdir():
|
||
if file_path.suffix in (".a", ".la"):
|
||
file_path.unlink(missing_ok=True)
|
||
|
||
# Update library linking
|
||
for so_file in lib_dir.glob("librocm_sysdeps_*.so"):
|
||
update_library_links(so_file)
|
||
|
||
# Fix .pc files to use relocatable paths.
|
||
pkgconfig_dir = lib_dir / "pkgconfig"
|
||
if pkgconfig_dir.exists():
|
||
for pc_file in pkgconfig_dir.glob("*.pc"):
|
||
relativize_pc_file(pc_file)
|
||
rename_pc_files(pc_file)
|
||
|
||
elif platform.system() == "Windows":
|
||
# Do nothing for now.
|
||
sys.exit(0)
|