Skip to content

Commit 0c96c49

Browse files
make it work on Windows
1 parent a5fd099 commit 0c96c49

4 files changed

Lines changed: 105 additions & 9 deletions

File tree

‎CMakeLists.txt‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,13 @@ target_link_libraries(engine_runtime PUBLIC ggml)
559559
target_link_libraries(engine_runtime PRIVATE sentencepiece cjson_vendor yaml_vendor)
560560
if (ENGINE_ENABLE_OPENMP)
561561
target_link_libraries(engine_runtime PRIVATE OpenMP::OpenMP_CXX)
562+
if (MSVC)
563+
# MSVC's default /openmp implements only OpenMP 2.0 and rejects the
564+
# '#pragma omp simd' directives in longformer_attention.cpp (error C7660).
565+
# /openmp:experimental enables the OpenMP 4.0 SIMD support; it overrides the
566+
# /openmp added by OpenMP::OpenMP_CXX above (harmless D9025 override notice).
567+
target_compile_options(engine_runtime PRIVATE /openmp:experimental)
568+
endif()
562569
endif()
563570
564571
if (ENGINE_ENABLE_CUDA)

‎_env.bat‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
@echo off
2+
REM _env.bat -- shared environment detection for the audio.cpp .bat launchers.
3+
REM Called (not run) by run_webui.bat / run_server.bat / run_cli_tts.bat. It sets
4+
REM common variables and deliberately does NOT use setlocal, so they propagate back
5+
REM to the caller. Change detection logic here only.
6+
REM
7+
REM Exports: ROOT BUNDLE WEBUI_DIR PY HAS_CUDA BACKEND SERVER_EXE CLI_EXE GGUF_EXE
8+
9+
REM --- ROOT = this script's directory, without the trailing backslash ---
10+
set "ROOT=%~dp0"
11+
if "%ROOT:~-1%"=="\" set "ROOT=%ROOT:~0,-1%"
12+
13+
REM Dev tree: the repo root doubles as the bundle (models\ live under it; the
14+
REM binaries live under build\). webui.py's own _find_bundle_root handles this.
15+
set "BUNDLE=%ROOT%"
16+
set "WEBUI_DIR=%ROOT%\webui"
17+
18+
REM --- Python with the deps (gradio/requests/torch/safetensors/opencc/...) ---
19+
REM Order: explicit override, project venv (Scripts\ on Windows), then a bundle venv.
20+
set "PY="
21+
if defined AUDIOCPP_PYTHON if exist "%AUDIOCPP_PYTHON%" set "PY=%AUDIOCPP_PYTHON%"
22+
if not defined PY if exist "%ROOT%\venv\Scripts\python.exe" set "PY=%ROOT%\venv\Scripts\python.exe"
23+
if not defined PY if exist "%ROOT%\venv\python.exe" set "PY=%ROOT%\venv\python.exe"
24+
if not defined PY if exist "%BUNDLE%\venv\Scripts\python.exe" set "PY=%BUNDLE%\venv\Scripts\python.exe"
25+
if not defined PY if exist "%BUNDLE%\venv\python.exe" set "PY=%BUNDLE%\venv\python.exe"
26+
27+
REM --- CUDA present? (NVIDIA driver installs nvcuda.dll in System32) ---
28+
set "HAS_CUDA="
29+
if exist "%SystemRoot%\System32\nvcuda.dll" set "HAS_CUDA=1"
30+
31+
REM --- Locate the from-source binaries. The default Visual Studio generator nests
32+
REM them in build\bin\Release (multi-config); Ninja/Makefiles use build\bin. ---
33+
set "BIN="
34+
if exist "%ROOT%\build\bin\Release\audiocpp_server.exe" set "BIN=%ROOT%\build\bin\Release"
35+
if not defined BIN if exist "%ROOT%\build\bin\audiocpp_server.exe" set "BIN=%ROOT%\build\bin"
36+
if defined BIN set "SERVER_EXE=%BIN%\audiocpp_server.exe"
37+
if defined BIN set "CLI_EXE=%BIN%\audiocpp_cli.exe"
38+
if defined BIN set "GGUF_EXE=%BIN%\audiocpp_gguf.exe"
39+
40+
REM --- BACKEND: read the actual build's GGML_CUDA flag from its CMakeCache, so we
41+
REM never advertise a GPU backend a CPU-only build can't serve. cuda when ON, else cpu. ---
42+
set "BACKEND=cpu"
43+
if exist "%ROOT%\build\CMakeCache.txt" (
44+
for /f "tokens=2 delims==" %%A in ('findstr /b /c:"GGML_CUDA:BOOL" "%ROOT%\build\CMakeCache.txt" 2^>nul') do (
45+
if /I "%%A"=="ON" set "BACKEND=cuda"
46+
)
47+
)

‎tools/model_manager.py‎

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,41 @@
3232
yaml: Any = None
3333

3434

35+
def _ensure_download_deps() -> None:
36+
"""Import only what a plain snapshot/file download needs: huggingface_hub + yaml.
37+
38+
Downloading model weights must not require Torch — importing Torch pulls in
39+
native DLLs (c10.dll etc.) that can fail to load in some environments (e.g. a
40+
conda-based interpreter on Windows), which would needlessly block downloads for
41+
models whose loading/inference happens entirely in the C++ server."""
42+
global hf_hub_download, yaml
43+
if hf_hub_download is not None:
44+
return
45+
from huggingface_hub import hf_hub_download as _hf_hub_download
46+
import yaml as _yaml
47+
48+
hf_hub_download = _hf_hub_download
49+
yaml = _yaml
50+
51+
3552
def _ensure_install_deps() -> None:
36-
"""Import Torch / huggingface_hub / safetensors / yaml on first install/convert use."""
53+
"""Import Torch / huggingface_hub / safetensors / yaml on first install/convert use.
54+
55+
Only needed for conversion (torch.load / safetensors round-trips). Snapshot
56+
downloads should call _ensure_download_deps() instead, so they don't drag in Torch."""
3757
global torch, hf_hub_download, safe_open, load_file, save_file, yaml
3858
if torch is not None:
3959
return
60+
_ensure_download_deps()
4061
import torch as _torch
41-
from huggingface_hub import hf_hub_download as _hf_hub_download
4262
from safetensors import safe_open as _safe_open
4363
from safetensors.torch import load_file as _load_file
4464
from safetensors.torch import save_file as _save_file
45-
import yaml as _yaml
4665

4766
torch = _torch
48-
hf_hub_download = _hf_hub_download
4967
safe_open = _safe_open
5068
load_file = _load_file
5169
save_file = _save_file
52-
yaml = _yaml
5370

5471

5572
REPO_ROOT = Path(__file__).resolve().parents[1]
@@ -2661,7 +2678,6 @@ def command_info(args: argparse.Namespace) -> int:
26612678

26622679

26632680
def command_install(args: argparse.Namespace) -> int:
2664-
_ensure_install_deps()
26652681
package = PACKAGE_BY_ID.get(args.package_id)
26662682
if package is None:
26672683
raise RuntimeError(f"unknown package id: {args.package_id}")
@@ -2671,10 +2687,15 @@ def command_install(args: argparse.Namespace) -> int:
26712687
if isinstance(source, UnsupportedSource):
26722688
raise RuntimeError(f"{package.id} is not installable: {source.reason}")
26732689
if isinstance(source, SnapshotSource):
2690+
# Plain download: huggingface_hub only, no Torch DLLs.
2691+
_ensure_download_deps()
26742692
install_path = install_snapshot(package, source, models_root, args.overwrite)
26752693
elif isinstance(source, CompositeSnapshotSource):
2694+
# Composite snapshots may run a Torch post-process step, so bring in full deps.
2695+
_ensure_install_deps()
26762696
install_path = install_composite_snapshot(package, source, models_root, args.overwrite)
26772697
else:
2698+
_ensure_install_deps()
26782699
install_path = install_converter(
26792700
package,
26802701
source,

‎webui/webui.py‎

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,22 @@ def _cmake_cache_backend(bin_dir):
215215
"""gpu/cpu for a build tree whose directory name doesn't say, read from its
216216
CMakeCache.txt (GGML_CUDA:BOOL=ON). Returns None when there is no cache to
217217
read — an installed tree, or a layout we don't recognize."""
218-
cache = os.path.join(os.path.dirname(bin_dir), "CMakeCache.txt")
218+
# Walk up from the bin dir to find the build tree's CMakeCache.txt. Single-config
219+
# generators put the exe in build/bin (cache one level up); multi-config ones
220+
# (Visual Studio) nest it in build/bin/Release, so the cache sits two levels up.
221+
cache = None
222+
d = os.path.dirname(bin_dir)
223+
for _ in range(4):
224+
cand = os.path.join(d, "CMakeCache.txt")
225+
if os.path.isfile(cand):
226+
cache = cand
227+
break
228+
parent = os.path.dirname(d)
229+
if parent == d:
230+
break
231+
d = parent
232+
if cache is None:
233+
return None
219234
try:
220235
with open(cache, encoding="utf-8", errors="replace") as fh:
221236
for line in fh:
@@ -240,8 +255,14 @@ def _discover_dev_bin_dirs():
240255
if os.path.isfile(os.path.join(d, SERVER_EXE_NAME)))
241256
if hits:
242257
out[backend] = hits[-1]
243-
plain = os.path.join(PROJECT_ROOT, "build", "bin")
244-
if os.path.isfile(os.path.join(plain, SERVER_EXE_NAME)):
258+
# A plain `cmake -B build` lands in build/bin with single-config generators
259+
# (Ninja, Makefiles); multi-config generators (Visual Studio, Xcode) nest the
260+
# exe in a per-config subdir, so also look in build/bin/Release and .../Debug.
261+
for plain in (os.path.join(PROJECT_ROOT, "build", "bin"),
262+
os.path.join(PROJECT_ROOT, "build", "bin", "Release"),
263+
os.path.join(PROJECT_ROOT, "build", "bin", "Debug")):
264+
if not os.path.isfile(os.path.join(plain, SERVER_EXE_NAME)):
265+
continue
245266
backend = _cmake_cache_backend(plain)
246267
# Only fill a backend the named-directory scan didn't already find, so an
247268
# explicit build/linux-cuda-release still wins over a stale plain build/.

0 commit comments

Comments
 (0)