Sync from v0.13
This commit is contained in:
180
tools/generate_cmake_presets.py
Normal file
180
tools/generate_cmake_presets.py
Normal file
@@ -0,0 +1,180 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
import argparse
|
||||
import json
|
||||
import multiprocessing
|
||||
import os
|
||||
import sys
|
||||
from shutil import which
|
||||
|
||||
try:
|
||||
# Try to get CUDA_HOME from PyTorch installation, which is the
|
||||
# most reliable source of truth for vLLM's build.
|
||||
from torch.utils.cpp_extension import CUDA_HOME
|
||||
except ImportError:
|
||||
print("Warning: PyTorch not found. Falling back to CUDA_HOME environment variable.")
|
||||
CUDA_HOME = os.environ.get("CUDA_HOME")
|
||||
|
||||
|
||||
def get_python_executable():
|
||||
"""Get the current Python executable, which is used to run this script."""
|
||||
return sys.executable
|
||||
|
||||
|
||||
def get_cpu_cores():
|
||||
"""Get the number of CPU cores."""
|
||||
return multiprocessing.cpu_count()
|
||||
|
||||
|
||||
def generate_presets(output_path="CMakeUserPresets.json", force_overwrite=False):
|
||||
"""Generates the CMakeUserPresets.json file."""
|
||||
|
||||
print("Attempting to detect your system configuration...")
|
||||
|
||||
# Detect NVCC
|
||||
nvcc_path = None
|
||||
if CUDA_HOME:
|
||||
prospective_path = os.path.join(CUDA_HOME, "bin", "nvcc")
|
||||
if os.path.exists(prospective_path):
|
||||
nvcc_path = prospective_path
|
||||
print(f"Found nvcc via torch.utils.cpp_extension.CUDA_HOME: {nvcc_path}")
|
||||
|
||||
if not nvcc_path:
|
||||
nvcc_path = which("nvcc")
|
||||
if nvcc_path:
|
||||
print(f"Found nvcc in PATH: {nvcc_path}")
|
||||
|
||||
if not nvcc_path:
|
||||
nvcc_path_input = input(
|
||||
"Could not automatically find 'nvcc'. Please provide the full "
|
||||
"path to nvcc (e.g., /usr/local/cuda/bin/nvcc): "
|
||||
)
|
||||
nvcc_path = nvcc_path_input.strip()
|
||||
print(f"Using NVCC path: {nvcc_path}")
|
||||
|
||||
# Detect Python executable
|
||||
python_executable = get_python_executable()
|
||||
if python_executable:
|
||||
print(f"Found Python via sys.executable: {python_executable}")
|
||||
else:
|
||||
python_executable_prompt = (
|
||||
"Could not automatically find Python executable. Please provide "
|
||||
"the full path to your Python executable for vLLM development "
|
||||
"(typically from your virtual environment, e.g., "
|
||||
"/home/user/venvs/vllm/bin/python): "
|
||||
)
|
||||
python_executable = input(python_executable_prompt).strip()
|
||||
if not python_executable:
|
||||
raise ValueError(
|
||||
"Could not determine Python executable. Please provide it manually."
|
||||
)
|
||||
|
||||
print(f"Using Python executable: {python_executable}")
|
||||
|
||||
# Get CPU cores
|
||||
cpu_cores = get_cpu_cores()
|
||||
nvcc_threads = min(4, cpu_cores)
|
||||
cmake_jobs = max(1, cpu_cores // nvcc_threads)
|
||||
print(
|
||||
f"Detected {cpu_cores} CPU cores. "
|
||||
f"Setting NVCC_THREADS={nvcc_threads} and CMake jobs={cmake_jobs}."
|
||||
)
|
||||
|
||||
# Get vLLM project root (assuming this script is in vllm/tools/)
|
||||
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
print(f"VLLM project root detected as: {project_root}")
|
||||
|
||||
# Ensure python_executable path is absolute or resolvable
|
||||
if not os.path.isabs(python_executable) and which(python_executable):
|
||||
python_executable = os.path.abspath(which(python_executable))
|
||||
elif not os.path.isabs(python_executable):
|
||||
print(
|
||||
f"Warning: Python executable '{python_executable}' is not an "
|
||||
"absolute path and not found in PATH. CMake might not find it."
|
||||
)
|
||||
|
||||
cache_variables = {
|
||||
"CMAKE_CUDA_COMPILER": nvcc_path,
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"VLLM_PYTHON_EXECUTABLE": python_executable,
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}",
|
||||
"CMAKE_CUDA_FLAGS": "",
|
||||
"NVCC_THREADS": str(nvcc_threads),
|
||||
}
|
||||
|
||||
# Detect compiler cache
|
||||
if which("sccache"):
|
||||
print("Using sccache for compiler caching.")
|
||||
for launcher in ("C", "CXX", "CUDA", "HIP"):
|
||||
cache_variables[f"CMAKE_{launcher}_COMPILER_LAUNCHER"] = "sccache"
|
||||
elif which("ccache"):
|
||||
print("Using ccache for compiler caching.")
|
||||
for launcher in ("C", "CXX", "CUDA", "HIP"):
|
||||
cache_variables[f"CMAKE_{launcher}_COMPILER_LAUNCHER"] = "ccache"
|
||||
else:
|
||||
print("No compiler cache ('ccache' or 'sccache') found.")
|
||||
|
||||
configure_preset = {
|
||||
"name": "release",
|
||||
"binaryDir": "${sourceDir}/cmake-build-release",
|
||||
"cacheVariables": cache_variables,
|
||||
}
|
||||
if which("ninja"):
|
||||
print("Using Ninja generator.")
|
||||
configure_preset["generator"] = "Ninja"
|
||||
cache_variables["CMAKE_JOB_POOLS"] = f"compile={cmake_jobs}"
|
||||
else:
|
||||
print("Ninja not found, using default generator. Build may be slower.")
|
||||
|
||||
presets = {
|
||||
"version": 6,
|
||||
# Keep in sync with CMakeLists.txt and requirements/build.txt
|
||||
"cmakeMinimumRequired": {"major": 3, "minor": 26, "patch": 1},
|
||||
"configurePresets": [configure_preset],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "release",
|
||||
"configurePreset": "release",
|
||||
"jobs": cmake_jobs,
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
output_file_path = os.path.join(project_root, output_path)
|
||||
|
||||
if os.path.exists(output_file_path):
|
||||
if force_overwrite:
|
||||
print(f"Overwriting existing file '{output_file_path}'")
|
||||
else:
|
||||
overwrite = (
|
||||
input(f"'{output_file_path}' already exists. Overwrite? (y/N): ")
|
||||
.strip()
|
||||
.lower()
|
||||
)
|
||||
if overwrite != "y":
|
||||
print("Generation cancelled.")
|
||||
return
|
||||
|
||||
try:
|
||||
with open(output_file_path, "w") as f:
|
||||
json.dump(presets, f, indent=4)
|
||||
print(f"Successfully generated '{output_file_path}'")
|
||||
print("\nTo use this preset:")
|
||||
print(f"1. Ensure you are in the vLLM root directory: cd {project_root}")
|
||||
print("2. Initialize CMake: cmake --preset release")
|
||||
print("3. Build+install: cmake --build --preset release --target install")
|
||||
|
||||
except OSError as e:
|
||||
print(f"Error writing file: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--force-overwrite",
|
||||
action="store_true",
|
||||
help="Force overwrite existing CMakeUserPresets.json without prompting",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
generate_presets(force_overwrite=args.force_overwrite)
|
||||
Reference in New Issue
Block a user