diff --git a/CMakeLists.txt b/CMakeLists.txt index 580e6dc..d216765 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,10 @@ add_compile_definitions(NEMO_SPEECH_VERSION_STR="${NEMO_SPEECH_VERSION}") include(GNUInstallDirs) include(CMakePackageConfigHelpers) +if(WIN32) + # Install the Visual C++ runtime required by Windows packages. + include(InstallRequiredSystemLibraries) +endif() set(NEMO_SPEECH_LICENSE_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/licenses/nemo-speech") install(FILES LICENSE NOTICE THIRD_PARTY_NOTICES.md @@ -116,6 +120,27 @@ endif() if(NEMO_SPEECH_BUILD_GRPC) set(NEMO_SPEECH_WITH_GRPC ON) endif() + +# Reject invalid component combinations early. +if(WIN32 AND NEMO_SPEECH_WITH_NORM) + message(FATAL_ERROR + "NEMO_SPEECH_WITH_NORM is not supported on Windows; disable normalization") +endif() +if(NEMO_SPEECH_BUILD_GRPC AND + (NOT NEMO_SPEECH_BUILD_ASR OR NOT NEMO_SPEECH_BUILD_TTS)) + message(FATAL_ERROR + "NEMO_SPEECH_BUILD_GRPC currently requires both ASR and TTS") +endif() +if(NEMO_SPEECH_WITH_FLASHLIGHT AND NOT NEMO_SPEECH_BUILD_ASR) + message(FATAL_ERROR "NEMO_SPEECH_WITH_FLASHLIGHT requires ASR") +endif() +if((NEMO_SPEECH_TTS_WITH_JA OR NEMO_SPEECH_TTS_WITH_ZH) AND + NOT NEMO_SPEECH_BUILD_TTS) + message(FATAL_ERROR "Optional TTS tokenizers require NEMO_SPEECH_BUILD_TTS=ON") +endif() +if(NEMO_SPEECH_HTTP_TLS AND NOT NEMO_SPEECH_BUILD_HTTP) + message(FATAL_ERROR "NEMO_SPEECH_HTTP_TLS requires NEMO_SPEECH_BUILD_HTTP=ON") +endif() if(NEMO_SPEECH_BUILD_TESTS) set(BUILD_TESTING ON CACHE BOOL "Build first-party test executables" FORCE) elseif(BUILD_TESTING) @@ -410,6 +435,17 @@ endif() set(NEMO_SPEECH_THIRD_PARTY_LICENSE_DIR "${NEMO_SPEECH_LICENSE_INSTALL_DIR}/third_party") +if(DEFINED VCPKG_INSTALLED_DIR AND DEFINED VCPKG_TARGET_TRIPLET) + file(GLOB _NEMO_SPEECH_VCPKG_COPYRIGHTS LIST_DIRECTORIES false + "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/*/copyright") + foreach(_copyright IN LISTS _NEMO_SPEECH_VCPKG_COPYRIGHTS) + get_filename_component(_share_dir "${_copyright}" DIRECTORY) + get_filename_component(_package "${_share_dir}" NAME) + install(FILES "${_copyright}" + DESTINATION "${NEMO_SPEECH_THIRD_PARTY_LICENSE_DIR}/vcpkg/${_package}" + RENAME LICENSE) + endforeach() +endif() install(FILES ggml/LICENSE DESTINATION "${NEMO_SPEECH_THIRD_PARTY_LICENSE_DIR}/ggml") if(TARGET nemo_speech_cublas_shim) diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index c164268..659ee7c 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -108,11 +108,13 @@ are explicitly excluded and are not compiled or linked. - Copyright The OpenSSL Project Authors and other contributors - License: Apache License 2.0 -OpenSSL is dynamically linked only when optional HTTP-server TLS is enabled. It -is not incorporated into the source tree. The default container disables HTTP -TLS, links gRPC's unsecure libraries, and does not distribute OpenSSL. -Distributions that enable HTTP TLS must include the applicable OpenSSL -attribution and Apache 2.0 terms. +OpenSSL is linked only when HTTP-server TLS is enabled. Windows packages include +its license. The default Linux container does not include OpenSSL. + +### Windows vcpkg dependencies + +Windows builds obtain optional dependencies through vcpkg. Installed packages +include each selected dependency's license. ### Container system libraries @@ -129,6 +131,15 @@ project notice set is installed under ## Other incorporated third-party code and data +### SentencePiece + +- Source: [`google/sentencepiece`](https://github.com/google/sentencepiece) +- Copyright 2018 Google Inc. +- License: Apache License 2.0 + +Default Windows ASR builds link SentencePiece statically and include its license +notice. + ### whisper.cpp sample audio The ASR quick-start fixture at `test_files/asr/wav/test/jfk.wav` is copied from diff --git a/docs/development/windows-build.md b/docs/development/windows-build.md index 1358606..7430030 100644 --- a/docs/development/windows-build.md +++ b/docs/development/windows-build.md @@ -26,11 +26,6 @@ compiler on Windows). - Warning flags are scoped to C/C++ compilation (`$`) so nvcc's `cl` host never receives them - with clang-cl as CXX they would otherwise leak into the CUDA compile (`D8021`). -- **clang-cl + gRPC:** linking clang-cl-compiled code against MSVC-built - *shared* protobuf (vcpkg `x64-windows`) can fail on `dllimport` symbols the - MSVC DLL doesn't export. For `-Grpc` builds with clang-cl, install the vcpkg - deps under the `x64-windows-static-md` triplet (static protobuf/gRPC) and - configure with that triplet. - **ARM64 specifics.** CUDA 13.4+/CCCL 3.4 requires the `cuda/iterator` include fix present in the current ggml pin. On integrated GPUs (e.g. Tegra), Vulkan devices enumerate as iGPU (`GGML_BACKEND_DEVICE_TYPE_IGPU`), which the ASR @@ -56,16 +51,9 @@ ARM64 builds also require the Visual Studio `Microsoft.VisualStudio.Component.VC.Tools.ARM64` and `Microsoft.VisualStudio.Component.VC.Llvm.Clang` individual components. -For the **gRPC server** or **Flashlight decoder** you also need vcpkg. The -commands below show gRPC's shared x64 dependencies; Flashlight's architecture- -specific command is in [Optional features](#optional-features-flashlight-itn). - -```powershell -git clone --depth 1 https://github.com/microsoft/vcpkg C:\vcpkg -C:\vcpkg\bootstrap-vcpkg.bat -disableMetrics -# grpc pulls protobuf and abseil. -C:\vcpkg\vcpkg.exe install grpc protobuf --triplet x64-windows -``` +The build driver downloads required vcpkg dependencies under +`%LOCALAPPDATA%\NeMoSpeech`. Use `-VcpkgRoot` or `-VcpkgTriplet` to override the +defaults. > **PATH note:** installers update the *machine* `PATH`, which an already-open > shell won't see. Open a new terminal afterward (or let `build.ps1` refresh the @@ -110,20 +98,28 @@ powershell -ExecutionPolicy Bypass -File scripts\windows\build.ps1 -Backend vulk powershell -ExecutionPolicy Bypass -File scripts\windows\build.ps1 -Backend cpu # CPU ASR + TTS + HTTP API, realtime WebSocket, and playground -powershell -ExecutionPolicy Bypass -File scripts\windows\build.ps1 -Backend cpu -Http +powershell -ExecutionPolicy Bypass -File scripts\windows\build.ps1 -Backend cpu -Profile server + +# Full runtime profile (add -HttpTls for TLS) +powershell -ExecutionPolicy Bypass -File scripts\windows\build.ps1 -Backend cpu -Profile full + +# Full profile plus tests, examples, and diagnostic tools +powershell -ExecutionPolicy Bypass -File scripts\windows\build.ps1 -Backend cpu -Profile developer # CPU + Flashlight decoder + dynamically linked KenLM powershell -ExecutionPolicy Bypass -File scripts\windows\build.ps1 -Backend cpu -Flashlight ``` -Key parameters: `-Backend cuda|vulkan|cpu`, `-Architecture auto|x64|arm64`, -`-Grpc`, `-Nmt`, `-AsrOnly`, `-Http`, `-Flashlight`, +Key parameters: `-Backend cuda|vulkan|cpu`, +`-Profile core|asr|server|full|developer`, +`-Architecture auto|x64|arm64`, +`-Grpc`, `-Nmt`, `-AsrOnly`, `-Http`, `-HttpTls`, `-Flashlight`, `-TtsJa`, +`-TtsZh`, `-Config Release|RelWithDebInfo|Debug`, `-CudaArch `, `-VcpkgRoot C:\vcpkg`, `-VcpkgTriplet `, `-BuildDir `, `-Jobs N`. -Binaries land in `build-\bin`; an explicit `-Architecture` uses -`build--\bin` by default so x64 and ARM64 caches cannot -collide. +Binaries land in `build-[-][-]\bin`; the default +`core` and `auto` suffixes are omitted. ## Build with raw CMake @@ -220,17 +216,11 @@ user-set value of the env var takes precedence over the auto-set. | Feature (CMake flag) | Windows status | |---|---| -| **Flashlight** (`-DNEMO_SPEECH_WITH_FLASHLIGHT=ON`) | ✅ Builds replaceable `kenlm.dll`. Install `sentencepiece` with vcpkg's `x64-windows-static-md` triplet on x64 or `arm64-windows-static-md` on ARM64, then use `build.ps1 -Flashlight`. | +| **Flashlight** (`-DNEMO_SPEECH_WITH_FLASHLIGHT=ON`) | ✅ Builds replaceable `kenlm.dll`; SentencePiece and compression libraries are provisioned automatically. | | **ITN/TN** (`-DNEMO_SPEECH_WITH_NORM=ON`) | ❌ Not supported on Windows. Requires the OpenFST 1.8 / Sparrowhawk WFST stack, which `scripts/build_itn_deps.sh` builds via Linux autotools (neither is in vcpkg). | -**Combining flashlight + gRPC on Windows:** the instructions above use different -vcpkg linkage (gRPC with the *shared* triplet, flashlight with *static-md*). For -one build with both, install **all** vcpkg deps (grpc + sentencepiece) -under a single static-md triplet matching the host architecture - -`x64-windows-static-md` on x64, `arm64-windows-static-md` on ARM64 (likewise -`x64-windows` / `arm64-windows` are the shared analogs elsewhere in this guide, -which shows x64 commands) - and configure with that triplet, so there's one -consistent protobuf/abseil. +Automatic dependencies use one architecture-matched `*-windows-static-md` +triplet. ## Next steps @@ -241,9 +231,6 @@ Model conversion and runtime commands are platform-neutral. Continue with: - [Server configuration](../server.md) - [Client integration](../clients.md) -> **Run-time PATH:** run from a shell that has the CUDA Toolkit `bin` and the MSVC -> runtime on `PATH` (an *x64 Native Tools* prompt, or after `vcvars64.bat`). -> `ggml-cuda.dll` loads `cudart`/`cublas` from the toolkit and the binaries link the -> VC++ runtime; without them Windows reports `STATUS_DLL_NOT_FOUND` (0xC0000135). The -> component DLLs themselves are already placed next to the `.exe` in -> `build-\bin`. +> **Run-time PATH:** CUDA build-tree binaries need the CUDA Toolkit `bin` on +> `PATH`. Installed packages place the project DLLs and Visual C++ runtime next +> to the executable. diff --git a/docs/install.md b/docs/install.md index fbfec19..3be6d36 100644 --- a/docs/install.md +++ b/docs/install.md @@ -57,12 +57,41 @@ Select a backend explicitly when needed: .\scripts\install.ps1 -Source -Backend cuda ``` +Select the components to install: + +```powershell +# ASR and diarization only +.\scripts\install.ps1 -Source -Backend cpu -Profile asr + +# Full runtime profile (add -HttpTls for TLS) +.\scripts\install.ps1 -Source -Backend cuda -Profile full +``` + +| Profile | Components | +|---|---| +| `core` | ASR, diarization, and TTS | +| `asr` | ASR and diarization | +| `server` (default) | `core` plus the HTTP API and playground | +| `full` | `server` plus NMT, gRPC, Flashlight, and JA/ZH tokenizers | + +Use `-Grpc`, `-Nmt`, `-Flashlight`, `-TtsJa`, `-TtsZh`, `-Http`, or `-HttpTls` +to customize a profile. Binary installation is limited to `server`; other +selections build from source. Contributors can run +`.\scripts\windows\build.ps1 -Backend cpu -Profile developer` to build `full` +plus tests, examples, and diagnostic tools. + The default prefix is `%LOCALAPPDATA%\Programs\NeMoSpeech`, and the installer updates only the current user's PATH. A Windows source build requires Git, CMake, Ninja, Visual Studio 2022 Build Tools, and the selected backend toolkit. It includes the same CLI, HTTP API, and playground as the Linux and macOS source installation. +The source installer downloads required C++ libraries automatically. Use +`-VcpkgRoot` to override its vcpkg location. + +CUDA requires the NVIDIA CUDA Toolkit and driver. Vulkan requires the LunarG +Vulkan SDK and a vendor driver. Text normalization is not supported on Windows. + A later installer run checks for the published binary archive first and replaces an existing source build automatically once the matching archive is available. diff --git a/scripts/install.ps1 b/scripts/install.ps1 index 774a4d5..6399d6a 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -6,6 +6,17 @@ param( [ValidateSet("stable", "nightly")][string]$Channel = "stable", [string]$Prefix = "$env:LOCALAPPDATA\Programs\NeMoSpeech", [ValidateSet("auto", "cpu", "cuda", "vulkan")][string]$Backend = "auto", + [ValidateSet("core", "asr", "server", "full")][string]$Profile = "server", + [switch]$Grpc, + [switch]$Nmt, + [switch]$Flashlight, + [switch]$TtsJa, + [switch]$TtsZh, + [switch]$Http, + [switch]$HttpTls, + [string]$CudaArch = "native", + [string]$VcpkgRoot, + [string]$VcpkgTriplet, [switch]$Source, [switch]$BinaryOnly, [switch]$NoModifyPath, @@ -20,9 +31,16 @@ $releaseBase = if ($env:NEMO_SPEECH_RELEASE_BASE_URL) { $sourceUrl = if ($env:NEMO_SPEECH_SOURCE_URL) { $env:NEMO_SPEECH_SOURCE_URL } else { - (Get-Location).Path + (Resolve-Path (Join-Path $PSScriptRoot '..')).Path } if ($Source -and $BinaryOnly) { throw "-Source and -BinaryOnly are mutually exclusive" } +$profileIncludesTts = $Profile -ne 'asr' +if ($Grpc -and -not $profileIncludesTts) { + throw 'The gRPC server requires both ASR and TTS. Use -Profile server or full.' +} +if (($TtsJa -or $TtsZh) -and -not $profileIncludesTts) { + throw 'The Japanese and Mandarin tokenizers require TTS. Use a profile that includes TTS.' +} function Assert-SourcePrerequisites { param([string]$SelectedBackend, [string]$Architecture) @@ -65,7 +83,8 @@ function Assert-SourcePrerequisites { $vulkanSdk = if ($env:VULKAN_SDK) { $env:VULKAN_SDK } else { - [Environment]::GetEnvironmentVariable('VULKAN_SDK', 'Machine') + $machineVulkan = [Environment]::GetEnvironmentVariable('VULKAN_SDK', 'Machine') + if ($machineVulkan) { $machineVulkan } else { [Environment]::GetEnvironmentVariable('VULKAN_SDK', 'User') } } if (-not $vulkanSdk -or -not (Test-Path (Join-Path $vulkanSdk 'Bin\glslc.exe'))) { throw "The Vulkan SDK (including glslc and SPIR-V headers) was not found. Install the LunarG Vulkan SDK, or select -Backend cpu." @@ -89,10 +108,28 @@ $arch = switch ([System.Runtime.InteropServices.RuntimeInformation,mscorlib]::OS "Arm64" { "aarch64" } default { throw "Unsupported Windows architecture: $_" } } +$machinePath = [Environment]::GetEnvironmentVariable('Path', 'Machine') +$userPath = [Environment]::GetEnvironmentVariable('Path', 'User') +$env:Path = "$machinePath;$userPath;$env:Path" if ($Backend -eq "auto") { - $Backend = if (Get-Command nvidia-smi.exe -ErrorAction SilentlyContinue) { "cuda" } else { "cpu" } + $Backend = "cpu" + $smi = Get-Command nvidia-smi.exe -ErrorAction SilentlyContinue + if ($smi) { + $gpu = & $smi.Source --query-gpu=name --format=csv,noheader 2>$null + if ($LASTEXITCODE -eq 0 -and $gpu) { + $Backend = "cuda" + } else { + Write-Host 'nvidia-smi is present but the NVIDIA driver is not working; selecting the CPU backend.' + } + } +} +$customSourceProfile = $Profile -ne 'server' -or + $Grpc -or $Nmt -or $Flashlight -or $TtsJa -or $TtsZh -or + $HttpTls +if ($BinaryOnly -and $customSourceProfile) { + throw '-BinaryOnly supports only the server profile without extra components.' } -$binaryCandidate = -not $Source -and [bool]$releaseBase +$binaryCandidate = -not $Source -and -not $customSourceProfile -and [bool]$releaseBase if ($BinaryOnly -and -not $releaseBase) { throw "-BinaryOnly requires NEMO_SPEECH_RELEASE_BASE_URL" } @@ -138,14 +175,24 @@ $sourceRef = if ($env:NEMO_SPEECH_SOURCE_REF) { $tag } -Write-Host "NeMo-Speech.cpp $releaseVersion (windows/$arch, $Backend)" +Write-Host "NeMo-Speech.cpp $releaseVersion (windows/$arch, $Backend, $Profile)" if (-not $Source -and $binaryCandidate) { Write-Host "Artifact: $url" } -if (-not $BinaryOnly) { Write-Host "Source: $sourceUrl#$sourceRef ($Backend speech server fallback)" } +if (-not $BinaryOnly) { Write-Host "Source: $sourceUrl#$sourceRef ($Backend/$Profile)" } Write-Host "Prefix: $Prefix" if ($DryRun) { return } $installIdentity = "$releaseVersion windows $arch $Backend" -$sourceIdentity = "$installIdentity source:$sourceRef profile:speech-server" +$extraComponents = [Collections.Generic.List[string]]::new() +foreach ($component in @( + @{ Name = 'grpc'; Enabled = $Grpc }, @{ Name = 'nmt'; Enabled = $Nmt }, + @{ Name = 'flashlight'; Enabled = $Flashlight }, @{ Name = 'tts-ja'; Enabled = $TtsJa }, + @{ Name = 'tts-zh'; Enabled = $TtsZh }, @{ Name = 'http'; Enabled = $Http }, + @{ Name = 'http-tls'; Enabled = $HttpTls } +)) { + if ($component.Enabled) { $extraComponents.Add($component.Name) } +} +$componentIdentity = if ($extraComponents.Count) { " components:$($extraComponents -join ',')" } else { '' } +$sourceIdentity = "$installIdentity source:$sourceRef profile:$Profile$componentIdentity" $installMetadata = Join-Path $Prefix ".nemo-speech-install" $installedBinary = Join-Path $Prefix "bin\nemo-speech.exe" if (-not $Source -and $binaryCandidate -and (Test-Path $installedBinary) -and (Test-Path $installMetadata) -and @@ -155,7 +202,7 @@ if (-not $Source -and $binaryCandidate -and (Test-Path $installedBinary) -and (T return } -$temp = Join-Path ([IO.Path]::GetTempPath()) ("nemo-speech-install-" + [guid]::NewGuid()) +$temp = Join-Path ([IO.Path]::GetTempPath()) ("nsi-" + [guid]::NewGuid().ToString('N').Substring(0, 8)) New-Item -ItemType Directory -Path $temp | Out-Null try { $archivePath = Join-Path $temp $archive @@ -195,29 +242,40 @@ try { & git clone --depth 1 --single-branch --branch $sourceRef $sourceUrl $sourceDir if ($LASTEXITCODE -ne 0) { throw "git clone failed ($LASTEXITCODE)" } - if (Test-Path (Join-Path $sourceDir ".gitmodules")) { - foreach ($submodule in @("ggml", "third_party/cpp-httplib")) { - $configuredPath = & git -C $sourceDir config -f .gitmodules --get-regexp '^submodule\..*\.path$' 2>$null | - ForEach-Object { ($_ -split '\s+', 2)[1] } | - Where-Object { $_ -eq $submodule } - if ($configuredPath) { - & git -C $sourceDir submodule update --init $submodule - if ($LASTEXITCODE -ne 0) { throw "git submodule update failed for $submodule" } - } - } - } $buildDir = Join-Path $temp "b" $buildScript = Join-Path $sourceDir "scripts\windows\build.ps1" - & $buildScript -Backend $Backend -BuildDir $buildDir -Config Release -Http + $buildParameters = @{ + Backend = $Backend + Profile = $Profile + BuildDir = $buildDir + Config = 'Release' + CudaArch = $CudaArch + } + foreach ($switchParameter in @( + @{ Name = 'Grpc'; Enabled = $Grpc }, @{ Name = 'Nmt'; Enabled = $Nmt }, + @{ Name = 'Flashlight'; Enabled = $Flashlight }, @{ Name = 'TtsJa'; Enabled = $TtsJa }, + @{ Name = 'TtsZh'; Enabled = $TtsZh }, @{ Name = 'Http'; Enabled = $Http }, + @{ Name = 'HttpTls'; Enabled = $HttpTls } + )) { + if ($switchParameter.Enabled) { $buildParameters[$switchParameter.Name] = $true } + } + if ($VcpkgRoot) { $buildParameters.VcpkgRoot = $VcpkgRoot } + if ($VcpkgTriplet) { $buildParameters.VcpkgTriplet = $VcpkgTriplet } + & $buildScript @buildParameters if ($LASTEXITCODE -ne 0) { throw "Source build failed ($LASTEXITCODE)" } $root = Join-Path $temp source-install & cmake --install $buildDir --config Release --prefix $root if ($LASTEXITCODE -ne 0) { throw "Source install failed ($LASTEXITCODE)" } $installIdentity = $sourceIdentity } - if (-not (Test-Path (Join-Path $root "bin\nemo-speech.exe"))) { + $stagedBinary = Join-Path $root "bin\nemo-speech.exe" + if (-not (Test-Path $stagedBinary)) { throw "Installation does not contain bin\nemo-speech.exe" } + & $stagedBinary --version + if ($LASTEXITCODE -ne 0) { throw "Installed binary failed its version check ($LASTEXITCODE)" } + & $stagedBinary --json doctor + if ($LASTEXITCODE -ne 0) { throw "Installed binary failed its runtime health check ($LASTEXITCODE)" } Set-Content -Path (Join-Path $root ".nemo-speech-install") -Value $installIdentity -NoNewline $parent = Split-Path -Parent $Prefix New-Item -ItemType Directory -Force -Path $parent | Out-Null diff --git a/scripts/windows/build.ps1 b/scripts/windows/build.ps1 index 8799623..9aa0270 100644 --- a/scripts/windows/build.ps1 +++ b/scripts/windows/build.ps1 @@ -11,17 +11,21 @@ 2. Imports the MSVC x64 dev environment (vcvars64.bat) so cl.exe / nvcc find the toolset. MSVC is required: nvcc on Windows only supports cl.exe as the CUDA host compiler. - 3. For a CUDA build, applies the CUDA-only ggml patches. - 4. Configures with CMake (Ninja) and builds. + 3. Provisions required C++ dependencies. + 4. For a CUDA build, applies the CUDA-only ggml patches. + 5. Configures with CMake (Ninja) and builds. .PARAMETER Backend cuda | vulkan | cpu. CUDA and Vulkan are separate build trees (different ggml config), so use a distinct -BuildDir for each. +.PARAMETER Profile + Component preset: core, asr, server (core + HTTP), full, or developer + (full + tests, examples, and tools). Component switches add features. + .PARAMETER Grpc - Also build the Riva-compatible riva_server. Requires grpc+protobuf from - vcpkg; pass -VcpkgRoot (default C:\vcpkg). Install once with: - C:\vcpkg\vcpkg.exe install grpc protobuf portaudio --triplet x64-windows + Also build the Riva-compatible riva_server. gRPC and protobuf are installed + from the vcpkg manifest automatically. .PARAMETER Nmt Also build the NMT translation component (links llama.cpp; checks out the @@ -30,7 +34,14 @@ .PARAMETER Flashlight Build LM-fused CTC decoding with Flashlight and dynamically linked KenLM - DLLs. Requires SentencePiece from vcpkg. + DLLs. Its required libraries are installed automatically. + +.PARAMETER HttpTls + Enable TLS in the HTTP server and install OpenSSL automatically. + +.PARAMETER VcpkgRoot + Existing vcpkg checkout to use. By default the driver bootstraps its pinned + version under %LOCALAPPDATA%\NeMoSpeech. .PARAMETER TtsJa Build the optional Japanese TTS tokenizer (Open JTalk, MeCab, and the NAIST @@ -61,14 +72,16 @@ Target architecture: auto (the host), x64, or arm64. .EXAMPLE - pwsh scripts\windows\build.ps1 -Backend cuda -Grpc - pwsh scripts\windows\build.ps1 -Backend cpu -Flashlight - pwsh scripts\windows\build.ps1 -Backend vulkan + pwsh scripts\windows\build.ps1 -Backend cuda -Profile server + pwsh scripts\windows\build.ps1 -Backend cpu -Profile full + pwsh scripts\windows\build.ps1 -Backend vulkan -Profile developer #> [CmdletBinding()] param( [ValidateSet('cuda', 'vulkan', 'cpu')] [string]$Backend = 'cuda', + [ValidateSet('core', 'asr', 'server', 'full', 'developer')] + [string]$Profile = 'core', [switch]$Grpc, [switch]$Nmt, [switch]$Flashlight, @@ -76,11 +89,12 @@ param( [switch]$TtsZh, [switch]$AsrOnly, [switch]$Http, + [switch]$HttpTls, [string]$BuildDir, [ValidateSet('Release', 'RelWithDebInfo', 'Debug')] [string]$Config = 'Release', [string]$CudaArch = 'native', - [string]$VcpkgRoot = 'C:\vcpkg', + [string]$VcpkgRoot, [string]$VcpkgTriplet, [ValidateSet('auto', 'x64', 'arm64')] [string]$Architecture = 'auto', @@ -88,13 +102,72 @@ param( # backend rejects MSVC). nvcc's CUDA host compiler is cl.exe in all cases. [ValidateSet('auto', 'msvc', 'clang-cl')] [string]$Compiler = 'auto', - [int]$Jobs = 0 + [int]$Jobs = 0, + [switch]$DryRun ) $ErrorActionPreference = 'Stop' $RepoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) +$VcpkgBootstrapTag = '2026.07.29' +$VcpkgBootstrapCommit = '9e593bb18ea69cc5095e012465dcd675a822ed0d' + +if ($AsrOnly) { + if ($Profile -ne 'core' -and $Profile -ne 'asr') { + throw '-AsrOnly cannot be combined with a non-ASR -Profile.' + } + $Profile = 'asr' +} +$BuildAsr = $false +$BuildDiar = $false +$BuildTts = $false +$BuildNmt = $false +$BuildHttp = $false +$BuildGrpc = $false +$BuildFlashlight = $false +$BuildTtsJa = $false +$BuildTtsZh = $false +$BuildTests = $false +$BuildExamples = $false +$BuildTools = $false + +switch ($Profile) { + 'core' { $BuildAsr = $true; $BuildDiar = $true; $BuildTts = $true } + 'asr' { $BuildAsr = $true; $BuildDiar = $true } + 'server' { $BuildAsr = $true; $BuildDiar = $true; $BuildTts = $true; $BuildHttp = $true } + 'full' { + $BuildAsr = $true; $BuildDiar = $true; $BuildTts = $true; $BuildNmt = $true + $BuildHttp = $true; $BuildGrpc = $true; $BuildFlashlight = $true + $BuildTtsJa = $true; $BuildTtsZh = $true + } + 'developer' { + $BuildAsr = $true; $BuildDiar = $true; $BuildTts = $true; $BuildNmt = $true + $BuildHttp = $true; $BuildGrpc = $true; $BuildFlashlight = $true + $BuildTtsJa = $true; $BuildTtsZh = $true + $BuildTests = $true; $BuildExamples = $true; $BuildTools = $true + } +} + +$BuildGrpc = $BuildGrpc -or $Grpc.IsPresent +$BuildNmt = $BuildNmt -or $Nmt.IsPresent +$BuildFlashlight = $BuildFlashlight -or $Flashlight.IsPresent +$BuildTtsJa = $BuildTtsJa -or $TtsJa.IsPresent +$BuildTtsZh = $BuildTtsZh -or $TtsZh.IsPresent +$BuildHttp = $BuildHttp -or $Http.IsPresent -or $HttpTls.IsPresent +$BuildHttpTls = $HttpTls.IsPresent +if ($BuildGrpc -and (-not $BuildAsr -or -not $BuildTts)) { + throw 'The gRPC server currently requires both ASR and TTS. Use -Profile server, full, or developer.' +} +if ($BuildFlashlight -and -not $BuildAsr) { + throw 'The Flashlight decoder requires ASR. Use -Profile asr, server, full, or developer.' +} +if (($BuildTtsJa -or $BuildTtsZh) -and -not $BuildTts) { + throw 'The Japanese and Mandarin tokenizers require TTS. Use a profile that includes TTS.' +} + if (-not $BuildDir) { - $buildName = if ($Architecture -eq 'auto') { "build-$Backend" } else { "build-$Backend-$Architecture" } + $profileSuffix = if ($Profile -eq 'core') { '' } else { "-$Profile" } + $archSuffix = if ($Architecture -eq 'auto') { '' } else { "-$Architecture" } + $buildName = "build-$Backend$profileSuffix$archSuffix" $BuildDir = Join-Path $RepoRoot $buildName } if ($Jobs -le 0) { $Jobs = [Environment]::ProcessorCount } @@ -115,21 +188,31 @@ if ($Backend -eq 'cuda' -and $CrossCompiling) { } $VcpkgArch = $TargetArch if (-not $VcpkgTriplet) { - $VcpkgTriplet = if ($Flashlight -or ($Grpc -and $Compiler -eq 'clang-cl')) { - "$VcpkgArch-windows-static-md" - } else { - "$VcpkgArch-windows" - } + # Link vcpkg libraries statically so installed binaries do not depend on the + # build tree. The Visual C++ runtime remains dynamically linked. + $VcpkgTriplet = "$VcpkgArch-windows-static-md" } +$VcpkgFeatures = [Collections.Generic.List[string]]::new() +if ($BuildAsr -or $BuildDiar) { $VcpkgFeatures.Add('asr') } +if ($BuildGrpc) { $VcpkgFeatures.Add('grpc') } +if ($BuildFlashlight) { $VcpkgFeatures.Add('flashlight') } +if ($BuildHttpTls) { $VcpkgFeatures.Add('http-tls') } +if ($BuildExamples) { $VcpkgFeatures.Add('examples') } + Write-Host "==> nemo-speech Windows build" -ForegroundColor Cyan -Write-Host " backend=$Backend grpc=$($Grpc.IsPresent) http=$($Http.IsPresent) nmt=$($Nmt.IsPresent) flashlight=$($Flashlight.IsPresent) tts-ja=$($TtsJa.IsPresent) tts-zh=$($TtsZh.IsPresent) config=$Config compiler=$Compiler host=$HostArch target=$TargetArch build=$BuildDir jobs=$Jobs" +Write-Host " backend=$Backend profile=$Profile asr=$BuildAsr diar=$BuildDiar tts=$BuildTts nmt=$BuildNmt http=$BuildHttp grpc=$BuildGrpc flashlight=$BuildFlashlight tts-ja=$BuildTtsJa tts-zh=$BuildTtsZh tests=$BuildTests examples=$BuildExamples tools=$BuildTools" +Write-Host " config=$Config compiler=$Compiler host=$HostArch target=$TargetArch build=$BuildDir jobs=$Jobs" +Write-Host " vcpkg=$($VcpkgFeatures -join ',') triplet=$VcpkgTriplet" +if ($DryRun) { return } # --- 1. Refresh environment from registry (choco/installers land there) --------- $machine = [Environment]::GetEnvironmentVariable('Path', 'Machine') $user = [Environment]::GetEnvironmentVariable('Path', 'User') -$env:Path = "$machine;$user" +$process = $env:Path +$env:Path = "$machine;$user;$process" $vk = [Environment]::GetEnvironmentVariable('VULKAN_SDK', 'Machine') +if (-not $vk) { $vk = [Environment]::GetEnvironmentVariable('VULKAN_SDK', 'User') } if ($vk) { $env:VULKAN_SDK = $vk } # --- 2. Import the MSVC dev environment (arch-specific vcvars) ------------------ @@ -157,60 +240,159 @@ cmd /c "`"$vcvars`" >NUL 2>&1 && set" | ForEach-Object { if ($_ -match '^([^=]+)=(.*)$') { Set-Item -Path "env:$($matches[1])" -Value $matches[2] } } -foreach ($tool in 'cl', 'cmake', 'ninja') { +foreach ($tool in 'git', 'cl', 'cmake', 'ninja') { if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) { throw "$tool not on PATH after env setup." } } if ($Compiler -eq 'clang-cl' -and -not (Get-Command clang-cl -ErrorAction SilentlyContinue)) { throw "clang-cl not on PATH; install LLVM (choco install llvm) or the VS 'C++ Clang tools' component." } -if ($Backend -eq 'cuda' -and -not (Get-Command nvcc -ErrorAction SilentlyContinue)) { throw "nvcc not found; install the CUDA Toolkit." } -if ($Backend -eq 'vulkan' -and -not $env:VULKAN_SDK) { throw "VULKAN_SDK not set; install the Vulkan SDK." } - -# --- 3. CUDA-only: apply the ggml patches --------------------------------------- if ($Backend -eq 'cuda') { - Write-Host "==> applying ggml patches (CUDA)" - & (Join-Path $PSScriptRoot 'apply-ggml-patches.ps1') + if (-not (Get-Command nvcc -ErrorAction SilentlyContinue)) { + throw 'nvcc not found; install a supported NVIDIA CUDA Toolkit.' + } + if ($CudaArch -eq 'native') { + $smi = Get-Command nvidia-smi.exe -ErrorAction SilentlyContinue + if (-not $smi) { + throw 'CUDA architecture auto-detection requires a working NVIDIA driver (nvidia-smi). Install the driver or pass -CudaArch explicitly for a cross-build.' + } + $gpu = & $smi.Source --query-gpu=name --format=csv,noheader 2>$null + if ($LASTEXITCODE -ne 0 -or -not $gpu) { + throw 'The NVIDIA driver is installed but not working. Repair the driver, or pass -CudaArch explicitly for a build host without a GPU.' + } + } +} +if ($Backend -eq 'vulkan') { + if (-not $env:VULKAN_SDK) { throw 'VULKAN_SDK not set; install the LunarG Vulkan SDK.' } + foreach ($required in 'Bin\glslc.exe', 'Lib\cmake\SPIRV-Headers\SPIRV-HeadersConfig.cmake') { + if (-not (Test-Path (Join-Path $env:VULKAN_SDK $required))) { + throw "The Vulkan SDK is incomplete: $required was not found under $env:VULKAN_SDK. Reinstall the LunarG Vulkan SDK." + } + } } -# --- 3b. NMT: ensure the llama.cpp submodule is checked out --------------------- -if ($Nmt -and -not (Test-Path (Join-Path $RepoRoot 'llama.cpp\CMakeLists.txt'))) { - Write-Host "==> initializing llama.cpp submodule (NMT)" - & git -C $RepoRoot submodule update --init llama.cpp - if ($LASTEXITCODE -ne 0) { throw "git submodule update --init llama.cpp failed" } +# --- 3. Provision manifest dependencies ----------------------------------------- +$toolchain = $null +if ($VcpkgFeatures.Count -gt 0) { + if (-not $VcpkgRoot) { + $VcpkgRoot = Join-Path $env:LOCALAPPDATA "NeMoSpeech\vcpkg-$VcpkgBootstrapTag" + } + $toolchain = Join-Path $VcpkgRoot 'scripts\buildsystems\vcpkg.cmake' + $vcpkg = Join-Path $VcpkgRoot 'vcpkg.exe' + if ((Test-Path $toolchain) -and -not (Test-Path (Join-Path $VcpkgRoot '.git'))) { + throw "vcpkg manifest mode requires a Git checkout, but $VcpkgRoot has no .git directory. Use the automatic user-local checkout or pass a valid -VcpkgRoot." + } + if (-not (Test-Path $toolchain)) { + if ((Test-Path $VcpkgRoot) -and @(Get-ChildItem -Force $VcpkgRoot).Count -gt 0) { + throw "vcpkg root exists but is incomplete: $VcpkgRoot. Pass -VcpkgRoot with a valid checkout or remove that incomplete directory." + } + New-Item -ItemType Directory -Force -Path (Split-Path -Parent $VcpkgRoot) | Out-Null + Write-Host "==> bootstrapping vcpkg $VcpkgBootstrapTag in $VcpkgRoot" + & git clone --depth 1 --branch $VcpkgBootstrapTag https://github.com/microsoft/vcpkg.git $VcpkgRoot + if ($LASTEXITCODE -ne 0) { throw "vcpkg clone failed ($LASTEXITCODE)" } + } + if (-not $PSBoundParameters.ContainsKey('VcpkgRoot')) { + $managedHead = (& git -C $VcpkgRoot rev-parse HEAD 2>$null) + if ($LASTEXITCODE -ne 0 -or $managedHead -ne $VcpkgBootstrapCommit) { + throw "The managed vcpkg checkout at $VcpkgRoot is not the expected $VcpkgBootstrapTag revision. Remove that directory and rerun, or pass a valid -VcpkgRoot explicitly." + } + } + if (-not (Test-Path $vcpkg)) { + $bootstrap = Join-Path $VcpkgRoot 'bootstrap-vcpkg.bat' + if (-not (Test-Path $bootstrap)) { throw "vcpkg bootstrap script not found at $bootstrap" } + Write-Host '==> building vcpkg' + & $bootstrap -disableMetrics + if ($LASTEXITCODE -ne 0) { throw "vcpkg bootstrap failed ($LASTEXITCODE)" } + } + $env:VCPKG_ROOT = $VcpkgRoot + $env:VCPKG_DISABLE_METRICS = '1' + Write-Host "==> vcpkg features: $($VcpkgFeatures -join ', ') ($VcpkgTriplet)" } -# --- 3c. HTTP: ensure cpp-httplib is checked out ------------------------------- -if ($Http -and -not (Test-Path (Join-Path $RepoRoot 'third_party\cpp-httplib\httplib.h'))) { - Write-Host "==> initializing third_party/cpp-httplib (HTTP and playground)" - & git -C $RepoRoot submodule update --init third_party/cpp-httplib - if ($LASTEXITCODE -ne 0) { throw "git submodule update --init third_party/cpp-httplib failed" } +# --- 4. Initialize exactly the required submodules ------------------------------ +function Initialize-RequiredSubmodule { + param([string]$Path, [string]$Sentinel, [switch]$Recursive) + if (Test-Path (Join-Path $RepoRoot "$Path\$Sentinel")) { return } + if (-not (Test-Path (Join-Path $RepoRoot '.gitmodules'))) { + throw "Required source dependency '$Path' is missing and this is not a Git checkout." + } + Write-Host "==> initializing $Path" + $arguments = @('-C', $RepoRoot, 'submodule', 'update', '--init') + if ($Recursive) { $arguments += '--recursive' } + $arguments += $Path + & git @arguments + if ($LASTEXITCODE -ne 0) { throw "git submodule update failed for $Path" } + if (-not (Test-Path (Join-Path $RepoRoot "$Path\$Sentinel"))) { + throw "Submodule $Path completed without the required file $Sentinel" + } } -# --- 3d. Flashlight: ensure the decoder and KenLM sources are checked out ------- -if ($Flashlight) { - foreach ($submodule in 'third_party/flashlight-text', 'third_party/kenlm') { - if (-not (Test-Path (Join-Path $RepoRoot "$submodule\CMakeLists.txt"))) { - Write-Host "==> initializing $submodule (Flashlight)" - & git -C $RepoRoot submodule update --init $submodule - if ($LASTEXITCODE -ne 0) { throw "git submodule update --init $submodule failed" } +Initialize-RequiredSubmodule 'ggml' 'CMakeLists.txt' +if ($BuildNmt) { Initialize-RequiredSubmodule 'llama.cpp' 'CMakeLists.txt' } +if ($BuildHttp) { Initialize-RequiredSubmodule 'third_party\cpp-httplib' 'httplib.h' } +if ($BuildGrpc) { Initialize-RequiredSubmodule 'proto\riva-common' 'LICENSE' } +if ($BuildFlashlight) { + Initialize-RequiredSubmodule 'third_party\flashlight-text' 'CMakeLists.txt' + Initialize-RequiredSubmodule 'third_party\kenlm' 'CMakeLists.txt' +} +if ($BuildTtsJa) { Initialize-RequiredSubmodule 'third_party\open_jtalk' 'src\CMakeLists.txt' } +if ($BuildTtsZh) { + Initialize-RequiredSubmodule 'third_party\cppjieba' 'deps\limonp\CMakeLists.txt' -Recursive + $lfsPointers = @(Get-ChildItem (Join-Path $RepoRoot 'src\tts\tokenizer\mandarin_data') -File | + Where-Object { (Get-Content $_.FullName -TotalCount 1) -eq 'version https://git-lfs.github.com/spec/v1' }) + if ($lfsPointers.Count -gt 0) { + & git lfs version *> $null + if ($LASTEXITCODE -ne 0) { + throw 'Mandarin TTS requires Git LFS data. Install Git for Windows with Git LFS, then rerun the build.' + } + Write-Host '==> downloading Mandarin tokenizer data with Git LFS' + & git -C $RepoRoot lfs pull --include='src/tts/tokenizer/mandarin_data/*' + if ($LASTEXITCODE -ne 0) { throw 'git lfs pull failed for Mandarin tokenizer data' } + foreach ($pointer in $lfsPointers) { + if ((Get-Content $pointer.FullName -TotalCount 1) -eq 'version https://git-lfs.github.com/spec/v1') { + throw "Git LFS did not materialize $($pointer.FullName)" + } } } } -# --- 3e. Optional TTS tokenizers: ensure their sources are checked out --------- -if ($TtsJa -and -not (Test-Path (Join-Path $RepoRoot 'third_party\open_jtalk\src\CMakeLists.txt'))) { - Write-Host "==> initializing third_party/open_jtalk (Japanese TTS tokenizer)" - & git -C $RepoRoot submodule update --init third_party/open_jtalk - if ($LASTEXITCODE -ne 0) { throw "git submodule update --init third_party/open_jtalk failed" } +# --- 5. CUDA-only: apply the ggml patches --------------------------------------- +if ($Backend -eq 'cuda') { + Write-Host "==> applying ggml patches (CUDA)" + & (Join-Path $PSScriptRoot 'apply-ggml-patches.ps1') } -if ($TtsZh -and -not (Test-Path (Join-Path $RepoRoot 'third_party\cppjieba\CMakeLists.txt'))) { - Write-Host "==> initializing third_party/cppjieba (Mandarin TTS tokenizer)" - & git -C $RepoRoot submodule update --init --recursive third_party/cppjieba - if ($LASTEXITCODE -ne 0) { throw "git submodule update --init --recursive third_party/cppjieba failed" } + +# --- 6. Configure + build ------------------------------------------------------- +function ConvertTo-CMakeBool([bool]$Value) { + if ($Value) { return 'ON' } + return 'OFF' } -# --- 4. Configure + build ------------------------------------------------------- -$cmakeArgs = @('-S', $RepoRoot, '-B', $BuildDir, '-G', 'Ninja', "-DCMAKE_BUILD_TYPE=$Config") +$cmakeArgs = @( + '-S', $RepoRoot, '-B', $BuildDir, '-G', 'Ninja', "-DCMAKE_BUILD_TYPE=$Config", + "-DNEMO_SPEECH_BUILD_ASR=$(ConvertTo-CMakeBool $BuildAsr)", + "-DNEMO_SPEECH_BUILD_DIAR=$(ConvertTo-CMakeBool $BuildDiar)", + "-DNEMO_SPEECH_BUILD_TTS=$(ConvertTo-CMakeBool $BuildTts)", + "-DNEMO_SPEECH_BUILD_NMT=$(ConvertTo-CMakeBool $BuildNmt)", + "-DNEMO_SPEECH_WITH_NMT=$(ConvertTo-CMakeBool $BuildNmt)", + "-DNEMO_SPEECH_BUILD_HTTP=$(ConvertTo-CMakeBool $BuildHttp)", + "-DNEMO_SPEECH_HTTP_TLS=$(ConvertTo-CMakeBool $BuildHttpTls)", + "-DNEMO_SPEECH_BUILD_GRPC=$(ConvertTo-CMakeBool $BuildGrpc)", + "-DNEMO_SPEECH_WITH_GRPC=$(ConvertTo-CMakeBool $BuildGrpc)", + "-DNEMO_SPEECH_WITH_FLASHLIGHT=$(ConvertTo-CMakeBool $BuildFlashlight)", + '-DNEMO_SPEECH_WITH_NORM=OFF', + "-DNEMO_SPEECH_TTS_WITH_JA=$(ConvertTo-CMakeBool $BuildTtsJa)", + "-DNEMO_SPEECH_TTS_WITH_ZH=$(ConvertTo-CMakeBool $BuildTtsZh)", + "-DNEMO_SPEECH_BUILD_TESTS=$(ConvertTo-CMakeBool $BuildTests)", + "-DBUILD_TESTING=$(ConvertTo-CMakeBool $BuildTests)", + "-DNEMO_SPEECH_BUILD_EXAMPLES=$(ConvertTo-CMakeBool $BuildExamples)", + "-DNEMO_SPEECH_BUILD_TOOLS=$(ConvertTo-CMakeBool $BuildTools)" +) +if ($VcpkgFeatures.Count -gt 0) { + $cmakeArgs += "-DCMAKE_TOOLCHAIN_FILE=$toolchain" + $cmakeArgs += "-DVCPKG_TARGET_TRIPLET=$VcpkgTriplet" + $cmakeArgs += "-DVCPKG_MANIFEST_FEATURES=$($VcpkgFeatures -join ';')" + $cmakeArgs += "-DVCPKG_INSTALLED_DIR=$(Join-Path $BuildDir 'vcpkg_installed')" +} if ($Compiler -eq 'clang-cl') { $cmakeArgs += '-DCMAKE_C_COMPILER=clang-cl' $cmakeArgs += '-DCMAKE_CXX_COMPILER=clang-cl' @@ -227,9 +409,18 @@ if ($Compiler -eq 'clang-cl') { $cmakeArgs += '-DCMAKE_CUDA_HOST_COMPILER=cl' } } +if ($TargetArch -eq 'arm64') { + # Avoid an additional OpenMP runtime DLL in ARM64 packages. + $cmakeArgs += '-DGGML_OPENMP=OFF' +} switch ($Backend) { - 'cuda' { $cmakeArgs += '-DGGML_CUDA=ON'; $cmakeArgs += "-DCMAKE_CUDA_ARCHITECTURES=$CudaArch" } + 'cuda' { + $cmakeArgs += '-DGGML_CUDA=ON' + $cmakeArgs += '-DGGML_VULKAN=OFF' + $cmakeArgs += "-DCMAKE_CUDA_ARCHITECTURES=$CudaArch" + } 'vulkan' { + $cmakeArgs += '-DGGML_CUDA=OFF' $cmakeArgs += '-DGGML_VULKAN=ON' $cmakeArgs += '-DNEMO_SPEECH_GGML_PATCHED=OFF' # ggml-vulkan hard-requires the SPIRV-Headers CMake package; the Vulkan @@ -237,41 +428,11 @@ switch ($Backend) { $spirvDir = Join-Path $env:VULKAN_SDK 'Lib\cmake\SPIRV-Headers' if (Test-Path $spirvDir) { $cmakeArgs += "-DSPIRV-Headers_DIR=$spirvDir" } } - 'cpu' { $cmakeArgs += '-DNEMO_SPEECH_GGML_PATCHED=OFF' } -} -if ($Grpc -or $Flashlight) { - $toolchain = Join-Path $VcpkgRoot 'scripts\buildsystems\vcpkg.cmake' - if (-not (Test-Path $toolchain)) { throw "vcpkg toolchain not found at $toolchain (bootstrap vcpkg first)." } - $cmakeArgs += "-DCMAKE_TOOLCHAIN_FILE=$toolchain" - $cmakeArgs += "-DVCPKG_TARGET_TRIPLET=$VcpkgTriplet" -} -if ($Grpc) { - $cmakeArgs += '-DNEMO_SPEECH_WITH_GRPC=ON' -} -if ($Nmt) { - $cmakeArgs += '-DNEMO_SPEECH_WITH_NMT=ON' -} -if ($Flashlight) { - $cmakeArgs += '-DNEMO_SPEECH_WITH_FLASHLIGHT=ON' -} -if ($TtsJa) { - $cmakeArgs += '-DNEMO_SPEECH_TTS_WITH_JA=ON' -} -if ($TtsZh) { - $cmakeArgs += '-DNEMO_SPEECH_TTS_WITH_ZH=ON' -} -if ($AsrOnly) { - $cmakeArgs += '-DNEMO_SPEECH_BUILD_ASR=ON' - $cmakeArgs += '-DNEMO_SPEECH_BUILD_DIAR=ON' - $cmakeArgs += '-DNEMO_SPEECH_BUILD_TTS=OFF' - $cmakeArgs += '-DNEMO_SPEECH_BUILD_NMT=OFF' - $cmakeArgs += '-DNEMO_SPEECH_WITH_NMT=OFF' - $cmakeArgs += '-DNEMO_SPEECH_BUILD_HTTP=OFF' - $cmakeArgs += '-DNEMO_SPEECH_BUILD_GRPC=OFF' - $cmakeArgs += '-DNEMO_SPEECH_WITH_GRPC=OFF' -} -if ($Http) { - $cmakeArgs += '-DNEMO_SPEECH_BUILD_HTTP=ON' + 'cpu' { + $cmakeArgs += '-DGGML_CUDA=OFF' + $cmakeArgs += '-DGGML_VULKAN=OFF' + $cmakeArgs += '-DNEMO_SPEECH_GGML_PATCHED=OFF' + } } Write-Host "==> cmake $($cmakeArgs -join ' ')" diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index f44decd..94c121e 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -9,3 +9,6 @@ if(NEMO_SPEECH_BUILD_NMT) target_link_libraries(riva_server PRIVATE nemo_speech_grpc_nmt) target_compile_definitions(riva_server PRIVATE NEMO_SPEECH_BUILD_NMT=1) endif() + +install(TARGETS riva_server + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/tests/cpp/asr/test_diar_streaming.cpp b/tests/cpp/asr/test_diar_streaming.cpp index 69f133e..9c3af7a 100644 --- a/tests/cpp/asr/test_diar_streaming.cpp +++ b/tests/cpp/asr/test_diar_streaming.cpp @@ -131,7 +131,9 @@ main(int argc, char** argv) { std::fprintf(stderr, "--batching-check requires streaming mode\n"); return 2; } - ggml_runtime::BackendManager bm({.use_gpu = use_gpu}); + ggml_runtime::Params backend_params; + backend_params.use_gpu = use_gpu; + ggml_runtime::BackendManager bm(backend_params); BatchingConfig batching; batching.enabled = batching_check; batching.max_batch_size = 8; diff --git a/tests/cpp/asr/test_rnnt_concurrency.cpp b/tests/cpp/asr/test_rnnt_concurrency.cpp index 2420d84..4119f8f 100644 --- a/tests/cpp/asr/test_rnnt_concurrency.cpp +++ b/tests/cpp/asr/test_rnnt_concurrency.cpp @@ -193,11 +193,13 @@ verify_encoder_batch(RnntModel& model, int right_context) { } struct BatchResult { - std::vector> values = std::vector>(B); - std::vector frames = std::vector(B); + explicit BatchResult(int batch_size) : values(batch_size), frames(batch_size) {} + + std::vector> values; + std::vector frames; }; auto run_batch = [&]() { - BatchResult result; + BatchResult result(B); std::vector states; for (int b = 0; b < B; ++b) states.push_back(model.make_cache_state()); std::atomic ready{0}; diff --git a/tests/cpp/asr/test_sortformer_parity.cpp b/tests/cpp/asr/test_sortformer_parity.cpp index 300c857..d26a6a5 100644 --- a/tests/cpp/asr/test_sortformer_parity.cpp +++ b/tests/cpp/asr/test_sortformer_parity.cpp @@ -113,7 +113,9 @@ main(int argc, char** argv) { if (std::string(argv[i]) == "--gpu") use_gpu = true; - ggml_runtime::BackendManager bm({.use_gpu = use_gpu}); + ggml_runtime::Params backend_params; + backend_params.use_gpu = use_gpu; + ggml_runtime::BackendManager bm(backend_params); nemo_speech::asr::SortformerModel model(bm, gguf_path); const int n_chunks = static_cast(load_ref(ref_dir, "n_chunks").i[0]); diff --git a/tests/install/install_ps1_test.py b/tests/install/install_ps1_test.py index 3f49e2a..a774a7f 100644 --- a/tests/install/install_ps1_test.py +++ b/tests/install/install_ps1_test.py @@ -62,10 +62,20 @@ def source_repository(root: Path, version: str, binary: Path) -> Path: """[CmdletBinding()] param( [string]$Backend, + [string]$Profile, [string]$BuildDir, [string]$Config, + [string]$CudaArch, + [string]$VcpkgRoot, + [string]$VcpkgTriplet, + [switch]$Grpc, + [switch]$Nmt, + [switch]$Flashlight, + [switch]$TtsJa, + [switch]$TtsZh, [switch]$AsrOnly, - [switch]$Http + [switch]$Http, + [switch]$HttpTls ) $ErrorActionPreference = 'Stop' $root = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) @@ -226,7 +236,7 @@ def run(*arguments: str, ok: bool = True) -> subprocess.CompletedProcess[str]: require((source_prefix / "bin" / "nemo-speech.exe").is_file(), "source binary") require( (source_prefix / ".nemo-speech-install").read_text(encoding="utf-8") - == f"1.2.6 windows {arch} cpu source:v1.2.6 profile:speech-server", + == f"1.2.6 windows {arch} cpu source:v1.2.6 profile:server", "source metadata", ) repeated = run( diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..52c4036 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "name": "nemo-speech", + "version-string": "1.0.0", + "builtin-baseline": "9e593bb18ea69cc5095e012465dcd675a822ed0d", + "dependencies": [], + "features": { + "asr": { + "description": "Dependencies shared by ASR and diarization", + "dependencies": [ + "sentencepiece" + ] + }, + "examples": { + "description": "Dependencies for all public examples", + "dependencies": [ + "portaudio" + ] + }, + "flashlight": { + "description": "Compression support for the Flashlight/KenLM decoder", + "dependencies": [ + "bzip2", + "liblzma", + "zlib" + ] + }, + "grpc": { + "description": "Dependencies for the Riva-compatible gRPC server", + "dependencies": [ + "grpc", + "protobuf" + ] + }, + "http-tls": { + "description": "TLS support for the HTTP server", + "dependencies": [ + "openssl" + ] + } + } +}