From 065ff3861a274ad68b6eaaa0cc0c7973989f2304 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Wed, 1 Jul 2026 14:33:42 +0800 Subject: [PATCH] =?UTF-8?q?build:=20Qt=E8=B7=AF=E5=BE=84=E6=94=B9$env{QT?= =?UTF-8?q?=5FROOT}+=E9=85=8D=E7=BD=AE=E6=9C=9F=E7=8E=AF=E5=A2=83=E6=8A=A4?= =?UTF-8?q?=E6=A0=8F(FATAL:QT=5FROOT/Qt=E7=89=88=E6=9C=AC/VTK=E5=B0=B1?= =?UTF-8?q?=E4=BD=8D/VTK=E7=89=88=E6=9C=AC;WARN:=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E9=9B=86)+=E6=96=87=E6=A1=A3=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 46 +++++++++++++++++++++++++++++++++++++++ CMakePresets.json | 2 +- build.bat | 10 +++++++++ docs/ENV_SETUP_Windows.md | 19 +++++++++++----- 4 files changed, 70 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e775c0..bd35344 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) if(MSVC) + # 显式钉死 MSVC 运行时库:Release=/MD,Debug=/MDd,杜绝静默漂移(ABI 一致性,见 ENV_SETUP §9.2)。 + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") add_compile_options(/utf-8 /MP /W4 /permissive-) # 生成 PDB——即使 Release 优化构建也产出调试符号,使 minidump / 运行期崩溃栈可符号化分析 # (生产桌面端排障必需)。/Zi 编译期调试信息;/DEBUG 链接产 PDB;/OPT:REF,ICF 抵消 /DEBUG @@ -31,7 +33,38 @@ endif() # - 仅非 Qt 依赖(GDAL/PROJ/OpenSSL/Eigen/...)走 vcpkg # ===================================================================== +# ===================================================================== +# 构建环境护栏(把「配置错→运行时随机崩溃」变成「配置期一眼可查」) +# 校准基准:本机 Qt 6.11.1 msvc2022_64 + VTK 9.6.x + VS2026-preview 工具集。 +# 工具集只 WARN 不 FATAL(本机 VS2026-preview 与预编译 Qt v143 ABI 兼容、可正常构建)。 +# 详见 docs/ENV_SETUP_Windows.md §4/§5/§9。 +# ===================================================================== + +if(WIN32) + # QT_ROOT 环境变量必须已设且指向有效的官方 MSVC Qt kit(预设的 CMAKE_PREFIX_PATH 读它)。 + if(NOT DEFINED ENV{QT_ROOT} OR "$ENV{QT_ROOT}" STREQUAL "" + OR NOT EXISTS "$ENV{QT_ROOT}/lib/cmake/Qt6") + message(FATAL_ERROR + "QT_ROOT 未设置或无效。请 setx QT_ROOT \"<你的Qt>\\6.11.1\\msvc2022_64\" 后重开终端。见 docs/ENV_SETUP_Windows.md §4。") + endif() +endif() + find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Network Sql Concurrent) + +# Qt 版本护栏:major.minor 必须是 6.11(任意补丁号可)。换大小版本会与源码编的 VTK/ADS ABI/兼容性错位。 +if(NOT Qt6_VERSION VERSION_LESS 6.11 AND Qt6_VERSION VERSION_LESS 6.12) + # 6.11.x —— 合规。 +else() + message(FATAL_ERROR + "Qt 版本不匹配:找到 ${Qt6_VERSION},需要 6.11.x(与源码编的 VTK/ADS 兼容)。请安装 6.11.1 msvc2022_64 并把 QT_ROOT 指向它。见 docs/ENV_SETUP_Windows.md §4。") +endif() + +# VTK 就位护栏(friendly):find_package REQUIRED 也会失败,但这里给出可操作的原因。 +if(NOT EXISTS "${CMAKE_SOURCE_DIR}/external/vtk-install/lib/cmake/vtk-9.6") + message(FATAL_ERROR + "VTK 未就位。请按 docs/ENV_SETUP_Windows.md §5.1 源码 Release 编 VTK 9.6.x 到 external/vtk-install。") +endif() + # VTK 9 必须指定 COMPONENTS,否则 VTK_LIBRARIES 为空、链接不到任何 VTK。 # 来自 VTK_DIR(external/vtk-install)。随渲染层增补模块(Volume/Filters 等)。 find_package(VTK REQUIRED COMPONENTS @@ -42,6 +75,19 @@ find_package(VTK REQUIRED COMPONENTS FiltersSources ) +# VTK 版本护栏:major.minor 须为 9.6(VTK_DIR 路径已带 vtk-9.6,越界基本是误装/误指)。 +if(VTK_VERSION VERSION_LESS 9.6 OR NOT VTK_VERSION VERSION_LESS 9.7) + message(FATAL_ERROR + "VTK 版本不匹配:找到 ${VTK_VERSION},需要 9.6.x。请按 docs/ENV_SETUP_Windows.md §5.1 用同一 Qt/工具集重编到 external/vtk-install。") +endif() + +# 工具集护栏(仅 WARN,绝不 FATAL):预编译 Qt 是 msvc2022(v143);VTK 必须与 app 用同一工具集编, +# 否则 std::map/std::string 跨界 ABI 崩溃(见 §10)。本机 VS2026-preview 与 v143 兼容、可正常构建。 +if(MSVC AND NOT MSVC_TOOLSET_VERSION STREQUAL "143") + message(WARNING + "MSVC 工具集为 v${MSVC_TOOLSET_VERSION}(非 v143)。预编译 Qt 为 msvc2022(v143);请确保 external/vtk-install 的 VTK 与本 app 用【同一工具集】编,避免 ABI 不匹配崩溃。见 docs/ENV_SETUP_Windows.md §9.2。") +endif() + # 非 Qt 依赖(vcpkg),随分层逐步启用: # find_package(GDAL CONFIG REQUIRED) # find_package(PROJ CONFIG REQUIRED) diff --git a/CMakePresets.json b/CMakePresets.json index aef7804..31b86fa 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -12,7 +12,7 @@ "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", "VCPKG_TARGET_TRIPLET": "x64-windows", "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", - "CMAKE_PREFIX_PATH": "D:/Qt/6.11.1/msvc2022_64", + "CMAKE_PREFIX_PATH": "$env{QT_ROOT}", "VTK_DIR": "${sourceDir}/external/vtk-install/lib/cmake/vtk-9.6" } }, diff --git a/build.bat b/build.bat index 1e23b5e..a9d005c 100644 --- a/build.bat +++ b/build.bat @@ -42,6 +42,16 @@ if not exist "%CMAKE%" ( echo [build] cmake not found: "%CMAKE%" & exit /b 1 ) REM --- activate MSVC environment (cl / link / include / lib) --- call "%VCVARS%" >nul +REM --- environment guardrails (fail loud & early, before cmake configure) --- +if not defined QT_ROOT ( + echo [build] QT_ROOT is not set. Run: setx QT_ROOT "D:\Qt\6.11.1\msvc2022_64" ^(see docs/ENV_SETUP_Windows.md^), then reopen the terminal. + exit /b 1 +) +if not defined VCPKG_ROOT ( + echo [build] VCPKG_ROOT is not set. Run: setx VCPKG_ROOT "C:\dev\vcpkg" ^(see docs/ENV_SETUP_Windows.md^), then reopen the terminal. + exit /b 1 +) + set "CMD=%~1" if "%CMD%"=="" set "CMD=app" diff --git a/docs/ENV_SETUP_Windows.md b/docs/ENV_SETUP_Windows.md index 831636f..8b0dcb6 100644 --- a/docs/ENV_SETUP_Windows.md +++ b/docs/ENV_SETUP_Windows.md @@ -68,9 +68,14 @@ setx VCPKG_ROOT "C:\dev\vcpkg" # 永久;新开终端生效 1. 用官方在线安装器(或已装则开 `D:\Qt\MaintenanceTool.exe`)→ Add or remove components → 登录 Qt 账号。 2. 展开 Qt → **Qt 6.11.1**,勾选 **MSVC 2022 64-bit**,安装。 3. 完成后应存在 `D:\Qt\6.11.1\msvc2022_64\lib\cmake\Qt6`。 -4. 预设通过 `CMAKE_PREFIX_PATH=D:/Qt/6.11.1/msvc2022_64` 找到它(§6)。**全链路只此一份 Qt。** +4. **设 `QT_ROOT` 环境变量指向该 kit**(与 `VCPKG_ROOT` 同一套路,预设 `CMAKE_PREFIX_PATH=$env{QT_ROOT}` 读它,§6): + ```powershell + setx QT_ROOT "<你的路径>\6.11.1\msvc2022_64" # 永久;新开终端生效 + ``` + **全链路只此一份 Qt。** 版本仍须是 **6.11.1**(换版本可能与源码编的 VTK/ADS 不匹配)。 -> 若你的 Qt 装在别处/别的版本:**改预设/环境的 `CMAKE_PREFIX_PATH` 指向你的 `msvc2022_64`,但版本仍须是 6.11.1**(换版本可能与源码编的 VTK/ADS 不匹配)。 +> 若你的 Qt 装在别处/别的版本:**改 `QT_ROOT` 指向你的 `msvc2022_64` 即可**,无需动预设;但版本仍须是 6.11.1。 +> 未设 `QT_ROOT` 时:`build.bat` 会立即报 `[build] QT_ROOT is not set...` 并退出;直接跑 cmake 则配置期 `FATAL_ERROR: QT_ROOT 未设置或无效`。 --- @@ -125,7 +130,7 @@ git clone --branch qwt-6.2 https://git.code.sf.net/p/qwt/git external/qwt-src "CMAKE_BUILD_TYPE": "Debug", "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", "VCPKG_TARGET_TRIPLET": "x64-windows", - "CMAKE_PREFIX_PATH": "D:/Qt/6.11.1/msvc2022_64", + "CMAKE_PREFIX_PATH": "$env{QT_ROOT}", "VTK_DIR": "${sourceDir}/external/vtk-install/lib/cmake/vtk-9.6" } }, @@ -135,7 +140,7 @@ git clone --branch qwt-6.2 https://git.code.sf.net/p/qwt/git external/qwt-src ] } ``` -- **预设确实设 `CMAKE_PREFIX_PATH`(官方 Qt)+ `VTK_DIR`(源码编的 VTK)**——这是「方案②-修订」的核心,别按旧文档去掉它。 +- **预设确实设 `CMAKE_PREFIX_PATH`(官方 Qt,读 `$env{QT_ROOT}`)+ `VTK_DIR`(源码编的 VTK,仓库相对、无需环境变量)**——这是「方案②-修订」的核心,别按旧文档去掉它。`QT_ROOT` 未 setx 时配置期会 FATAL(§4)。 - vcpkg 只经 `CMAKE_TOOLCHAIN_FILE` 管非 Qt 依赖;triplet `x64-windows`。 ### 6.2 根 `CMakeLists.txt` 要点 @@ -181,7 +186,7 @@ build.bat configure # CMakeLists 改动后强制重跑 configure ### 9.1 前置就位 - [ ] `cl` / `cmake`(≥3.21) / `ninja` / `git` 可用;`VCPKG_ROOT` 已设。 -- [ ] Qt **6.11.1** 的 **`msvc2022_64`**(MSVC,非 MinGW)存在于 `CMAKE_PREFIX_PATH` 指向处;`.../msvc2022_64/lib/cmake/Qt6` 在。 +- [ ] `QT_ROOT` 已 setx 指向 **6.11.1 `msvc2022_64`** kit(MSVC,非 MinGW);`$QT_ROOT/lib/cmake/Qt6` 在(预设 `CMAKE_PREFIX_PATH=$env{QT_ROOT}` 读它;未设则配置期 FATAL)。 - [ ] `external/vtk-install/lib/cmake/vtk-9.6` 存在(VTK 已源码编 install)。 - [ ] `external/qwt-src/src` 存在(如需详情页图表)。 - [ ] `vcpkg.json` 的 `builtin-baseline` 未被改动。 @@ -205,7 +210,9 @@ build.bat configure # CMakeLists 改动后强制重跑 configure | 现象 | 根因 | 处理 | |---|---|---| | **点对象树/渲染时,崩在 `std::_Tree::_Find_lower_bound`(`std::map`/`set` 查找),`_Myhead` 是 `0xFFFF...` 之类垃圾值,读取访问冲突** | **STL ABI 不匹配**:Debug/Release 混链、`/MD` vs `/MDd`、`_ITERATOR_DEBUG_LEVEL` 不一致、或工具集不匹配(最常见:**别处/别配置的 VTK/Qt**,或 **Debug app 链 Release 依赖**) | 按 §9.2 逐项核对;**删 `build/` 全 Release 干净重建**;确认 VTK 是 §5.1 那份 | -| 链接期报「找不到 Qt6::/VTK::」 | 预设 `CMAKE_PREFIX_PATH`/`VTK_DIR` 指向不存在 | 按 §4/§5 就位或改预设路径 | +| 配置期 `FATAL_ERROR: QT_ROOT 未设置或无效` / `build.bat` 报 `[build] QT_ROOT is not set` | 未 setx `QT_ROOT` 或指向的 kit 不含 `lib/cmake/Qt6` | `setx QT_ROOT "<你的Qt>\6.11.1\msvc2022_64"` 后**重开终端**(§4) | +| 配置期 `FATAL_ERROR: Qt 版本不匹配` / `VTK 版本不匹配` / `VTK 未就位` | 装了非 6.11.x Qt、非 9.6.x VTK,或 `external/vtk-install` 缺失 | 按 §4/§5 装对版本/就位 VTK | +| 链接期报「找不到 Qt6::/VTK::」 | 预设 `CMAKE_PREFIX_PATH`(`$env{QT_ROOT}`)/`VTK_DIR` 指向不存在 | 按 §4/§5 就位或修正 `QT_ROOT` | | 配置报「add_subdirectory ... 不是已存在目录」 | 引用了未随仓库的目录(如误提交本地临时工具目录) | 从 `CMakeLists.txt` 去掉该引用,或补齐该目录 | | 详情页图表缺失但不报错 | `external/qwt-src` 未就位(§5.3) | 克隆 Qwt 后重配置 | | 双 Qt / 起不来找不到 platform 插件 | 混入了 vcpkg/别处的 Qt dll | 只用官方 `windeployqt` 对齐单一 Qt |