feat: 优化客户端跨平台配置和运行态管理
This commit is contained in:
+4
-2
@@ -7,6 +7,8 @@
|
||||
|
||||
1. package-sdk.ps1
|
||||
在 Windows 上生成给其他软件接入用的 UpdateClientSDK 包。
|
||||
注意:SDK 包只面向运行接入,不包含 config/server_config.json 和 config/server_config.qrc。
|
||||
服务端地址必须在打包前写入源码目录 config/server_config.json,并重新编译进 Launcher/Updater。
|
||||
|
||||
2. package-client.ps1
|
||||
在 Windows 上生成某个具体产品的最终客户端发布包。
|
||||
@@ -24,7 +26,7 @@
|
||||
|
||||
```powershell
|
||||
.\scripts\package-sdk.ps1 `
|
||||
-SourceDir .\out\bin `
|
||||
-SourceDir .\out\bin\Release `
|
||||
-OutputDir .\dist\UpdateClientSDK `
|
||||
-ZipFile .\dist\UpdateClientSDK.zip `
|
||||
-SdkVersion 0.1.0
|
||||
@@ -32,7 +34,7 @@
|
||||
|
||||
```powershell
|
||||
.\scripts\package-client.ps1 `
|
||||
-SourceDir .\out\bin `
|
||||
-SourceDir .\out\bin\Release `
|
||||
-ConfigFile .\config\app_config.json `
|
||||
-OutputDir .\dist\UpdateClient `
|
||||
-ZipFile .\dist\UpdateClient.zip
|
||||
|
||||
+47
-23
@@ -10,7 +10,7 @@ $ErrorActionPreference = "Stop"
|
||||
|
||||
$RepoRoot = Split-Path -Parent $PSScriptRoot
|
||||
if ([string]::IsNullOrWhiteSpace($SourceDir)) {
|
||||
$SourceDir = Join-Path $RepoRoot "out/bin"
|
||||
$SourceDir = Join-Path $RepoRoot "out/bin/Release"
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($OutputDir)) {
|
||||
$OutputDir = Join-Path $RepoRoot "dist/UpdateClient"
|
||||
@@ -40,13 +40,32 @@ $configRelativeParent = Split-Path $configRelativePath -Parent
|
||||
$runtimeDirRelative = Normalize-RelativePath (Split-Path $configRelativeParent -Parent)
|
||||
if ($runtimeDirRelative -eq ".") { $runtimeDirRelative = "" }
|
||||
|
||||
function Join-RelativePath([string]$Base, [string]$Child) {
|
||||
$baseNorm = Normalize-RelativePath $Base
|
||||
$childNorm = Normalize-RelativePath $Child
|
||||
if ([string]::IsNullOrWhiteSpace($baseNorm)) { return $childNorm }
|
||||
if ([string]::IsNullOrWhiteSpace($childNorm)) { return $baseNorm }
|
||||
return "$baseNorm/$childNorm"
|
||||
}
|
||||
function Join-RelativePath([string]$Base, [string]$Child) {
|
||||
$baseNorm = Normalize-RelativePath $Base
|
||||
$childNorm = Normalize-RelativePath $Child
|
||||
if ([string]::IsNullOrWhiteSpace($baseNorm)) { return $childNorm }
|
||||
if ([string]::IsNullOrWhiteSpace($childNorm)) { return $baseNorm }
|
||||
return "$baseNorm/$childNorm"
|
||||
}
|
||||
|
||||
function Get-InstallDirectoryId([string]$RuntimeDir) {
|
||||
$normalized = ([IO.Path]::GetFullPath($RuntimeDir) -replace '\\', '/').TrimEnd('/')
|
||||
$sha = [System.Security.Cryptography.SHA256]::Create()
|
||||
try {
|
||||
$bytes = [System.Text.Encoding]::UTF8.GetBytes($normalized)
|
||||
$hash = $sha.ComputeHash($bytes)
|
||||
return -join ($hash | ForEach-Object { $_.ToString("x2") })
|
||||
} finally {
|
||||
$sha.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
function Get-UserDataManifestCandidate([string]$RuntimeDir, [string]$ManifestName) {
|
||||
$localData = [Environment]::GetFolderPath("LocalApplicationData")
|
||||
if ([string]::IsNullOrWhiteSpace($localData)) { return "" }
|
||||
$installId = Get-InstallDirectoryId $RuntimeDir
|
||||
return Join-Path $localData "Marsco\UpdateClientSDK\installations\$installId\update\manifest_cache\$ManifestName"
|
||||
}
|
||||
|
||||
$requiredFields = @(
|
||||
"app_id", "channel", "current_version",
|
||||
@@ -81,9 +100,9 @@ $debugArtifacts = Get-ChildItem $source -Recurse -File | Where-Object {
|
||||
$_.Name -match '^(Qt5.*d|qwindowsd|libEGLd|libGLESv2d|msvcp.*d|vcruntime.*d)\.dll$' -or
|
||||
$_.Extension -in @('.pdb', '.ilk')
|
||||
}
|
||||
if ($debugArtifacts) {
|
||||
throw "Source directory contains Debug artifacts. Clean out/bin and rebuild Release first. Example: $($debugArtifacts[0].FullName)"
|
||||
}
|
||||
if ($debugArtifacts) {
|
||||
throw "Source directory contains Debug artifacts. Clean the Release output directory and rebuild Release first. Example: $($debugArtifacts[0].FullName)"
|
||||
}
|
||||
|
||||
$expectedMainPath = Join-RelativePath $runtimeDirRelative $mainExecutable
|
||||
$mainLeafName = Split-Path $mainExecutable -Leaf
|
||||
@@ -95,18 +114,23 @@ if ($duplicateMain) {
|
||||
throw "Source directory contains a duplicate main executable outside $expectedMainPath. Use a clean Release root directory: $($duplicateMain.FullName)"
|
||||
}
|
||||
|
||||
$manifestName = "manifest_$($settings.current_version).json"
|
||||
$sourceManifestRelative = Join-RelativePath $runtimeDirRelative "update/manifest_cache/$manifestName"
|
||||
$sourceManifest = Join-Path $source ($sourceManifestRelative -replace '/', [IO.Path]::DirectorySeparatorChar)
|
||||
if (-not (Test-Path $sourceManifest)) {
|
||||
$legacySourceManifest = Join-Path $source "update/manifest_cache/$manifestName"
|
||||
if (Test-Path $legacySourceManifest) {
|
||||
$sourceManifest = $legacySourceManifest
|
||||
}
|
||||
}
|
||||
if (-not (Test-Path $sourceManifest)) {
|
||||
throw "Missing signed Manifest cache for current version: $sourceManifest. Complete online update/verification for this version before packaging."
|
||||
}
|
||||
$manifestName = "manifest_$($settings.current_version).json"
|
||||
$runtimeDirAbsolute = if ([string]::IsNullOrWhiteSpace($runtimeDirRelative)) {
|
||||
$source
|
||||
} else {
|
||||
Join-Path $source ($runtimeDirRelative -replace '/', [IO.Path]::DirectorySeparatorChar)
|
||||
}
|
||||
$sourceManifestRelative = Join-RelativePath $runtimeDirRelative "update/manifest_cache/$manifestName"
|
||||
$manifestCandidates = @(
|
||||
(Get-UserDataManifestCandidate $runtimeDirAbsolute $manifestName),
|
||||
(Join-Path $source ($sourceManifestRelative -replace '/', [IO.Path]::DirectorySeparatorChar)),
|
||||
(Join-Path $source "update/manifest_cache/$manifestName")
|
||||
) | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
|
||||
$sourceManifest = $manifestCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
if (-not $sourceManifest -or -not (Test-Path $sourceManifest)) {
|
||||
$searched = ($manifestCandidates | ForEach-Object { " - $_" }) -join [Environment]::NewLine
|
||||
throw "Missing signed Manifest cache for current version: $manifestName. Complete online update/verification for this version before packaging. Searched paths:$([Environment]::NewLine)$searched"
|
||||
}
|
||||
|
||||
if (Test-Path $OutputDir) {
|
||||
Remove-Item $OutputDir -Recurse -Force
|
||||
|
||||
@@ -72,6 +72,27 @@ print(rel.replace(os.sep, "/").strip("/"))
|
||||
PY
|
||||
}
|
||||
|
||||
install_directory_id() {
|
||||
python3 - "$1" <<'PY'
|
||||
import hashlib
|
||||
import os
|
||||
import sys
|
||||
|
||||
value = os.path.realpath(sys.argv[1]).replace(os.sep, "/").rstrip("/")
|
||||
print(hashlib.sha256(value.encode("utf-8")).hexdigest())
|
||||
PY
|
||||
}
|
||||
|
||||
user_data_manifest_candidate() {
|
||||
local runtime_dir="$1"
|
||||
local manifest_name="$2"
|
||||
local data_home="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
local install_id
|
||||
install_id="$(install_directory_id "$runtime_dir")"
|
||||
printf '%s/Marsco/UpdateClientSDK/installations/%s/update/manifest_cache/%s' \
|
||||
"$data_home" "$install_id" "$manifest_name"
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--source-dir) SOURCE_DIR="$2"; shift 2 ;;
|
||||
@@ -148,12 +169,27 @@ if [[ -n "$DUPLICATE_MAIN" ]]; then
|
||||
fi
|
||||
|
||||
MANIFEST_NAME="manifest_${CURRENT_VERSION}.json"
|
||||
SOURCE_MANIFEST="$SOURCE_DIR/$(join_relative_path "$RUNTIME_DIR_RELATIVE" "update/manifest_cache/$MANIFEST_NAME")"
|
||||
if [[ ! -f "$SOURCE_MANIFEST" && -f "$SOURCE_DIR/update/manifest_cache/$MANIFEST_NAME" ]]; then
|
||||
SOURCE_MANIFEST="$SOURCE_DIR/update/manifest_cache/$MANIFEST_NAME"
|
||||
if [[ -z "$RUNTIME_DIR_RELATIVE" ]]; then
|
||||
RUNTIME_DIR_ABSOLUTE="$SOURCE_DIR"
|
||||
else
|
||||
RUNTIME_DIR_ABSOLUTE="$SOURCE_DIR/$RUNTIME_DIR_RELATIVE"
|
||||
fi
|
||||
MANIFEST_CANDIDATES=(
|
||||
"$(user_data_manifest_candidate "$RUNTIME_DIR_ABSOLUTE" "$MANIFEST_NAME")"
|
||||
"$SOURCE_DIR/$(join_relative_path "$RUNTIME_DIR_RELATIVE" "update/manifest_cache/$MANIFEST_NAME")"
|
||||
"$SOURCE_DIR/update/manifest_cache/$MANIFEST_NAME"
|
||||
)
|
||||
SOURCE_MANIFEST=""
|
||||
for candidate in "${MANIFEST_CANDIDATES[@]}"; do
|
||||
if [[ -f "$candidate" ]]; then
|
||||
SOURCE_MANIFEST="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "$SKIP_MANIFEST_CHECK" -eq 0 && ! -f "$SOURCE_MANIFEST" ]]; then
|
||||
echo "Missing signed Manifest cache for current version: $SOURCE_MANIFEST. Complete online update/verification for this version before packaging." >&2
|
||||
echo "Missing signed Manifest cache for current version: $MANIFEST_NAME." >&2
|
||||
echo "Complete online update/verification for this version before packaging. Searched paths:" >&2
|
||||
printf ' - %s\n' "${MANIFEST_CANDIDATES[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
+15
-8
@@ -12,7 +12,7 @@ $ErrorActionPreference = "Stop"
|
||||
|
||||
$RepoRoot = Split-Path -Parent $PSScriptRoot
|
||||
if ([string]::IsNullOrWhiteSpace($SourceDir)) {
|
||||
$SourceDir = Join-Path $RepoRoot "out/bin"
|
||||
$SourceDir = Join-Path $RepoRoot "out/bin/Release"
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($OutputDir)) {
|
||||
$OutputDir = Join-Path $RepoRoot "dist/UpdateClientSDK"
|
||||
@@ -60,7 +60,8 @@ $binDir = Join-Path $OutputDir "bin"
|
||||
$configDir = Join-Path $OutputDir "config"
|
||||
$scriptsDir = Join-Path $OutputDir "scripts"
|
||||
$commonDir = Join-Path $OutputDir "Common"
|
||||
New-Item $binDir,$configDir,$scriptsDir,$commonDir -ItemType Directory -Force | Out-Null
|
||||
$docsDir = Join-Path $OutputDir "Docs"
|
||||
New-Item $binDir,$configDir,$scriptsDir,$commonDir,$docsDir -ItemType Directory -Force | Out-Null
|
||||
|
||||
$excludedTopLevel = @("config", "update", "update_temp", "manifest_public_key.pem")
|
||||
if (-not $IncludeDemoMainApp) { $excludedTopLevel += "MainApp.exe" }
|
||||
@@ -100,8 +101,6 @@ Get-ChildItem $source -Force | Where-Object {
|
||||
|
||||
Copy-Item $exampleConfigPath (Join-Path $configDir "app_config.json") -Force
|
||||
Copy-Item $publicKey (Join-Path $configDir "manifest_public_key.pem") -Force
|
||||
Copy-Item (Join-Path $RepoRoot "config/server_config.json") (Join-Path $configDir "server_config.json") -Force
|
||||
Copy-Item (Join-Path $RepoRoot "config/server_config.qrc") (Join-Path $configDir "server_config.qrc") -Force
|
||||
|
||||
$commonSourceDir = Join-Path $RepoRoot "Common"
|
||||
$commonSourceFiles = @(
|
||||
@@ -118,16 +117,22 @@ foreach ($commonFile in $commonSourceFiles) {
|
||||
Copy-Item $commonPath (Join-Path $commonDir $commonFile) -Force
|
||||
}
|
||||
|
||||
$wordGuideSource = @($RepoRoot, (Join-Path $RepoRoot "Docs")) |
|
||||
$docsSourceDir = Join-Path $RepoRoot "Docs"
|
||||
if (Test-Path $docsSourceDir) {
|
||||
Copy-Item (Join-Path $docsSourceDir "*") $docsDir -Recurse -Force
|
||||
}
|
||||
|
||||
$wordGuideSource = @($RepoRoot, $docsSourceDir) |
|
||||
Where-Object { Test-Path $_ } |
|
||||
ForEach-Object { Get-ChildItem $_ -File -Filter "*.docx" } |
|
||||
Where-Object { $_.Name -like "*SDK*.docx" -and $_.Name -notlike "~$*" } |
|
||||
Sort-Object Name |
|
||||
Select-Object -First 1
|
||||
if (-not $wordGuideSource) {
|
||||
throw "SDK integration Word guide is missing. Expected a *SDK*.docx file in the repository root or Docs directory."
|
||||
if ($wordGuideSource) {
|
||||
Copy-Item $wordGuideSource.FullName (Join-Path $OutputDir $wordGuideSource.Name) -Force
|
||||
} else {
|
||||
Write-Warning "SDK Word guide is missing. Continue packaging with Markdown documents in Docs/."
|
||||
}
|
||||
Copy-Item $wordGuideSource.FullName (Join-Path $OutputDir $wordGuideSource.Name) -Force
|
||||
|
||||
Copy-Item (Join-Path $PSScriptRoot "package-client.ps1") (Join-Path $scriptsDir "package-client.ps1") -Force
|
||||
Copy-Item (Join-Path $PSScriptRoot "package-sdk.ps1") (Join-Path $scriptsDir "package-sdk.ps1") -Force
|
||||
@@ -139,6 +144,8 @@ Copy-Item (Join-Path $PSScriptRoot "install-sdk.ps1") (Join-Path $scriptsDir "in
|
||||
sdk_type = "external-updater-runtime"
|
||||
required_entry = "Launcher.exe"
|
||||
contains_demo_main_app = [bool]$IncludeDemoMainApp
|
||||
docs_entry = "Docs/01-客户端接入打包部署指南.md"
|
||||
word_guide_included = [bool]$wordGuideSource
|
||||
integration_sources = $commonSourceFiles
|
||||
} | ConvertTo-Json -Depth 3 | Set-Content (Join-Path $OutputDir "sdk_manifest.json") -Encoding UTF8
|
||||
|
||||
|
||||
+14
-8
@@ -74,7 +74,7 @@ if [[ -n "$DEBUG_ARTIFACT" ]]; then
|
||||
fi
|
||||
|
||||
rm -rf "$OUTPUT_DIR"
|
||||
mkdir -p "$OUTPUT_DIR/bin" "$OUTPUT_DIR/config" "$OUTPUT_DIR/scripts" "$OUTPUT_DIR/Common"
|
||||
mkdir -p "$OUTPUT_DIR/bin" "$OUTPUT_DIR/config" "$OUTPUT_DIR/scripts" "$OUTPUT_DIR/Common" "$OUTPUT_DIR/Docs"
|
||||
|
||||
shopt -s dotglob nullglob
|
||||
for item in "$SOURCE_DIR"/*; do
|
||||
@@ -94,8 +94,6 @@ shopt -u dotglob nullglob
|
||||
|
||||
cp "$EXAMPLE_CONFIG" "$OUTPUT_DIR/config/app_config.json"
|
||||
cp "$PUBLIC_KEY" "$OUTPUT_DIR/config/manifest_public_key.pem"
|
||||
cp "$REPO_ROOT/config/server_config.json" "$OUTPUT_DIR/config/server_config.json"
|
||||
cp "$REPO_ROOT/config/server_config.qrc" "$OUTPUT_DIR/config/server_config.qrc"
|
||||
|
||||
for common_file in ConfigHelper.h ConfigHelper.cpp TicketHelper.h TicketHelper.cpp; do
|
||||
common_path="$REPO_ROOT/Common/$common_file"
|
||||
@@ -106,12 +104,18 @@ for common_file in ConfigHelper.h ConfigHelper.cpp TicketHelper.h TicketHelper.c
|
||||
cp "$common_path" "$OUTPUT_DIR/Common/$common_file"
|
||||
done
|
||||
|
||||
WORD_GUIDE="$(find "$REPO_ROOT" "$REPO_ROOT/Docs" -maxdepth 1 -type f -name '*SDK*.docx' ! -name '~$*' 2>/dev/null | sort | sed -n '1p')"
|
||||
if [[ -z "$WORD_GUIDE" ]]; then
|
||||
echo "SDK integration Word guide is missing. Expected a *SDK*.docx file in the repository root or Docs directory." >&2
|
||||
exit 1
|
||||
if [[ -d "$REPO_ROOT/Docs" ]]; then
|
||||
cp -a "$REPO_ROOT/Docs/." "$OUTPUT_DIR/Docs/"
|
||||
fi
|
||||
|
||||
WORD_GUIDE="$(find "$REPO_ROOT" "$REPO_ROOT/Docs" -maxdepth 1 -type f -name '*SDK*.docx' ! -name '~$*' 2>/dev/null | sort | sed -n '1p')"
|
||||
WORD_GUIDE_INCLUDED=false
|
||||
if [[ -n "$WORD_GUIDE" ]]; then
|
||||
cp "$WORD_GUIDE" "$OUTPUT_DIR/$(basename "$WORD_GUIDE")"
|
||||
WORD_GUIDE_INCLUDED=true
|
||||
else
|
||||
echo "Warning: SDK Word guide is missing. Continue packaging with Markdown documents in Docs/." >&2
|
||||
fi
|
||||
cp "$WORD_GUIDE" "$OUTPUT_DIR/$(basename "$WORD_GUIDE")"
|
||||
|
||||
cp "$SCRIPT_DIR/package-sdk.sh" "$OUTPUT_DIR/scripts/package-sdk.sh"
|
||||
cp "$SCRIPT_DIR/package-client.sh" "$OUTPUT_DIR/scripts/package-client.sh"
|
||||
@@ -130,6 +134,8 @@ cat > "$OUTPUT_DIR/sdk_manifest.json" <<EOF
|
||||
"platform": "linux",
|
||||
"required_entry": "Launcher",
|
||||
"contains_demo_main_app": $([[ "$INCLUDE_DEMO_MAIN_APP" -eq 1 ]] && echo true || echo false),
|
||||
"docs_entry": "Docs/01-客户端接入打包部署指南.md",
|
||||
"word_guide_included": $WORD_GUIDE_INCLUDED,
|
||||
"integration_sources": [
|
||||
"ConfigHelper.h",
|
||||
"ConfigHelper.cpp",
|
||||
|
||||
Reference in New Issue
Block a user