aboutsummaryrefslogtreecommitdiff
path: root/app/backends/audiocpp/build.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-28 16:52:14 -0400
committerhistoria <historiavg@proton.me>2026-08-28 16:52:14 -0400
commit270fa60c01866c4431d540be960b6cd2bc2b9c44 (patch)
tree7e5b682472622634d78226479c2f1526a6efc1d3 /app/backends/audiocpp/build.py
parentdb38085d07ce75f8961eecdc1919e98748254c53 (diff)
downloadtts-audiobook-generator-270fa60c01866c4431d540be960b6cd2bc2b9c44.tar.gz
feat: run auto-build audio.cpp scripts for macos and windows
Diffstat (limited to 'app/backends/audiocpp/build.py')
-rw-r--r--app/backends/audiocpp/build.py91
1 files changed, 77 insertions, 14 deletions
diff --git a/app/backends/audiocpp/build.py b/app/backends/audiocpp/build.py
index 1ad6018..22d2fa1 100644
--- a/app/backends/audiocpp/build.py
+++ b/app/backends/audiocpp/build.py
@@ -6,6 +6,7 @@ import os
import re
import shlex
import shutil
+import sys
from pathlib import Path
from typing import List, Optional
@@ -232,17 +233,37 @@ def built_server_binary(audiocpp_dir: Path, backend: str) -> Optional[Path]:
return None
-def find_build_script(audiocpp_dir: Path) -> Optional[Path]:
+def find_build_script(audiocpp_dir: Path,
+ backend: Optional[str] = None) -> Optional[Path]:
"""Return the audio.cpp build helper script to run, or None.
- Prefers ``scripts/build_linux.sh``; otherwise the first
- ``scripts/build_*.sh`` it finds. (Windows ``.bat`` scripts are not run
- automatically — build manually there.)
+ Platform-aware, because audio.cpp ships one helper per platform: macOS
+ builds through ``scripts/build_metal.sh`` (Metal is the only buildable
+ inference backend there, recorded as ``cpu``), Windows through
+ ``scripts/build_windows.ps1`` — or ``scripts/build_windows_hip.ps1``
+ when BACKEND is ``hip`` — and every other platform through
+ ``scripts/build_linux.sh``. The first ``scripts/build_*.sh`` found is
+ the fallback for the shell-script platforms, so a fork that renamed the
+ helper still builds.
+
+ Running the Windows scripts is supported: they are driven through
+ ``powershell.exe`` (stock Windows PowerShell 5.1, present on every
+ Windows 10/11 install) with ``-ExecutionPolicy Bypass``. BACKEND is
+ only consulted on Windows (HIP uses its own script); on other platforms
+ it is ignored.
"""
scripts = audiocpp_dir / "scripts"
if not scripts.is_dir():
return None
- preferred = scripts / "build_linux.sh"
+ if sys.platform == "win32":
+ name = ("build_windows_hip.ps1" if backend == "hip"
+ else "build_windows.ps1")
+ candidate = scripts / name
+ return candidate if candidate.exists() else None
+ if sys.platform == "darwin":
+ preferred = scripts / "build_metal.sh"
+ else:
+ preferred = scripts / "build_linux.sh"
if preferred.exists():
return preferred
try:
@@ -318,15 +339,21 @@ def detect_cuda_arch() -> Optional[str]:
def _cuda_arch_argv(backend: str, emit=None) -> List[str]:
- """The ``--cuda-arch`` flags for a CUDA build, plus a status line.
+ """The CUDA-architecture flags for a CUDA build, plus a status line.
EMIT is the in-TUI line sink when building from the task view (the
line lands in the view, not the real terminal behind curses); without
it the line prints to the console. Detection failure is not an error:
the build then uses audio.cpp's portable default arch list, which is
slower to compile but runs on any GPU.
+
+ The flag name follows the platform's helper script: ``--cuda-arch`` for
+ ``build_linux.sh``, ``-CudaArchitectures`` for ``build_windows.ps1``
+ (both accept a ';'-separated compute-capability list verbatim). macOS
+ builds are Metal-only — ``build_metal.sh`` takes no arch flags — so a
+ stray CUDA backend there gets no flags.
"""
- if backend != "cuda":
+ if backend != "cuda" or sys.platform == "darwin":
return []
arch = detect_cuda_arch()
say = emit if emit is not None else print
@@ -335,9 +362,10 @@ def _cuda_arch_argv(backend: str, emit=None) -> List[str]:
f"detect a GPU; set {CUDA_ARCH_ENV}=<arch> to build only for "
"this machine's GPU — much faster)")
return []
+ flag = "-CudaArchitectures" if sys.platform == "win32" else "--cuda-arch"
say(f"[INFO] CUDA architecture: {arch} (detected via nvidia-smi; "
f"override with {CUDA_ARCH_ENV})")
- return ["--cuda-arch", arch]
+ return [flag, arch]
def _ptxas_failure_hint(log_path: Path) -> str:
@@ -440,6 +468,14 @@ def build_audiocpp(audiocpp_dir: Path, backend: str, *,
emit=None, cancel=None) -> int:
"""Build audiocpp_server for BACKEND, streaming output.
+ The platform's own helper script runs the build (see
+ ``find_build_script``): ``build_metal.sh`` under bash on macOS (Metal
+ is the only backend there; it takes no ``--backend`` flag, so BACKEND
+ only records what server.json names), ``build_windows.ps1`` — or
+ ``build_windows_hip.ps1`` for hip — under stock ``powershell.exe`` on
+ Windows (presets ``windows-{cuda,vulkan,cpu}-release``), and
+ ``build_linux.sh`` under bash everywhere else.
+
With EMIT None the build script runs on the console (inherits the
terminal); with EMIT given (the in-TUI task view) its output streams line
by line to EMIT so the view can show progress, and CANCEL aborts it.
@@ -453,7 +489,7 @@ def build_audiocpp(audiocpp_dir: Path, backend: str, *,
Returns the build script's exit code (non-zero when the script is
missing).
"""
- script = find_build_script(audiocpp_dir)
+ script = find_build_script(audiocpp_dir, backend)
if script is None:
message = (f"[ERROR] No build script found in {audiocpp_dir}/scripts; "
"build audiocpp_server manually (see the audio.cpp README)")
@@ -461,8 +497,23 @@ def build_audiocpp(audiocpp_dir: Path, backend: str, *,
if emit is not None:
common.record_post_tui_notice(message)
return 1
- argv = ["sh", str(script), "--backend", backend, "--target",
- "audiocpp_server", "--deployment-build"]
+ if sys.platform == "win32":
+ argv = ["powershell", "-NoProfile", "-NonInteractive",
+ "-ExecutionPolicy", "Bypass", "-File", str(script)]
+ if backend == "hip":
+ # The HIP helper's default build dir (build/hip) carries no
+ # "-hip-" token, so detect_backend/built_server_binary would
+ # never find the binary; name the dir after the preset instead.
+ argv += ["-Target", "audiocpp_server", "-DeploymentBuild",
+ "-BuildDir", "build/windows-hip-release"]
+ else:
+ argv += ["-Preset", f"windows-{backend}-release", "-Target",
+ "audiocpp_server", "-DeploymentBuild"]
+ else:
+ argv = ["bash", str(script)]
+ if sys.platform != "darwin":
+ argv += ["--backend", backend]
+ argv += ["--target", "audiocpp_server", "--deployment-build"]
argv += _cuda_arch_argv(backend, emit=emit)
command = f"cd {audiocpp_dir} && {shlex.join(argv)}"
if emit is None:
@@ -554,15 +605,27 @@ def _print_launch_hint(audiocpp_dir: Path, output_path: Path) -> None:
no manual launch instructions. When no binary was built, though, the
user needs to know how to build and run it by hand. The commands are
prefixed with ``cd <checkout> &&`` because the server discovers
- model_specs/<family>.json relative to its working directory.
+ model_specs/<family>.json relative to its working directory, and the
+ build command mirrors what ``build_audiocpp`` would run on this
+ platform.
"""
if find_audiocpp_server_bin(audiocpp_dir) is not None:
return
print("\n[INFO] audiocpp_server binary not found. Build it first, e.g.:")
script = find_build_script(audiocpp_dir)
if script is not None:
- print(f" sh {script} --backend <cuda|vulkan|hip|cpu> "
- "--target audiocpp_server --deployment-build")
+ if sys.platform == "win32":
+ print(f" powershell -NoProfile -ExecutionPolicy Bypass -File "
+ f"{script} -Preset windows-cuda-release -Target "
+ "audiocpp_server -DeploymentBuild")
+ print(" presets: windows-cpu-release, windows-vulkan-release, "
+ "windows-cuda-release (HIP: scripts/build_windows_hip.ps1)")
+ elif sys.platform == "darwin":
+ print(f" bash {script} --target audiocpp_server "
+ "--deployment-build")
+ else:
+ print(f" bash {script} --backend <cuda|vulkan|hip|cpu> "
+ "--target audiocpp_server --deployment-build")
print(f" then run: cd {audiocpp_dir} && ./build/<platform>-<backend>"
f"-release/bin/audiocpp_server --config {output_path}")