diff --git a/README.md b/README.md index ccda1c6..4b67414 100644 --- a/README.md +++ b/README.md @@ -56,43 +56,46 @@ choco install ffmpeg scoop install ffmpeg ``` -### NVIDIA GPU support -To Install the package with CUDA support, make sure you have [cuda](https://developer.nvidia.com/cuda-downloads) installed and use `GGML_CUDA=1`: +### Hardware Acceleration -```shell -GGML_CUDA=1 pip install git+https://github.com/absadiki/pywhispercpp -``` -### CoreML support - -Install the package with `WHISPER_COREML=1`: +To build with hardware acceleration support, use the `--config-settings` flag: +#### NVIDIA GPU (CUDA) +Requires [CUDA toolkit](https://developer.nvidia.com/cuda-downloads) installed. ```shell -WHISPER_COREML=1 pip install git+https://github.com/absadiki/pywhispercpp -``` +# With pip +pip install git+https://github.com/absadiki/pywhispercpp --config-settings="accel=cuda" -### Vulkan support +# With uv +uv add git+https://github.com/absadiki/pywhispercpp -Caccel=cuda -Install the package with `GGML_VULKAN=1`: +# Local install +pip install . --config-settings="accel=cuda" +``` +#### CoreML (Apple Silicon) ```shell -GGML_VULKAN=1 pip install git+https://github.com/absadiki/pywhispercpp +pip install git+https://github.com/absadiki/pywhispercpp --config-settings="accel=coreml" ``` -### OpenBLAS support - -If OpenBLAS is installed, you can use `GGML_BLAS=1`. The other flags ensure you're installing fresh with the correct flags, and printing output for sanity checking. +#### Vulkan ```shell -GGML_BLAS=1 pip install git+https://github.com/absadiki/pywhispercpp --no-cache --force-reinstall -v +pip install git+https://github.com/absadiki/pywhispercpp --config-settings="accel=vulkan" ``` -### OpenVINO support +#### OpenBLAS +Requires OpenBLAS to be installed on your system. +```shell +pip install git+https://github.com/absadiki/pywhispercpp --config-settings="accel=openblas" +``` -Follow the the steps to download correct OpenVINO package (https://github.com/ggerganov/whisper.cpp?tab=readme-ov-file#openvino-support). +#### OpenVINO +Follow the steps to download correct OpenVINO package from [whisper.cpp OpenVINO docs](https://github.com/ggerganov/whisper.cpp?tab=readme-ov-file#openvino-support). -Then init the OpenVINO environment and build. -``` +Then initialize the OpenVINO environment and build: +```shell source ~/l_openvino_toolkit_ubuntu22_2023.0.0.10926.b4452d56304_x86_64/setupvars.sh -WHISPER_OPENVINO=1 pip install git+https://github.com/absadiki/pywhispercpp --no-cache --force-reinstall +pip install git+https://github.com/absadiki/pywhispercpp --config-settings="accel=openvino" ``` Note that the toolkit for Ubuntu22 works on Ubuntu24 diff --git a/backend.py b/backend.py new file mode 100644 index 0000000..402933d --- /dev/null +++ b/backend.py @@ -0,0 +1,59 @@ +"""Custom PEP 517 build backend that handles config settings for acceleration.""" + +import os +from setuptools import build_meta as _orig + +# Re-export everything from setuptools +__all__ = _orig.__all__ + +def build_wheel(wheel_directory, config_settings=None, metadata_directory=None): + """Build wheel with config_settings support for acceleration and repair options.""" + + if config_settings: + # Handle uv -C flag format: -Caccel=cuda, -Crepair=false, etc. + for key, value in config_settings.items(): + if key == 'accel': + # Handle acceleration options + if isinstance(value, str): + value = [value] + elif not isinstance(value, list): + value = [str(value)] + + for accel in value: + accel = accel.lower() + if 'cuda' in accel: + os.environ['GGML_CUDA'] = '1' + print("Enabling CUDA support via config-settings") + elif 'coreml' in accel: + os.environ['WHISPER_COREML'] = '1' + os.environ['WHISPER_COREML_ALLOW_FALLBACK'] = '1' + print("Enabling CoreML support via config-settings") + elif 'vulkan' in accel: + os.environ['GGML_VULKAN'] = '1' + print("Enabling Vulkan support via config-settings") + elif 'openblas' in accel or 'blas' in accel: + os.environ['GGML_BLAS'] = '1' + print("Enabling OpenBLAS support via config-settings") + + elif key == 'repair': + # Handle repair option + if str(value).lower() in ['false', '0', 'no', 'off']: + os.environ['NO_REPAIR'] = '1' + print("Disabling wheel repair via config-settings") + elif str(value).lower() in ['true', '1', 'yes', 'on']: + os.environ.pop('NO_REPAIR', None) + print("Enabling wheel repair via config-settings") + + # Remove our custom options before passing to setuptools + # setuptools doesn't understand them and will error + cleaned_settings = {k: v for k, v in config_settings.items() + if k not in ['accel', 'repair']} + config_settings = cleaned_settings if cleaned_settings else None + + return _orig.build_wheel(wheel_directory, config_settings, metadata_directory) + +# Re-export other functions +build_sdist = _orig.build_sdist +prepare_metadata_for_build_wheel = _orig.prepare_metadata_for_build_wheel +get_requires_for_build_wheel = _orig.get_requires_for_build_wheel +get_requires_for_build_sdist = _orig.get_requires_for_build_sdist \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index fa6b22a..7883b4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,8 @@ requires = [ "repairwheel", "setuptools-scm>=8" ] -build-backend = "setuptools.build_meta" +build-backend = "backend" +backend-path = ["."] [tool.mypy] files = "setup.py" diff --git a/setup.py b/setup.py index d13545f..9e95239 100644 --- a/setup.py +++ b/setup.py @@ -67,6 +67,7 @@ def build_extension(self, ext: CMakeExtension) -> None: cmake_args = [ f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extdir}{os.sep}", f"-DPYTHON_EXECUTABLE={sys.executable}", + f"-DPython_EXECUTABLE={sys.executable}", # Alternative Python executable setting f"-DCMAKE_BUILD_TYPE={cfg}", # not used on MSVC, but no harm ] if self.editable_mode: @@ -149,9 +150,35 @@ def build_extension(self, ext: CMakeExtension) -> None: build_temp = Path(self.build_temp) / ext.name if not build_temp.exists(): build_temp.mkdir(parents=True) - + else: + # Clean up any corrupted CMake cache files + cmake_cache = build_temp / "CMakeCache.txt" + if cmake_cache.exists(): + try: + cmake_cache.unlink() + print("Removed corrupted CMakeCache.txt") + except Exception as e: + print(f"Warning: Could not remove CMakeCache.txt: {e}") + + # Only pass specific environment variables that are safe for CMake + # and relevant to the build process + safe_env_vars = [ + 'GGML_CUDA', 'GGML_VULKAN', 'GGML_BLAS', 'GGML_OPENBLAS', + 'WHISPER_COREML', 'WHISPER_COREML_ALLOW_FALLBACK', + 'CMAKE_BUILD_PARALLEL_LEVEL', 'CMAKE_GENERATOR', + 'CMAKE_ARGS', 'DEBUG', 'VERBOSE' + ] + for key, value in os.environ.items(): - cmake_args.append(f'-D{key}={value}') + # Only pass safe environment variables that don't contain problematic characters + if (key in safe_env_vars and + value and + '\n' not in value and + '\r' not in value and + not key.startswith('FZF_') and + not key.startswith('PS1') and + not key.startswith('PROMPT')): + cmake_args.append(f'-D{key}={value}') subprocess.run( ["cmake", ext.sourcedir, *cmake_args], cwd=build_temp, check=True diff --git a/whisper.cpp b/whisper.cpp index a8d002c..5904d00 160000 --- a/whisper.cpp +++ b/whisper.cpp @@ -1 +1 @@ -Subproject commit a8d002cfd879315632a579e73f0148d06959de36 +Subproject commit 5904d00dbb5a5cfc7e27fefa727f79509f6cd37d