Skip to content

Commit cb9650e

Browse files
committed
Commit local patches to submodules
1 parent 1b031ce commit cb9650e

5 files changed

Lines changed: 9746 additions & 5 deletions

File tree

CMakeLists.txt

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,45 @@
11
# Copyright (C) 2026, Advanced Micro Devices, Inc. All rights reserved.
22
# SPDX-License-Identifier: MIT
33

4-
project(triton-xdna)
5-
64
cmake_minimum_required(VERSION 3.24)
75

8-
find_package(Python3 REQUIRED COMPONENTS Interpreter)
6+
project(triton-xdna)
97

8+
find_package(Python3 REQUIRED COMPONENTS Interpreter)
109
find_package(Git REQUIRED)
1110

11+
# =============================================================================
12+
# Patch Management Targets
13+
# =============================================================================
14+
15+
# Apply patches to third-party submodules
16+
add_custom_target(apply-patches
17+
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/apply_patches.py
18+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
19+
COMMENT "Applying patches to third-party submodules..."
20+
USES_TERMINAL
21+
)
22+
23+
# Reset submodules to clean state (removes patches)
24+
add_custom_target(reset-submodules
25+
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/apply_patches.py --reset-only
26+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
27+
COMMENT "Resetting third-party submodules to clean state..."
28+
USES_TERMINAL
29+
)
30+
31+
# Force re-apply patches (reset + apply)
32+
add_custom_target(reapply-patches
33+
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/apply_patches.py --reset
34+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
35+
COMMENT "Re-applying patches to third-party submodules..."
36+
USES_TERMINAL
37+
)
38+
39+
# =============================================================================
40+
# Build Configuration
41+
# =============================================================================
42+
1243
set(PIP_INSTALL_ARGS) # Pip install command args
1344
list(APPEND PIP_INSTALL_ARGS "--no-build-isolation")
1445
list(APPEND PIP_INSTALL_ARGS "-vvv")
@@ -26,5 +57,9 @@ add_custom_target(triton-build ALL
2657
"TRITON_PLUGIN_DIRS=${CMAKE_CURRENT_SOURCE_DIR}/third_party/triton_shared\;${CMAKE_CURRENT_SOURCE_DIR}/amd_triton_npu"
2758
${Python3_EXECUTABLE} -m pip install ${PIP_INSTALL_ARGS} .
2859
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
60+
COMMENT "Building Triton with XDNA plugins..."
2961
USES_TERMINAL
3062
)
63+
64+
# Ensure patches are applied before building
65+
add_dependencies(triton-build apply-patches)

scripts/apply_patches.py

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
#!/usr/bin/env python3
2+
# Copyright (C) 2026, Advanced Micro Devices, Inc. All rights reserved.
3+
# SPDX-License-Identifier: MIT
4+
5+
"""
6+
Apply local patches to third-party submodules before building.
7+
8+
This script applies patch files from third_party/ to their respective submodules.
9+
It uses marker files to track whether patches have been applied to avoid
10+
re-applying them on subsequent builds.
11+
12+
Usage:
13+
python scripts/apply_patches.py [--reset] [--force]
14+
15+
Options:
16+
--reset Reset submodules to clean state before applying patches
17+
--force Force re-apply patches even if marker exists
18+
"""
19+
20+
import argparse
21+
import subprocess
22+
import sys
23+
from pathlib import Path
24+
25+
# Base directory (project root)
26+
BASE_DIR = Path(__file__).parent.parent.resolve()
27+
THIRD_PARTY_DIR = BASE_DIR / "third_party"
28+
29+
# Patch configuration: (submodule_name, patch_file)
30+
PATCHES = [
31+
("triton", "triton.patch"),
32+
("triton_shared", "triton_shared.patch"),
33+
]
34+
35+
# Marker file name to track if patches have been applied
36+
MARKER_FILE = ".patches_applied"
37+
38+
39+
def run_git(args: list, cwd: Path, check: bool = True) -> subprocess.CompletedProcess:
40+
"""Run a git command in the specified directory."""
41+
cmd = ["git"] + args
42+
return subprocess.run(
43+
cmd,
44+
cwd=cwd,
45+
capture_output=True,
46+
text=True,
47+
check=check,
48+
)
49+
50+
51+
def reset_submodule(submodule_dir: Path) -> bool:
52+
"""Reset a submodule to its clean state."""
53+
print(f" Resetting {submodule_dir.name}...", file=sys.stderr)
54+
55+
try:
56+
# Discard all local changes
57+
run_git(["checkout", "."], cwd=submodule_dir)
58+
# Remove untracked files
59+
run_git(["clean", "-fd"], cwd=submodule_dir)
60+
61+
# Remove marker file if it exists
62+
marker = submodule_dir / MARKER_FILE
63+
if marker.exists():
64+
marker.unlink()
65+
66+
print(f" ✓ Reset {submodule_dir.name}", file=sys.stderr)
67+
return True
68+
except subprocess.CalledProcessError as e:
69+
print(f" ✗ Failed to reset {submodule_dir.name}: {e.stderr}", file=sys.stderr)
70+
return False
71+
72+
73+
def check_patch_applicable(patch_file: Path, target_dir: Path) -> tuple[bool, str]:
74+
"""
75+
Check if a patch can be applied.
76+
77+
Returns:
78+
(can_apply, reason) tuple
79+
"""
80+
result = run_git(
81+
["apply", "--check", str(patch_file)],
82+
cwd=target_dir,
83+
check=False,
84+
)
85+
86+
if result.returncode == 0:
87+
return True, "Patch can be applied"
88+
89+
# Check if patch is already applied by trying reverse
90+
result_reverse = run_git(
91+
["apply", "--check", "--reverse", str(patch_file)],
92+
cwd=target_dir,
93+
check=False,
94+
)
95+
96+
if result_reverse.returncode == 0:
97+
return False, "Patch already applied"
98+
99+
return False, f"Patch conflict: {result.stderr.strip()}"
100+
101+
102+
def apply_patch(patch_file: Path, target_dir: Path) -> bool:
103+
"""Apply a patch file to the target directory."""
104+
try:
105+
run_git(["apply", str(patch_file)], cwd=target_dir)
106+
return True
107+
except subprocess.CalledProcessError as e:
108+
print(f" ✗ Failed to apply patch: {e.stderr}", file=sys.stderr)
109+
return False
110+
111+
112+
def apply_patches(force: bool = False, reset: bool = False) -> bool:
113+
"""
114+
Apply all configured patches to their submodules.
115+
116+
Args:
117+
force: Force re-apply patches even if marker exists
118+
reset: Reset submodules before applying patches
119+
120+
Returns:
121+
True if all patches were applied successfully, False otherwise
122+
"""
123+
print("=" * 60, file=sys.stderr)
124+
print("Applying patches to submodules", file=sys.stderr)
125+
print("=" * 60, file=sys.stderr)
126+
127+
all_success = True
128+
129+
for submodule_name, patch_name in PATCHES:
130+
submodule_dir = THIRD_PARTY_DIR / submodule_name
131+
patch_file = THIRD_PARTY_DIR / patch_name
132+
marker_file = submodule_dir / MARKER_FILE
133+
134+
print(f"\n[{submodule_name}]", file=sys.stderr)
135+
136+
# Check if submodule directory exists
137+
if not submodule_dir.exists():
138+
print(
139+
f" ⚠ Submodule directory not found: {submodule_dir}", file=sys.stderr
140+
)
141+
continue
142+
143+
# Check if patch file exists
144+
if not patch_file.exists():
145+
print(f" ⚠ Patch file not found: {patch_file}", file=sys.stderr)
146+
continue
147+
148+
# Reset if requested
149+
if reset:
150+
if not reset_submodule(submodule_dir):
151+
all_success = False
152+
continue
153+
154+
# Check if already applied (marker exists)
155+
if marker_file.exists() and not force:
156+
print(f" ✓ Patches already applied (marker exists)", file=sys.stderr)
157+
continue
158+
159+
# Check if patch can be applied
160+
can_apply, reason = check_patch_applicable(patch_file, submodule_dir)
161+
162+
if not can_apply:
163+
if "already applied" in reason.lower():
164+
print(f" ✓ {reason}", file=sys.stderr)
165+
# Create marker file
166+
marker_file.touch()
167+
else:
168+
print(f" ✗ {reason}", file=sys.stderr)
169+
all_success = False
170+
continue
171+
172+
# Apply the patch
173+
print(f" Applying {patch_name}...", file=sys.stderr)
174+
if apply_patch(patch_file, submodule_dir):
175+
print(f" ✓ Patch applied successfully", file=sys.stderr)
176+
# Create marker file
177+
marker_file.touch()
178+
else:
179+
all_success = False
180+
181+
print("\n" + "=" * 60, file=sys.stderr)
182+
if all_success:
183+
print("All patches applied successfully!", file=sys.stderr)
184+
else:
185+
print("Some patches failed to apply.", file=sys.stderr)
186+
print("=" * 60, file=sys.stderr)
187+
188+
return all_success
189+
190+
191+
def reset_all_submodules() -> bool:
192+
"""Reset all configured submodules to clean state."""
193+
print("=" * 60, file=sys.stderr)
194+
print("Resetting submodules to clean state", file=sys.stderr)
195+
print("=" * 60, file=sys.stderr)
196+
197+
all_success = True
198+
199+
for submodule_name, _ in PATCHES:
200+
submodule_dir = THIRD_PARTY_DIR / submodule_name
201+
202+
if not submodule_dir.exists():
203+
print(
204+
f" ⚠ Submodule directory not found: {submodule_dir}", file=sys.stderr
205+
)
206+
continue
207+
208+
if not reset_submodule(submodule_dir):
209+
all_success = False
210+
211+
return all_success
212+
213+
214+
def main():
215+
parser = argparse.ArgumentParser(
216+
description="Apply local patches to third-party submodules"
217+
)
218+
parser.add_argument(
219+
"--reset",
220+
action="store_true",
221+
help="Reset submodules to clean state before applying patches",
222+
)
223+
parser.add_argument(
224+
"--force",
225+
action="store_true",
226+
help="Force re-apply patches even if marker exists",
227+
)
228+
parser.add_argument(
229+
"--reset-only",
230+
action="store_true",
231+
help="Only reset submodules, don't apply patches",
232+
)
233+
234+
args = parser.parse_args()
235+
236+
if args.reset_only:
237+
success = reset_all_submodules()
238+
else:
239+
success = apply_patches(force=args.force, reset=args.reset)
240+
241+
sys.exit(0 if success else 1)
242+
243+
244+
if __name__ == "__main__":
245+
main()

0 commit comments

Comments
 (0)