feat: 添加 Windows 依赖下载与配置脚本

1. scripts/setup_deps_windows.ps1
   - 自动检测 Qt 5.12 MinGW 工具链路径
   - 下载 ONNX Runtime Windows x64 预编译库 (1.21.0)
   - 从源码编译 PortAudio (MinGW WASAPI+WMME)
   - 将库文件放入 third_party/*/lib/win64/ 子目录
   - 可视化依赖安装状态汇总

2. cmake/dependencies.cmake
   - ONNX Runtime: Windows 查找 win64/lib/ 子目录
   - 自动将 onnxruntime.dll 复制到输出目录
   - PortAudio: 保持 win64/macos/linux 平台分离

3. CMakeLists.txt
   - Windows 链接 winmm ksuser setupapi ole32 (PortAudio 需要)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Alvin Young 2026-05-13 18:12:26 +08:00
parent 68b512d5cd
commit e36fb1d931
3 changed files with 312 additions and 2 deletions

View File

@ -156,6 +156,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
$<$<NOT:$<BOOL:${WIN32}>>:Qt5::DBus> $<$<NOT:$<BOOL:${WIN32}>>:Qt5::DBus>
${ONNXRUNTIME_LIBRARIES} ${ONNXRUNTIME_LIBRARIES}
${PORTAUDIO_LIBRARIES} ${PORTAUDIO_LIBRARIES}
$<$<BOOL:${WIN32}>:winmm ksuser setupapi ole32>
$<$<NOT:$<BOOL:${WIN32}>>:pthread> $<$<NOT:$<BOOL:${WIN32}>>:pthread>
) )

View File

@ -7,9 +7,17 @@ set(THIRD_PARTY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party")
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
set(ONNXRUNTIME_ROOT "${THIRD_PARTY_DIR}/onnxruntime") set(ONNXRUNTIME_ROOT "${THIRD_PARTY_DIR}/onnxruntime")
# Windows Windows Linux
if(WIN32)
set(ONNXRUNTIME_LIB_PATH "${ONNXRUNTIME_ROOT}/win64/lib")
set(ONNXRUNTIME_BIN_PATH "${ONNXRUNTIME_ROOT}/win64/bin")
else()
set(ONNXRUNTIME_LIB_PATH "${ONNXRUNTIME_ROOT}/lib")
endif()
find_library(ONNXRUNTIME_LIB find_library(ONNXRUNTIME_LIB
NAMES onnxruntime NAMES onnxruntime onnxruntime.lib
PATHS "${ONNXRUNTIME_ROOT}/lib" PATHS "${ONNXRUNTIME_LIB_PATH}"
NO_DEFAULT_PATH NO_DEFAULT_PATH
) )
find_path(ONNXRUNTIME_INCLUDE_DIR find_path(ONNXRUNTIME_INCLUDE_DIR
@ -23,6 +31,20 @@ if(ONNXRUNTIME_LIB AND ONNXRUNTIME_INCLUDE_DIR)
set(ONNXRUNTIME_INCLUDE_DIRS ${ONNXRUNTIME_INCLUDE_DIR}) set(ONNXRUNTIME_INCLUDE_DIRS ${ONNXRUNTIME_INCLUDE_DIR})
message(STATUS "找到 ONNX Runtime: ${ONNXRUNTIME_LIB}") message(STATUS "找到 ONNX Runtime: ${ONNXRUNTIME_LIB}")
add_compile_definitions(HAVE_ONNXRUNTIME) add_compile_definitions(HAVE_ONNXRUNTIME)
# Windows DLL
if(WIN32 AND EXISTS "${ONNXRUNTIME_BIN_PATH}")
file(GLOB ONNX_DLLS "${ONNXRUNTIME_BIN_PATH}/*.dll")
foreach(DLL ${ONNX_DLLS})
get_filename_component(DLL_NAME ${DLL} NAME)
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${DLL}"
"$<TARGET_FILE_DIR:${PROJECT_NAME}>/${DLL_NAME}"
COMMENT " ${DLL_NAME} "
)
endforeach()
endif()
else() else()
message(WARNING "未找到 ONNX Runtime推理功能将使用占位实现") message(WARNING "未找到 ONNX Runtime推理功能将使用占位实现")
endif() endif()

View File

@ -0,0 +1,287 @@
# ============================================================================
# Windows 依赖库下载与配置脚本
# 用途:为 Qt 5.12 MinGW 64-bit 编译环境下载/编译第三方依赖
# 运行:在 PowerShell 中执行 .\scripts\setup_deps_windows.ps1
# ============================================================================
$ErrorActionPreference = "Stop"
# 项目根目录
$ProjectRoot = Split-Path $PSScriptRoot -Parent
$ThirdParty = Join-Path $ProjectRoot "third_party"
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " Impress Voice Input - Windows 依赖配置" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
Write-Host ""
# ============================================================================
# 1. 检测 MinGW 工具链(来自 Qt 5.12
# ============================================================================
function Find-MinGW {
# 常见 Qt 5.12 MinGW 路径
$Paths = @(
"D:\Qt\Qt5.12.10\Tools\mingw730_64\bin",
"D:\Qt\Qt5.12\Tools\mingw730_64\bin",
"C:\Qt\Qt5.12.10\Tools\mingw730_64\bin",
"C:\Qt\Qt5.12\Tools\mingw730_64\bin"
)
foreach ($p in $Paths) {
$gcc = Join-Path $p "gcc.exe"
if (Test-Path $gcc) { return $p }
}
# 尝试从 PATH 查找
$gccPath = Get-Command "x86_64-w64-mingw32-gcc.exe" -ErrorAction SilentlyContinue
if ($gccPath) { return Split-Path $gccPath.Source -Parent }
$gccPath = Get-Command "gcc.exe" -ErrorAction SilentlyContinue
if ($gccPath) {
$dir = Split-Path $gccPath.Source -Parent
if ($dir -match "mingw") { return $dir }
}
return $null
}
$MingwBin = Find-MinGW
if (-not $MingwBin) {
Write-Host "[ERROR] 未找到 MinGW 工具链" -ForegroundColor Red
Write-Host "请确保已安装 Qt 5.12 MinGW 64-bit或手动设置路径。" -ForegroundColor Red
Write-Host "常见路径:" -ForegroundColor Red
Write-Host " D:\Qt\Qt5.12.10\Tools\mingw730_64\bin" -ForegroundColor Yellow
exit 1
}
Write-Host "[OK] MinGW 工具链: $MingwBin" -ForegroundColor Green
$CCompiler = Join-Path $MingwBin "gcc.exe"
$CxxCompiler = Join-Path $MingwBin "g++.exe"
$MakeTool = Join-Path $MingwBin "mingw32-make.exe"
if (-not (Test-Path $MakeTool)) {
$MakeTool = Get-Command "make.exe" -ErrorAction SilentlyContinue
if (-not $MakeTool) {
Write-Host "[WARN] 未找到 mingw32-make.exe尝试使用 make.exe" -ForegroundColor Yellow
$MakeTool = "make"
} else {
$MakeTool = $MakeTool.Source
}
}
# 将 MinGW 加入 PATH
$env:PATH = "$MingwBin;" + $env:PATH
# ============================================================================
# 2. 下载 ONNX Runtime (Windows x64)
# ============================================================================
Write-Host ""
Write-Host "--------------------------------------------" -ForegroundColor Cyan
Write-Host " [1/2] 下载 ONNX Runtime" -ForegroundColor Cyan
Write-Host "--------------------------------------------" -ForegroundColor Cyan
$OnnxVersion = "1.21.0"
$OnnxDir = Join-Path $ThirdParty "onnxruntime"
$OnnxWinDir = Join-Path $OnnxDir "win64"
if ((Test-Path (Join-Path $OnnxWinDir "lib\onnxruntime.lib")) -or
(Test-Path (Join-Path $OnnxWinDir "lib\onnxruntime.dll"))) {
Write-Host "[SKIP] ONNX Runtime win64 已存在: $OnnxWinDir" -ForegroundColor Yellow
} else {
Write-Host "[INFO] 下载 ONNX Runtime $OnnxVersion (Windows x64)..." -ForegroundColor White
$ZipUrl = "https://github.com/microsoft/onnxruntime/releases/download/v$OnnxVersion/onnxruntime-win-x64-$OnnxVersion.zip"
$ZipPath = Join-Path $env:TEMP "onnxruntime-win-x64.zip"
# 创建临时目录用于下载
if (Test-Path $ZipPath) { Remove-Item $ZipPath -Force }
try {
# 使用 .NET 下载(比 Invoke-WebRequest 快)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$client = New-Object System.Net.WebClient
$client.Headers.Add("User-Agent", "PowerShell")
$client.DownloadFile($ZipUrl, $ZipPath)
Write-Host "[OK] 下载完成" -ForegroundColor Green
} catch {
Write-Host "[ERROR] 下载失败: $_" -ForegroundColor Red
Write-Host "请手动下载: $ZipUrl" -ForegroundColor Yellow
Write-Host "解压到: $OnnxWinDir" -ForegroundColor Yellow
exit 1
}
# 解压
Write-Host "[INFO] 解压到 $OnnxWinDir..." -ForegroundColor White
$ExtractTemp = Join-Path $env:TEMP "onnxruntime_extract"
if (Test-Path $ExtractTemp) { Remove-Item $ExtractTemp -Recurse -Force }
Expand-Archive -Path $ZipPath -DestinationPath $ExtractTemp -Force
# 找到解压目录(通常是 onnxruntime-win-x64-1.21.0
$ExtractedDir = Get-ChildItem $ExtractTemp -Directory | Select-Object -First 1
# 创建目标目录结构
New-Item -ItemType Directory -Force -Path (Join-Path $OnnxWinDir "lib") | Out-Null
New-Item -ItemType Directory -Force -Path (Join-Path $OnnxWinDir "include") | Out-Null
New-Item -ItemType Directory -Force -Path (Join-Path $OnnxWinDir "bin") | Out-Null
# 复制文件
Copy-Item "$($ExtractedDir.FullName)\lib\*" (Join-Path $OnnxWinDir "lib") -Recurse -Force
Copy-Item "$($ExtractedDir.FullName)\include\*" (Join-Path $OnnxWinDir "include") -Recurse -Force
Copy-Item "$($ExtractedDir.FullName)\lib\*.dll" (Join-Path $OnnxWinDir "bin") -Force -ErrorAction SilentlyContinue
# 清理
Remove-Item $ZipPath -Force
Remove-Item $ExtractTemp -Recurse -Force
Write-Host "[OK] ONNX Runtime 已安装到: $OnnxWinDir" -ForegroundColor Green
}
# ============================================================================
# 3. 编译 PortAudio (MinGW)
# ============================================================================
Write-Host ""
Write-Host "--------------------------------------------" -ForegroundColor Cyan
Write-Host " [2/2] 编译 PortAudio (MinGW)" -ForegroundColor Cyan
Write-Host "--------------------------------------------" -ForegroundColor Cyan
$PortaudioDir = Join-Path $ThirdParty "portaudio"
$PortaudioWinDir = Join-Path $PortaudioDir "lib" "win64"
if (Test-Path (Join-Path $PortaudioWinDir "libportaudio.a")) {
Write-Host "[SKIP] PortAudio win64 已存在: $PortaudioWinDir" -ForegroundColor Yellow
} else {
if (-not (Test-Path (Join-Path $PortaudioDir "CMakeLists.txt"))) {
Write-Host "[ERROR] PortAudio 源码不存在: $PortaudioDir" -ForegroundColor Red
Write-Host "请确保 third_party/portaudio 目录下有 PortAudio 源码" -ForegroundColor Yellow
exit 1
}
$BuildDir = Join-Path $ProjectRoot "build_portaudio"
if (Test-Path $BuildDir) { Remove-Item $BuildDir -Recurse -Force }
New-Item -ItemType Directory -Force -Path $BuildDir | Out-Null
# 检测 CMake
$CmakeCmd = Get-Command "cmake.exe" -ErrorAction SilentlyContinue
if (-not $CmakeCmd) {
# 尝试从 Qt 自带的 cmake
$QtCmake = "D:\Qt\Qt5.12.10\Tools\CMake_64\bin\cmake.exe"
if (-not (Test-Path $QtCmake)) {
$QtCmake = "C:\Qt\Qt5.12.10\Tools\CMake_64\bin\cmake.exe"
}
if (Test-Path $QtCmake) {
$CmakeCmd = $QtCmake
} else {
Write-Host "[ERROR] 未找到 cmake.exe" -ForegroundColor Red
Write-Host "请安装 CMake 或确保 Qt 包含 CMake 工具" -ForegroundColor Yellow
exit 1
}
} else {
$CmakeCmd = $CmakeCmd.Source
}
Write-Host "[INFO] CMake: $CmakeCmd" -ForegroundColor White
Write-Host "[INFO] 编译目录: $BuildDir" -ForegroundColor White
# 配置 CMake
Push-Location $BuildDir
try {
$ConfigureArgs = @(
$PortaudioDir
"-G", "MinGW Makefiles"
"-DCMAKE_BUILD_TYPE=Release"
"-DCMAKE_C_COMPILER=$CCompiler"
"-DCMAKE_CXX_COMPILER=$CxxCompiler"
"-DPA_BUILD_SHARED_LIBS=OFF"
"-DPA_USE_WMME=ON"
"-DPA_USE_WASAPI=ON"
"-DPA_USE_DS=OFF"
"-DPA_USE_ASIO=OFF"
"-DPA_USE_WDMKS=OFF"
)
Write-Host "[INFO] 配置 CMake..." -ForegroundColor White
& $CmakeCmd @ConfigureArgs 2>&1 | ForEach-Object { Write-Host $_ }
# 编译
Write-Host "[INFO] 编译 PortAudio..." -ForegroundColor White
& $MakeTool 2>&1 | ForEach-Object { Write-Host $_ }
# 查找编译产物
$LibFile = Get-ChildItem $BuildDir -Recurse -Filter "libportaudio.a" -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $LibFile) {
# 可能叫 portaudio.lib 或其他名字
$LibFile = Get-ChildItem $BuildDir -Recurse -Filter "*.a" -ErrorAction SilentlyContinue |
Where-Object { $_.Name -match "portaudio" } | Select-Object -First 1
}
if (-not $LibFile) {
Write-Host "[ERROR] 未找到编译产物 libportaudio.a" -ForegroundColor Red
Write-Host "请检查上面的编译输出" -ForegroundColor Yellow
exit 1
}
# 复制到头文件目录旁边
New-Item -ItemType Directory -Force -Path $PortaudioWinDir | Out-Null
Copy-Item $LibFile.FullName (Join-Path $PortaudioWinDir "libportaudio.a") -Force
Write-Host "[OK] PortAudio 已编译并安装到: $PortaudioWinDir" -ForegroundColor Green
} finally {
Pop-Location
}
# 清理编译目录
if (Test-Path $BuildDir) {
Remove-Item $BuildDir -Recurse -Force
}
}
# ============================================================================
# 4. 更新 CMake 依赖配置以支持 Windows 子目录
# ============================================================================
Write-Host ""
Write-Host "--------------------------------------------" -ForegroundColor Cyan
Write-Host " [配置] 检查 CMake 依赖路径" -ForegroundColor Cyan
Write-Host "--------------------------------------------" -ForegroundColor Cyan
$DepsFile = Join-Path $ProjectRoot "cmake" "dependencies.cmake"
if (Test-Path $DepsFile) {
$DepsContent = Get-Content $DepsFile -Raw -Encoding UTF8
if ($DepsContent -notmatch "PORTAUDIO_LIB_PATH") {
Write-Host "[WARN] dependencies.cmake 似乎未包含 Windows 平台分离逻辑" -ForegroundColor Yellow
Write-Host "请确保使用 qt5 分支的最新代码" -ForegroundColor Yellow
} else {
Write-Host "[OK] dependencies.cmake 已包含 Windows 平台配置" -ForegroundColor Green
}
}
# ============================================================================
# 5. 汇总
# ============================================================================
Write-Host ""
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " 依赖配置完成!" -ForegroundColor Green
Write-Host "============================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "第三方库结构:" -ForegroundColor White
Write-Host ""
Write-Host "third_party/" -ForegroundColor Gray
Write-Host "├── portaudio/" -ForegroundColor Gray
Write-Host "│ ├── include/ (头文件,已有)" -ForegroundColor Gray
Write-Host "│ └── lib/win64/ (MinGW 编译的库)" -ForegroundColor Gray
if (Test-Path (Join-Path $PortaudioWinDir "libportaudio.a")) {
Write-Host "│ └── libportaudio.a [已就绪]" -ForegroundColor Green
} else {
Write-Host "│ └── libportaudio.a [缺失]" -ForegroundColor Red
}
Write-Host "├── onnxruntime/" -ForegroundColor Gray
Write-Host "│ ├── include/ (头文件,已有)" -ForegroundColor Gray
Write-Host "│ ├── lib/ (Linux 库)" -ForegroundColor Gray
Write-Host "│ └── win64/ (Windows 库)" -ForegroundColor Gray
if (Test-Path (Join-Path $OnnxWinDir "lib\onnxruntime.lib")) {
Write-Host "│ ├── onnxruntime.lib [已就绪]" -ForegroundColor Green
Write-Host "│ └── onnxruntime.dll [已就绪]" -ForegroundColor Green
} else {
Write-Host "│ ├── onnxruntime.lib [缺失]" -ForegroundColor Red
}
Write-Host "├── dr_libs/ (header-only)" -ForegroundColor Gray
Write-Host "└── nlohmann_json/ (header-only)" -ForegroundColor Gray
Write-Host ""
Write-Host "下一步:" -ForegroundColor White
Write-Host "1. 在 Qt Creator 中重新运行 CMake Configure" -ForegroundColor Yellow
Write-Host "2. 重新构建项目" -ForegroundColor Yellow
Write-Host ""