summaryrefslogtreecommitdiffstats
path: root/packaging/win/build-node-runtime.ps1
diff options
context:
space:
mode:
Diffstat (limited to 'packaging/win/build-node-runtime.ps1')
-rw-r--r--packaging/win/build-node-runtime.ps1138
1 files changed, 138 insertions, 0 deletions
diff --git a/packaging/win/build-node-runtime.ps1 b/packaging/win/build-node-runtime.ps1
new file mode 100644
index 0000000..c432e01
--- /dev/null
+++ b/packaging/win/build-node-runtime.ps1
@@ -0,0 +1,138 @@
+<#
+.SYNOPSIS
+ Freeze the MeshBay node daemon into a relocatable Windows binary.
+
+.DESCRIPTION
+ Produces packages/meshbay-client/node-runtime/meshbay-node.exe (+ its
+ onedir payload) with PyInstaller. electron-builder then carries that tree
+ into the NSIS installer as an extraResource (see package.json build.win).
+
+ The frozen binary is what the desktop client spawns and what the W3
+ autostart launcher points at, so it must be a genuine single .exe -- which
+ is why this uses PyInstaller and not the python-embed zip (whose pip
+ console-script wrapper bakes in an absolute interpreter path and does not
+ survive being installed somewhere else).
+
+ ffmpeg/ffprobe are NOT bundled by default. Pass -FfmpegDir (or set
+ MESHBAY_FFMPEG_DIR) to copy them in beside the daemon; otherwise the node
+ resolves them from PATH at startup (meshbay_node.platform.check_media_tools)
+ and streaming needs ffmpeg installed separately.
+
+.PARAMETER Python
+ Interpreter used to build. Must be 3.12+ and able to install the packages.
+ Default: a throwaway venv this script creates under build/_node-build-venv.
+
+.PARAMETER FfmpegDir
+ Directory containing ffmpeg.exe and ffprobe.exe to bundle. Optional.
+
+.PARAMETER KeepBuildVenv
+ Do not delete the throwaway build venv on success (faster re-runs).
+#>
+[CmdletBinding()]
+param(
+ [string]$Python = "",
+ [string]$FfmpegDir = $env:MESHBAY_FFMPEG_DIR,
+ [switch]$KeepBuildVenv
+)
+
+$ErrorActionPreference = "Stop"
+Set-StrictMode -Version Latest
+
+$WinDir = $PSScriptRoot
+$Repo = (Resolve-Path (Join-Path $WinDir "..\..")).Path
+$Client = Join-Path $Repo "packages\meshbay-client"
+$OutDir = Join-Path $Client "node-runtime"
+$BuildVenv = Join-Path $Client "build\_node-build-venv"
+$SpecFile = Join-Path $WinDir "meshbay-node.spec"
+
+function Step($msg) { Write-Host "==> $msg" -ForegroundColor Cyan }
+
+# --- 1. interpreter --------------------------------------------------------
+$createdVenv = $false
+if (-not $Python) {
+ Step "creating build venv ($BuildVenv)"
+ if (Get-Command py -ErrorAction SilentlyContinue) {
+ & py -3.12 -m venv --clear $BuildVenv
+ } else {
+ & python -m venv --clear $BuildVenv
+ }
+ if ($LASTEXITCODE -ne 0) { throw "venv creation failed" }
+ $Python = Join-Path $BuildVenv "Scripts\python.exe"
+ $createdVenv = $true
+}
+if (-not (Test-Path $Python)) { throw "Python not found: $Python" }
+
+$verOut = (& $Python -c "import sys; print(sys.version_info[0]); print(sys.version_info[1])")
+$verMajor = [int]$verOut[0]
+$verMinor = [int]$verOut[1]
+if ($verMajor -lt 3 -or ($verMajor -eq 3 -and $verMinor -lt 12)) {
+ throw "need Python 3.12 or newer, got $verMajor.$verMinor"
+}
+Step "python $verMajor.$verMinor ($Python)"
+
+# --- 2. dependencies -----------------------------------------------------
+Step "installing meshbay-common, meshbay-node and PyInstaller"
+& $Python -m pip install --upgrade pip --quiet
+& $Python -m pip install --quiet `
+ (Join-Path $Repo "packages\meshbay-common") `
+ (Join-Path $Repo "packages\meshbay-node") `
+ "pyinstaller>=6.10" `
+ "tzdata"
+# tzdata: Windows ships no IANA zone database, so zoneinfo (pulled in
+# transitively) has nothing to read without it. PyInstaller warns
+# 'Hidden import "tzdata" not found' when it is absent.
+if ($LASTEXITCODE -ne 0) { throw "pip install failed" }
+
+# --- 3. freeze --------------------------------------------------------
+if (Test-Path $OutDir) { Remove-Item -Recurse -Force $OutDir }
+$pyiWork = Join-Path $Client "build\_pyinstaller"
+$pyiDist = Join-Path $Client "build\_pyinstaller-dist"
+Step "running PyInstaller (this takes a few minutes)"
+Push-Location $WinDir
+try {
+ & $Python -m PyInstaller --noconfirm --clean `
+ --workpath $pyiWork --distpath $pyiDist `
+ $SpecFile
+ if ($LASTEXITCODE -ne 0) { throw "PyInstaller failed" }
+}
+finally {
+ Pop-Location
+}
+
+$frozen = Join-Path $pyiDist "meshbay-node"
+if (-not (Test-Path (Join-Path $frozen "meshbay-node.exe"))) {
+ throw "PyInstaller did not produce meshbay-node.exe at $frozen"
+}
+
+# --- 4. optional ffmpeg ----------------------------------------------
+if ($FfmpegDir) {
+ foreach ($tool in @("ffmpeg.exe", "ffprobe.exe")) {
+ $src = Join-Path $FfmpegDir $tool
+ if (-not (Test-Path $src)) { throw "$tool not found in $FfmpegDir" }
+ Copy-Item $src (Join-Path $frozen $tool)
+ Step "bundled $tool"
+ }
+}
+else {
+ Write-Host " ffmpeg not bundled -- the node will look for it on PATH" -ForegroundColor Yellow
+}
+
+# --- 5. publish ----------------------------------------------------
+Move-Item $frozen $OutDir
+Remove-Item -Recurse -Force $pyiWork, $pyiDist -ErrorAction SilentlyContinue
+if ($createdVenv -and -not $KeepBuildVenv) {
+ Remove-Item -Recurse -Force $BuildVenv -ErrorAction SilentlyContinue
+}
+
+# --- 6. smoke test -----------------------------------------------
+# Capture, do NOT pipe to Select-Object -First: that stops the native process
+# mid-write and reports a spurious non-zero exit.
+Step "smoke test: meshbay-node --help"
+$exe = Join-Path $OutDir "meshbay-node.exe"
+$help = & $exe --help 2>&1
+if ($LASTEXITCODE -ne 0) { throw "frozen meshbay-node --help exited $LASTEXITCODE" }
+if ($help -notmatch "meshbay-node") { throw "frozen --help output looks wrong" }
+
+$mb = (Get-ChildItem $OutDir -Recurse | Measure-Object Length -Sum).Sum / 1MB
+Write-Host ""
+Write-Host ("OK node-runtime ready at {0} ({1:N0} MB)" -f $OutDir, $mb) -ForegroundColor Green