437 lines
14 KiB
YAML
437 lines
14 KiB
YAML
name: Build Windows
|
|
run-name: 构建Win流程
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
- dev
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
- dev
|
|
|
|
jobs:
|
|
# 先编译 libcore
|
|
build-libcore:
|
|
name: 编译 libcore (Windows)
|
|
runs-on: client-server
|
|
container:
|
|
image: node:20
|
|
strategy:
|
|
matrix:
|
|
# 只有node支持版本号别名
|
|
node: ['20.15.1']
|
|
|
|
steps:
|
|
- name: 📥 Checkout 代码
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
fetch-depth: 0
|
|
|
|
- name: 🔧 设置 Go 环境
|
|
uses: actions/setup-go@v5
|
|
with:
|
|
go-version: '1.23'
|
|
cache: true
|
|
cache-dependency-path: libcore/go.sum
|
|
|
|
- name: 🔧 安装 MinGW
|
|
run: |
|
|
# 在 GitHub 托管 runner(有 sudo)与 act/自托管容器(无 sudo)均可运行
|
|
if command -v sudo >/dev/null 2>&1; then
|
|
sudo apt-get update
|
|
sudo apt-get install -y mingw-w64
|
|
else
|
|
echo "sudo 不存在,按 root 用户直接执行 apt-get"
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update || apt update
|
|
apt-get install -y mingw-w64 || apt install -y mingw-w64
|
|
fi
|
|
|
|
- name: 📦 编译 libcore.dll
|
|
working-directory: libcore
|
|
run: |
|
|
echo "🚀 开始编译 Windows libcore..."
|
|
make windows-amd64
|
|
|
|
if [ -f "bin/libcore.dll" ] && [ -f "bin/HiddifyCli.exe" ]; then
|
|
echo "✅ Windows libcore 编译成功"
|
|
ls -lh bin/
|
|
else
|
|
echo "❌ Windows libcore 编译失败"
|
|
exit 1
|
|
fi
|
|
|
|
- name: 📤 上传 Windows libcore
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: libcore-windows
|
|
path: |
|
|
libcore/bin/libcore.dll
|
|
libcore/bin/HiddifyCli.exe
|
|
libcore/bin/webui/**
|
|
retention-days: 7
|
|
|
|
|
|
# 构建 Windows 应用
|
|
build:
|
|
runs-on: windows-latest
|
|
needs: build-libcore
|
|
steps:
|
|
- name: 🔧 Add Git to PATH (Windows)
|
|
if: ${{ runner.os == 'Windows' }}
|
|
shell: powershell
|
|
run: |
|
|
$paths = @(
|
|
'C:\Program Files\Git\cmd',
|
|
'C:\Program Files\Git\bin',
|
|
'C:\Program Files (x86)\Git\cmd',
|
|
'C:\Program Files (x86)\Git\bin'
|
|
)
|
|
foreach ($p in $paths) {
|
|
if (Test-Path $p) {
|
|
Add-Content -Path $env:GITHUB_PATH -Value $p
|
|
$env:PATH = "$p;$env:PATH"
|
|
Write-Host ("Added to PATH: {0}" -f $p)
|
|
}
|
|
}
|
|
$candidates = @(
|
|
'C:\Program Files\Git\cmd\git.exe',
|
|
'C:\Program Files\Git\bin\git.exe',
|
|
'C:\Program Files (x86)\Git\cmd\git.exe',
|
|
'C:\Program Files (x86)\Git\bin\git.exe'
|
|
)
|
|
$found = $false
|
|
foreach ($g in $candidates) {
|
|
if (Test-Path $g) {
|
|
& $g --version
|
|
$found = $true
|
|
break
|
|
}
|
|
}
|
|
if (-not $found) {
|
|
Write-Host "Git executable not found in common locations; continuing."
|
|
}
|
|
|
|
- name: 📥 Checkout 代码
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
fetch-depth: 0
|
|
|
|
- name: 📥 下载 libcore
|
|
uses: actions/download-artifact@v3
|
|
with:
|
|
name: libcore-windows
|
|
path: .
|
|
|
|
- name: 🔧 复制 libcore 文件到正确位置并重命名
|
|
shell: cmd
|
|
run: call copy_libcore.bat
|
|
|
|
- name: 🔍 Verify jq Installation (ACT)
|
|
shell: powershell
|
|
run: |
|
|
# Check if jq is available
|
|
$jqFound = $false
|
|
try {
|
|
$version = jq --version 2>&1
|
|
if ($version -match 'jq-[\d\.]+') {
|
|
Write-Host "jq is already installed: $version"
|
|
$jqFound = $true
|
|
}
|
|
} catch {
|
|
Write-Host "jq not installed or not in PATH"
|
|
}
|
|
if (-not $jqFound) {
|
|
Write-Host "Preparing to install jq..."
|
|
# Check if Chocolatey is available
|
|
$chocoFound = $false
|
|
try {
|
|
choco --version 2>&1 | Out-Null
|
|
$chocoFound = $true
|
|
} catch {}
|
|
if (-not $chocoFound) {
|
|
Write-Host "Installing Chocolatey..."
|
|
Set-ExecutionPolicy Bypass -Scope Process -Force
|
|
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
|
|
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
|
|
# Refresh PATH
|
|
$env:PATH = [System.Environment]::GetEnvironmentVariable('PATH', 'Machine') + ';' + [System.Environment]::GetEnvironmentVariable('PATH', 'User')
|
|
Write-Host "Chocolatey installed successfully"
|
|
}
|
|
Write-Host "Installing jq using Chocolatey..."
|
|
choco install jq -y
|
|
if ($LASTEXITCODE -eq 0) {
|
|
Write-Host "jq installed successfully"
|
|
# Verify again
|
|
$version = jq --version 2>&1
|
|
Write-Host "jq version: $version"
|
|
} else {
|
|
Write-Host "jq installation failed, exit code: $LASTEXITCODE"
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
- name: Add jq to PATH
|
|
shell: powershell
|
|
run: |
|
|
$jqPath = "C:\ProgramData\chocolatey\bin"
|
|
if (Test-Path $jqPath) {
|
|
Add-Content -Path $env:GITHUB_PATH -Value $jqPath
|
|
$env:PATH = "$jqPath;$env:PATH"
|
|
Write-Host "Added jq path to GITHUB_PATH and current PATH"
|
|
} else {
|
|
Write-Host "jq installation path not found"
|
|
exit 1
|
|
}
|
|
|
|
- name: Add Flutter to PATH
|
|
shell: powershell
|
|
run: |
|
|
# Add Flutter to PATH for current session and GitHub Actions
|
|
$flutterPath = "C:\flutter\bin"
|
|
if (Test-Path $flutterPath) {
|
|
Write-Host "Adding Flutter to PATH: $flutterPath"
|
|
$env:PATH = "$flutterPath;$env:PATH"
|
|
Add-Content -Path $env:GITHUB_PATH -Value $flutterPath
|
|
|
|
# Verify Flutter is accessible
|
|
$flutterVersion = flutter --version 2>&1
|
|
if ($LASTEXITCODE -eq 0) {
|
|
Write-Host "Flutter verified: $flutterVersion"
|
|
} else {
|
|
Write-Host "Flutter not found at $flutterPath"
|
|
exit 1
|
|
}
|
|
} else {
|
|
Write-Host "ERROR: Flutter not found at C:\flutter\bin"
|
|
exit 1
|
|
}
|
|
|
|
- name: Enable Windows desktop
|
|
shell: powershell
|
|
run: |
|
|
$env:PATH = "C:\flutter\bin;$env:PATH"
|
|
flutter config --enable-windows-desktop
|
|
|
|
- name: Get dependencies
|
|
shell: powershell
|
|
run: |
|
|
$env:PATH = "C:\flutter\bin;$env:PATH"
|
|
flutter pub get
|
|
|
|
- name: Generate code
|
|
shell: powershell
|
|
run: |
|
|
$env:PATH = "C:\flutter\bin;$env:PATH"
|
|
dart run build_runner build --delete-conflicting-outputs
|
|
|
|
- name: Install NuGet
|
|
shell: powershell
|
|
run: |
|
|
Write-Host "Installing NuGet..."
|
|
|
|
# Check if NuGet is already available
|
|
$nugetPath = Get-Command nuget -ErrorAction SilentlyContinue
|
|
if ($nugetPath) {
|
|
Write-Host "NuGet already installed: $($nugetPath.Source)"
|
|
$nugetVersion = nuget help | Select-String -Pattern "NuGet Version" | Select-Object -First 1
|
|
Write-Host "NuGet version: $nugetVersion"
|
|
return
|
|
}
|
|
|
|
# Use Chocolatey to install NuGet (proven to work)
|
|
Write-Host "Installing NuGet via Chocolatey..."
|
|
choco install nuget.commandline -y
|
|
|
|
# Update PATH to include Chocolatey
|
|
$env:PATH = "C:\ProgramData\chocolatey\bin;$env:PATH"
|
|
Add-Content -Path $env:GITHUB_PATH -Value "C:\ProgramData\chocolatey\bin"
|
|
|
|
# Verify installation
|
|
if (Get-Command nuget -ErrorAction SilentlyContinue) {
|
|
Write-Host "NuGet installed successfully via Chocolatey"
|
|
$nugetVersion = nuget help | Select-String -Pattern "NuGet Version" | Select-Object -First 1
|
|
Write-Host "NuGet version: $nugetVersion"
|
|
} else {
|
|
Write-Host "WARNING: NuGet installation may have failed, but continuing..."
|
|
}
|
|
|
|
- name: Fix long paths
|
|
shell: powershell
|
|
run: |
|
|
Write-Host "Enabling long path support..."
|
|
|
|
# Enable long paths in Windows
|
|
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -Type DWORD -Force
|
|
|
|
# Also set for current user
|
|
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\AppModel\StateRepository\Cache\Package\Data\" -Name "LongPathsEnabled" -Value 1 -Type DWORD -Force -ErrorAction SilentlyContinue
|
|
|
|
Write-Host "Long path support enabled"
|
|
|
|
- name: Clean build cache
|
|
shell: powershell
|
|
run: |
|
|
$env:PATH = "C:\flutter\bin;$env:PATH"
|
|
Write-Host "Cleaning build cache..."
|
|
flutter clean
|
|
|
|
Write-Host "Removing old build directories..."
|
|
if (Test-Path "build") {
|
|
Remove-Item -Path "build" -Recurse -Force
|
|
}
|
|
if (Test-Path "windows") {
|
|
Remove-Item -Path "windows" -Recurse -Force
|
|
}
|
|
|
|
Write-Host "Recreating Windows project..."
|
|
flutter create --platforms=windows .
|
|
|
|
- name: Build Windows Debug
|
|
shell: powershell
|
|
run: |
|
|
$env:PATH = "C:\flutter\bin;C:\ProgramData\chocolatey\bin;$env:PATH"
|
|
flutter build windows
|
|
|
|
- name: Build Windows Release
|
|
shell: powershell
|
|
run: |
|
|
$env:PATH = "C:\flutter\bin;C:\ProgramData\chocolatey\bin;$env:PATH"
|
|
flutter build windows --release
|
|
|
|
- name: Upload Debug build artifacts
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: windows-debug-build
|
|
path: build/windows/x64/runner/Debug/
|
|
|
|
- name: Upload Release build artifacts
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: windows-release-build
|
|
path: build/windows/x64/runner/Release/
|
|
|
|
- name: Download Enigma Virtual Box
|
|
shell: powershell
|
|
run: |
|
|
Write-Host "下载 Enigma Virtual Box..."
|
|
$enigmaUrl = "https://enigmaprotector.com/assets/files/enigmavb.exe"
|
|
$enigmaPath = "C:\enigmavb.exe"
|
|
|
|
try {
|
|
Invoke-WebRequest -Uri $enigmaUrl -OutFile $enigmaPath -UseBasicParsing
|
|
Write-Host "✅ Enigma Virtual Box 下载成功"
|
|
} catch {
|
|
Write-Host "⚠️ 下载失败,跳过 Enigma 打包"
|
|
}
|
|
|
|
- name: Package Single EXE
|
|
shell: powershell
|
|
run: |
|
|
Write-Host "=== 开始打包单文件 EXE ==="
|
|
|
|
$buildPath = "build\windows\x64\runner\Release"
|
|
$outputPath = "dist"
|
|
$enigmaPath = "C:\enigmavb.exe"
|
|
|
|
# 创建输出目录
|
|
if (-not (Test-Path $outputPath)) {
|
|
New-Item -ItemType Directory -Path $outputPath -Force | Out-Null
|
|
}
|
|
|
|
# 获取主程序
|
|
$exeFile = Get-ChildItem -Path $buildPath -Filter "*.exe" | Select-Object -First 1
|
|
if (-not $exeFile) {
|
|
Write-Host "❌ 未找到可执行文件"
|
|
exit 1
|
|
}
|
|
|
|
$inputExe = $exeFile.FullName
|
|
$outputExe = "$outputPath\$($exeFile.BaseName)_Single.exe"
|
|
|
|
Write-Host "主程序: $inputExe"
|
|
Write-Host "输出: $outputExe"
|
|
|
|
# 尝试使用 Enigma Virtual Box
|
|
if (Test-Path $enigmaPath) {
|
|
Write-Host "使用 Enigma Virtual Box 打包..."
|
|
|
|
# 创建配置文件
|
|
$configContent = "[Config]`nInputFile=$inputExe`nOutputFile=$outputExe`nFiles=%DEFAULT FOLDER%`nVirtualizationMode=Never Write To Disk`nCompression=Yes`nShareVirtualSystem=Yes`n`n[Files]`nFolder=$buildPath\*"
|
|
|
|
$configFile = "$outputPath\package_config.evb"
|
|
Set-Content -Path $configFile -Value $configContent
|
|
|
|
# 执行打包
|
|
$process = Start-Process -FilePath $enigmaPath -ArgumentList "/sf", $inputExe, "/lf", $outputExe, "/folder", $buildPath, "/compress" -Wait -PassThru -NoNewWindow
|
|
|
|
if ($process.ExitCode -eq 0) {
|
|
Write-Host "✅ 单文件打包成功!"
|
|
|
|
# 显示压缩信息
|
|
$originalSize = (Get-Item $inputExe).Length / 1MB
|
|
$packedSize = (Get-Item $outputExe).Length / 1MB
|
|
Write-Host "原始大小: $([math]::Round($originalSize, 2)) MB"
|
|
Write-Host "打包大小: $([math]::Round($packedSize, 2)) MB"
|
|
} else {
|
|
Write-Host "⚠️ Enigma 打包失败,使用备选方案"
|
|
exit 1
|
|
}
|
|
} else {
|
|
Write-Host "⚠️ Enigma 未找到,使用 7-Zip 自解压方案"
|
|
exit 1
|
|
}
|
|
|
|
- name: Package with 7-Zip Alternative
|
|
if: failure()
|
|
shell: powershell
|
|
run: |
|
|
Write-Host "使用 7-Zip 自解压方案..."
|
|
|
|
$buildPath = "build\windows\x64\runner\Release"
|
|
$outputPath = "dist"
|
|
|
|
# 检查 7-Zip
|
|
$7zipPath = "C:\Program Files\7-Zip\7z.exe"
|
|
if (-not (Test-Path $7zipPath)) {
|
|
Write-Host "安装 7-Zip..."
|
|
choco install 7zip -y
|
|
$7zipPath = "C:\Program Files\7-Zip\7z.exe"
|
|
}
|
|
|
|
# 获取主程序名称
|
|
$exeFile = Get-ChildItem -Path $buildPath -Filter "*.exe" | Select-Object -First 1
|
|
$outputSfx = "$outputPath\$($exeFile.BaseName)_Package.exe"
|
|
|
|
Write-Host "创建自解压包..."
|
|
|
|
# 创建配置文件
|
|
$configContent = ";!@Install@!UTF-8!`nTitle=\"HostExecutor Windows Package\"`nBeginPrompt=\"正在解压 HostExecutor...\"`nExtractDialogText=\"请稍候,正在解压文件...\"`nExtractPathText=\"解压路径:\"`nExtractTitle=\"解压中\"`nFinishMessage=\"解压完成!\"`nGUIFlags=\"8\"`n;!@InstallEnd@!"
|
|
|
|
$configFile = "$outputPath\config.txt"
|
|
Set-Content -Path $configFile -Value $configContent -Encoding UTF8
|
|
|
|
# 创建压缩包
|
|
& $7zipPath a -sfx "$outputSfx" "$buildPath\*" -mmt=on -mx=9
|
|
|
|
if (Test-Path $outputSfx) {
|
|
Write-Host "✅ 7-Zip 自解压包创建成功!"
|
|
Write-Host "输出文件: $outputSfx"
|
|
|
|
$size = (Get-Item $outputSfx).Length / 1MB
|
|
Write-Host "文件大小: $([math]::Round($size, 2)) MB"
|
|
} else {
|
|
Write-Host "❌ 7-Zip 打包失败"
|
|
}
|
|
|
|
- name: Upload Single EXE Package
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: windows-single-exe
|
|
path: dist/*.exe
|
|
if: always()
|