diff options
| author | historia <historiavg@proton.me> | 2026-08-28 16:52:14 -0400 |
|---|---|---|
| committer | historia <historiavg@proton.me> | 2026-08-28 16:52:14 -0400 |
| commit | 270fa60c01866c4431d540be960b6cd2bc2b9c44 (patch) | |
| tree | 7e5b682472622634d78226479c2f1526a6efc1d3 /app/backends/audiocpp | |
| parent | db38085d07ce75f8961eecdc1919e98748254c53 (diff) | |
| download | tts-audiobook-generator-270fa60c01866c4431d540be960b6cd2bc2b9c44.tar.gz | |
feat: run auto-build audio.cpp scripts for macos and windows
Diffstat (limited to 'app/backends/audiocpp')
| -rw-r--r-- | app/backends/audiocpp/build.py | 91 | ||||
| -rw-r--r-- | app/backends/audiocpp/catalog.py | 14 |
2 files changed, 90 insertions, 15 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}") diff --git a/app/backends/audiocpp/catalog.py b/app/backends/audiocpp/catalog.py index 412fdf1..5d49fac 100644 --- a/app/backends/audiocpp/catalog.py +++ b/app/backends/audiocpp/catalog.py @@ -2,6 +2,7 @@ import json import re +import sys from pathlib import Path from typing import Dict, List, Optional, Set, Tuple @@ -73,9 +74,20 @@ def _backend_options(detected: Optional[str] = None options, that option gets ``[auto-detected]`` appended and is the default (cursor/start) selection; otherwise the first option is the default as before. Returns (options, default_index). + + On macOS only ``cpu`` is offered: Metal (via ``build_metal.sh``) is + the only buildable inference backend there, and it is recorded as + ``cpu`` (see the ``-metal-`` -> ``cpu`` mapping in ``detect_backend`` + and ``built_server_binary``), so cuda/vulkan/hip — which cannot build + on macOS — never reach the build step. """ + if sys.platform == "darwin": + label = "cpu - Apple Metal (recorded as cpu)" + if detected == "cpu": + label += " [auto-detected]" + return [(label, "cpu")], 0 width = max(len(name) for name, _ in _BACKEND_DESCRIPTIONS) - options: List[Tuple[str, str]] = [] + options = [] default_index = 0 for index, (name, desc) in enumerate(_BACKEND_DESCRIPTIONS): label = f"{name.ljust(width)} - {desc}" |
