diff --git a/t/torchaudio-rocm/build_info.json b/t/torchaudio-rocm/build_info.json new file mode 100644 index 0000000000..6e92a72ad9 --- /dev/null +++ b/t/torchaudio-rocm/build_info.json @@ -0,0 +1,31 @@ +{ + "maintainer": "Ameil Kumar ", + "package_name": "torchaudio-rocm", + "github_url": "https://github.com/pytorch/audio.git", + "version": "v2.11.0", + "wheel_build": true, + "default_branch": "main", + "package_dir": "t/torchaudio-rocm", + "build_script": "torchaudio_2.11.0_rocm_ubi_10.sh", + "docker_build": false, + "validate_build_script": true, + "use_non_root_user": false, + "wheel_name": "torchaudio-rocm", + "skip_python_versions": ["3.12", "3.14"], + "auditwheel_exclude": [ + "libtorchaudio.so", + "libc10.so", + "libc10_hip.so", + "libtorch.so", + "libtorch_cpu.so", + "libtorch_hip.so", + "libtorch_python.so" + ], + "v2.11.0": { + "build_script": "torchaudio_2.11.0_rocm_ubi_10.sh" + }, + "*": { + "build_script": "torchaudio_2.11.0_rocm_ubi_10.sh" + } +} + diff --git a/t/torchaudio-rocm/torchaudio_2.11.0_rocm_ubi_10.sh b/t/torchaudio-rocm/torchaudio_2.11.0_rocm_ubi_10.sh new file mode 100644 index 0000000000..5f38e25dec --- /dev/null +++ b/t/torchaudio-rocm/torchaudio_2.11.0_rocm_ubi_10.sh @@ -0,0 +1,341 @@ +#!/bin/bash -e +# ----------------------------------------------------------------------------- +# +# Package : torchaudio +# Version : v2.11.0 +# Source repo : https://github.com/pytorch/audio.git +# Tested on : UBI:10 (ppc64le) +# Language : Python +# Ci-Check : True +# Script License: Apache License, Version 2.0 +# Maintainer : Ameil Kumar +# +# Disclaimer : This script has been tested in root mode on given +# ========== platform using the mentioned version of the package. +# It may not work as expected with newer versions of the +# package and/or distribution. In such case, please +# contact "Maintainer" of this script. +# +# ---------------------------------------------------------------------------- +# +# ROCm installation mode (ROCM_INSTALL_MODE env var): +# rpms (default) - Install ROCm RPMs from a provided repo URL +# path - Assume ROCm is already present; use ROCM_PATH as-is +# +# PyTorch is built from source before torchaudio so that the ROCm-enabled +# torch shared libraries are available at torchaudio's CMake configure time. +# +# Usage: +# ./torchaudio_2.11.0_rocm_ubi_10.sh [--rocm-install-mode rpms|path] +# [--version v2.11.0] +# +# Environment variables honoured (can be set before running): +# PACKAGE_VERSION - torchaudio tag to build (default: v2.11.0) +# PYTORCH_VERSION - PyTorch tag to build and install (default: v2.13.0) +# ROCM_PATH - Path to ROCm installation (default: /opt/rocm) +# ROCM_REPO_URL - RPM repo baseurl for ROCm +# PYTORCH_ROCM_ARCH - Semicolon-separated GPU targets +# (default: "gfx90a;gfx950") +# PYTORCH_PATCH_BASE - Base URL for PyTorch patches +# +# --------------------------------------------------------------------------- + +set -e + +PACKAGE_NAME=audio +PACKAGE_URL=https://github.com/pytorch/audio.git +PACKAGE_VERSION=${PACKAGE_VERSION:-v2.11.0} +SCRIPT_DIR=$(pwd) +OS_NAME=$(grep ^PRETTY_NAME /etc/os-release | cut -d= -f2) + +PYTORCH_VERSION=${PYTORCH_VERSION:-v2.13.0} +PYTORCH_URL=https://github.com/pytorch/pytorch.git + +ROCM_INSTALL_MODE=${ROCM_INSTALL_MODE:-"rpms"} # rpms | path +ROCM_REPO_URL=${ROCM_REPO_URL:-"https://public.dhe.ibm.com/software/server/POWER/Linux/AMD/ROCm/RHEL/10/ppc64le"} +ROCM_PATH=${ROCM_PATH:-/opt/rocm} + +# GPU architecture targets — override via env var +PYTORCH_ROCM_ARCH=${PYTORCH_ROCM_ARCH:-"gfx90a;gfx950"} + +# --------------------------------------------------------------------------- +# Argument parsing +# --------------------------------------------------------------------------- +while [[ $# -gt 0 ]]; do + case "$1" in + --rocm-install-mode) + ROCM_INSTALL_MODE="$2" + shift 2 + ;; + --version) + PACKAGE_VERSION="$2" + shift 2 + ;; + *) + echo "Unknown argument: $1" + echo "Usage: $0 [--rocm-install-mode rpms|path] [--version v2.11.0]" + exit 1 + ;; + esac +done + +if [[ "$ROCM_INSTALL_MODE" != "rpms" && "$ROCM_INSTALL_MODE" != "path" ]]; then + echo "ERROR: --rocm-install-mode must be one of: rpms, path" + exit 1 +fi + +echo "=== TorchAudio ROCm Build (torch from source) ===" +echo " PACKAGE_VERSION : $PACKAGE_VERSION" +echo " PYTORCH_VERSION : $PYTORCH_VERSION" +echo " ROCM_INSTALL_MODE : $ROCM_INSTALL_MODE" +echo " ROCM_PATH : $ROCM_PATH" +echo " PYTORCH_ROCM_ARCH : $PYTORCH_ROCM_ARCH" +echo "==================================================" + +# --------------------------------------------------------------------------- +# Install system build dependencies +# --------------------------------------------------------------------------- + +# Python packages must appear first (wrapper script requirement). +yum install -y python3.12 python3.12-devel python3.12-pip \ + gcc-toolset-15 gcc-toolset-15-gcc gcc-toolset-15-gcc-c++ \ + git make wget patch cmake ninja-build \ + openblas openblas-devel + +# Configure GCC Toolset 15 +if [[ -f /opt/rh/gcc-toolset-15/enable ]]; then + source /opt/rh/gcc-toolset-15/enable +elif [[ -d /opt/rh/gcc-toolset-15/root/usr/bin ]]; then + export PATH="/opt/rh/gcc-toolset-15/root/usr/bin:$PATH" + export LD_LIBRARY_PATH="/opt/rh/gcc-toolset-15/root/usr/lib64:${LD_LIBRARY_PATH:-}" +else + echo "ERROR: gcc-toolset-15 not found" + exit 1 +fi + +echo "Using gcc: $(gcc --version | head -1)" + +# Use Python 3.12 for the build so the produced wheels are cp312 +PYTHON=python3.12 + +# --------------------------------------------------------------------------- +# MODE: rpms — install ROCm from a provided RPM repository +# --------------------------------------------------------------------------- +if [[ "$ROCM_INSTALL_MODE" == "rpms" ]]; then + if [[ ! "$ROCM_REPO_URL" =~ ^(https?|file):// ]]; then + echo "ERROR: ROCM_REPO_URL does not look like a valid URL (got: ${ROCM_REPO_URL})" + exit 1 + fi + echo "Installing ROCm from ${ROCM_REPO_URL}" + + cat > /etc/yum.repos.d/rocm.repo </dev/null; then + echo "ERROR: hipcc not found under ROCM_PATH=${ROCM_PATH}. Check your ROCm installation." + exit 1 +fi +echo "ROCm hipcc: $(hipcc --version | head -1)" + +# --------------------------------------------------------------------------- +# Build PyTorch from source (ROCm) +# --------------------------------------------------------------------------- + +# Use OpenBLAS instead of MKL (MKL does not support Power). +# Disable CUDA/Intel tooling so cmake does not search for them. +export PYTORCH_ROCM_ARCH +export BLAS=OpenBLAS +export USE_CUDA=0 +export USE_XPU=0 +export USE_ROCM=1 + +export CMAKE_PREFIX_PATH="${ROCM_PATH}:${CMAKE_PREFIX_PATH:-}" + +echo "Cloning PyTorch ${PYTORCH_VERSION}" +if [ -d "${SCRIPT_DIR}/pytorch" ]; then + echo "pytorch directory already exists, reusing." + cd "${SCRIPT_DIR}/pytorch" + git checkout "$PYTORCH_VERSION" +else + if ! git clone --recursive --branch "$PYTORCH_VERSION" "$PYTORCH_URL" "${SCRIPT_DIR}/pytorch"; then + echo "------------------pytorch:clone_fails---------------------------------------" + echo "$PYTORCH_URL pytorch" + echo "pytorch | $PYTORCH_URL | $PYTORCH_VERSION | GitHub | Fail | Clone_Fails" + exit 1 + fi + cd "${SCRIPT_DIR}/pytorch" +fi + +git submodule sync +git submodule update --init --recursive + +# Install PyTorch build dependencies +$PYTHON -m pip install --upgrade pip +$PYTHON -m pip install --group dev || $PYTHON -m pip install -r requirements.txt + +# Run ROCm source transformation +echo "Running ROCm hipify transformation" +$PYTHON tools/amd_build/build_amd.py + +# Apply patches +# Fix CUDAGuard narrowing conversion errors under GCC 14 in ROCm HIP flash-attn files +# This patch is required — fail loudly if it cannot be applied +wget https://raw.githubusercontent.com/ppc64le/build-scripts/9c57d3b2c54a629d3cf6f45095b394f85374da3f/p/pytorch-rocm/pytorch_v2.13.0_rocm_cuda_guard_narrowing.patch +git apply pytorch_v2.13.0_rocm_cuda_guard_narrowing.patch + +# Fix FastGeluAsm explicit specializations rejected by AMD clang 23.0 in composable_kernel +# This patch is required — fail loudly if it cannot be applied +wget https://raw.githubusercontent.com/ppc64le/build-scripts/9c57d3b2c54a629d3cf6f45095b394f85374da3f/p/pytorch-rocm/pytorch_v2.13.0_rocm_fastgeluasm.patch +git apply --directory=third_party/composable_kernel pytorch_v2.13.0_rocm_fastgeluasm.patch + +# Build +echo "Building PyTorch ${PYTORCH_VERSION} (this will take a while)" +export PYTORCH_BUILD_VERSION=${PYTORCH_VERSION#v}+rocm7.14 +export PYTORCH_BUILD_NUMBER=1 + +# Rename the pip distribution to "torch-rocm" for ROCm stack isolation on devpi. +# The import name (torch) is unchanged — only the wheel distribution name changes. +# +# WHY sed on pyproject.toml: +# PyTorch v2.13.0 has a pyproject.toml with [project] name = "torch". +# setuptools>=77 (which this build requires) reads pyproject.toml as the +# authoritative metadata source — it takes precedence over setup.py's +# setup(name=...) call. TORCH_PACKAGE_NAME env var only affects setup.py +# but never reaches the wheel name because setuptools overwrites it from +# pyproject.toml. The only reliable fix is to patch the name in-place +# before the build runs, exactly as torchaudio-rocm patches setup.py. +sed -i 's/^name = "torch"$/name = "torch-rocm"/' pyproject.toml +echo "Patched pyproject.toml: name = torch-rocm" + +# Build wheel via setup.py directly. +# pip wheel always invokes PEP 517 (even with --no-build-isolation), which +# spawns a subprocess that does not inherit the current environment — causing +# cmake to re-configure without PYTORCH_ROCM_ARCH and fail. +# setup.py bdist_wheel runs in-process: all exported env vars are visible, +# cmake skips recompilation because build/ already exists and targets are +# up to date, and setuptools reads the patched pyproject.toml for the name. +echo "Building distribution wheel" +if ! MAX_JOBS=$(nproc) $PYTHON setup.py bdist_wheel --dist-dir "${SCRIPT_DIR}/dist"; then + echo "------------------pytorch:Install_fails-------------------------------------" + echo "$PYTORCH_URL pytorch" + echo "pytorch | $PYTORCH_URL | $PYTORCH_VERSION | GitHub | Fail | Install_Fails" + exit 1 +fi + +# Install from the renamed wheel so pip registers it as torch-rocm +$PYTHON -m pip install --no-build-isolation "${SCRIPT_DIR}/dist"/torch_rocm-*.whl + +# Verify torch is importable and ROCm is visible through it +echo "Verifying torch install" +cd "${SCRIPT_DIR}" +export ROCPROFILER_LOG_LEVEL=0 +$PYTHON -c "import torch; print('torch version :', torch.__version__); print('ROCm available:', torch.cuda.is_available())" + +# --------------------------------------------------------------------------- +# Clone torchaudio +# --------------------------------------------------------------------------- +echo "Cloning torchaudio ${PACKAGE_VERSION}" +if [ -d "${SCRIPT_DIR}/audio" ]; then + echo "audio directory already exists, reusing." + cd "${SCRIPT_DIR}/audio" + git checkout "$PACKAGE_VERSION" +else + if ! git clone --branch "$PACKAGE_VERSION" "$PACKAGE_URL" "${SCRIPT_DIR}/audio"; then + echo "------------------$PACKAGE_NAME:clone_fails---------------------------------------" + echo "$PACKAGE_URL $PACKAGE_NAME" + echo "$PACKAGE_NAME | $PACKAGE_URL | $PACKAGE_VERSION | $OS_NAME | GitHub | Fail | Clone_Fails" + exit 1 + fi + cd "${SCRIPT_DIR}/audio" +fi + +# --------------------------------------------------------------------------- +# Apply patches +# --------------------------------------------------------------------------- +PATCH_BASE_URL=${PATCH_BASE_URL:-"https://raw.githubusercontent.com/ppc64le/build-scripts/refs/heads/master/t/torchaudio"} + +# License exclusion patch — required; removes commercially licensed source files +LICENSE_PATCH_FILE="0001-Excluded-source-that-has-commercial-license-new.patch" +wget -q -O "${SCRIPT_DIR}/${LICENSE_PATCH_FILE}" "${PATCH_BASE_URL}/${LICENSE_PATCH_FILE}" +git apply "${SCRIPT_DIR}/${LICENSE_PATCH_FILE}" +echo "Applied license exclusion patch" + +# --------------------------------------------------------------------------- +# Build torchaudio-rocm wheel +# --------------------------------------------------------------------------- +echo "Building torchaudio-rocm wheel" + +# Rename distribution to torchaudio-rocm for ROCm stack isolation. +# torchaudio's setup.py hardcodes name="torchaudio" with no env var override, +# so we patch it directly. The import name (torchaudio) is unchanged. +sed -i 's/name="torchaudio"/name="torchaudio-rocm"/' setup.py + +export BUILD_VERSION="${PACKAGE_VERSION#v}" +export SETUPTOOLS_SCM_PRETEND_VERSION="${BUILD_VERSION}" + +# Let torchaudio's CMake find the installed torch +export TORCH_CMAKE_PREFIX=$($PYTHON -c 'import torch; print(torch.utils.cmake_prefix_path)') +export CMAKE_PREFIX_PATH="${TORCH_CMAKE_PREFIX}:${ROCM_PATH}:${CMAKE_PREFIX_PATH:-}" + +# Disable optional media deps — not needed for the ROCm wheel +export USE_FFMPEG=OFF +export BUILD_SOX=OFF +export USE_OPENMP=OFF +export BUILD_TORCHAUDIO_PYTHON_EXTENSION=ON + +$PYTHON -m pip install --upgrade setuptools wheel + +# Build the wheel and install it in one step. pip wheel saves the .whl to +# $SCRIPT_DIR; pip install then installs it for the import test. +if ! $PYTHON -m pip wheel . --no-build-isolation --no-deps -w "${SCRIPT_DIR}"; then + echo "------------------$PACKAGE_NAME:install_fails---------------------------------------" + echo "$PACKAGE_URL $PACKAGE_NAME" + echo "$PACKAGE_NAME | $PACKAGE_URL | $PACKAGE_VERSION | $OS_NAME | GitHub | Fail | Install_Fails" + exit 1 +fi + +ROCM_WHL=$(ls "${SCRIPT_DIR}"/torchaudio_rocm-${BUILD_VERSION}-*.whl) +echo "Built wheel: $(basename $ROCM_WHL)" +$PYTHON -m pip install "$ROCM_WHL" + +# --------------------------------------------------------------------------- +# Import test +# --------------------------------------------------------------------------- +echo "Running import test" +cd "${SCRIPT_DIR}" + +if ! $PYTHON -c "import torch; import torch._C; import torchaudio; print('torchaudio version:', torchaudio.__version__)"; then + echo "------------------$PACKAGE_NAME:install_success_but_test_fails---------------------" + echo "$PACKAGE_URL $PACKAGE_NAME" + echo "$PACKAGE_NAME | $PACKAGE_URL | $PACKAGE_VERSION | $OS_NAME | GitHub | Fail | Install_success_but_Import_Fails" + exit 2 +fi + +echo "------------------$PACKAGE_NAME:install_&_test_both_success-------------------------" +echo "$PACKAGE_URL $PACKAGE_NAME" +echo "$PACKAGE_NAME | $PACKAGE_URL | $PACKAGE_VERSION | $OS_NAME | GitHub | Pass | Both_Install_and_Import_Success" +exit 0 diff --git a/t/torchvision-rocm/build-info.json b/t/torchvision-rocm/build-info.json new file mode 100644 index 0000000000..57a6e23e50 --- /dev/null +++ b/t/torchvision-rocm/build-info.json @@ -0,0 +1,30 @@ +{ + "maintainer": "Ameil Kumar ", + "package_name": "torchvision-rocm", + "github_url": "https://github.com/pytorch/vision.git", + "version": "v0.28.0", + "wheel_build": true, + "default_branch": "main", + "package_dir": "t/torchvision-rocm", + "build_script": "torchvision_0.28.0_rocm_ubi_10.sh", + "docker_build": false, + "validate_build_script": true, + "use_non_root_user": false, + "wheel_name": "torchvision-rocm", + "skip_python_versions": ["3.12", "3.14"], + "auditwheel_exclude": [ + "libtorchvision.so", + "libc10.so", + "libc10_hip.so", + "libtorch.so", + "libtorch_cpu.so", + "libtorch_hip.so", + "libtorch_python.so" + ], + "v0.28.0": { + "build_script": "torchvision_0.28.0_rocm_ubi_10.sh" + }, + "*": { + "build_script": "torchvision_0.28.0_rocm_ubi_10.sh" + } +} diff --git a/t/torchvision-rocm/torchvision_0.28.0_rocm_ubi_10.sh b/t/torchvision-rocm/torchvision_0.28.0_rocm_ubi_10.sh new file mode 100644 index 0000000000..89d130c25d --- /dev/null +++ b/t/torchvision-rocm/torchvision_0.28.0_rocm_ubi_10.sh @@ -0,0 +1,324 @@ +#!/bin/bash -e +# ----------------------------------------------------------------------------- +# +# Package : torchvision-rocm +# Version : v0.28.0 +# Source repo : https://github.com/pytorch/vision.git +# Tested on : UBI:10 (ppc64le) +# Language : Python +# Ci-Check : True +# Script License: Apache License, Version 2 or later +# Maintainer : Ameil Kumar +# +# Disclaimer: This script has been tested in root mode on given +# ========== platform using the mentioned version of the package. +# It may not work as expected with newer versions of the +# package and/or distribution. In such case, please +# contact "Maintainer" of this script. +# +# ----------------------------------------------------------------------------- +# +# ROCm installation mode (ROCM_INSTALL_MODE env var): +# rpms (default) - Install ROCm RPMs from a provided repo URL +# path - Assume ROCm is already present; use ROCM_PATH as-is +# +# PyTorch is built from source before torchvision so that the ROCm-enabled +# torch shared libraries are available at torchvision's CMake configure time. +# +# Usage: +# ./torchvision_0.28.0_rocm_ubi_10.sh [v0.28.0] +# +# Environment variables honoured (can be set before running): +# PACKAGE_VERSION - torchvision tag to build (default: v0.28.0) +# PYTORCH_VERSION - PyTorch tag to build and install (default: v2.13.0) +# ROCM_INSTALL_MODE - rpms (default) or path +# ROCM_PATH - Path to ROCm installation (default: /opt/rocm) +# ROCM_REPO_URL - RPM repo baseurl for ROCm +# PYTORCH_ROCM_ARCH - Semicolon-separated GPU targets +# (default: "gfx90a;gfx950") +# PYTORCH_PATCH_BASE - Base URL for PyTorch patches +# +# --------------------------------------------------------------------------- + +set -e + +PACKAGE_NAME=torchvision +PACKAGE_VERSION=${1:-v0.28.0} +PACKAGE_URL=https://github.com/pytorch/vision.git +CURRENT_DIR=$(pwd) + +PYTORCH_VERSION=${PYTORCH_VERSION:-v2.13.0} +PYTORCH_URL=https://github.com/pytorch/pytorch.git + +ROCM_INSTALL_MODE=${ROCM_INSTALL_MODE:-"rpms"} # rpms | path +ROCM_REPO_URL=${ROCM_REPO_URL:-"https://public.dhe.ibm.com/software/server/POWER/Linux/AMD/ROCm/RHEL/10/ppc64le"} +ROCM_PATH=${ROCM_PATH:-/opt/rocm} + +# GPU architecture targets — override via env var +PYTORCH_ROCM_ARCH=${PYTORCH_ROCM_ARCH:-"gfx90a;gfx950"} + +if [[ "$ROCM_INSTALL_MODE" != "rpms" && "$ROCM_INSTALL_MODE" != "path" ]]; then + echo "ERROR: ROCM_INSTALL_MODE must be one of: rpms, path" + exit 1 +fi + +echo "=== TorchVision ROCm Build (torch from source) ===" +echo " PACKAGE_VERSION : $PACKAGE_VERSION" +echo " PYTORCH_VERSION : $PYTORCH_VERSION" +echo " ROCM_INSTALL_MODE : $ROCM_INSTALL_MODE" +echo " ROCM_PATH : $ROCM_PATH" +echo " PYTORCH_ROCM_ARCH : $PYTORCH_ROCM_ARCH" +echo "===================================================" + +# --------------------------------------------------------------------------- +# Install system build dependencies +# --------------------------------------------------------------------------- + +# Python packages must appear first (wrapper script requirement). +yum install -y python3.12 python3.12-devel python3.12-pip \ + gcc-toolset-15 gcc-toolset-15-gcc gcc-toolset-15-gcc-c++ \ + git make wget patch cmake ninja-build \ + openblas openblas-devel \ + libjpeg-devel libpng-devel + +# Configure GCC Toolset 15 +if [[ -f /opt/rh/gcc-toolset-15/enable ]]; then + source /opt/rh/gcc-toolset-15/enable +elif [[ -d /opt/rh/gcc-toolset-15/root/usr/bin ]]; then + export PATH="/opt/rh/gcc-toolset-15/root/usr/bin:$PATH" + export LD_LIBRARY_PATH="/opt/rh/gcc-toolset-15/root/usr/lib64:${LD_LIBRARY_PATH:-}" +else + echo "ERROR: gcc-toolset-15 not found" + exit 1 +fi + +echo "Using gcc: $(gcc --version | head -1)" + +# Use Python 3.12 for the build so the produced wheels are cp312 +PYTHON=python3.12 + +# --------------------------------------------------------------------------- +# MODE: rpms — install ROCm from a provided RPM repository +# --------------------------------------------------------------------------- +if [[ "$ROCM_INSTALL_MODE" == "rpms" ]]; then + if [[ ! "$ROCM_REPO_URL" =~ ^(https?|file):// ]]; then + echo "ERROR: ROCM_REPO_URL does not look like a valid URL (got: ${ROCM_REPO_URL})" + exit 1 + fi + echo "Installing ROCm from ${ROCM_REPO_URL}" + + cat > /etc/yum.repos.d/rocm.repo </dev/null; then + echo "ERROR: hipcc not found under ROCM_PATH=${ROCM_PATH}. Check your ROCm installation." + exit 1 +fi +echo "ROCm hipcc: $(hipcc --version | head -1)" + +# --------------------------------------------------------------------------- +# Build PyTorch from source (ROCm) +# --------------------------------------------------------------------------- + +# Use OpenBLAS instead of MKL (MKL does not support Power). +# Disable CUDA/Intel tooling so cmake does not search for them. +export PYTORCH_ROCM_ARCH +export BLAS=OpenBLAS +export USE_CUDA=0 +export USE_XPU=0 +export USE_ROCM=1 + +export CMAKE_PREFIX_PATH="${ROCM_PATH}:${CMAKE_PREFIX_PATH:-}" + +echo "Cloning PyTorch ${PYTORCH_VERSION}" +if [ -d "${CURRENT_DIR}/pytorch" ]; then + echo "pytorch directory already exists, reusing." + cd "${CURRENT_DIR}/pytorch" + git checkout "$PYTORCH_VERSION" +else + if ! git clone --recursive --branch "$PYTORCH_VERSION" "$PYTORCH_URL" "${CURRENT_DIR}/pytorch"; then + echo "------------------pytorch:clone_fails---------------------------------------" + echo "$PYTORCH_URL pytorch" + echo "pytorch | $PYTORCH_URL | $PYTORCH_VERSION | GitHub | Fail | Clone_Fails" + exit 1 + fi + cd "${CURRENT_DIR}/pytorch" +fi + +git submodule sync +git submodule update --init --recursive + +# Install PyTorch build dependencies +$PYTHON -m pip install --upgrade pip +$PYTHON -m pip install --group dev || $PYTHON -m pip install -r requirements.txt + +# Run ROCm source transformation +echo "Running ROCm hipify transformation" +$PYTHON tools/amd_build/build_amd.py + +# Apply patches +# Fix CUDAGuard narrowing conversion errors under GCC 14 in ROCm HIP flash-attn files +# This patch is required — fail loudly if it cannot be applied +wget https://raw.githubusercontent.com/ppc64le/build-scripts/9c57d3b2c54a629d3cf6f45095b394f85374da3f/p/pytorch-rocm/pytorch_v2.13.0_rocm_cuda_guard_narrowing.patch +git apply pytorch_v2.13.0_rocm_cuda_guard_narrowing.patch + +# Fix FastGeluAsm explicit specializations rejected by AMD clang 23.0 in composable_kernel +# This patch is required — fail loudly if it cannot be applied +wget https://raw.githubusercontent.com/ppc64le/build-scripts/9c57d3b2c54a629d3cf6f45095b394f85374da3f/p/pytorch-rocm/pytorch_v2.13.0_rocm_fastgeluasm.patch +git apply --directory=third_party/composable_kernel pytorch_v2.13.0_rocm_fastgeluasm.patch + +# Build +echo "Building PyTorch ${PYTORCH_VERSION} (this will take a while)" +export PYTORCH_BUILD_VERSION=${PYTORCH_VERSION#v}+rocm7.14 +export PYTORCH_BUILD_NUMBER=1 + +# Rename the pip distribution to "torch-rocm" for ROCm stack isolation on devpi. +# The import name (torch) is unchanged — only the wheel distribution name changes. +# +# WHY sed on pyproject.toml: +# PyTorch v2.13.0 has a pyproject.toml with [project] name = "torch". +# setuptools>=77 (which this build requires) reads pyproject.toml as the +# authoritative metadata source — it takes precedence over setup.py's +# setup(name=...) call. TORCH_PACKAGE_NAME env var only affects setup.py +# but never reaches the wheel name because setuptools overwrites it from +# pyproject.toml. The only reliable fix is to patch the name in-place +# before the build runs, exactly as torchaudio-rocm patches setup.py. +sed -i 's/^name = "torch"$/name = "torch-rocm"/' pyproject.toml +echo "Patched pyproject.toml: name = torch-rocm" + +# Build wheel via setup.py directly. +# pip wheel always invokes PEP 517 (even with --no-build-isolation), which +# spawns a subprocess that does not inherit the current environment — causing +# cmake to re-configure without PYTORCH_ROCM_ARCH and fail. +# setup.py bdist_wheel runs in-process: all exported env vars are visible, +# cmake skips recompilation because build/ already exists and targets are +# up to date, and setuptools reads the patched pyproject.toml for the name. +echo "Building distribution wheel" +if ! MAX_JOBS=$(nproc) $PYTHON setup.py bdist_wheel --dist-dir "${CURRENT_DIR}/dist"; then + echo "------------------pytorch:Install_fails-------------------------------------" + echo "$PYTORCH_URL pytorch" + echo "pytorch | $PYTORCH_URL | $PYTORCH_VERSION | GitHub | Fail | Install_Fails" + exit 1 +fi + +# Install from the renamed wheel so pip registers it as torch-rocm +$PYTHON -m pip install --no-build-isolation "${CURRENT_DIR}/dist"/torch_rocm-*.whl + +# Verify torch is importable and ROCm is visible through it +echo "Verifying torch install" +cd "${CURRENT_DIR}" +export ROCPROFILER_LOG_LEVEL=0 +$PYTHON -c "import torch; print('torch version :', torch.__version__); print('ROCm available:', torch.cuda.is_available())" + +# --------------------------------------------------------------------------- +# Clone torchvision +# --------------------------------------------------------------------------- +echo "Cloning torchvision ${PACKAGE_VERSION}" +if [ -d "${CURRENT_DIR}/vision" ]; then + echo "vision directory already exists, reusing." + cd "${CURRENT_DIR}/vision" + git checkout "$PACKAGE_VERSION" +else + if ! git clone --branch "$PACKAGE_VERSION" "$PACKAGE_URL" "${CURRENT_DIR}/vision"; then + echo "------------------$PACKAGE_NAME:clone_fails---------------------------------------" + echo "$PACKAGE_URL $PACKAGE_NAME" + echo "$PACKAGE_NAME | $PACKAGE_URL | $PACKAGE_VERSION | GitHub | Fail | Clone_Fails" + exit 1 + fi + cd "${CURRENT_DIR}/vision" +fi + +# --------------------------------------------------------------------------- +# Apply patches +# --------------------------------------------------------------------------- +PATCH_BASE_URL=${PATCH_BASE_URL:-"https://raw.githubusercontent.com/ppc64le/build-scripts/refs/heads/master/t/torchvision"} + +# License exclusion patch — required; removes SWAG CC-BY-NC-4.0 licensed +# models (regnet.py, vision_transformer SWAG weights) from the wheel. +LICENSE_PATCH_FILE="0001-Exclude-source-that-has-commercial-license_v0.28.0.patch" +wget -q -O "${CURRENT_DIR}/${LICENSE_PATCH_FILE}" "${PATCH_BASE_URL}/${LICENSE_PATCH_FILE}" +git apply "${CURRENT_DIR}/${LICENSE_PATCH_FILE}" + +# Patch out the git-sha injection in setup.py that breaks reproducible builds +sed -i '/elif sha != "Unknown":/,+1d' setup.py + +# Rename the distribution to "torchvision-rocm" via the env var that +# torchvision's setup.py already supports (TORCHVISION_PACKAGE_NAME). +# The import name (torchvision) is unchanged — only the pip distribution name +# changes. +export TORCHVISION_PACKAGE_NAME="torchvision-rocm" + +# Tell torchvision's get_requirements() to list "torch-rocm" as its torch +# dependency instead of "torch". torchvision's setup.py reads TORCH_PACKAGE_NAME +# at install_requires time. Without this, pip fails to install the wheel because +# it looks for "torch" which doesn't exist — only "torch-rocm" is installed. +export TORCH_PACKAGE_NAME="torch-rocm" + +# --------------------------------------------------------------------------- +# Build torchvision-rocm wheel +# --------------------------------------------------------------------------- +echo "Building torchvision-rocm wheel" + +# Let torchvision's CMake find the installed torch (editable install above) +export TORCH_CMAKE_PREFIX=$($PYTHON -c 'import torch; print(torch.utils.cmake_prefix_path)') +export CMAKE_PREFIX_PATH="${TORCH_CMAKE_PREFIX}:${ROCM_PATH}:${CMAKE_PREFIX_PATH:-}" + +export BUILD_VERSION="${PACKAGE_VERSION#v}" +export SETUPTOOLS_SCM_PRETEND_VERSION="${BUILD_VERSION}" + +if ! MAX_JOBS=$(nproc) $PYTHON setup.py bdist_wheel --dist-dir "${CURRENT_DIR}"; then + echo "------------------$PACKAGE_NAME:Install_fails-------------------------------------" + echo "$PACKAGE_URL $PACKAGE_NAME" + echo "$PACKAGE_NAME | $PACKAGE_URL | $PACKAGE_VERSION | GitHub | Fail | Install_Fails" + exit 1 +fi + +# Install the wheel we just built so the import test can run. +# torch-rocm is already installed (editable); pass --find-links so pip can +# satisfy that dependency without hitting PyPI for it. +ROCM_WHL=$(ls "${CURRENT_DIR}"/torchvision_rocm-${BUILD_VERSION}-*.whl) +echo "Built wheel: $(basename $ROCM_WHL)" +$PYTHON -m pip install --find-links "${CURRENT_DIR}" "$ROCM_WHL" + +# --------------------------------------------------------------------------- +# Import test +# --------------------------------------------------------------------------- +echo "Running import test" +cd "${CURRENT_DIR}" + + +if ! $PYTHON -c "import torch; import torchvision; print('torch version :', torch.__version__); print('torchvision version:', torchvision.__version__); print('ROCm available :', torch.cuda.is_available())"; then + echo "------------------$PACKAGE_NAME:Install_success_but_test_fails---------------------" + echo "$PACKAGE_URL $PACKAGE_NAME" + echo "$PACKAGE_NAME | $PACKAGE_URL | $PACKAGE_VERSION | GitHub | Fail | Install_success_but_test_Fails" + exit 2 +else + echo "------------------$PACKAGE_NAME:Install_&_test_both_success-------------------------" + echo "$PACKAGE_URL $PACKAGE_NAME" + echo "$PACKAGE_NAME | $PACKAGE_URL | $PACKAGE_VERSION | GitHub | Pass | Both_Install_and_Test_Success" + exit 0 +fi diff --git a/v/vllm-rocm/build_info.json b/v/vllm-rocm/build_info.json new file mode 100644 index 0000000000..a1657bc505 --- /dev/null +++ b/v/vllm-rocm/build_info.json @@ -0,0 +1,34 @@ +{ + "maintainer": "Daniel Schenker ", + "package_name": "vllm-rocm", + "github_url": "https://github.com/vllm-project/vllm.git", + "version": "v0.24.0", + "wheel_build": true, + "default_branch": "main", + "package_dir": "v/vllm-rocm", + "build_script": "vllm_rocm_v0.24.0_ubi_10.sh", + "docker_build": false, + "validate_build_script": true, + "use_non_root_user": false, + "wheel_name": "vllm", + "skip_python_versions": ["3.12", "3.14"], + "auditwheel_exclude": [ + "libc10.so", + "libc10_hip.so", + "libtorch.so", + "libtorch_cpu.so", + "libtorch_hip.so", + "libtorch_python.so", + "libtorchaudio.so", + "libtorchvision.so", + "libamdhip64.so", + "librocblas.so", + "librocm_smi64.so" + ], + "v0.24.0": { + "build_script": "vllm_rocm_v0.24.0_ubi_10.sh" + }, + "*": { + "build_script": "vllm_rocm_v0.24.0_ubi_10.sh" + } +} diff --git a/v/vllm-rocm/vllm_rocm_v0.24.0_ubi_10.sh b/v/vllm-rocm/vllm_rocm_v0.24.0_ubi_10.sh new file mode 100644 index 0000000000..669cd7c66a --- /dev/null +++ b/v/vllm-rocm/vllm_rocm_v0.24.0_ubi_10.sh @@ -0,0 +1,621 @@ +#!/bin/bash -e +# ----------------------------------------------------------------------------- +# +# Package : vllm +# Version : v0.24.0 +# Source repo : https://github.com/vllm-project/vllm.git +# Tested on : UBI:10 (ppc64le) +# Language : Python, C++, HIP +# Ci-Check : True +# Script License: Apache License, Version 2 or later +# Maintainer : Daniel Schenker +# +# Disclaimer: This script has been tested in root mode on given +# ========== platform using the mentioned version of the package. +# It may not work as expected with newer versions of the +# package and/or distribution. In such case, please +# contact "Maintainer" of this script. +# +# ----------------------------------------------------------------------------- +# +# ROCm installation mode (ROCM_INSTALL_MODE env var): +# rpms (default) - Install ROCm RPMs from a provided repo URL +# path - Assume ROCm is already present; use ROCM_PATH as-is +# +# PyTorch, torchvision, and torchaudio are all built from source before vLLM +# so that ROCm-enabled shared libraries are available at vLLM's CMake +# configure time. +# +# Usage: +# ./vllm_rocm_v0.24.0_ubi_10.sh [v0.24.0] +# +# Environment variables honoured (can be set before running): +# PACKAGE_VERSION - vLLM tag to build (default: v0.24.0) +# PYTORCH_VERSION - PyTorch tag to build (default: v2.13.0) +# TORCHVISION_VERSION - torchvision tag to build (default: v0.28.0) +# TORCHAUDIO_VERSION - torchaudio tag to build (default: v2.11.0) +# ROCM_INSTALL_MODE - rpms (default) or path +# ROCM_PATH - Path to ROCm installation (default: /opt/rocm) +# ROCM_REPO_URL - RPM repo baseurl for ROCm +# PYTORCH_ROCM_ARCH - Semicolon-separated GPU targets +# (default: "gfx90a;gfx950") +# +# --------------------------------------------------------------------------- + +set -e + +PACKAGE_NAME=vllm +PACKAGE_VERSION=${1:-v0.24.0} +PACKAGE_URL=https://github.com/vllm-project/vllm.git +CURRENT_DIR=$(pwd) +OS_NAME=$(grep ^PRETTY_NAME /etc/os-release | cut -d= -f2) + +PYTORCH_VERSION=${PYTORCH_VERSION:-v2.13.0} +PYTORCH_URL=https://github.com/pytorch/pytorch.git + +TORCHVISION_VERSION=${TORCHVISION_VERSION:-v0.28.0} +TORCHVISION_URL=https://github.com/pytorch/vision.git + +TORCHAUDIO_VERSION=${TORCHAUDIO_VERSION:-v2.11.0} +TORCHAUDIO_URL=https://github.com/pytorch/audio.git + +ROCM_INSTALL_MODE=${ROCM_INSTALL_MODE:-"rpms"} # rpms | path +ROCM_REPO_URL=${ROCM_REPO_URL:-"https://public.dhe.ibm.com/software/server/POWER/Linux/AMD/ROCm/RHEL/10/ppc64le"} +ROCM_PATH=${ROCM_PATH:-/opt/rocm} + +# GPU architecture targets — override via env var +PYTORCH_ROCM_ARCH=${PYTORCH_ROCM_ARCH:-"gfx90a;gfx950"} + +if [[ "$ROCM_INSTALL_MODE" != "rpms" && "$ROCM_INSTALL_MODE" != "path" ]]; then + echo "ERROR: ROCM_INSTALL_MODE must be one of: rpms, path" + exit 1 +fi + +echo "=== vLLM ROCm Build (torch/torchvision/torchaudio from source) ===" +echo " PACKAGE_VERSION : $PACKAGE_VERSION" +echo " PYTORCH_VERSION : $PYTORCH_VERSION" +echo " TORCHVISION_VERSION : $TORCHVISION_VERSION" +echo " TORCHAUDIO_VERSION : $TORCHAUDIO_VERSION" +echo " ROCM_INSTALL_MODE : $ROCM_INSTALL_MODE" +echo " ROCM_PATH : $ROCM_PATH" +echo " PYTORCH_ROCM_ARCH : $PYTORCH_ROCM_ARCH" +echo "===================================================================" + +# --------------------------------------------------------------------------- +# Install system build dependencies +# --------------------------------------------------------------------------- + +# Python packages must appear first (wrapper script requirement). +# Note: libdrm is not available in the UBI 10 repo — it is built from source below. +yum install -y python3.12 python3.12-devel python3.12-pip \ + gcc-toolset-15 gcc-toolset-15-gcc gcc-toolset-15-gcc-c++ \ + git make wget patch cmake ninja-build \ + openblas openblas-devel \ + libjpeg-devel libpng-devel \ + zlib-devel curl \ + meson pkgconf-pkg-config pciaccess-devel + +# Configure GCC Toolset 15 +if [[ -f /opt/rh/gcc-toolset-15/enable ]]; then + source /opt/rh/gcc-toolset-15/enable +elif [[ -d /opt/rh/gcc-toolset-15/root/usr/bin ]]; then + export PATH="/opt/rh/gcc-toolset-15/root/usr/bin:$PATH" + export LD_LIBRARY_PATH="/opt/rh/gcc-toolset-15/root/usr/lib64:${LD_LIBRARY_PATH:-}" +else + echo "ERROR: gcc-toolset-15 not found" + exit 1 +fi + +echo "Using gcc: $(gcc --version | head -1)" + +# Use Python 3.12 for the build so all produced wheels are cp312 +PYTHON=python3.12 + +# --------------------------------------------------------------------------- +# Build libdrm from source +# libdrm is not available in the UBI 10 package repository. We clone the +# upstream freedesktop.org release, build it with meson, and install it into +# /usr/local so every subsequent build step can find it via pkg-config. +# --------------------------------------------------------------------------- +LIBDRM_VERSION=${LIBDRM_VERSION:-"libdrm-2.4.124"} +LIBDRM_URL="https://gitlab.freedesktop.org/mesa/drm.git" + +echo "Building libdrm ${LIBDRM_VERSION} from source" +if [ -d "${CURRENT_DIR}/drm" ]; then + echo "drm directory already exists, reusing." + cd "${CURRENT_DIR}/drm" + git checkout "$LIBDRM_VERSION" +else + if ! git clone --branch "$LIBDRM_VERSION" --depth 1 "$LIBDRM_URL" "${CURRENT_DIR}/drm"; then + echo "ERROR: Failed to clone libdrm ${LIBDRM_VERSION}" + exit 1 + fi + cd "${CURRENT_DIR}/drm" +fi + +meson setup build \ + --prefix=/usr/local \ + --buildtype=release \ + -Damdgpu=enabled \ + -Dradeon=enabled \ + -Dintel=disabled \ + -Dnouveau=disabled \ + -Dvmwgfx=disabled \ + -Dtests=false + +ninja -C build +ninja -C build install + +# Make the freshly installed libdrm visible to pkg-config and the linker +export PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig:/usr/local/lib/pkgconfig:${PKG_CONFIG_PATH:-}" +export LD_LIBRARY_PATH="/usr/local/lib64:/usr/local/lib:${LD_LIBRARY_PATH:-}" +echo "libdrm installed: $(pkg-config --modversion libdrm)" + +cd "${CURRENT_DIR}" + +# --------------------------------------------------------------------------- +# Install Rust (required by vLLM build) +# --------------------------------------------------------------------------- +if command -v cargo &>/dev/null; then + echo "Rust already installed: $(cargo --version)" +else + echo "Installing Rust via rustup" + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /tmp/rust-install.sh + sh /tmp/rust-install.sh --no-modify-path --default-toolchain stable --profile minimal -y + rm /tmp/rust-install.sh + export PATH="$PATH:$HOME/.cargo/bin" + echo "Rust installed: $(cargo --version)" +fi + +# --------------------------------------------------------------------------- +# MODE: rpms — install ROCm from a provided RPM repository +# --------------------------------------------------------------------------- +if [[ "$ROCM_INSTALL_MODE" == "rpms" ]]; then + if [[ ! "$ROCM_REPO_URL" =~ ^(https?|file):// ]]; then + echo "ERROR: ROCM_REPO_URL does not look like a valid URL (got: ${ROCM_REPO_URL})" + exit 1 + fi + echo "Installing ROCm from ${ROCM_REPO_URL}" + + cat > /etc/yum.repos.d/rocm.repo </dev/null; then + echo "ERROR: hipcc not found under ROCM_PATH=${ROCM_PATH}. Check your ROCm installation." + exit 1 +fi +echo "ROCm hipcc: $(hipcc --version | head -1)" + +# --------------------------------------------------------------------------- +# Build PyTorch from source (ROCm) +# --------------------------------------------------------------------------- + +# Use OpenBLAS instead of MKL (MKL does not support Power). +# Disable CUDA/Intel tooling so cmake does not search for them. +export PYTORCH_ROCM_ARCH +export BLAS=OpenBLAS +export USE_CUDA=0 +export USE_XPU=0 +export USE_ROCM=1 + +export CMAKE_PREFIX_PATH="${ROCM_PATH}:${CMAKE_PREFIX_PATH:-}" + +echo "Cloning PyTorch ${PYTORCH_VERSION}" +if [ -d "${CURRENT_DIR}/pytorch" ]; then + echo "pytorch directory already exists, reusing." + cd "${CURRENT_DIR}/pytorch" + git checkout "$PYTORCH_VERSION" +else + if ! git clone --recursive --branch "$PYTORCH_VERSION" "$PYTORCH_URL" "${CURRENT_DIR}/pytorch"; then + echo "------------------pytorch:clone_fails---------------------------------------" + echo "$PYTORCH_URL pytorch" + echo "pytorch | $PYTORCH_URL | $PYTORCH_VERSION | GitHub | Fail | Clone_Fails" + exit 1 + fi + cd "${CURRENT_DIR}/pytorch" +fi + +git submodule sync +git submodule update --init --recursive + +# Install PyTorch build dependencies +$PYTHON -m pip install --upgrade pip +$PYTHON -m pip install --group dev || $PYTHON -m pip install -r requirements.txt + +# Run ROCm source transformation +echo "Running ROCm hipify transformation" +$PYTHON tools/amd_build/build_amd.py + +# Apply patches +# Fix CUDAGuard narrowing conversion errors under GCC 14 in ROCm HIP flash-attn files +# This patch is required — fail loudly if it cannot be applied +wget https://raw.githubusercontent.com/ppc64le/build-scripts/9c57d3b2c54a629d3cf6f45095b394f85374da3f/p/pytorch-rocm/pytorch_v2.13.0_rocm_cuda_guard_narrowing.patch +git apply pytorch_v2.13.0_rocm_cuda_guard_narrowing.patch + +# Fix FastGeluAsm explicit specializations rejected by AMD clang 23.0 in composable_kernel +# This patch is required — fail loudly if it cannot be applied +wget https://raw.githubusercontent.com/ppc64le/build-scripts/9c57d3b2c54a629d3cf6f45095b394f85374da3f/p/pytorch-rocm/pytorch_v2.13.0_rocm_fastgeluasm.patch +git apply --directory=third_party/composable_kernel pytorch_v2.13.0_rocm_fastgeluasm.patch + +# Build +echo "Building PyTorch ${PYTORCH_VERSION} (this will take a while)" +export PYTORCH_BUILD_VERSION=${PYTORCH_VERSION#v}+rocm7.14 +export PYTORCH_BUILD_NUMBER=1 + +# Rename the pip distribution to "torch-rocm" for ROCm stack isolation on devpi. +# The import name (torch) is unchanged — only the wheel distribution name changes. +# +# WHY sed on pyproject.toml: +# PyTorch v2.13.0 has a pyproject.toml with [project] name = "torch". +# setuptools>=77 (which this build requires) reads pyproject.toml as the +# authoritative metadata source — it takes precedence over setup.py's +# setup(name=...) call. TORCH_PACKAGE_NAME env var only affects setup.py +# but never reaches the wheel name because setuptools overwrites it from +# pyproject.toml. The only reliable fix is to patch the name in-place +# before the build runs, exactly as torchaudio-rocm patches setup.py. +sed -i 's/^name = "torch"$/name = "torch-rocm"/' pyproject.toml +echo "Patched pyproject.toml: name = torch-rocm" + +# Build wheel via setup.py directly. +# pip wheel always invokes PEP 517 (even with --no-build-isolation), which +# spawns a subprocess that does not inherit the current environment — causing +# cmake to re-configure without PYTORCH_ROCM_ARCH and fail. +# setup.py bdist_wheel runs in-process: all exported env vars are visible, +# cmake skips recompilation because build/ already exists and targets are +# up to date, and setuptools reads the patched pyproject.toml for the name. +echo "Building distribution wheel" +if ! MAX_JOBS=$(nproc) $PYTHON setup.py bdist_wheel --dist-dir "${CURRENT_DIR}/dist"; then + echo "------------------pytorch:Install_fails-------------------------------------" + echo "$PYTORCH_URL pytorch" + echo "pytorch | $PYTORCH_URL | $PYTORCH_VERSION | GitHub | Fail | Install_Fails" + exit 1 +fi + +# Install from the renamed wheel so pip registers it as torch-rocm +$PYTHON -m pip install --no-build-isolation "${CURRENT_DIR}/dist"/torch_rocm-*.whl + +# Verify torch is importable and ROCm is visible through it +echo "Verifying torch install" +cd "${CURRENT_DIR}" +export ROCPROFILER_LOG_LEVEL=0 +$PYTHON -c "import torch; print('torch version :', torch.__version__); print('ROCm available:', torch.cuda.is_available())" + +# --------------------------------------------------------------------------- +# Build torchvision from source (ROCm) +# --------------------------------------------------------------------------- +echo "Cloning torchvision ${TORCHVISION_VERSION}" +if [ -d "${CURRENT_DIR}/vision" ]; then + echo "vision directory already exists, reusing." + cd "${CURRENT_DIR}/vision" + git checkout "$TORCHVISION_VERSION" +else + if ! git clone --branch "$TORCHVISION_VERSION" "$TORCHVISION_URL" "${CURRENT_DIR}/vision"; then + echo "------------------torchvision:clone_fails---------------------------------------" + echo "$TORCHVISION_URL torchvision" + echo "torchvision | $TORCHVISION_URL | $TORCHVISION_VERSION | GitHub | Fail | Clone_Fails" + exit 1 + fi + cd "${CURRENT_DIR}/vision" +fi + +TORCHVISION_PATCH_BASE_URL=${TORCHVISION_PATCH_BASE_URL:-"https://raw.githubusercontent.com/ppc64le/build-scripts/refs/heads/master/t/torchvision"} + +# License exclusion patch — required; removes SWAG CC-BY-NC-4.0 licensed +# models (regnet.py, vision_transformer SWAG weights) from the wheel. +TORCHVISION_LICENSE_PATCH="0001-Exclude-source-that-has-commercial-license_v0.28.0.patch" +wget -q -O "${CURRENT_DIR}/${TORCHVISION_LICENSE_PATCH}" "${TORCHVISION_PATCH_BASE_URL}/${TORCHVISION_LICENSE_PATCH}" +git apply "${CURRENT_DIR}/${TORCHVISION_LICENSE_PATCH}" + +# Patch out the git-sha injection in setup.py that breaks reproducible builds +sed -i '/elif sha != "Unknown":/,+1d' setup.py + +# Rename the distribution to "torchvision-rocm" via the env var that +# torchvision's setup.py already supports (TORCHVISION_PACKAGE_NAME). +# The import name (torchvision) is unchanged — only the pip distribution name changes. +export TORCHVISION_PACKAGE_NAME="torchvision-rocm" + +# Tell torchvision's get_requirements() to list "torch-rocm" as its torch +# dependency instead of "torch". torchvision's setup.py reads TORCH_PACKAGE_NAME +# at install_requires time. Without this, pip fails to install the wheel because +# it looks for "torch" which doesn't exist — only "torch-rocm" is installed. +export TORCH_PACKAGE_NAME="torch-rocm" + +echo "Building torchvision-rocm wheel" + +export TORCH_CMAKE_PREFIX=$($PYTHON -c 'import torch; print(torch.utils.cmake_prefix_path)') +export CMAKE_PREFIX_PATH="${TORCH_CMAKE_PREFIX}:${ROCM_PATH}:${CMAKE_PREFIX_PATH:-}" + +export BUILD_VERSION="${TORCHVISION_VERSION#v}" +export SETUPTOOLS_SCM_PRETEND_VERSION="${BUILD_VERSION}" + +if ! MAX_JOBS=$(nproc) $PYTHON setup.py bdist_wheel --dist-dir "${CURRENT_DIR}"; then + echo "------------------torchvision:Install_fails-------------------------------------" + echo "$TORCHVISION_URL torchvision" + echo "torchvision | $TORCHVISION_URL | $TORCHVISION_VERSION | GitHub | Fail | Install_Fails" + exit 1 +fi + +TORCHVISION_WHL=$(ls "${CURRENT_DIR}"/torchvision_rocm-${BUILD_VERSION}-*.whl) +echo "Built wheel: $(basename $TORCHVISION_WHL)" +$PYTHON -m pip install --find-links "${CURRENT_DIR}" "$TORCHVISION_WHL" + +# Verify torchvision is importable +echo "Verifying torchvision install" +cd "${CURRENT_DIR}" +$PYTHON -c "import torchvision; print('torchvision version:', torchvision.__version__)" + +# --------------------------------------------------------------------------- +# Build torchaudio from source (ROCm) +# --------------------------------------------------------------------------- +echo "Cloning torchaudio ${TORCHAUDIO_VERSION}" +if [ -d "${CURRENT_DIR}/audio" ]; then + echo "audio directory already exists, reusing." + cd "${CURRENT_DIR}/audio" + git checkout "$TORCHAUDIO_VERSION" +else + if ! git clone --branch "$TORCHAUDIO_VERSION" "$TORCHAUDIO_URL" "${CURRENT_DIR}/audio"; then + echo "------------------torchaudio:clone_fails---------------------------------------" + echo "$TORCHAUDIO_URL torchaudio" + echo "torchaudio | $TORCHAUDIO_URL | $TORCHAUDIO_VERSION | GitHub | Fail | Clone_Fails" + exit 1 + fi + cd "${CURRENT_DIR}/audio" +fi + +TORCHAUDIO_PATCH_BASE_URL=${TORCHAUDIO_PATCH_BASE_URL:-"https://raw.githubusercontent.com/ppc64le/build-scripts/refs/heads/master/t/torchaudio"} + +# License exclusion patch — required; removes commercially licensed source files +TORCHAUDIO_LICENSE_PATCH="0001-Excluded-source-that-has-commercial-license-new.patch" +wget -q -O "${CURRENT_DIR}/${TORCHAUDIO_LICENSE_PATCH}" "${TORCHAUDIO_PATCH_BASE_URL}/${TORCHAUDIO_LICENSE_PATCH}" +git apply "${CURRENT_DIR}/${TORCHAUDIO_LICENSE_PATCH}" +echo "Applied torchaudio license exclusion patch" + +# Rename distribution to torchaudio-rocm for ROCm stack isolation. +# torchaudio's setup.py hardcodes name="torchaudio" with no env var override, +# so we patch it directly. The import name (torchaudio) is unchanged. +sed -i 's/name="torchaudio"/name="torchaudio-rocm"/' setup.py + +export BUILD_VERSION="${TORCHAUDIO_VERSION#v}" +export SETUPTOOLS_SCM_PRETEND_VERSION="${BUILD_VERSION}" + +export TORCH_CMAKE_PREFIX=$($PYTHON -c 'import torch; print(torch.utils.cmake_prefix_path)') +export CMAKE_PREFIX_PATH="${TORCH_CMAKE_PREFIX}:${ROCM_PATH}:${CMAKE_PREFIX_PATH:-}" + +# Disable optional media deps — not needed for the ROCm wheel +export USE_FFMPEG=OFF +export BUILD_SOX=OFF +export USE_OPENMP=OFF +export BUILD_TORCHAUDIO_PYTHON_EXTENSION=ON + +$PYTHON -m pip install --upgrade setuptools wheel + +echo "Building torchaudio-rocm wheel" +if ! $PYTHON -m pip wheel . --no-build-isolation --no-deps -w "${CURRENT_DIR}"; then + echo "------------------torchaudio:Install_fails-------------------------------------" + echo "$TORCHAUDIO_URL torchaudio" + echo "torchaudio | $TORCHAUDIO_URL | $TORCHAUDIO_VERSION | GitHub | Fail | Install_Fails" + exit 1 +fi + +TORCHAUDIO_WHL=$(ls "${CURRENT_DIR}"/torchaudio_rocm-${BUILD_VERSION}-*.whl) +echo "Built wheel: $(basename $TORCHAUDIO_WHL)" +$PYTHON -m pip install "$TORCHAUDIO_WHL" + +# Verify torchaudio is importable +echo "Verifying torchaudio install" +cd "${CURRENT_DIR}" +$PYTHON -c "import torchaudio; print('torchaudio version:', torchaudio.__version__)" + +# --------------------------------------------------------------------------- +# Clone vLLM +# --------------------------------------------------------------------------- +echo "Cloning vLLM ${PACKAGE_VERSION}" +if [ -d "${CURRENT_DIR}/vllm/.git" ]; then + echo "vllm directory already exists, reusing." + cd "${CURRENT_DIR}/vllm" + git fetch --tags origin + git checkout "$PACKAGE_VERSION" +else + if ! git clone "$PACKAGE_URL" "${CURRENT_DIR}/vllm"; then + echo "------------------$PACKAGE_NAME:clone_fails---------------------------------------" + echo "$PACKAGE_URL $PACKAGE_NAME" + echo "$PACKAGE_NAME | $PACKAGE_URL | $PACKAGE_VERSION | GitHub | Fail | Clone_Fails" + exit 1 + fi + cd "${CURRENT_DIR}/vllm" + git checkout "$PACKAGE_VERSION" +fi + +echo "Current vLLM commit:" +git --no-pager log -1 --oneline + +# --------------------------------------------------------------------------- +# Apply vLLM patches +# --------------------------------------------------------------------------- + +# use_existing_torch.py — removes vLLM's bundled torch build in favour of +# the torch-rocm wheel already installed above +echo "Running vLLM use_existing_torch.py patch" +[[ -f "use_existing_torch.py" ]] || { echo "ERROR: use_existing_torch.py not found"; exit 1; } +$PYTHON use_existing_torch.py + +# Patch requirements/build/rocm.txt: +# 1. Relax triton pin (==3.6.0 → >=3.6.0) for ppc64le wheel compatibility +# 2. Remove amdsmi PyPI pin — installed from system ROCm below +REQ_FILE="requirements/build/rocm.txt" +[[ -f "$REQ_FILE" ]] || { echo "ERROR: $REQ_FILE not found"; exit 1; } + +if grep -q '^triton==3\.6\.0$' "$REQ_FILE"; then + sed -i 's/^triton==3\.6\.0$/triton>=3.6.0/' "$REQ_FILE" + echo "Patched $REQ_FILE: triton==3.6.0 -> triton>=3.6.0" +elif grep -q '^triton>=3\.6\.0$' "$REQ_FILE"; then + echo "$REQ_FILE already patched for triton>=3.6.0" +else + echo "ERROR: Could not find expected triton==3.6.0 line in $REQ_FILE" + exit 1 +fi + +if grep -q '^amdsmi' "$REQ_FILE"; then + sed -i '/^amdsmi/d' "$REQ_FILE" + echo "Patched $REQ_FILE: removed amdsmi line (installed from system ROCm instead)" +fi + +# Inject ROCm bitcode path into CMAKE_HIP_FLAGS in setup.py +ROCM_BITCODE_DIR="$ROCM_PATH/lib/llvm/amdgcn/bitcode" +[[ -d "$ROCM_BITCODE_DIR" ]] || { echo "ERROR: ROCm bitcode directory not found: $ROCM_BITCODE_DIR"; exit 1; } + +echo "Patching setup.py CMAKE_HIP_FLAGS with ROCm bitcode path" +$PYTHON - <