From 2a70d6245e94b20246dc1d04294ce2348ebceaed Mon Sep 17 00:00:00 2001 From: luochen570 <1160510664@qq.com> Date: Fri, 29 May 2026 22:59:55 +0800 Subject: [PATCH] ci: build Windows release package --- .gitea/workflows/build-linux-release.yml | 49 -------- .gitea/workflows/build-windows-release.yml | 49 ++++++++ CMakeLists.txt | 11 +- README.md | 133 ++++++++++----------- docs/windows/build-windows.ps1 | 4 +- docs/windows/setup-deps-windows.ps1 | 2 +- docs/windows/setup-python-venv-windows.ps1 | 4 +- scripts/package-linux-release.sh | 96 --------------- scripts/package-windows-release.ps1 | 59 +++++++++ 9 files changed, 183 insertions(+), 224 deletions(-) delete mode 100644 .gitea/workflows/build-linux-release.yml create mode 100644 .gitea/workflows/build-windows-release.yml delete mode 100755 scripts/package-linux-release.sh create mode 100644 scripts/package-windows-release.ps1 diff --git a/.gitea/workflows/build-linux-release.yml b/.gitea/workflows/build-linux-release.yml deleted file mode 100644 index 4d318d2..0000000 --- a/.gitea/workflows/build-linux-release.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Build Linux Release - -on: - push: - branches: - - main - tags: - - 'v*' - pull_request: - branches: - - main - workflow_dispatch: - -jobs: - build-linux: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install host tools - run: | - sudo apt-get update - sudo apt-get install -y --no-install-recommends \ - ca-certificates \ - curl \ - bzip2 \ - tar \ - file - - - name: Build release package - run: | - chmod +x scripts/*.sh - ./scripts/package-linux-release.sh - - - name: Verify package - run: | - test -s dist-linux/chengnan-linux-x86_64.tar.gz - sha256sum -c dist-linux/chengnan-linux-x86_64.tar.gz.sha256 - tar -tzf dist-linux/chengnan-linux-x86_64.tar.gz | grep -E '^chengnan-linux-x86_64/(bin/chengnan|run-chengnan.sh)$' - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: chengnan-linux-x86_64 - path: | - dist-linux/chengnan-linux-x86_64.tar.gz - dist-linux/chengnan-linux-x86_64.tar.gz.sha256 - if-no-files-found: error diff --git a/.gitea/workflows/build-windows-release.yml b/.gitea/workflows/build-windows-release.yml new file mode 100644 index 0000000..bd66550 --- /dev/null +++ b/.gitea/workflows/build-windows-release.yml @@ -0,0 +1,49 @@ +name: Build Windows Release + +on: + push: + branches: + - main + tags: + - 'v*' + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + build-windows: + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Configure MSVC environment + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + + - name: Build and package Windows app + shell: pwsh + run: | + Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force + .\scripts\package-windows-release.ps1 -Toolchain msvc + + - name: Verify package + shell: pwsh + run: | + if (!(Test-Path .\dist-windows\chengnan-windows-x86_64.zip)) { throw "missing zip" } + if (!(Test-Path .\dist-windows\chengnan-windows-x86_64.zip.sha256)) { throw "missing sha256" } + $zip = Get-Item .\dist-windows\chengnan-windows-x86_64.zip + if ($zip.Length -le 0) { throw "empty zip" } + $hashLine = Get-Content .\dist-windows\chengnan-windows-x86_64.zip.sha256 + if ($hashLine -notmatch '^[0-9a-f]{64}\s+chengnan-windows-x86_64\.zip$') { throw "invalid sha256 file" } + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: chengnan-windows-x86_64 + path: | + dist-windows/chengnan-windows-x86_64.zip + dist-windows/chengnan-windows-x86_64.zip.sha256 + if-no-files-found: error diff --git a/CMakeLists.txt b/CMakeLists.txt index 280768c..8e424e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,11 +8,6 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC OFF) -# 本项目目标为 Linux 本地构建。Windows 工具链文件仅作为历史参考,不参与构建。 -if (WIN32) - message(FATAL_ERROR "chengnan 当前按 README 要求只支持 Linux 构建,请不要使用 Windows 编译工具链。") -endif() - find_package(Qt6 QUIET COMPONENTS Widgets Concurrent) if (NOT Qt6_FOUND) find_package(Qt5 REQUIRED COMPONENTS Widgets Concurrent) @@ -53,6 +48,10 @@ target_compile_definitions(chengnan PRIVATE CHENGNAN_APP_VERSION="${PROJECT_VERSION}" ) -target_compile_options(chengnan PRIVATE -Wall -Wextra -Wpedantic) +if (MSVC) + target_compile_options(chengnan PRIVATE /W4 /permissive-) +else() + target_compile_options(chengnan PRIVATE -Wall -Wextra -Wpedantic) +endif() install(TARGETS chengnan RUNTIME DESTINATION bin) diff --git a/README.md b/README.md index f101d2e..43b10ef 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ chengnan:基于 Qt 与 OpenCV 的图像显示与处理系统 ## 当前实现状态 -本项目已初始化为一个 Qt Widgets + OpenCV + CMake 的 C++ 图像处理应用。当前构建策略已调整为:**在 Linux 中编译,不使用 Windows 编译工具链;所有构建项目所需工具和依赖均采用项目目录内的二进制安装方式,不使用源码编译安装依赖。** +本项目已初始化为一个 Qt Widgets + OpenCV + CMake 的 C++ 图像处理应用。当前发布目标为:**Windows x64 桌面应用**,使用 MSVC、Qt Windows 运行时、OpenCV Windows 预编译 DLL 构建并打包;Linux 构建仅作为代码验证用途。 已实现功能: @@ -24,59 +24,80 @@ chengnan:基于 Qt 与 OpenCV 的图像显示与处理系统 - 基于 HSV 均值的简单规则分类 - 使用 `QThread` + 信号槽执行 OpenCV 处理任务,避免阻塞 UI -## Linux 二进制构建原则 +## Windows 发布与隔离依赖原则 -本项目后续构建以 Linux 环境为准,要求如下: +本项目发布目标为 Windows x64 桌面应用,要求如下: -- 在 Linux 中编译本项目 -- 不使用 Windows 编译工具链 -- 不使用 `cl.exe`、`windeployqt.exe`、Windows `cmake.exe`、Windows `ninja.exe` 构建本项目 -- 不使用当前系统上的 GCC / G++ 作为项目构建工具链 -- 不全局安装 Qt、OpenCV、CMake、Ninja、Python 包等依赖 -- 不污染系统 `/usr`、`/usr/local`、系统 Python site-packages 或全局环境变量 -- 所有构建项目所需工具和依赖必须放在项目目录内 -- 所有构建项目所需依赖必须优先使用官方或可信来源的二进制包 -- 不使用源码编译安装 Qt / OpenCV 等依赖 -- Python 使用项目目录内虚拟环境,不使用 uv 安装或管理环境 -- 构建脚本只能临时设置当前进程环境变量,不能修改系统环境变量 +- 在 Windows x64 + Visual Studio MSVC 环境中构建发布包 +- 使用 `cl.exe`、Windows `cmake.exe`、Windows `ninja.exe`、`windeployqt.exe` 构建和部署 +- Qt、OpenCV、CMake、Ninja 等依赖优先使用项目目录内二进制包或 CI 缓存中的可信二进制包 +- 不把 Qt/OpenCV 安装到系统目录,不修改系统全局环境变量 +- 发布包必须包含 `chengnan.exe`、Qt 运行时、Qt plugins、OpenCV DLL 和校验文件 +- Linux 构建脚本仅用于代码验证,不作为最终发布制品来源 -推荐目录约定: +推荐 Windows 依赖目录约定: ```text chengnan/ ├── tools/ -│ ├── cmake-linux/ # Linux 版 CMake 二进制 -│ ├── ninja-linux/ # Linux 版 Ninja 二进制 -│ ├── compiler-linux/ # Linux 版二进制编译器工具链,如 LLVM/Clang -│ ├── python-bin/ # Python 二进制包 -│ └── python-venv/ # Python 虚拟环境 +│ ├── cmake-current-windows/ # Windows 版 CMake +│ └── python-bin/ # 可选:项目内 Python 二进制 ├── third_party/ -│ ├── qt-linux/ # Linux 版 Qt 二进制包 -│ └── opencv-linux/ # Linux 版 OpenCV 二进制包 -└── build-linux/ # Linux 构建输出目录 +│ ├── qt-windows-msvc/ # Windows 版 Qt MSVC +│ ├── opencv-windows/ # Windows 版 OpenCV 预编译包 +│ └── qt-tools/ # Ninja 等 Qt 工具 +├── build-windows/ # Windows 构建输出目录 +└── dist-windows/ # Windows 发布包输出目录 ``` -> 注意:如果 OpenCV 没有适配当前 Linux 发行版的官方二进制包,不应退回源码编译安装。应改为寻找可信的预编译包、容器化二进制 SDK、发行版无污染解包方案,或更换依赖来源。 +> 注意:Windows 发布包依赖 Qt 与 OpenCV Windows 预编译二进制。CI Runner 必须能访问这些依赖,或仓库/缓存中已经准备好对应目录。 ## 编译工具链与版本声明 -本项目当前已验证的 Linux 二进制工具链如下,全部位于项目目录内的 `tools/linux-build-env/`,不依赖全局安装的 Qt / OpenCV / CMake / Ninja,也不使用 Windows 编译工具链。 +本项目发布目标为 Windows x64,推荐工具链如下: -| 工具 / 依赖 | 当前版本 | 项目内路径 | 说明 | -| --- | --- | --- | --- | -| micromamba | 2.6.2 | `tools/micromamba/bin/micromamba` | 仅用于在项目目录内获取二进制包 | -| CMake | 4.3.3 | `tools/linux-build-env/bin/cmake` | CMake 最低要求 3.21,当前验证版本 4.3.3 | -| Ninja | 1.13.2 | `tools/linux-build-env/bin/ninja` | CMake 使用 `-G Ninja` 生成构建系统 | -| Clang / Clang++ | 22.1.6 | `tools/linux-build-env/bin/clang++` | 本项目指定使用项目内 Clang,不使用系统 GCC / G++ | -| Qt | 5.15.15 | `tools/linux-build-env/`、`third_party/qt-linux` | 使用 Qt Widgets / Qt Concurrent;CMake 也兼容 Qt6 | -| OpenCV | 4.13.0 | `tools/linux-build-env/`、`third_party/opencv-linux` | 使用 `core`、`imgproc`、`imgcodecs` 组件 | -| C++ 标准 | C++17 | `CMakeLists.txt` | `CMAKE_CXX_STANDARD 17` | +| 工具 / 依赖 | 项目内路径 | 说明 | +| --- | --- | --- | +| Visual Studio Build Tools / MSVC | Runner 系统环境 | 提供 `cl.exe`,需通过 x64 Native Tools 或 `msvc-dev-cmd` 初始化 | +| CMake | `tools/cmake-current-windows/bin/cmake.exe` | CMake 最低要求 3.21 | +| Ninja | `third_party/qt-tools/Tools/Ninja/ninja.exe` | CMake 使用 `-G Ninja` 生成构建系统 | +| Qt | `third_party/qt-windows-msvc` | 使用 Qt Widgets / Qt Concurrent,部署时调用 `windeployqt.exe` | +| OpenCV | `third_party/opencv-windows/x64/vc16` | 使用 `core`、`imgproc`、`imgcodecs` 组件,发布时复制 DLL | +| C++ 标准 | `CMakeLists.txt` | `CMAKE_CXX_STANDARD 17` | -> 说明:`third_party/qt-linux` 和 `third_party/opencv-linux` 是指向 `tools/linux-build-env` 的项目内软链接,方便保持 README 中的依赖目录语义;真正的二进制依赖仍统一存放在 `tools/linux-build-env/`。 +Linux 二进制工具链仍可用于代码验证,但不作为发布包来源。 ## 如何构建 -### 一键构建 +### Windows 发布构建 + +本项目目标是 Windows 桌面应用。推荐在 Windows x64 + Visual Studio MSVC 环境中构建,仓库内 Windows 依赖约定如下: + +```text +third_party/qt-windows-msvc/ +third_party/opencv-windows/x64/vc16/ +third_party/qt-tools/Tools/Ninja/ninja.exe +tools/cmake-current-windows/bin/cmake.exe +``` + +在 Windows Runner 或 “x64 Native Tools Command Prompt for VS” 中执行: + +```powershell +powershell -ExecutionPolicy Bypass -File .\scripts\package-windows-release.ps1 -Toolchain msvc +``` + +生成的发布包: + +```text +dist-windows/chengnan-windows-x86_64.zip +dist-windows/chengnan-windows-x86_64.zip.sha256 +``` + +发布包内包含 `chengnan.exe`、Qt 运行时、Qt plugins 和 OpenCV DLL。解压后双击 `chengnan.exe` 运行。 + +### Linux 本地验证构建 + +Linux 构建仅用于本地验证 Qt/OpenCV 代码,不作为最终 Windows 发布包。 在 Linux 中进入项目目录执行: @@ -97,29 +118,6 @@ cd /root/chengnan build-linux/chengnan ``` -### 生成发布包 - -如需生成可分发的 Linux x86_64 发布包,执行: - -```bash -cd /root/chengnan -./scripts/package-linux-release.sh -``` - -脚本会先执行 Release 构建,再将程序、项目内 Qt/OpenCV 运行时库、Qt 插件和启动脚本打包到: - -```text -dist-linux/chengnan-linux-x86_64.tar.gz -dist-linux/chengnan-linux-x86_64.tar.gz.sha256 -``` - -解压后在有 X11 / Wayland 图形会话的 Linux 桌面环境中运行: - -```bash -tar -xzf chengnan-linux-x86_64.tar.gz -./chengnan-linux-x86_64/run-chengnan.sh -``` - ### 分步构建 如果希望先准备依赖,再单独构建: @@ -194,7 +192,7 @@ tools/cmake.tar.gz ## 当前项目内已有的二进制依赖记录 -当前目录中仍保留过 Windows 方案准备的二进制包和脚本,作为历史记录和可选参考,但**后续 Linux 构建不应使用这些 Windows 工具链**: +当前目录中准备或约定了 Windows 方案所需的二进制依赖和脚本: ```text third_party/qt-windows-msvc-sdk/ @@ -223,11 +221,11 @@ tools/cmake-current-windows/bin/cmake.exe tools/python-bin/python.exe ``` -这些 Windows 二进制内容不满足“在 Linux 里面编译,不使用 Windows 编译工具链”的新要求,因此 Linux 构建流程不应引用它们。 +这些 Windows 二进制内容是发布包构建所需依赖;Linux 验证构建不会引用它们。 -## Linux 构建目标 +## Linux 验证构建说明 -后续应补充或替换为 Linux 二进制依赖: +如需在 Linux 上做代码验证,可使用项目内 Linux 二进制依赖: - Linux 版 CMake 二进制包 - Linux 版 Ninja 二进制包 @@ -385,9 +383,8 @@ export CMAKE_PREFIX_PATH="$PWD/third_party/qt-linux;$PWD/third_party/opencv-linu 要求: -- 在 Linux 中编译本项目 -- 不使用 Windows 编译工具链 -- 不使用系统 GCC / G++ 作为项目构建工具链 +- Windows 发布包在 Windows x64 + MSVC 环境中构建 +- Linux 构建仅用于本地代码验证 - 不使用源码编译安装 Qt / OpenCV 等依赖 - 不建议直接全局安装 Qt 或 OpenCV - 不建议污染系统 `/usr`、`/usr/local` 等全局路径 @@ -424,7 +421,7 @@ chengnan/ │ ├── ImageWorker.cpp │ └── ImageConverter.cpp ├── docs/ -│ └── windows/ # 历史 Windows 依赖说明和脚本,仅作参考,不参与 Linux 构建 +│ └── windows/ # Windows 依赖说明和构建脚本 ├── scripts/ │ ├── setup-linux-binary-deps.sh │ ├── setup-python-venv-linux.sh @@ -502,7 +499,7 @@ export LD_LIBRARY_PATH="$PWD/third_party/qt-linux/lib:$PWD/third_party/opencv-li - 图像显示使用 QWidget 体系,不使用 `cv::imshow` - 图像处理任务不会明显阻塞 UI - 依赖安装和构建必须限制在项目目录内,不污染系统环境 -- 在 Linux 中编译,不使用 Windows 编译工具链 +- Windows 发布包可通过 Windows x64 + MSVC 构建生成 - 所有工具和依赖使用二进制包或解压式安装,不使用源码编译安装 ## 注意事项 diff --git a/docs/windows/build-windows.ps1 b/docs/windows/build-windows.ps1 index c5108e4..059ad28 100644 --- a/docs/windows/build-windows.ps1 +++ b/docs/windows/build-windows.ps1 @@ -1,13 +1,13 @@ param( [ValidateSet("msvc", "mingw")] [string]$Toolchain = "msvc", - [string]$BuildDir = "$PSScriptRoot\..\build-windows", + [string]$BuildDir = "$PSScriptRoot\..\..\build-windows", [switch]$Deploy ) $ErrorActionPreference = "Stop" -$ProjectRoot = Resolve-Path "$PSScriptRoot\.." +$ProjectRoot = Resolve-Path "$PSScriptRoot\..\.." $BuildDir = [System.IO.Path]::GetFullPath($BuildDir) $ThirdParty = Join-Path $ProjectRoot "third_party" $Tools = Join-Path $ProjectRoot "tools" diff --git a/docs/windows/setup-deps-windows.ps1 b/docs/windows/setup-deps-windows.ps1 index 44cb38b..cb07680 100644 --- a/docs/windows/setup-deps-windows.ps1 +++ b/docs/windows/setup-deps-windows.ps1 @@ -1,5 +1,5 @@ param( - [string]$InstallRoot = "$PSScriptRoot\..\third_party" + [string]$InstallRoot = "$PSScriptRoot\..\..\third_party" ) $ErrorActionPreference = "Stop" diff --git a/docs/windows/setup-python-venv-windows.ps1 b/docs/windows/setup-python-venv-windows.ps1 index b50b6e8..17efae3 100644 --- a/docs/windows/setup-python-venv-windows.ps1 +++ b/docs/windows/setup-python-venv-windows.ps1 @@ -1,6 +1,6 @@ param( - [string]$PythonBin = "$PSScriptRoot\..\tools\python-bin", - [string]$VenvDir = "$PSScriptRoot\..\tools\python-venv" + [string]$PythonBin = "$PSScriptRoot\..\..\tools\python-bin", + [string]$VenvDir = "$PSScriptRoot\..\..\tools\python-venv" ) $ErrorActionPreference = "Stop" diff --git a/scripts/package-linux-release.sh b/scripts/package-linux-release.sh deleted file mode 100755 index d4c6378..0000000 --- a/scripts/package-linux-release.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -ENV_DIR="$ROOT_DIR/tools/linux-build-env" -BUILD_DIR="$ROOT_DIR/build-linux" -DIST_DIR="$ROOT_DIR/dist-linux" -PACKAGE_ROOT="$DIST_DIR/chengnan-linux-x86_64" -APP_BIN="$PACKAGE_ROOT/bin/chengnan" -LIB_DIR="$PACKAGE_ROOT/lib" -PLUGIN_DIR="$PACKAGE_ROOT/plugins" -QT_CONF="$PACKAGE_ROOT/bin/qt.conf" -ARCHIVE="$DIST_DIR/chengnan-linux-x86_64.tar.gz" - -"$ROOT_DIR/scripts/build-linux-binary.sh" - -rm -rf "$PACKAGE_ROOT" "$ARCHIVE" -mkdir -p "$PACKAGE_ROOT/bin" "$LIB_DIR" "$PLUGIN_DIR" - -"$ENV_DIR/bin/cmake" --install "$BUILD_DIR" --prefix "$PACKAGE_ROOT" - -if [[ ! -x "$APP_BIN" ]]; then - echo "[package] 未找到可执行文件:$APP_BIN" >&2 - exit 1 -fi - -copy_lib() { - local lib="$1" - if [[ -f "$lib" ]]; then - cp -L -n "$lib" "$LIB_DIR/" - fi -} - -# 只打包项目内二进制环境中的依赖,避免把系统 /lib、/usr/lib 复制进制品。 -while IFS= read -r lib; do - case "$lib" in - "$ENV_DIR"/*) copy_lib "$lib" ;; - esac -done < <(LD_LIBRARY_PATH="$ENV_DIR/lib:${LD_LIBRARY_PATH:-}" ldd "$APP_BIN" | awk '/=>/ {print $3}' | sort -u) - -# Qt GUI 程序运行需要平台插件;同时带上常用图片格式插件,保证 jpg/png 等格式可打开。 -for subdir in platforms imageformats xcbglintegrations platformthemes styles iconengines; do - if [[ -d "$ENV_DIR/plugins/$subdir" ]]; then - mkdir -p "$PLUGIN_DIR/$subdir" - cp -L "$ENV_DIR/plugins/$subdir"/*.so "$PLUGIN_DIR/$subdir/" 2>/dev/null || true - fi -done - -# 平台插件自身还有二级依赖,继续收集项目内环境中的 .so。 -if [[ -d "$PLUGIN_DIR" ]]; then - while IFS= read -r plugin; do - while IFS= read -r lib; do - case "$lib" in - "$ENV_DIR"/*) copy_lib "$lib" ;; - esac - done < <(LD_LIBRARY_PATH="$ENV_DIR/lib:$LIB_DIR:${LD_LIBRARY_PATH:-}" ldd "$plugin" | awk '/=>/ {print $3}' | sort -u || true) - done < <(find "$PLUGIN_DIR" -type f -name '*.so' | sort) -fi - -cat > "$QT_CONF" <<'QTCFG' -[Paths] -Plugins = ../plugins -QTCFG - -cat > "$PACKAGE_ROOT/run-chengnan.sh" <<'RUNNER' -#!/usr/bin/env bash -set -euo pipefail -APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -export LD_LIBRARY_PATH="$APP_DIR/lib:${LD_LIBRARY_PATH:-}" -export QT_PLUGIN_PATH="$APP_DIR/plugins" -exec "$APP_DIR/bin/chengnan" "$@" -RUNNER -chmod +x "$PACKAGE_ROOT/run-chengnan.sh" - -if command -v patchelf >/dev/null 2>&1; then - patchelf --set-rpath '$ORIGIN/../lib' "$APP_BIN" || true -elif [[ -x "$ENV_DIR/bin/patchelf" ]]; then - "$ENV_DIR/bin/patchelf" --set-rpath '$ORIGIN/../lib' "$APP_BIN" || true -else - echo "[package] 未找到 patchelf,制品可通过 run-chengnan.sh 设置 LD_LIBRARY_PATH 运行。" -fi - -find "$PACKAGE_ROOT" -type f -name '*.so*' -exec chmod 0644 {} + -chmod +x "$APP_BIN" - -tar -C "$DIST_DIR" -czf "$ARCHIVE" "$(basename "$PACKAGE_ROOT")" - -if [[ ! -s "$ARCHIVE" ]]; then - echo "[package] 打包失败:$ARCHIVE 为空或不存在" >&2 - exit 1 -fi - -sha256sum "$ARCHIVE" > "$ARCHIVE.sha256" - -echo "[package] 发布包:$ARCHIVE" -echo "[package] 校验文件:$ARCHIVE.sha256" diff --git a/scripts/package-windows-release.ps1 b/scripts/package-windows-release.ps1 new file mode 100644 index 0000000..3bfea13 --- /dev/null +++ b/scripts/package-windows-release.ps1 @@ -0,0 +1,59 @@ +param( + [ValidateSet("msvc")] + [string]$Toolchain = "msvc", + [string]$BuildDir = "$PSScriptRoot\..\build-windows", + [string]$DistDir = "$PSScriptRoot\..\dist-windows" +) + +$ErrorActionPreference = "Stop" + +$ProjectRoot = Resolve-Path "$PSScriptRoot\.." +$BuildDir = [System.IO.Path]::GetFullPath($BuildDir) +$DistDir = [System.IO.Path]::GetFullPath($DistDir) +$PackageName = "chengnan-windows-x86_64" +$PackageDir = Join-Path $DistDir $PackageName +$ZipPath = Join-Path $DistDir "$PackageName.zip" +$HashPath = "$ZipPath.sha256" + +Write-Host "[package] ProjectRoot: $ProjectRoot" +Write-Host "[package] BuildDir: $BuildDir" +Write-Host "[package] DistDir: $DistDir" + +& "$ProjectRoot\docs\windows\build-windows.ps1" -Toolchain $Toolchain -BuildDir $BuildDir -Deploy + +$DeployDir = Join-Path $BuildDir "deploy" +$Exe = Join-Path $DeployDir "chengnan.exe" +if (!(Test-Path $Exe)) { + throw "未找到部署后的 Windows 可执行文件:$Exe" +} + +if (Test-Path $PackageDir) { Remove-Item -Recurse -Force $PackageDir } +if (Test-Path $ZipPath) { Remove-Item -Force $ZipPath } +if (Test-Path $HashPath) { Remove-Item -Force $HashPath } +New-Item -ItemType Directory -Force -Path $DistDir | Out-Null +Copy-Item -Recurse -Force $DeployDir $PackageDir + +$ReadmePath = Join-Path $PackageDir "README.txt" +@" +chengnan Windows x86_64 发布包 + +运行方式: +1. 解压整个目录。 +2. 双击 chengnan.exe 运行。 + +说明: +- 本目录已包含 Qt 运行时和 OpenCV DLL。 +- 请不要只复制 chengnan.exe,需保留同目录 DLL 和 Qt plugins 子目录。 +"@ | Set-Content -Encoding UTF8 $ReadmePath + +Compress-Archive -Path (Join-Path $PackageDir "*") -DestinationPath $ZipPath -Force + +$Hash = Get-FileHash -Algorithm SHA256 $ZipPath +"$($Hash.Hash.ToLower()) $(Split-Path -Leaf $ZipPath)" | Set-Content -Encoding ASCII $HashPath + +if (!(Test-Path $ZipPath) -or ((Get-Item $ZipPath).Length -le 0)) { + throw "发布包生成失败:$ZipPath" +} + +Write-Host "[package] 发布包:$ZipPath" +Write-Host "[package] 校验文件:$HashPath"