Files
曾志威 5ef362ba22
ci / rust (push) Canceled after 0s
ci / native-client (push) Canceled after 0s
ci / package-windows-client (push) Canceled after 0s
ci / linux-agent (push) Canceled after 0s
ci / edge-service (push) Canceled after 0s
ci / coturn-pop (push) Canceled after 0s
ci / package-windows-host (push) Canceled after 0s
migrate runtime and packaging to Rust WebRTC
2026-08-14 16:08:28 +08:00

163 lines
11 KiB
PowerShell

[CmdletBinding()]
param()
$ErrorActionPreference = 'Stop'
$repoRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..\..'))
$targetRoot = Join-Path $repoRoot 'target'
$artifactsRoot = Join-Path $repoRoot 'artifacts'
$buildRoot = Join-Path $targetRoot 'package-linux-musl'
$gnuTar = 'C:\Program Files\Git\usr\bin\tar.exe'
$gzip = 'C:\Program Files\Git\usr\bin\gzip.exe'
$fileTool = 'C:\Program Files\Git\usr\bin\file.exe'
function Invoke-Checked {
param([Parameter(Mandatory)][scriptblock]$Command, [Parameter(Mandatory)][string]$Description)
& $Command
if ($LASTEXITCODE -ne 0) { throw "$Description failed with exit code $LASTEXITCODE" }
}
function Assert-PathWithin {
param([Parameter(Mandatory)][string]$Path, [Parameter(Mandatory)][string]$Root)
$fullPath = [IO.Path]::GetFullPath($Path)
$prefix = [IO.Path]::GetFullPath($Root).TrimEnd([IO.Path]::DirectorySeparatorChar) + [IO.Path]::DirectorySeparatorChar
if (-not $fullPath.StartsWith($prefix, [StringComparison]::OrdinalIgnoreCase)) {
throw "Refusing to modify a path outside $Root"
}
}
foreach ($tool in @($gnuTar, $gzip, $fileTool)) {
if (-not (Test-Path -LiteralPath $tool -PathType Leaf)) { throw "Required build tool is missing: $tool" }
}
$ndkRoot = if ($env:ANDROID_NDK_HOME) {
Split-Path -Parent ([IO.Path]::GetFullPath($env:ANDROID_NDK_HOME))
} else {
Join-Path $env:LOCALAPPDATA 'Android\Sdk\ndk'
}
$ndk = Get-ChildItem -LiteralPath $ndkRoot -Directory -ErrorAction SilentlyContinue |
Sort-Object Name -Descending |
Where-Object { Test-Path -LiteralPath (Join-Path $_.FullName 'toolchains\llvm\prebuilt\windows-x86_64\bin\x86_64-linux-android21-clang.cmd') } |
Select-Object -First 1
if ($null -eq $ndk) { throw 'Android NDK LLVM is required for the local musl build.' }
$ndkBin = Join-Path $ndk.FullName 'toolchains\llvm\prebuilt\windows-x86_64\bin'
$clang = Join-Path $ndkBin 'x86_64-linux-android21-clang.cmd'
$llvmAr = Join-Path $ndkBin 'llvm-ar.exe'
$llvmStrip = Join-Path $ndkBin 'llvm-strip.exe'
$rustSysroot = (& rustc --print sysroot).Trim()
if ($LASTEXITCODE -ne 0) { throw 'Unable to locate the active Rust sysroot.' }
$rustHost = ((& rustc -vV | Select-String '^host: ').Line -replace '^host:\s*', '').Trim()
$rustLld = Join-Path $rustSysroot "lib\rustlib\$rustHost\bin\rust-lld.exe"
Push-Location $repoRoot
try {
$metadata = cargo metadata --no-deps --format-version 1 | ConvertFrom-Json
if ($LASTEXITCODE -ne 0) { throw 'Unable to read Cargo workspace metadata.' }
$package = $metadata.packages | Where-Object name -eq 'remotedesk-agent-runtime' | Select-Object -First 1
$version = [string]$package.version
if ($version -notmatch '^\d+\.\d+\.\d+$') { throw "Invalid package version: $version" }
$env:CC_x86_64_unknown_linux_musl = $clang
$env:AR_x86_64_unknown_linux_musl = $llvmAr
$env:CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER = $rustLld
Invoke-Checked -Description 'Static Linux Agent build' -Command {
cargo build --locked --release --jobs 2 --target x86_64-unknown-linux-musl -p remotedesk-agent-runtime --no-default-features --features gstreamer-h264,wayland-eis
}
Assert-PathWithin -Path $buildRoot -Root $targetRoot
if (Test-Path -LiteralPath $buildRoot) { Remove-Item -LiteralPath $buildRoot -Recurse -Force }
New-Item -ItemType Directory -Force -Path $buildRoot, $artifactsRoot | Out-Null
$portableName = "RemoteDesk-Agent-$version-linux-x64"
$portableRoot = Join-Path $buildRoot $portableName
New-Item -ItemType Directory -Force -Path (Join-Path $portableRoot 'bin'), `
(Join-Path $portableRoot 'systemd'), (Join-Path $portableRoot 'config') | Out-Null
foreach ($binary in @('remotedesk-agentd', 'remotedesk-agent-session', 'remotedesk-shell-session', 'remotedesk-file-session')) {
$destination = Join-Path $portableRoot "bin\$binary"
Copy-Item -LiteralPath (Join-Path $targetRoot "x86_64-unknown-linux-musl\release\$binary") -Destination $destination
Invoke-Checked -Description "Strip $binary" -Command { & $llvmStrip $destination }
}
Copy-Item -LiteralPath (Join-Path $PSScriptRoot 'remotedesk-agentd.service') -Destination (Join-Path $portableRoot 'systemd')
Copy-Item -LiteralPath (Join-Path $PSScriptRoot 'remotedesk-agent-session.service') -Destination (Join-Path $portableRoot 'systemd')
Copy-Item -LiteralPath (Join-Path $PSScriptRoot 'agent.env') -Destination (Join-Path $portableRoot 'config')
Copy-Item -LiteralPath (Join-Path $PSScriptRoot 'install.sh') -Destination $portableRoot
Copy-Item -LiteralPath (Join-Path $PSScriptRoot 'uninstall.sh') -Destination $portableRoot
Copy-Item -LiteralPath (Join-Path $PSScriptRoot 'README.md') -Destination $portableRoot
$hashLines = Get-ChildItem -LiteralPath $portableRoot -Recurse -File | Sort-Object FullName | ForEach-Object {
$relative = [IO.Path]::GetRelativePath($portableRoot, $_.FullName).Replace('\', '/')
$hash = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
"$hash $relative"
}
$hashLines | Set-Content -LiteralPath (Join-Path $portableRoot 'SHA256SUMS.txt') -Encoding ascii
$portableTar = Join-Path $buildRoot "$portableName.tar"
$portableGzip = "$portableTar.gz"
$portableDirectories = @($portableName, "$portableName/bin", "$portableName/config", "$portableName/systemd")
$portableExecutables = @("$portableName/install.sh", "$portableName/uninstall.sh", "$portableName/bin/remotedesk-agentd", "$portableName/bin/remotedesk-agent-session", "$portableName/bin/remotedesk-shell-session", "$portableName/bin/remotedesk-file-session")
$portableData = @("$portableName/README.md", "$portableName/SHA256SUMS.txt", "$portableName/config/agent.env", "$portableName/systemd/remotedesk-agentd.service", "$portableName/systemd/remotedesk-agent-session.service")
Push-Location $buildRoot
try {
Invoke-Checked -Description 'Portable directory archive' -Command { & $gnuTar --force-local --no-recursion --format=gnu --owner=0 --group=0 --mode=0755 -cf $portableTar @portableDirectories }
Invoke-Checked -Description 'Portable executable archive' -Command { & $gnuTar --force-local --format=gnu --owner=0 --group=0 --mode=0755 -rf $portableTar @portableExecutables }
Invoke-Checked -Description 'Portable data archive' -Command { & $gnuTar --force-local --format=gnu --owner=0 --group=0 --mode=0644 -rf $portableTar @portableData }
} finally { Pop-Location }
Invoke-Checked -Description 'Portable gzip compression' -Command { & $gzip -n -f $portableTar }
$portableOutput = Join-Path $artifactsRoot "$portableName.tar.gz"
Move-Item -LiteralPath $portableGzip -Destination $portableOutput -Force
$debianRoot = Join-Path $buildRoot 'debian-root'
New-Item -ItemType Directory -Force -Path (Join-Path $debianRoot 'DEBIAN'), `
(Join-Path $debianRoot 'usr\bin'), (Join-Path $debianRoot 'usr\libexec'), `
(Join-Path $debianRoot 'usr\lib\systemd\system'), (Join-Path $debianRoot 'usr\lib\systemd\user'), `
(Join-Path $debianRoot 'etc\remotedesk'), (Join-Path $debianRoot 'usr\share\doc\remotedesk-agent') | Out-Null
Copy-Item -LiteralPath (Join-Path $portableRoot 'bin\remotedesk-agentd') -Destination (Join-Path $debianRoot 'usr\bin')
Copy-Item -LiteralPath (Join-Path $portableRoot 'bin\remotedesk-agent-session') -Destination (Join-Path $debianRoot 'usr\bin')
Copy-Item -LiteralPath (Join-Path $portableRoot 'bin\remotedesk-shell-session') -Destination (Join-Path $debianRoot 'usr\libexec')
Copy-Item -LiteralPath (Join-Path $portableRoot 'bin\remotedesk-file-session') -Destination (Join-Path $debianRoot 'usr\libexec')
Copy-Item -LiteralPath (Join-Path $portableRoot 'systemd\remotedesk-agentd.service') -Destination (Join-Path $debianRoot 'usr\lib\systemd\system')
Copy-Item -LiteralPath (Join-Path $portableRoot 'systemd\remotedesk-agent-session.service') -Destination (Join-Path $debianRoot 'usr\lib\systemd\user')
Copy-Item -LiteralPath (Join-Path $portableRoot 'config\agent.env') -Destination (Join-Path $debianRoot 'etc\remotedesk')
Copy-Item -LiteralPath (Join-Path $portableRoot 'README.md') -Destination (Join-Path $debianRoot 'usr\share\doc\remotedesk-agent\README.md')
$control = (Get-Content -LiteralPath (Join-Path $PSScriptRoot 'debian\control') -Raw).Replace('@VERSION@', $version).Replace('@ARCH@', 'amd64')
$control = $control.Replace(', gstreamer1.0-plugins-base, gstreamer1.0-plugins-good, gstreamer1.0-plugins-bad, gstreamer1.0-plugins-ugly', '')
[IO.File]::WriteAllText((Join-Path $debianRoot 'DEBIAN\control'), $control.Replace("`r`n", "`n"), [Text.UTF8Encoding]::new($false))
foreach ($script in @('postinst', 'prerm', 'postrm')) {
Copy-Item -LiteralPath (Join-Path $PSScriptRoot "debian\$script") -Destination (Join-Path $debianRoot "DEBIAN\$script")
}
$debParts = Join-Path $buildRoot 'deb-parts'
New-Item -ItemType Directory -Force -Path $debParts | Out-Null
[IO.File]::WriteAllText((Join-Path $debParts 'debian-binary'), "2.0`n", [Text.Encoding]::ASCII)
$controlTar = Join-Path $debParts 'control.tar'
Push-Location (Join-Path $debianRoot 'DEBIAN')
try {
Invoke-Checked -Description 'DEB control archive' -Command { & $gnuTar --force-local --format=gnu --owner=0 --group=0 --mode=0644 -cf $controlTar control }
Invoke-Checked -Description 'DEB maintainer scripts' -Command { & $gnuTar --force-local --format=gnu --owner=0 --group=0 --mode=0755 -rf $controlTar postinst prerm postrm }
} finally { Pop-Location }
Invoke-Checked -Description 'DEB control compression' -Command { & $gzip -n -f $controlTar }
$dataTar = Join-Path $debParts 'data.tar'
$execFiles = @('./usr/bin/remotedesk-agentd', './usr/bin/remotedesk-agent-session', './usr/libexec/remotedesk-shell-session', './usr/libexec/remotedesk-file-session')
$dataFiles = @('./usr/lib/systemd/system/remotedesk-agentd.service', './usr/lib/systemd/user/remotedesk-agent-session.service', './etc/remotedesk/agent.env', './usr/share/doc/remotedesk-agent/README.md')
Push-Location $debianRoot
try {
Invoke-Checked -Description 'DEB executable payload' -Command { & $gnuTar --force-local --format=gnu --owner=0 --group=0 --mode=0755 -cf $dataTar @execFiles }
Invoke-Checked -Description 'DEB data payload' -Command { & $gnuTar --force-local --format=gnu --owner=0 --group=0 --mode=0644 -rf $dataTar @dataFiles }
} finally { Pop-Location }
Invoke-Checked -Description 'DEB data compression' -Command { & $gzip -n -f $dataTar }
$debOutput = Join-Path $artifactsRoot "remotedesk-agent_${version}_amd64-musl.deb"
Push-Location $debParts
try {
Invoke-Checked -Description 'DEB ar archive' -Command { & $llvmAr rc $debOutput debian-binary control.tar.gz data.tar.gz }
} finally { Pop-Location }
foreach ($output in @($portableOutput, $debOutput)) {
$hash = (Get-FileHash -LiteralPath $output -Algorithm SHA256).Hash.ToLowerInvariant()
"$hash $([IO.Path]::GetFileName($output))" | Set-Content -LiteralPath "$output.sha256" -Encoding ascii
Write-Output "Package: $output"
Write-Output "SHA256: $hash"
}
} finally {
Remove-Item Env:CC_x86_64_unknown_linux_musl -ErrorAction SilentlyContinue
Remove-Item Env:AR_x86_64_unknown_linux_musl -ErrorAction SilentlyContinue
Remove-Item Env:CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER -ErrorAction SilentlyContinue
Pop-Location
}