Files
2026-03-18 23:15:53 +05:30

226 lines
7.6 KiB
Python

import os
import sys
import subprocess
import platform
import argparse
import shutil
def run_command(command):
try:
subprocess.check_call(command)
except subprocess.CalledProcessError as e:
print(f"Error executing command: {e}")
return False
return True
def is_uv_available():
try:
subprocess.check_call([sys.executable, "-m", "uv", "--version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return True
except:
return False
def get_env_info():
info = {}
# OS
if platform.system() == "Windows":
info['platform'] = "win_amd64"
else:
info['platform'] = "manylinux_2_35_x86_64" # Default specialized tag
# Python version
py_ver = f"cp{sys.version_info.major}{sys.version_info.minor}"
info['python'] = py_ver
# Torch and CUDA
try:
import torch
torch_raw = torch.__version__.split('+')[0]
torch_ver = torch_raw.split('.')
info['torch'] = f"torch{torch_ver[0]}{torch_ver[1]}"
info['torch_raw'] = torch_raw
if torch.version.cuda:
cuda_ver = torch.version.cuda.split('.')
info['cuda'] = f"cu{cuda_ver[0]}{cuda_ver[1]}"
else:
info['cuda'] = None
except ImportError:
print("PyTorch not found. Please install PyTorch with CUDA support first.")
sys.exit(1)
return info
def show_recommendations():
print("\n" + "="*50)
print("RECOMMENDED ENVIRONMENTS")
print("="*50)
print("If you encounter 404 errors, it is likely because your environment")
print("combination is not yet supported on the wheel repository.")
print("\nPreferred configurations:")
print("1. CUDA 12.4 + PyTorch 2.5 (Most compatible)")
print("2. CUDA 12.6 + PyTorch 2.6 (Latest compatible)")
print("3. CUDA 12.1 + PyTorch 2.4 (Legacy compatible)")
print("\nYou can install the preferred Torch version using:")
print("pip install torch==2.5.1 --index-url https://download.pytorch.org/whl/cu124")
print("="*50 + "\n")
def find_wheel_url(lib_name, env):
import urllib.request
import re
index_url = f"https://pozzettiandrea.github.io/cuda-wheels/{lib_name}/"
try:
req = urllib.request.Request(index_url, headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req) as response:
html = response.read().decode('utf-8')
except Exception as e:
print(f" Warning: Could not access {lib_name} wheel index: {e}")
return None
cuda = env['cuda']
torch_tag = env['torch']
python_tag = env['python']
torch_base = torch_tag[:5] # 'torch'
torch_ver = torch_tag[5:] # '210'
v_major = torch_ver[0]
v_minor = torch_ver[1:]
lib_name_fixed = lib_name.replace("-", "_")
pattern = rf'https://github\.com/[^"\s]+{lib_name_fixed}-[^"\s]+(?:\+|%2B){cuda}{torch_base}{v_major}\.?{v_minor}-{python_tag}-{python_tag}-[^"\s]+\.whl'
matches = re.findall(pattern, html)
if matches:
return matches[0]
return None
def install_flash_attn(pip_base, env, dry_run=False):
print("\n--- Installing flash-attn ---")
wheel_url = find_wheel_url("flash-attn", env)
if wheel_url:
print(f" Found matching wheel: {wheel_url}")
if dry_run:
print(f" [Dry Run] Would run: {' '.join(pip_base + ['install', wheel_url])}")
return True
else:
return run_command(pip_base + ["install", wheel_url])
else:
print(f" Warning: No matching flash-attn wheel found for {env['cuda']}, {env['torch']}, {env['python']} on {env['platform']}.")
return False
def install_triton_windows(pip_base, env, dry_run=False):
if platform.system() != "Windows":
return True
print("\n--- Installing triton-windows ---")
torch_raw = env.get('torch_raw', '2.0.0')
try:
from packaging import version
except ImportError:
class VersionFallback:
def __init__(self, v): self.v = [int(x) for x in v.split('.')[:2]]
def __ge__(self, other): return self.v >= [int(x) for x in other.split('.')[:2]]
version = type('obj', (object,), {'parse': lambda v: VersionFallback(v)})
v_torch = version.parse(torch_raw)
triton_spec = "triton-windows"
if v_torch >= version.parse("2.10.0"):
triton_spec = "triton-windows<3.7"
elif v_torch >= version.parse("2.9.0"):
triton_spec = "triton-windows<3.6"
elif v_torch >= version.parse("2.8.0"):
triton_spec = "triton-windows<3.5"
elif v_torch >= version.parse("2.7.0"):
triton_spec = "triton-windows<3.4"
elif v_torch >= version.parse("2.6.0"):
triton_spec = "triton-windows<3.3"
if dry_run:
print(f" [Dry Run] Would run: {' '.join(pip_base + ['install', '-U', triton_spec])}")
return True
else:
return run_command(pip_base + ["install", "-U", triton_spec])
def install():
parser = argparse.ArgumentParser(description="ComfyUI-SegviGen Installation")
parser.add_argument("--dry-run", action="store_true", help="Print the steps without installing")
args = parser.parse_args()
print("--- ComfyUI-SegviGen Installation ---")
if args.dry_run:
print("(DRY RUN MODE)")
env = get_env_info()
print(f"Detected Environment:")
print(f" OS: {platform.system()}")
print(f" Python: {env['python']}")
print(f" PyTorch: {env['torch']}")
print(f" CUDA: {env['cuda']}")
if not env['cuda']:
print("Error: CUDA not detected in PyTorch. These wheels require CUDA.")
sys.exit(1)
# 1. Install standard requirements
current_dir = os.path.dirname(os.path.abspath(__file__))
requirements_path = os.path.join(current_dir, "requirements.txt")
use_uv = is_uv_available()
pip_base = [sys.executable, "-m", "uv", "pip"] if use_uv else [sys.executable, "-m", "pip"]
if os.path.exists(requirements_path):
print(f"\nInstalling requirements from {requirements_path}...")
if args.dry_run:
print(f" [Dry Run] Would run: {' '.join(pip_base + ['install', '-r', requirements_path])}")
else:
run_command(pip_base + ["install", "-r", requirements_path])
# 2. Install flash-attn
install_flash_attn(pip_base, env, dry_run=args.dry_run)
# 3. Install correct triton-windows version
install_triton_windows(pip_base, env, dry_run=args.dry_run)
# 4. Define other CUDA wheels
packages = [
{"name": "cumesh", "tag": "cumesh-latest"},
{"name": "flex-gemm", "tag": "flex_gemm-latest"},
{"name": "nvdiffrast", "tag": "nvdiffrast-latest"},
{"name": "nvdiffrec-render", "tag": "nvdiffrec_render-latest"},
{"name": "o-voxel", "tag": "o_voxel-latest"},
]
print("\nInstalling CUDA wheels...")
errors_occurred = False
for pkg in packages:
print(f"Installing {pkg['name']}...")
wheel_url = find_wheel_url(pkg['name'], env)
if wheel_url:
print(f" Found matching wheel: {wheel_url}")
if args.dry_run:
print(f" [Dry Run] Would run: {' '.join(pip_base + ['install', wheel_url])}")
else:
if not run_command(pip_base + ["install", wheel_url]):
print(f"Warning: Failed to install {pkg['name']}.")
errors_occurred = True
else:
print(f" Warning: No matching {pkg['name']} wheel found in the index.")
errors_occurred = True
if errors_occurred:
show_recommendations()
print("\nInstallation complete!")
if __name__ == "__main__":
install()