Files
TheRock/build_tools/patch_rocm_libraries.py
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

163 lines
4.8 KiB
Python
Executable File

#!/usr/bin/env python
# Copyright Advanced Micro Devices, Inc.
# SPDX-License-Identifier: MIT
"""Applies patches to a monorepo.
This script is available for users, but it is primarily the mechanism
the CI uses to apply patches to a monorepo.
A monorepo like `rocm-libraries` can be fetch with the `fetch_repo.py`
script, whereas patches carried in TheRock would be applied with this
script.
Example usage:
# Apply all patches to `rocm-libraries/projects`:
python patch_monorepo.py --repo /tmp/rocm-libraries
# Apply patches to `rocm-libraries/projects/rocblas`:
python patch_monorepo.py --repo /tmp/rocm-libraries --projects rocBLAS
# Apply patches to `rocm-libraries/projects/{rocblas,rocthrust}`
python patch_monorepo.py --repo /tmp/rocm-libraries --projects rocBLAS rocThrust
"""
import argparse
from pathlib import Path
import shlex
import subprocess
import sys
THIS_SCRIPT_DIR = Path(__file__).resolve().parent
THEROCK_DIR = THIS_SCRIPT_DIR.parent
PATCHES_DIR = THEROCK_DIR / "patches"
def log(*args, **kwargs):
print(*args, **kwargs)
sys.stdout.flush()
def run_command(args: list[str | Path], cwd: Path):
args = [str(arg) for arg in args]
log(f"++ Exec [{cwd}]$ {shlex.join(args)}")
sys.stdout.flush()
subprocess.check_call(args, cwd=str(cwd), stdin=subprocess.DEVNULL)
def get_monorepo_path(repo: Path, category: str, name: str) -> Path:
relpath = repo / category / Path(name.lower())
return relpath
def run(args):
projects = list(args.projects)
shared = list()
if args.include_shared:
shared = list(args.shared)
# TODO: This is take over from `fetch_sources` and likley only applies
# to submodules. Re-evaluate here if needed.
# Because we allow local patches, if a submodule is in a patched state,
# we manually set it to skip-worktree since recording the commit is
# then meaningless. Here on each fetch, we reset the flag so that if
# patches are aged out, the tree is restored to normal.
run_command(
["git", "update-index", "--skip-worktree"],
cwd=args.repo,
)
patch_version_dir: Path = PATCHES_DIR / args.patch_tag
if not patch_version_dir.exists():
log(f"ERROR: Patch directory {patch_version_dir} does not exist")
for patch_project_dir in patch_version_dir.iterdir():
log(f"* Processing project patch directory {patch_project_dir}:")
# Check that project patch directory was included and set the category
project_to_patch = patch_project_dir.name
if project_to_patch in projects:
category = "projects"
elif project_to_patch in shared:
category = "shared"
else:
log(
f"* Project patch directory {patch_project_dir.name} was not included. Skipping."
)
continue
project_path = get_monorepo_path(args.repo, category, project_to_patch)
patch_files = list(patch_project_dir.glob("*.patch"))
patch_files.sort()
log(f"Applying {len(patch_files)} patches to {project_to_patch}")
apply_directory = str(project_path.relative_to(args.repo))
run_command(
[
"git",
"-c",
"user.name=therockbot",
"-c",
"user.email=therockbot@amd.com",
"am",
"--whitespace=nowarn",
"--directory",
f"{apply_directory}",
]
+ patch_files,
cwd=args.repo,
)
# TODO: This is take over from `fetch_sources` and likley only applies
# to submodules. Re-evaluate here if needed.
# Since it is in a patched state, make it invisible to changes.
run_command(
["git", "update-index", "--skip-worktree"],
cwd=args.repo,
)
def main(argv):
parser = argparse.ArgumentParser(prog="patch_monorepo")
parser.add_argument(
"--patch-tag",
type=str,
default="amd-mainline",
help="Patch tag to apply to sources after sync",
)
parser.add_argument(
"--projects",
nargs="+",
type=str,
default=[
"hipSOLVER",
"rocSOLVER",
"composable_kernel",
],
)
parser.add_argument(
"--shared",
nargs="+",
type=str,
default=[
"Tensile",
],
)
parser.add_argument(
"--include-shared",
# TODO: Set to True once the patchset applies to Tensile
default=False,
action=argparse.BooleanOptionalAction,
help="Include shared projects",
)
parser.add_argument(
"--repo",
type=Path,
required=True,
help="Path to the monorepo",
)
args = parser.parse_args(argv)
run(args)
if __name__ == "__main__":
main(sys.argv[1:])