SOUI 项目打包发布指南¶
本章详细介绍如何将 SOUI 项目打包并发布到目标环境,包括依赖管理、资源打包、部署配置和分发策略等关键步骤。
概述¶
部署架构¶
SOUI 应用程序采用模块化架构,部署时需要考虑以下组件:
SOUI 应用程序
├── 核心可执行文件 (YourApp.exe)
├── SOUI 核心库 (soui.dll, utilities.dll)
├── 渲染模块 (render-gdi.dll/render-skia.dll)
├── 图像解码模块 (imgdecoder-stb.dll/imgdecoder-gdip.dll)
├── 应用资源 (uires/ 或 uires.zip)
└── 系统资源 (soui-sys-resource.dll)
部署方式对比¶
部署方式 | 优势 | 劣势 | 适用场景 |
---|---|---|---|
绿色部署 | 无需安装,即拷即用 | 文件较多,易丢失 | 便携应用,开发测试 |
安装包部署 | 专业化,集成度高 | 需要安装权限 | 商业软件发布 |
单文件部署 | 文件单一,易分发 | 启动稍慢,占用内存大 | 工具类软件 |
构建准备¶
构建环境要求¶
- Visual Studio 2017+ 或兼容的编译器
- Windows SDK 10.0+
- CMake 3.16+(可选)
依赖分析¶
核心依赖库¶
# 使用 dumpbin 分析依赖
dumpbin /DEPENDENTS your_app.exe
# SOUI 核心依赖
soui.dll # SOUI 核心库
utilities.dll # 工具库
render-gdi.dll # GDI 渲染器
imgdecoder-stb.dll # stb 图像解码器
soui-sys-resource.dll # 系统资源
# 系统依赖
kernel32.dll, user32.dll, gdi32.dll, ole32.dll
项目配置检查清单¶
- ✅ 运行时库:设置为
/MT
(静态链接)或/MD
(动态链接) - ✅ 字符集:统一使用 Unicode 字符集
- ✅ 优化级别:Release 版本使用
/O2
优化 - ✅ 调试信息:Release 版本移除调试信息或使用
/Zi
- ✅ 清单文件:包含 DPI 感知和兼容性设置
资源打包¶
资源组织策略¶
1. 文件夹部署¶
YourApp/
├── YourApp.exe
├── soui.dll
├── utilities.dll
├── render-gdi.dll
├── imgdecoder-wic.dll
├── soui-sys-resource.dll
└── uires/
├── uires.idx
├── xml/
├── image/
└── translation/
优势:资源易于修改和更新,支持热更新 劣势:文件数量多,容易被误删或修改
2. 压缩包部署¶
SouiFactory souiFactory;
// 使用 ZIP 压缩资源
SAutoRefPtr<IResProvider> pResProvider;
souiFactory.CreateResProvider(RES_ZIP, (IObjRef**)&pResProvider);
if (!pResProvider->Init((LPARAM)_T("uires.zip"), 0))
{
return FALSE;
}
theApp->AddResProvider(pResProvider);
打包脚本示例:
#!/bin/bash
echo "开始打包资源..."
mkdir -p temp_package
cp -r uires/* temp_package/
cd temp_package
zip -r ../uires.zip .
cd .. && rm -rf temp_package
echo "资源打包完成:uires.zip"
3. PE 资源嵌入¶
// 将资源编译到可执行文件中
SouiFactory souiFactory;
SAutoRefPtr<IResProvider> pResProvider;
souiFactory.CreateResProvider(RES_PE, (IObjRef**)&pResProvider);
if (!pResProvider->Init((WPARAM)GetModuleHandle(NULL), 0))
{
return FALSE;
}
theApp->AddResProvider(pResProvider);
资源文件配置(.rc 文件):
#include "resource.h"
IDR_RES_ZIP ZIPRES DISCARDABLE "uires.zip"
IDR_LAYOUT_MAIN XML DISCARDABLE "xml\\main.xml"
多语言资源管理¶
语言包结构¶
translation/
├── zh-cn.xml # 简体中文
├── zh-tw.xml # 繁体中文
├── en-us.xml # 英语
├── ja-jp.xml # 日语
└── ko-kr.xml # 韩语
动态语言切换¶
class CLanguageManager
{
public:
static bool LoadLanguage(const SStringT& strLangCode)
{
SStringT strLangFile;
strLangFile.Format(_T("translation\\%s.xml"), strLangCode);
CAutoRefPtr<IResProvider> pLangRes;
CreateResProvider(RES_FILE, (IObjRef**)&pLangRes);
if (pLangRes->Init((LPARAM)strLangFile.c_str(), 0))
{
SApplication::getSingleton().AddResProvider(pLangRes);
return true;
}
return false;
}
static void SwitchLanguage(const SStringT& strLangCode)
{
RemoveCurrentLanguage();
LoadLanguage(strLangCode);
RefreshAllWindows();
}
};
自动化构建¶
PowerShell 构建脚本¶
# build-release.ps1
param(
[string]$Configuration = "Release",
[string]$Platform = "x64",
[switch]$Clean
)
$ErrorActionPreference = "Stop"
Write-Host "开始构建 SOUI 项目..." -ForegroundColor Green
# 清理构建
if ($Clean) {
Remove-Item -Path "build" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "bin" -Recurse -Force -ErrorAction SilentlyContinue
}
# 创建构建目录
New-Item -ItemType Directory -Force -Path "build"
New-Item -ItemType Directory -Force -Path "bin\\$Configuration"
# 构建项目
try {
& "MSBuild.exe" `
"YourProject.sln" `
"/p:Configuration=$Configuration" `
"/p:Platform=$Platform" `
"/p:OutDir=..\\bin\\$Configuration\\" `
"/maxcpucount" `
"/verbosity:minimal"
if ($LASTEXITCODE -ne 0) {
throw "编译失败,退出码:$LASTEXITCODE"
}
}
catch {
Write-Error "编译失败:$_"
exit 1
}
# 复制依赖库
$Dependencies = @(
"soui.dll",
"utilities.dll",
"render-gdi.dll",
"imgdecoder-wic.dll",
"soui-sys-resource.dll"
)
foreach ($Dependency in $Dependencies) {
$SourcePath = "third_party\\soui\\bin\\$Dependency"
$DestPath = "bin\\$Configuration\\$Dependency"
if (Test-Path $SourcePath) {
Copy-Item $SourcePath $DestPath -Force
}
}
# 打包资源
& ".\\scripts\\package-resources.ps1" -OutputPath "bin\\$Configuration"
Write-Host "构建完成!" -ForegroundColor Green
CMake 构建配置¶
# CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(SOUIApp VERSION 1.0.0)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 发布配置
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2 /DNDEBUG")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /SUBSYSTEM:WINDOWS")
endif()
# SOUI 库路径
set(SOUI_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/soui)
# 包含和链接目录
include_directories(${SOUI_ROOT}/include/soui)
include_directories(${SOUI_ROOT}/include/utilities)
link_directories(${SOUI_ROOT}/lib)
# 源文件
file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h")
add_executable(${PROJECT_NAME} WIN32 ${SOURCES})
# 链接库
target_link_libraries(${PROJECT_NAME}
soui utilities comctl32 ole32 oleaut32
uuid kernel32 user32 gdi32
)
# 后构建事件:复制依赖文件
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${SOUI_ROOT}/bin/soui.dll"
"${SOUI_ROOT}/bin/utilities.dll"
"${SOUI_ROOT}/bin/render-gdi.dll"
"${SOUI_ROOT}/bin/imgdecoder-wic.dll"
"${SOUI_ROOT}/bin/soui-sys-resource.dll"
$<TARGET_FILE_DIR:${PROJECT_NAME}>
)
# 复制资源文件
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/uires"
"$<TARGET_FILE_DIR:${PROJECT_NAME}>/uires"
)
安装包制作¶
NSIS 安装脚本¶
; installer.nsi
!include "MUI2.nsh"
Name "SOUI应用程序"
OutFile "SOUIApp_Setup.exe"
InstallDir "$PROGRAMFILES\\SOUIApp"
RequestExecutionLevel admin
; 版本信息
VIProductVersion "1.0.0.0"
VIAddVersionKey "ProductName" "SOUI应用程序"
VIAddVersionKey "FileVersion" "1.0.0.0"
; 现代UI配置
!define MUI_ABORTWARNING
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "license.txt"
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "SimpChinese"
; 安装文件
Section "核心程序" SecCore
SectionIn RO
SetOutPath "$INSTDIR"
File "bin\\Release\\SOUIApp.exe"
File "bin\\Release\\soui.dll"
File "bin\\Release\\utilities.dll"
File "bin\\Release\\render-gdi.dll"
File "bin\\Release\\imgdecoder-wic.dll"
File "bin\\Release\\soui-sys-resource.dll"
SetOutPath "$INSTDIR\\uires"
File /r "bin\\Release\\uires\\*.*"
; 注册表项
WriteRegStr HKLM "Software\\SOUIApp" "InstallPath" "$INSTDIR"
; 卸载信息
WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\SOUIApp" "DisplayName" "SOUI应用程序"
WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\SOUIApp" "UninstallString" "$INSTDIR\\Uninstall.exe"
WriteUninstaller "$INSTDIR\\Uninstall.exe"
SectionEnd
Section "桌面快捷方式" SecDesktop
CreateShortCut "$DESKTOP\\SOUI应用程序.lnk" "$INSTDIR\\SOUIApp.exe"
SectionEnd
; 卸载程序
Section "Uninstall"
Delete "$INSTDIR\\SOUIApp.exe"
Delete "$INSTDIR\\*.dll"
RMDir /r "$INSTDIR\\uires"
Delete "$DESKTOP\\SOUI应用程序.lnk"
DeleteRegKey HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\SOUIApp"
DeleteRegKey HKLM "Software\\SOUIApp"
Delete "$INSTDIR\\Uninstall.exe"
RMDir "$INSTDIR"
SectionEnd
部署策略¶
绿色部署¶
适用场景:便携应用、开发测试、内部工具
部署步骤: 1. 创建应用程序目录 2. 复制所有依赖文件 3. 配置相对路径资源加载 4. 创建启动脚本(可选)
@echo off
REM startup.bat
set APP_DIR=%~dp0
cd /d "%APP_DIR%"
start "" "SOUIApp.exe"
安装包部署¶
适用场景:商业软件发布、企业级应用
部署特点: - 专业的安装向导 - 系统集成(注册表、开始菜单) - 自动依赖检测和安装 - 完整的卸载功能
单文件部署¶
适用场景:工具类软件、快速分发
实现方式: 1. 使用资源嵌入技术 2. 静态链接所有依赖 3. 压缩可执行文件
// 单文件部署配置
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
#pragma comment(lib, "soui_static.lib")
#pragma comment(lib, "utilities_static.lib")
// 嵌入所有资源
#define USE_EMBEDDED_RESOURCES
测试与验证¶
部署测试清单¶
- ✅ 干净环境测试:在未安装开发工具的机器上测试
- ✅ 权限测试:在受限用户权限下测试
- ✅ 路径测试:测试中文路径和特殊字符路径
- ✅ 依赖检查:验证所有依赖库都已包含
- ✅ 功能验证:确保所有功能正常工作
- ✅ 多语言测试:验证多语言切换功能
- ✅ 性能测试:检查启动时间和内存占用
自动化测试脚本¶
# test-deployment.ps1
param([string]$PackagePath)
Write-Host "开始部署测试..." -ForegroundColor Green
# 检查文件完整性
$RequiredFiles = @(
"SOUIApp.exe",
"soui.dll",
"utilities.dll",
"render-gdi.dll",
"imgdecoder-wic.dll",
"soui-sys-resource.dll"
)
foreach ($File in $RequiredFiles) {
$FilePath = Join-Path $PackagePath $File
if (Test-Path $FilePath) {
Write-Host "✅ $File" -ForegroundColor Green
} else {
Write-Host "❌ $File 缺失" -ForegroundColor Red
}
}
# 启动测试
Write-Host "启动应用程序测试..." -ForegroundColor Yellow
$AppPath = Join-Path $PackagePath "SOUIApp.exe"
if (Test-Path $AppPath) {
$Process = Start-Process $AppPath -PassThru
Start-Sleep -Seconds 3
if (!$Process.HasExited) {
Write-Host "✅ 应用程序启动成功" -ForegroundColor Green
$Process | Stop-Process -Force
} else {
Write-Host "❌ 应用程序启动失败" -ForegroundColor Red
}
}
最佳实践¶
版本管理¶
- 语义化版本控制:使用 MAJOR.MINOR.PATCH 格式
- 版本信息嵌入:在可执行文件中嵌入版本信息
- 自动更新机制:实现增量更新功能
安全考虑¶
- 代码签名:对可执行文件进行数字签名
- 完整性检查:使用校验和验证文件完整性
- 权限最小化:避免请求不必要的管理员权限
性能优化¶
- 启动优化:延迟加载非关键资源
- 内存管理:合理配置静态/动态链接
- 文件压缩:使用合适的压缩算法减小体积
总结¶
SOUI 项目的打包发布需要综合考虑多个方面:
✅ 模块化架构:合理组织核心库和应用资源
✅ 多种部署方式:根据应用场景选择合适的部署策略
✅ 自动化构建:使用脚本和工具提高构建效率
✅ 完整性验证:确保部署包的完整性和功能正确性
✅ 最佳实践:遵循安全、性能和维护性原则
通过合理的打包策略和自动化流程,可以确保 SOUI 应用程序的稳定部署和高效分发,为用户提供优质的软件体验。