Skip to content

Instantly share code, notes, and snippets.

@scottt
Last active May 21, 2025 14:31
Show Gist options
  • Save scottt/7ade08163bab3c3e6ba863f56e5f4b22 to your computer and use it in GitHub Desktop.
Save scottt/7ade08163bab3c3e6ba863f56e5f4b22 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import os
import sys
import subprocess
import platform
import time
import signal
from pathlib import Path
def run_command(cmd_list, cwd=None):
"""Runs a command, prints it, times it, and checks for errors."""
print(f"\n--- Executing: {' '.join(map(str, cmd_list))} ---", flush=True)
start_time = time.monotonic()
try:
process = subprocess.run(cmd_list, cwd=cwd, check=True, text=True)
except FileNotFoundError:
print(f"ERROR: Command not found: {cmd_list[0]}. Is it installed and in PATH?", file=sys.stderr)
sys.exit(1)
except subprocess.CalledProcessError as e:
print(f"ERROR: Command failed with exit code {e.returncode}", file=sys.stderr)
sys.exit(e.returncode)
except Exception as e:
print(f"ERROR: An unexpected error occurred: {e}", file=sys.stderr)
sys.exit(1)
end_time = time.monotonic()
print(f"--- Command finished successfully in {end_time - start_time:.2f} seconds ---", flush=True)
return process
def build(gpu_target):
script_dir = Path(os.path.dirname(sys.argv[0]))
fork_name = 'r-st'
if sys.platform == 'win32':
os.environ['THEROCK_OUTPUT_DIR'] = os.path.expanduser(f'/o/{fork_name}-{gpu_target}')
os.environ['THEROCK_SOURCE_DIR'] = os.path.expanduser(f'/w/{fork_name}')
else:
os.environ['THEROCK_OUTPUT_DIR'] = os.path.expanduser(f'~/o/{fork_name}-{gpu_target}')
os.environ['THEROCK_SOURCE_DIR'] = os.path.expanduser(f'~/w/{fork_name}')
os.environ['THEROCK_INTERACTIVE'] = '1'
# "-DTHEROCK_ENABLE_ALL=ON",
# "-DTHEROCK_RESET_FEATURES=ON",
therock_build_cmd = [
sys.executable,
script_dir / 'therock-build.py',
f"-DTHEROCK_AMDGPU_FAMILIES={gpu_target}",
"-DTHEROCK_ENABLE_ALL=OFF",
"-DTHEROCK_BUNDLE_SYSDEPS=ON",
"-DTHEROCK_ENABLE_HOST_BLAS=ON",
"-DTHEROCK_ENABLE_COMPILER=ON",
"-DTHEROCK_ENABLE_HIPIFY=ON",
"-DTHEROCK_ENABLE_HIP_RUNTIME=ON",
"-DTHEROCK_ENABLE_PRIM=ON",
"-DTHEROCK_ENABLE_BLAS=ON",
"-DTHEROCK_ENABLE_RAND=ON",
"-DTHEROCK_ENABLE_FFT=ON",
"-DTHEROCK_BUILD_TESTING=ON",
"-DTHEROCK_ENABLE_SPARSE=ON",
"-DTHEROCK_ENABLE_SOLVER=ON",
"-DTHEROCK_ENABLE_COMM_LIBS=OFF",
"-DTHEROCK_ENABLE_RCCL=OFF",
"-DTHEROCK_ENABLE_MIOPEN=ON",
]
run_command(therock_build_cmd)
with open(os.path.expanduser('~/THEROCK-GPU-TARGET')) as f:
gpu_target = f.read().strip()
print(f'gpu_target: {gpu_target}')
if gpu_target == '':
sys.stderr.write('Try:\n\techo gfx1151 > $HOME/THEROCK-GPU-TARGET\n')
sys.exit(2)
build(gpu_target)
import os
import sys
import subprocess
import platform
import time
import signal
from pathlib import Path
# --- Configuration ---
output_base_dir = Path(os.environ['THEROCK_OUTPUT_DIR']).resolve()
source_dir = Path(os.environ['THEROCK_SOURCE_DIR']).resolve()
CCACHE_EXECUTABLE = "ccache"
# --- Setup ---
build_dir = output_base_dir / "build"
caches_dir = output_base_dir / ".." / "caches"
ccache_dir = caches_dir / "ccache"
pip_cache_dir = caches_dir / "pip"
print(f"--- Configuration ---")
print(f"Source Directory: {source_dir}")
print(f"Output Base Directory: {output_base_dir}")
print(f"Build Directory: {build_dir}")
print(f"Cache Directory: {caches_dir}")
print(f"Script Arguments: {sys.argv[1:]}")
print(f"---------------------")
print(f"Ensuring directories exist...")
ccache_dir.mkdir(parents=True, exist_ok=True)
pip_cache_dir.mkdir(parents=True, exist_ok=True)
build_dir.mkdir(parents=True, exist_ok=True) # Also ensure build dir exists early
print("Setting environment variables...")
os.environ['CCACHE_DIR'] = str(ccache_dir.resolve())
os.environ['PIP_CACHE_DIR'] = str(pip_cache_dir.resolve())
use_ccache = True
if use_ccache:
print(f"Configuring CMake to use ccache ('{CCACHE_EXECUTABLE}')...")
os.environ['CMAKE_C_COMPILER_LAUNCHER'] = CCACHE_EXECUTABLE
os.environ['CMAKE_CXX_COMPILER_LAUNCHER'] = CCACHE_EXECUTABLE
else:
print("Skipping ccache configuration.")
# Ensure they are unset if they existed before
os.environ.pop('CMAKE_C_COMPILER_LAUNCHER', None)
os.environ.pop('CMAKE_CXX_COMPILER_LAUNCHER', None)
print(f"CCACHE_DIR = {os.environ.get('CCACHE_DIR')}")
print(f"PIP_CACHE_DIR = {os.environ.get('PIP_CACHE_DIR')}")
print(f"CMAKE_C_COMPILER_LAUNCHER = {os.environ.get('CMAKE_C_COMPILER_LAUNCHER')}")
print(f"CMAKE_CXX_COMPILER_LAUNCHER = {os.environ.get('CMAKE_CXX_COMPILER_LAUNCHER')}")
# --- Helper function to run commands ---
def run_command(cmd_list, cwd=None):
"""Runs a command, prints it, times it, and checks for errors."""
print(f"\n--- Executing: {' '.join(map(str, cmd_list))} ---", flush=True)
start_time = time.monotonic()
try:
# Use shell=False (default) for better security and argument handling
# check=True raises CalledProcessError on non-zero exit code (like set -e)
process = subprocess.run(cmd_list, cwd=cwd, check=True, text=True)
#stdout=sys.stdout, stderr=sys.stderr) # Redirect streams directly
except FileNotFoundError:
print(f"ERROR: Command not found: {cmd_list[0]}. Is it installed and in PATH?", file=sys.stderr)
sys.exit(1)
except subprocess.CalledProcessError as e:
print(f"ERROR: Command failed with exit code {e.returncode}", file=sys.stderr)
sys.exit(e.returncode)
except Exception as e:
print(f"ERROR: An unexpected error occurred: {e}", file=sys.stderr)
sys.exit(1)
end_time = time.monotonic()
print(f"--- Command finished successfully in {end_time - start_time:.2f} seconds ---", flush=True)
return process
# --- Build Steps ---
# 1. CMake Configure Step
# Pass through any extra arguments given to this python script ($@)
cmake_configure_cmd = [
"cmake",
"-G", "Ninja", # Make sure Ninja is installed and in PATH
"-S", str(source_dir.resolve()),
"-B", str(build_dir.resolve()),
]
cmake_configure_cmd.extend(sys.argv[1:]) # Add extra arguments from script call
run_command(cmake_configure_cmd)
# 2. CMake Build Step
cmake_build_cmd = [
"cmake",
"--build", str(build_dir.resolve())
]
# Add parallel build flag common on Windows (optional)
# Get number of processors, leave one free
cpu_count = os.cpu_count()
if cpu_count and cpu_count > 1:
cmake_build_cmd.extend(["--", f"-j{max(1, cpu_count - 1)}"]) # Pass '-jN' to underlying Ninja
print(f"Using parallel build flag: -j{max(1, cpu_count - 1)}")
run_command(cmake_build_cmd)
print("\nBuild script completed successfully.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment