Skip to content

Commit 50f6445

Browse files
committed
Add hardware acceleration support via config-settings
- Implement custom PEP 517 build backend to handle acceleration options - Support CUDA, CoreML, Vulkan, OpenBLAS, and OpenVINO via --config-settings - Usage: pip install . --config-settings="accel=cuda" or uv add . -Caccel=cuda - Add wheel repair control via config-settings (repair=false to disable) - Improve CMake build robustness: - Clean corrupted CMake cache files automatically - Filter environment variables to only pass safe, relevant ones - Add alternative Python executable setting for better compatibility - Update README with unified hardware acceleration documentation - Remove legacy environment variable approach in favor of config-settings
1 parent f6ae8b0 commit 50f6445

4 files changed

Lines changed: 115 additions & 25 deletions

File tree

README.md

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -56,43 +56,46 @@ choco install ffmpeg
5656
scoop install ffmpeg
5757
```
5858

59-
### NVIDIA GPU support
60-
To Install the package with CUDA support, make sure you have [cuda](https://developer.nvidia.com/cuda-downloads) installed and use `GGML_CUDA=1`:
59+
### Hardware Acceleration
6160

62-
```shell
63-
GGML_CUDA=1 pip install git+https://github.com/absadiki/pywhispercpp
64-
```
65-
### CoreML support
66-
67-
Install the package with `WHISPER_COREML=1`:
61+
To build with hardware acceleration support, use the `--config-settings` flag:
6862

63+
#### NVIDIA GPU (CUDA)
64+
Requires [CUDA toolkit](https://developer.nvidia.com/cuda-downloads) installed.
6965
```shell
70-
WHISPER_COREML=1 pip install git+https://github.com/absadiki/pywhispercpp
71-
```
66+
# With pip
67+
pip install git+https://github.com/absadiki/pywhispercpp --config-settings="accel=cuda"
7268

73-
### Vulkan support
69+
# With uv
70+
uv add git+https://github.com/absadiki/pywhispercpp -Caccel=cuda
7471

75-
Install the package with `GGML_VULKAN=1`:
72+
# Local install
73+
pip install . --config-settings="accel=cuda"
74+
```
7675

76+
#### CoreML (Apple Silicon)
7777
```shell
78-
GGML_VULKAN=1 pip install git+https://github.com/absadiki/pywhispercpp
78+
pip install git+https://github.com/absadiki/pywhispercpp --config-settings="accel=coreml"
7979
```
8080

81-
### OpenBLAS support
82-
83-
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.
81+
#### Vulkan
8482
```shell
85-
GGML_BLAS=1 pip install git+https://github.com/absadiki/pywhispercpp --no-cache --force-reinstall -v
83+
pip install git+https://github.com/absadiki/pywhispercpp --config-settings="accel=vulkan"
8684
```
8785

88-
### OpenVINO support
86+
#### OpenBLAS
87+
Requires OpenBLAS to be installed on your system.
88+
```shell
89+
pip install git+https://github.com/absadiki/pywhispercpp --config-settings="accel=openblas"
90+
```
8991

90-
Follow the the steps to download correct OpenVINO package (https://github.com/ggerganov/whisper.cpp?tab=readme-ov-file#openvino-support).
92+
#### OpenVINO
93+
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).
9194

92-
Then init the OpenVINO environment and build.
93-
```
95+
Then initialize the OpenVINO environment and build:
96+
```shell
9497
source ~/l_openvino_toolkit_ubuntu22_2023.0.0.10926.b4452d56304_x86_64/setupvars.sh
95-
WHISPER_OPENVINO=1 pip install git+https://github.com/absadiki/pywhispercpp --no-cache --force-reinstall
98+
pip install git+https://github.com/absadiki/pywhispercpp --config-settings="accel=openvino"
9699
```
97100

98101
Note that the toolkit for Ubuntu22 works on Ubuntu24

backend.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""Custom PEP 517 build backend that handles config settings for acceleration."""
2+
3+
import os
4+
from setuptools import build_meta as _orig
5+
6+
# Re-export everything from setuptools
7+
__all__ = _orig.__all__
8+
9+
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
10+
"""Build wheel with config_settings support for acceleration and repair options."""
11+
12+
if config_settings:
13+
# Handle uv -C flag format: -Caccel=cuda, -Crepair=false, etc.
14+
for key, value in config_settings.items():
15+
if key == 'accel':
16+
# Handle acceleration options
17+
if isinstance(value, str):
18+
value = [value]
19+
elif not isinstance(value, list):
20+
value = [str(value)]
21+
22+
for accel in value:
23+
accel = accel.lower()
24+
if 'cuda' in accel:
25+
os.environ['GGML_CUDA'] = '1'
26+
print("Enabling CUDA support via config-settings")
27+
elif 'coreml' in accel:
28+
os.environ['WHISPER_COREML'] = '1'
29+
os.environ['WHISPER_COREML_ALLOW_FALLBACK'] = '1'
30+
print("Enabling CoreML support via config-settings")
31+
elif 'vulkan' in accel:
32+
os.environ['GGML_VULKAN'] = '1'
33+
print("Enabling Vulkan support via config-settings")
34+
elif 'openblas' in accel or 'blas' in accel:
35+
os.environ['GGML_BLAS'] = '1'
36+
print("Enabling OpenBLAS support via config-settings")
37+
38+
elif key == 'repair':
39+
# Handle repair option
40+
if str(value).lower() in ['false', '0', 'no', 'off']:
41+
os.environ['NO_REPAIR'] = '1'
42+
print("Disabling wheel repair via config-settings")
43+
elif str(value).lower() in ['true', '1', 'yes', 'on']:
44+
os.environ.pop('NO_REPAIR', None)
45+
print("Enabling wheel repair via config-settings")
46+
47+
# Remove our custom options before passing to setuptools
48+
# setuptools doesn't understand them and will error
49+
cleaned_settings = {k: v for k, v in config_settings.items()
50+
if k not in ['accel', 'repair']}
51+
config_settings = cleaned_settings if cleaned_settings else None
52+
53+
return _orig.build_wheel(wheel_directory, config_settings, metadata_directory)
54+
55+
# Re-export other functions
56+
build_sdist = _orig.build_sdist
57+
prepare_metadata_for_build_wheel = _orig.prepare_metadata_for_build_wheel
58+
get_requires_for_build_wheel = _orig.get_requires_for_build_wheel
59+
get_requires_for_build_sdist = _orig.get_requires_for_build_sdist

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ requires = [
77
"repairwheel",
88
"setuptools-scm>=8"
99
]
10-
build-backend = "setuptools.build_meta"
10+
build-backend = "backend"
11+
backend-path = ["."]
1112

1213
[tool.mypy]
1314
files = "setup.py"

setup.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def build_extension(self, ext: CMakeExtension) -> None:
6767
cmake_args = [
6868
f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extdir}{os.sep}",
6969
f"-DPYTHON_EXECUTABLE={sys.executable}",
70+
f"-DPython_EXECUTABLE={sys.executable}", # Alternative Python executable setting
7071
f"-DCMAKE_BUILD_TYPE={cfg}", # not used on MSVC, but no harm
7172
]
7273
if self.editable_mode:
@@ -149,9 +150,35 @@ def build_extension(self, ext: CMakeExtension) -> None:
149150
build_temp = Path(self.build_temp) / ext.name
150151
if not build_temp.exists():
151152
build_temp.mkdir(parents=True)
152-
153+
else:
154+
# Clean up any corrupted CMake cache files
155+
cmake_cache = build_temp / "CMakeCache.txt"
156+
if cmake_cache.exists():
157+
try:
158+
cmake_cache.unlink()
159+
print("Removed corrupted CMakeCache.txt")
160+
except Exception as e:
161+
print(f"Warning: Could not remove CMakeCache.txt: {e}")
162+
163+
# Only pass specific environment variables that are safe for CMake
164+
# and relevant to the build process
165+
safe_env_vars = [
166+
'GGML_CUDA', 'GGML_VULKAN', 'GGML_BLAS', 'GGML_OPENBLAS',
167+
'WHISPER_COREML', 'WHISPER_COREML_ALLOW_FALLBACK',
168+
'CMAKE_BUILD_PARALLEL_LEVEL', 'CMAKE_GENERATOR',
169+
'CMAKE_ARGS', 'DEBUG', 'VERBOSE'
170+
]
171+
153172
for key, value in os.environ.items():
154-
cmake_args.append(f'-D{key}={value}')
173+
# Only pass safe environment variables that don't contain problematic characters
174+
if (key in safe_env_vars and
175+
value and
176+
'\n' not in value and
177+
'\r' not in value and
178+
not key.startswith('FZF_') and
179+
not key.startswith('PS1') and
180+
not key.startswith('PROMPT')):
181+
cmake_args.append(f'-D{key}={value}')
155182

156183
subprocess.run(
157184
["cmake", ext.sourcedir, *cmake_args], cwd=build_temp, check=True

0 commit comments

Comments
 (0)