From d3646c86ecc5004b8c4d5d8ae31609473869c252 Mon Sep 17 00:00:00 2001 From: luke Date: Sun, 24 Aug 2025 22:02:54 +0800 Subject: [PATCH 01/11] =?UTF-8?q?chore:=20=E5=A2=9E=E5=8A=A0docker?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=9E=84=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 57 ++++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 8 +++++++ pom.xml | 46 ++++++++++++++++--------------------- 3 files changed, 84 insertions(+), 27 deletions(-) create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a05335e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,57 @@ +# Stage 1: 官方 GraalVM 社区版(已含 native-image) +FROM ghcr.io/graalvm/native-image-community:latest AS builder + +RUN microdnf install -y \ + gcc gcc-c++ make git wget tar gzip which findutils maven \ + && microdnf clean all + +# ---------- 构建 musl ---------- +ARG MUSL_VER=1.2.5 +WORKDIR /tmp +RUN wget -q https://musl.libc.org/releases/musl-${MUSL_VER}.tar.gz \ + && tar -xzf musl-${MUSL_VER}.tar.gz \ + && cd musl-${MUSL_VER} \ + && ./configure --prefix=/opt/musl-${MUSL_VER} --disable-shared \ + && make -j"$(nproc)" \ + && make install \ + && ln -s /opt/musl-${MUSL_VER} /opt/musl \ + && cd / && rm -rf /tmp/musl-${MUSL_VER}* + +RUN ln -s /opt/musl/bin/musl-gcc /usr/local/bin/x86_64-linux-musl-gcc \ + && ln -s /opt/musl/bin/musl-gcc /usr/local/bin/x86_64-linux-musl-cc + +ENV PATH="/opt/musl/bin:${PATH}" +ENV CC="musl-gcc" +ENV C_INCLUDE_PATH="/opt/musl/include" +ENV LIBRARY_PATH="/opt/musl/lib" + +# ---------- 静态 zlib ---------- +ARG ZLIB_VERSION=1.3.1 +WORKDIR /tmp +RUN wget -q https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \ + && tar -xzf zlib-${ZLIB_VERSION}.tar.gz \ + && cd zlib-${ZLIB_VERSION} \ + && CC=musl-gcc ./configure --static --prefix=/opt/musl \ + && make -j"$(nproc)" \ + && make install \ + && cd / && rm -rf /tmp/zlib-${ZLIB_VERSION}* + +# ---------- Maven 缓存优化 ---------- +WORKDIR /app +COPY pom.xml ./ + +# 先拉依赖并缓存 +RUN mvn -B -P native-linux dependency:go-offline + +# ---------- 复制源码 ---------- +COPY . /app + +# ---------- 编译 native image ---------- +RUN mvn -P native-linux -DskipTests clean package + +# ------------------------------------------------------------ +# Stage 2: 输出产物镜像(可以直接 cp 出二进制) +# ------------------------------------------------------------ +FROM busybox AS export +WORKDIR /export +COPY --from=builder /app/org.jcnc.snow.cli.SnowCLI /export/Snow \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..21bca91 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +services: + snow-export: + image: my-snow-export + build: + context: . + command: [ "/bin/sh", "-c", "cp /export/Snow /output/Snow" ] + volumes: + - ./target:/output diff --git a/pom.xml b/pom.xml index 6b8b27d..e4b48da 100644 --- a/pom.xml +++ b/pom.xml @@ -70,11 +70,7 @@ - + native-linux @@ -82,25 +78,39 @@ unix + org.graalvm.buildtools native-maven-plugin ${native.maven.plugin.version} - true + + + org.jcnc.snow.cli.SnowCLI + Snow + ${project.build.directory} + + --static + --libc=musl + --emit=build-report + -O2 + -H:Class=org.jcnc.snow.cli.SnowCLI + -H:CCompilerPath=/opt/musl/bin/musl-gcc + -H:CLibraryPath=/opt/musl/lib + + + - build-native - compile-no-fork package - + test-native @@ -109,24 +119,6 @@ test - - - - --static - - --libc=musl - - --emit build-report - - -O2 - - - - /opt/musl-1.2.5/bin:${env.PATH} - /opt/musl-1.2.5/include - /opt/musl-1.2.5/lib - - From a16f0ac059e239483a70776608d7134cc90dd8e7 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 25 Aug 2025 12:32:10 +0800 Subject: [PATCH 02/11] =?UTF-8?q?chore:=20=E6=B7=BB=E5=8A=A0=20Linux=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=AF=BC=E5=87=BA=E8=84=9A=E6=9C=AC=E5=92=8C?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 .env 文件和生成脚本 - 更新 docker-compose.yml 和 Dockerfile 以支持 Linux 版本导出 - 添加 PowerShell 脚本生成 .env 文件 - 实现 Linux 版本导出的完整流程 --- .env | 2 ++ Dockerfile | 2 +- build/release-linux.ps1 | 26 ++++++++++++++++++++++++++ build/tools/generate-dotenv.ps1 | 23 +++++++++++++++++++++++ docker-compose.yml | 22 +++++++++++++++++++--- 5 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 .env create mode 100644 build/release-linux.ps1 create mode 100644 build/tools/generate-dotenv.ps1 diff --git a/.env b/.env new file mode 100644 index 0000000..528ad70 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +# Auto-generated by build\tools\generate-dotenv.ps1 +SNOW_VERSION=0.7.0 diff --git a/Dockerfile b/Dockerfile index a05335e..bfc25e7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Stage 1: 官方 GraalVM 社区版(已含 native-image) -FROM ghcr.io/graalvm/native-image-community:latest AS builder +FROM ghcr.io/graalvm/native-image-community:24.0.2 AS builder RUN microdnf install -y \ gcc gcc-c++ make git wget tar gzip which findutils maven \ diff --git a/build/release-linux.ps1 b/build/release-linux.ps1 new file mode 100644 index 0000000..b3a332b --- /dev/null +++ b/build/release-linux.ps1 @@ -0,0 +1,26 @@ +# run-linux-snow-export.ps1 + +Write-Host "Step 0: Generate .env..." +try { + & "$PSScriptRoot\tools\generate-dotenv.ps1" -ErrorAction Stop +} +catch { + Write-Error "Failed to generate .env: $($_.Exception.Message)" + exit 1 +} + +Write-Host "Step 1: Build and run linux-snow-export..." +docker compose run --build --rm linux-snow-export +if ($LASTEXITCODE -ne 0) { + Write-Error "Build & Run failed, exiting script." + exit $LASTEXITCODE +} + +Write-Host "Step 2: Run linux-snow-export without rebuild..." +docker compose run --rm linux-snow-export +if ($LASTEXITCODE -ne 0) { + Write-Error "Run without rebuild failed, exiting script." + exit $LASTEXITCODE +} + +Write-Host "All steps completed successfully!" diff --git a/build/tools/generate-dotenv.ps1 b/build/tools/generate-dotenv.ps1 new file mode 100644 index 0000000..8a00eba --- /dev/null +++ b/build/tools/generate-dotenv.ps1 @@ -0,0 +1,23 @@ +# build\tools\generate-dotenv.ps1 + +# Repository root: go up two levels from build\tools\ +$repoRoot = (Get-Item $PSScriptRoot).Parent.Parent.FullName +$envPath = Join-Path $repoRoot ".env" +$pomPath = Join-Path $repoRoot "pom.xml" + +if (-not (Test-Path $pomPath -PathType Leaf)) { + throw "pom.xml not found: $pomPath" +} + +[xml]$pom = Get-Content $pomPath -Encoding UTF8 +$version = $pom.project.version + +$lines = @( + "# Auto-generated by build\tools\generate-dotenv.ps1" + "SNOW_VERSION=$version" +) + +$utf8NoBom = New-Object System.Text.UTF8Encoding($false) +[System.IO.File]::WriteAllLines($envPath, $lines, $utf8NoBom) +Write-Host "Generated/overwritten $envPath (version: $version)" +return diff --git a/docker-compose.yml b/docker-compose.yml index 21bca91..f60b702 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,24 @@ services: - snow-export: - image: my-snow-export + # Run with: docker compose run --rm linux-snow-export + linux-snow-export: build: context: . - command: [ "/bin/sh", "-c", "cp /export/Snow /output/Snow" ] + target: export + command: + - /bin/sh + - -c + - | + set -e + ver="Snow-v${SNOW_VERSION}-linux-x64" + mkdir -p "/output/release/$$ver/bin" + cp /export/Snow "/output/release/$$ver/bin/" + if [ -d /export/lib ]; then + mkdir -p "/output/release/$$ver/lib" + cp -a /export/lib/. "/output/release/$$ver/lib/" + fi + tar -C /output/release -czf "/output/release/$$ver.tgz" "$$ver" volumes: - ./target:/output + - ./lib:/export/lib:ro + env_file: + - .env From b2c0b986c4c432526b5aae6959184e84168e017d Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 25 Aug 2025 13:17:16 +0800 Subject: [PATCH 03/11] =?UTF-8?q?build:=20=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7=E5=B9=B6=E9=87=8D=E6=9E=84=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -重构 release-linux.ps1 脚本,添加版本号读取和输出路径定义 - 新增 release-windows.ps1 脚本,实现 Windows 版本的构建和打包 - 添加 dotenv.ps1工具脚本,用于统一解析 .env 文件 --- .env | 2 +- build/release-linux.ps1 | 37 ++++++++++-- build/release-windows.ps1 | 117 ++++++++++++++++++++++++++++++++++++++ build/tools/dotenv.ps1 | 53 +++++++++++++++++ 4 files changed, 204 insertions(+), 5 deletions(-) create mode 100644 build/release-windows.ps1 create mode 100644 build/tools/dotenv.ps1 diff --git a/.env b/.env index 528ad70..0d696e3 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ # Auto-generated by build\tools\generate-dotenv.ps1 -SNOW_VERSION=0.7.0 +SNOW_VERSION=0.8.0 diff --git a/build/release-linux.ps1 b/build/release-linux.ps1 index b3a332b..5503242 100644 --- a/build/release-linux.ps1 +++ b/build/release-linux.ps1 @@ -1,11 +1,17 @@ # run-linux-snow-export.ps1 +# Build and package linux-snow-export, version read from SNOW_VERSION in .env + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +# Import shared dotenv parser function +. "$PSScriptRoot\tools\dotenv.ps1" Write-Host "Step 0: Generate .env..." try { & "$PSScriptRoot\tools\generate-dotenv.ps1" -ErrorAction Stop -} -catch { - Write-Error "Failed to generate .env: $($_.Exception.Message)" +} catch { + Write-Error "Failed to generate .env: $( $_.Exception.Message )" exit 1 } @@ -23,4 +29,27 @@ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } -Write-Host "All steps completed successfully!" +# ===== Step 3: Read version from .env ===== +$projectRoot = Resolve-Path (Join-Path $PSScriptRoot "..") +$dotenvPath = Join-Path $projectRoot ".env" + +if (-not (Test-Path -LiteralPath $dotenvPath)) { + Write-Error ".env not found at: $dotenvPath" + exit 1 +} + +$version = Read-DotEnvValue -FilePath $dotenvPath -Key 'SNOW_VERSION' +if (-not $version) { + Write-Error "SNOW_VERSION not found in .env" + exit 1 +} + +# ===== Step 4: Define output paths ===== +$targetDir = Join-Path $projectRoot "target\release" +$outDir = Join-Path $targetDir "Snow-v$version-linux-x64" +$tgzPath = Join-Path $targetDir "Snow-v$version-linux-x64.tgz" + +Write-Host ">>> Package ready!" -ForegroundColor Green +Write-Host "Version : $version" +Write-Host "Output Dir : $outDir" +Write-Host "Tgz File : $tgzPath" \ No newline at end of file diff --git a/build/release-windows.ps1 b/build/release-windows.ps1 new file mode 100644 index 0000000..f3c24f7 --- /dev/null +++ b/build/release-windows.ps1 @@ -0,0 +1,117 @@ +# release-windows.ps1 + +$ErrorActionPreference = 'Stop' +$ProgressPreference = 'SilentlyContinue' +Set-StrictMode -Version Latest + +# Import shared dotenv parser function +. "$PSScriptRoot\tools\dotenv.ps1" + +# ===== Utility Functions ===== +function Find-PomUpwards([string]$startDir) { + $dir = Resolve-Path $startDir + while ($true) { + $pom = Join-Path $dir "pom.xml" + if (Test-Path $pom) { return $pom } + $parent = Split-Path $dir -Parent + if ($parent -eq $dir -or [string]::IsNullOrEmpty($parent)) { return $null } + $dir = $parent + } +} + +# ===== Step 0: Generate .env ===== +Write-Host "Step 0: Generate .env..." +try { + & "$PSScriptRoot\tools\generate-dotenv.ps1" -ErrorAction Stop +} catch { + Write-Error "Failed to generate .env: $($_.Exception.Message)" + exit 1 +} + +# ===== Step 1: Locate project root & build ===== +Write-Host "Step 1: Locate project root and build..." +$pom = Find-PomUpwards -startDir $PSScriptRoot +if (-not $pom) { + Write-Error "pom.xml not found. Please run this script within the project." + exit 1 +} + +$projectRoot = Split-Path $pom -Parent +Push-Location $projectRoot +try { + Write-Host "→ Running: mvn clean package" + mvn clean package + if ($LASTEXITCODE -ne 0) { + Write-Error "Maven build failed, exiting script." + exit $LASTEXITCODE + } + + # ===== Step 2: Read SNOW_VERSION ===== + Write-Host "Step 2: Read SNOW_VERSION from .env..." + $dotenvPath = Join-Path $projectRoot ".env" + $snowVersion = Read-DotEnvValue -FilePath $dotenvPath -Key "SNOW_VERSION" + if (-not $snowVersion) { + Write-Host "SNOW_VERSION not found in .env, using placeholder 0.0.0." -ForegroundColor Yellow + $snowVersion = "0.0.0" + } + Write-Host "SNOW_VERSION = $snowVersion" + + # ===== Step 3: Prepare release directory structure ===== + Write-Host "Step 3: Prepare release directory structure..." + $targetDir = Join-Path $projectRoot "target" + $exePath = Join-Path $targetDir "Snow.exe" + if (-not (Test-Path $exePath)) { + Write-Error "Expected build artifact not found: $exePath" + exit 1 + } + + $verName = "Snow-v${snowVersion}-windows-x64" + $releaseRoot = Join-Path $targetDir "release" + $outDir = Join-Path $releaseRoot $verName + $binDir = Join-Path $outDir "bin" + $libDir = Join-Path $outDir "lib" + + # Clean old directory + if (Test-Path $outDir) { + Write-Host "→ Cleaning previous output directory..." + Remove-Item $outDir -Recurse -Force + } + + New-Item -ItemType Directory -Force -Path $binDir | Out-Null + Copy-Item -Path $exePath -Destination (Join-Path $binDir "Snow.exe") -Force + Write-Host ">>> Collected Snow.exe" + + # Optional lib + $projectLib = Join-Path $projectRoot "lib" + if (Test-Path $projectLib) { + New-Item -ItemType Directory -Force -Path $libDir | Out-Null + Copy-Item -Path (Join-Path $projectLib "*") -Destination $libDir -Recurse -Force + Write-Host ">>> Copied lib directory" + } else { + Write-Host ">>> lib directory not found, skipping." -ForegroundColor Yellow + } + + # ===== Step 4: Create zip ===== + Write-Host "Step 4: Create release zip..." + New-Item -ItemType Directory -Force -Path $releaseRoot | Out-Null + $zipPath = Join-Path $releaseRoot ("{0}.zip" -f $verName) + if (Test-Path $zipPath) { + Write-Host "→ Removing existing zip: $zipPath" + Remove-Item $zipPath -Force + } + + try { + Compress-Archive -Path $outDir -DestinationPath $zipPath -Force + } catch { + Write-Error "Failed to create zip: $($_.Exception.Message)" + exit 1 + } + + Write-Host ">>> Package ready!" -ForegroundColor Green + Write-Host "Version : $snowVersion" + Write-Host "Output Dir : $outDir" + Write-Host "Zip File : $zipPath" +} +finally { + Pop-Location +} diff --git a/build/tools/dotenv.ps1 b/build/tools/dotenv.ps1 new file mode 100644 index 0000000..f3c1eb1 --- /dev/null +++ b/build/tools/dotenv.ps1 @@ -0,0 +1,53 @@ +# tools/dotenv.ps1 +# Unified .env reader function: +# - Supports `KEY=VAL` and `export KEY=VAL` +# - Skips blank lines and comments +# - Handles quoted values (single or double quotes) +# - Allows inline comments at the end of a line (space + #) +# - If the same KEY is defined multiple times, the last one takes precedence + +Set-StrictMode -Version Latest + +function Read-DotEnvValue { + [CmdletBinding()] + param( + [Parameter(Mandatory=$true)][string]$FilePath, + [Parameter(Mandatory=$true)][string]$Key + ) + + if (-not (Test-Path -LiteralPath $FilePath)) { return $null } + + # Match the target key (escaped), allowing optional "export" prefix + $pattern = '^(?:\s*export\s+)?(?' + [regex]::Escape($Key) + ')\s*=\s*(?.*)$' + $value = $null + + # Read line by line for large file compatibility + Get-Content -LiteralPath $FilePath | ForEach-Object { + $line = $_ + + # Skip blank lines and full-line comments + if ($line -match '^\s*$') { return } + if ($line -match '^\s*#') { return } + + if ($line -match $pattern) { + $v = $matches['v'] + + # Remove surrounding quotes if present + $trimmed = $v.Trim() + if ($trimmed -match '^\s*"(.*)"\s*$') { + $v = $matches[1] + } elseif ($trimmed -match "^\s*'(.*)'\s*$") { + $v = $matches[1] + } else { + # Strip inline comments (space + # …), ignoring escaped \# + if ($v -match '^(.*?)(? Date: Mon, 25 Aug 2025 13:17:34 +0800 Subject: [PATCH 04/11] =?UTF-8?q?build:=20=E9=99=8D=E7=BA=A7=20SNOW=5FVERS?= =?UTF-8?q?ION=20=E8=87=B3=200.7.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index 0d696e3..528ad70 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ # Auto-generated by build\tools\generate-dotenv.ps1 -SNOW_VERSION=0.8.0 +SNOW_VERSION=0.7.0 From 7dd273759a579d9c28ae3edb8788d8405ab23b64 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 25 Aug 2025 13:41:04 +0800 Subject: [PATCH 05/11] =?UTF-8?q?build:=20=E5=AE=9E=E7=8E=B0=20Windows=20?= =?UTF-8?q?=E5=92=8C=20Linux=E5=B9=B6=E8=A1=8C=E6=9E=84=E5=BB=BA=E8=84=9A?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 build-parallel.ps1脚本,用于同时执行 Windows 和 Linux 构建任务 - 实现了日志实时输出和错误处理功能 - 添加了构建结果摘要和错误代码处理 --- build/build-parallel.ps1 | 142 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 build/build-parallel.ps1 diff --git a/build/build-parallel.ps1 b/build/build-parallel.ps1 new file mode 100644 index 0000000..4455390 --- /dev/null +++ b/build/build-parallel.ps1 @@ -0,0 +1,142 @@ +param( + [string]$LogDir = (Join-Path $PSScriptRoot 'target\parallel-logs') +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +$winScript = Join-Path $PSScriptRoot 'release-windows.ps1' +$linScript = Join-Path $PSScriptRoot 'release-linux.ps1' + +if (-not (Test-Path $winScript)) { throw "File not found: $winScript" } +if (-not (Test-Path $linScript)) { throw "File not found: $linScript" } + +$winLogOut = [System.IO.Path]::GetTempFileName() +$winLogErr = [System.IO.Path]::GetTempFileName() +$linLogOut = [System.IO.Path]::GetTempFileName() +$linLogErr = [System.IO.Path]::GetTempFileName() + +# Use only -NoNewWindow, remove -WindowStyle +$winProc = Start-Process powershell.exe -ArgumentList @('-NoProfile','-ExecutionPolicy','Bypass','-File',"`"$winScript`"") ` + -RedirectStandardOutput $winLogOut -RedirectStandardError $winLogErr -NoNewWindow -PassThru +$linProc = Start-Process powershell.exe -ArgumentList @('-NoProfile','-ExecutionPolicy','Bypass','-File',"`"$linScript`"") ` + -RedirectStandardOutput $linLogOut -RedirectStandardError $linLogErr -NoNewWindow -PassThru + +$winPosOut = 0 +$winPosErr = 0 +$linPosOut = 0 +$linPosErr = 0 + +Write-Host "===== Build Started =====" +while (-not $winProc.HasExited -or -not $linProc.HasExited) { + # windows-release stdout + if (Test-Path $winLogOut) { + $size = (Get-Item $winLogOut).Length + if ($size -gt $winPosOut) { + $fs = [System.IO.File]::Open($winLogOut, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite) + $fs.Position = $winPosOut + $sr = New-Object System.IO.StreamReader($fs) + while (!$sr.EndOfStream) { + $line = $sr.ReadLine() + if ($line) { Write-Host "[windows-release][OUT] $line" } + } + $winPosOut = $fs.Position + $sr.Close() + $fs.Close() + } + } + # windows-release stderr + if (Test-Path $winLogErr) { + $size = (Get-Item $winLogErr).Length + if ($size -gt $winPosErr) { + $fs = [System.IO.File]::Open($winLogErr, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite) + $fs.Position = $winPosErr + $sr = New-Object System.IO.StreamReader($fs) + while (!$sr.EndOfStream) { + $line = $sr.ReadLine() + if ($line) { Write-Host "[windows-release][ERR] $line" -ForegroundColor Red } + } + $winPosErr = $fs.Position + $sr.Close() + $fs.Close() + } + } + # linux-release stdout + if (Test-Path $linLogOut) { + $size = (Get-Item $linLogOut).Length + if ($size -gt $linPosOut) { + $fs = [System.IO.File]::Open($linLogOut, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite) + $fs.Position = $linPosOut + $sr = New-Object System.IO.StreamReader($fs) + while (!$sr.EndOfStream) { + $line = $sr.ReadLine() + if ($line) { Write-Host "[linux-release][OUT] $line" } + } + $linPosOut = $fs.Position + $sr.Close() + $fs.Close() + } + } + # linux-release stderr + if (Test-Path $linLogErr) { + $size = (Get-Item $linLogErr).Length + if ($size -gt $linPosErr) { + $fs = [System.IO.File]::Open($linLogErr, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite) + $fs.Position = $linPosErr + $sr = New-Object System.IO.StreamReader($fs) + while (!$sr.EndOfStream) { + $line = $sr.ReadLine() + if ($line) { Write-Host "[linux-release][ERR] $line" -ForegroundColor Red } + } + $linPosErr = $fs.Position + $sr.Close() + $fs.Close() + } + } + Start-Sleep -Milliseconds 200 +} + +# After processes exit, print any remaining output +$tasks = @( + @{proc=$winProc; log=$winLogOut; tag='windows-release'; type='OUT'; skip=$winPosOut}, + @{proc=$winProc; log=$winLogErr; tag='windows-release'; type='ERR'; skip=$winPosErr}, + @{proc=$linProc; log=$linLogOut; tag='linux-release'; type='OUT'; skip=$linPosOut}, + @{proc=$linProc; log=$linLogErr; tag='linux-release'; type='ERR'; skip=$linPosErr} +) +foreach ($item in $tasks) { + if (Test-Path $item.log) { + $fs = [System.IO.File]::Open($item.log, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite) + $fs.Position = $item.skip + $sr = New-Object System.IO.StreamReader($fs) + while (!$sr.EndOfStream) { + $line = $sr.ReadLine() + if ($line) { + if ($item.type -eq 'ERR') { + Write-Host "[$($item.tag)][ERR] $line" -ForegroundColor Red + } else { + Write-Host "[$($item.tag)][OUT] $line" + } + } + } + $sr.Close() + $fs.Close() + } +} + +Write-Host "" +Write-Host "===== Parallel Build Summary =====" +Write-Host ("windows-release: " + ($(if ($winProc.ExitCode -eq 0) { 'Success' } else { 'Failed' }))) +Write-Host ("linux-release: " + ($(if ($linProc.ExitCode -eq 0) { 'Success' } else { 'Failed' }))) + +if (($winProc.ExitCode -ne 0) -or ($linProc.ExitCode -ne 0)) { + Write-Host "" + Write-Host "One or more tasks failed." -ForegroundColor Red + Remove-Item $winLogOut, $winLogErr, $linLogOut, $linLogErr -Force + exit 1 +} + +Write-Host "" +Write-Host "All tasks completed successfully." -ForegroundColor Green + +Remove-Item $winLogOut, $winLogErr, $linLogOut, $linLogErr -Force +exit 0 From f11303f0e8c905bcdba4bf7b0a5282650bc16b7b Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 25 Aug 2025 13:41:40 +0800 Subject: [PATCH 06/11] =?UTF-8?q?build:=20=E6=B7=BB=E5=8A=A0=20Linux=20?= =?UTF-8?q?=E5=92=8C=20Windows=20=E5=B9=B3=E5=8F=B0=E7=9A=84=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E8=84=9A=E6=9C=AC=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .run/release-linux.ps1.run.xml | 6 ++++++ .run/release-windows.ps1.run.xml | 6 ++++++ 2 files changed, 12 insertions(+) create mode 100644 .run/release-linux.ps1.run.xml create mode 100644 .run/release-windows.ps1.run.xml diff --git a/.run/release-linux.ps1.run.xml b/.run/release-linux.ps1.run.xml new file mode 100644 index 0000000..06f300e --- /dev/null +++ b/.run/release-linux.ps1.run.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.run/release-windows.ps1.run.xml b/.run/release-windows.ps1.run.xml new file mode 100644 index 0000000..eb5a30c --- /dev/null +++ b/.run/release-windows.ps1.run.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From 2a9d2b7f5fb6a9bfb4ea954a5139b345e09d0dbd Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 25 Aug 2025 13:43:38 +0800 Subject: [PATCH 07/11] =?UTF-8?q?chore:=20=E4=BF=AE=E6=94=B9=E8=84=9A?= =?UTF-8?q?=E6=9C=AC=E5=90=8D=E8=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/{build_project2tar.ps1 => build-project2tar.ps1} | 0 build/{build-parallel.ps1 => build-release-all.ps1} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename build/{build_project2tar.ps1 => build-project2tar.ps1} (100%) rename build/{build-parallel.ps1 => build-release-all.ps1} (100%) diff --git a/build/build_project2tar.ps1 b/build/build-project2tar.ps1 similarity index 100% rename from build/build_project2tar.ps1 rename to build/build-project2tar.ps1 diff --git a/build/build-parallel.ps1 b/build/build-release-all.ps1 similarity index 100% rename from build/build-parallel.ps1 rename to build/build-release-all.ps1 From 9afc1caac7d2e50b913e8ead1988c8092dc95d46 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 25 Aug 2025 13:47:08 +0800 Subject: [PATCH 08/11] =?UTF-8?q?build:=20=E7=A7=BB=E9=99=A4=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E5=A4=B1=E8=B4=A5=E6=97=B6=E7=9A=84=E5=86=97=E4=BD=99?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/build-release-all.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/build-release-all.ps1 b/build/build-release-all.ps1 index 4455390..63f5419 100644 --- a/build/build-release-all.ps1 +++ b/build/build-release-all.ps1 @@ -129,8 +129,6 @@ Write-Host ("windows-release: " + ($(if ($winProc.ExitCode -eq 0) { 'Success' } Write-Host ("linux-release: " + ($(if ($linProc.ExitCode -eq 0) { 'Success' } else { 'Failed' }))) if (($winProc.ExitCode -ne 0) -or ($linProc.ExitCode -ne 0)) { - Write-Host "" - Write-Host "One or more tasks failed." -ForegroundColor Red Remove-Item $winLogOut, $winLogErr, $linLogOut, $linLogErr -Force exit 1 } From f7db4fcce8a0abd7424d08d99b5a28ad1a61fb85 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 25 Aug 2025 13:47:20 +0800 Subject: [PATCH 09/11] =?UTF-8?q?chore:=20=E6=B7=BB=E5=8A=A0=20build-relea?= =?UTF-8?q?se-all.ps1=20=E8=BF=90=E8=A1=8C=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .run/build-release-all.ps1.run.xml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .run/build-release-all.ps1.run.xml diff --git a/.run/build-release-all.ps1.run.xml b/.run/build-release-all.ps1.run.xml new file mode 100644 index 0000000..2a862b4 --- /dev/null +++ b/.run/build-release-all.ps1.run.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From 926e87888c05a97b5f3735465a8ed5a46e4f7b24 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 25 Aug 2025 15:20:36 +0800 Subject: [PATCH 10/11] =?UTF-8?q?build:=20=E4=BC=98=E5=8C=96=E6=89=93?= =?UTF-8?q?=E5=8C=85=E8=84=9A=E6=9C=AC=E5=B9=B6=E7=A7=BB=E9=99=A4=E5=B9=B6?= =?UTF-8?q?=E8=A1=8C=E6=9E=84=E5=BB=BA=E6=80=BB=E7=BB=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/build-project2tar.ps1 | 35 ++++++++++++++++++----------------- build/build-release-all.ps1 | 10 ---------- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/build/build-project2tar.ps1 b/build/build-project2tar.ps1 index 81b5d69..2ee7146 100644 --- a/build/build-project2tar.ps1 +++ b/build/build-project2tar.ps1 @@ -1,47 +1,48 @@ -# 设定 tar 包的名称 +# Set the tar package name $tarName = "Snow.tar" -# 获取脚本当前目录(build文件夹) +# Get the script's current directory (build folder) $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition -# 获取上一级目录(snow 根目录) +# Get the parent directory (the project root) $parentDir = Split-Path -Parent $scriptDir -# 设置 tar 包的完整路径 +# Set the full path to the tar package $tarPath = Join-Path $parentDir $tarName -# 输出开始创建 tar 包的消息 -Write-Output "开始创建 tar 包: $tarName 到 $parentDir ..." +# Output message: starting to create tar package +Write-Output "Starting to create tar package: $tarName in $parentDir ..." -# 如果存在旧 tar 包,先删除它 +# Remove old tar package if it exists if (Test-Path $tarPath) { - Write-Output "发现旧的 $tarName,正在删除..." + Write-Output "Found an old $tarName, removing it..." Remove-Item $tarPath -Force } -# 确保 tar 命令可用 +# Make sure the tar command is available $tarCommand = "tar" if (-not (Get-Command $tarCommand -ErrorAction SilentlyContinue)) { - Write-Error "❌ tar 命令不可用。请确保 tar 已安装并可在 PowerShell 中执行。" + Write-Error "❌ 'tar' command is not available. Please make sure 'tar' is installed and can be run from PowerShell." exit 1 } -# 执行打包操作: 切换到 org\jcnc 目录下再压缩 snow 文件夹 +# Execute tar: change to org\jcnc directory and compress the snow folder try { - # 构建命令并执行 + # Build the command and run it $tarCommandArgs = "-cf", $tarPath, "-C", "$scriptDir\..\src\main\java\org\jcnc", "snow" - Write-Output "执行 tar 命令: tar $tarCommandArgs" + Write-Output "Running tar command: tar $tarCommandArgs" & $tarCommand @tarCommandArgs } catch { - Write-Error "❌ 创建 tar 包失败。错误信息: $_" + Write-Error "❌ Failed to create tar package. Error: $_" exit 1 } -# 检查 tar 包是否创建成功 +# Check if tar package was created successfully if (Test-Path $tarPath) { - Write-Output "✅ 成功创建 $tarName" + Write-Output "✅ Successfully created $tarName" + exit 0 } else { - Write-Error "❌ 创建失败,请检查 tar 命令和路径是否正确。" + Write-Error "❌ Creation failed. Please check the tar command and paths." exit 1 } diff --git a/build/build-release-all.ps1 b/build/build-release-all.ps1 index 63f5419..45bb602 100644 --- a/build/build-release-all.ps1 +++ b/build/build-release-all.ps1 @@ -123,16 +123,6 @@ foreach ($item in $tasks) { } } -Write-Host "" -Write-Host "===== Parallel Build Summary =====" -Write-Host ("windows-release: " + ($(if ($winProc.ExitCode -eq 0) { 'Success' } else { 'Failed' }))) -Write-Host ("linux-release: " + ($(if ($linProc.ExitCode -eq 0) { 'Success' } else { 'Failed' }))) - -if (($winProc.ExitCode -ne 0) -or ($linProc.ExitCode -ne 0)) { - Remove-Item $winLogOut, $winLogErr, $linLogOut, $linLogErr -Force - exit 1 -} - Write-Host "" Write-Host "All tasks completed successfully." -ForegroundColor Green From 3b3478ee306916b661ec9b8614a55dc6ab3a54d4 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 25 Aug 2025 15:20:58 +0800 Subject: [PATCH 11/11] =?UTF-8?q?style:=20=E5=88=A0=E9=99=A4=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/build-release-all.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/build/build-release-all.ps1 b/build/build-release-all.ps1 index 45bb602..3c42adb 100644 --- a/build/build-release-all.ps1 +++ b/build/build-release-all.ps1 @@ -16,7 +16,6 @@ $winLogErr = [System.IO.Path]::GetTempFileName() $linLogOut = [System.IO.Path]::GetTempFileName() $linLogErr = [System.IO.Path]::GetTempFileName() -# Use only -NoNewWindow, remove -WindowStyle $winProc = Start-Process powershell.exe -ArgumentList @('-NoProfile','-ExecutionPolicy','Bypass','-File',"`"$winScript`"") ` -RedirectStandardOutput $winLogOut -RedirectStandardError $winLogErr -NoNewWindow -PassThru $linProc = Start-Process powershell.exe -ArgumentList @('-NoProfile','-ExecutionPolicy','Bypass','-File',"`"$linScript`"") `