From e36fb1d9318215c0ece6146f4844d78364ea3519 Mon Sep 17 00:00:00 2001 From: impressionyang Date: Wed, 13 May 2026 18:12:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20Windows=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E4=B8=8B=E8=BD=BD=E4=B8=8E=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- CMakeLists.txt | 1 + cmake/dependencies.cmake | 26 ++- scripts/setup_deps_windows.ps1 | 287 +++++++++++++++++++++++++++++++++ 3 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 scripts/setup_deps_windows.ps1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 77e5e47..f373fb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,6 +156,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE $<$>:Qt5::DBus> ${ONNXRUNTIME_LIBRARIES} ${PORTAUDIO_LIBRARIES} + $<$:winmm ksuser setupapi ole32> $<$>:pthread> ) diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index 73a5498..669edd9 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -7,9 +7,17 @@ set(THIRD_PARTY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party") # ---------------------------------------------------------------------------- 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 - NAMES onnxruntime - PATHS "${ONNXRUNTIME_ROOT}/lib" + NAMES onnxruntime onnxruntime.lib + PATHS "${ONNXRUNTIME_LIB_PATH}" NO_DEFAULT_PATH ) find_path(ONNXRUNTIME_INCLUDE_DIR @@ -23,6 +31,20 @@ if(ONNXRUNTIME_LIB AND ONNXRUNTIME_INCLUDE_DIR) set(ONNXRUNTIME_INCLUDE_DIRS ${ONNXRUNTIME_INCLUDE_DIR}) message(STATUS "找到 ONNX Runtime: ${ONNXRUNTIME_LIB}") 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}" + "$/${DLL_NAME}" + COMMENT "复制 ${DLL_NAME} 到输出目录" + ) + endforeach() + endif() else() message(WARNING "未找到 ONNX Runtime,推理功能将使用占位实现") endif() diff --git a/scripts/setup_deps_windows.ps1 b/scripts/setup_deps_windows.ps1 new file mode 100644 index 0000000..63809c9 --- /dev/null +++ b/scripts/setup_deps_windows.ps1 @@ -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 ""