Lumi/companion/scripts/build-obs-bridge.ps1
2026-07-24 22:12:39 +02:00

112 lines
5.9 KiB
PowerShell

param(
[string]$ObsVersion = "31.1.1",
[string]$BridgeVersion = "0.2.0",
[string]$CacheRoot = "$env:LOCALAPPDATA\LumiCompanionBuild"
)
$ErrorActionPreference = "Stop"
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..\..")).Path
$nativeRoot = Join-Path $repoRoot "companion\native\obs-bridge"
$componentRoot = Join-Path $repoRoot "companion\src\Lumi.Companion.App\components\obs-bridge"
$obsRoot = Join-Path $CacheRoot "obs-$ObsVersion"
$runtimeArchive = Join-Path $obsRoot "obs-windows.zip"
$sourceArchive = Join-Path $obsRoot "obs-source.zip"
$runtimeRoot = Join-Path $obsRoot "runtime"
$sourceParent = Join-Path $obsRoot "source"
$sourceRoot = Join-Path $sourceParent "obs-studio-$ObsVersion"
$importRoot = Join-Path $obsRoot "imports"
$buildRoot = Join-Path $obsRoot "bridge-build"
function Invoke-Native([string]$FilePath, [string[]]$Arguments) {
$argumentLine = ($Arguments | ForEach-Object { '"' + ([string]$_).Replace('"', '\"') + '"' }) -join ' '
$process = Start-Process -FilePath $FilePath -ArgumentList $argumentLine -NoNewWindow -Wait -PassThru
return $process.ExitCode
}
$runtimeUrl = "https://github.com/obsproject/obs-studio/releases/download/$ObsVersion/OBS-Studio-$ObsVersion-Windows-x64.zip"
$sourceUrl = "https://github.com/obsproject/obs-studio/archive/refs/tags/$ObsVersion.zip"
$runtimeSha256 = "9d8dceb77acd8af04af23f877061f63c9bef78ca73d2093d0ccba1bb9104173f"
$sourceSha256 = "2c8427c10b55ac6d68008df2e9a3e82f4647aaad18f105e30d4713c2de678ccf"
function Get-VerifiedArchive([string]$Url, [string]$Path, [string]$ExpectedSha256) {
if (!(Test-Path $Path) -or (Get-FileHash $Path -Algorithm SHA256).Hash.ToLowerInvariant() -ne $ExpectedSha256) {
New-Item -ItemType Directory -Force -Path (Split-Path $Path) | Out-Null
$partial = "$Path.partial"
Remove-Item $partial -Force -ErrorAction SilentlyContinue
Invoke-WebRequest -Uri $Url -OutFile $partial
if ((Get-FileHash $partial -Algorithm SHA256).Hash.ToLowerInvariant() -ne $ExpectedSha256) {
Remove-Item $partial -Force -ErrorAction SilentlyContinue
throw "Checksum mismatch while downloading $Url"
}
Move-Item $partial $Path -Force
}
}
function New-ImportLibrary([string]$Dll, [string]$Name, [string]$Dumpbin, [string]$LibExe) {
$definition = Join-Path $importRoot "$Name.def"
$dumpOutputPath = Join-Path $importRoot "$Name.exports.txt"
$dump = Start-Process -FilePath $Dumpbin -ArgumentList @("/nologo", "/exports", "`"$Dll`"") -RedirectStandardOutput $dumpOutputPath -NoNewWindow -Wait -PassThru
if ($dump.ExitCode) { throw "Could not inspect exports for $Name." }
$dumpOutput = Get-Content $dumpOutputPath
$exports = @($dumpOutput | ForEach-Object {
if ($_ -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]+\s+(\S+)') { $Matches[1] }
})
@("LIBRARY $Name", "EXPORTS") + ($exports | ForEach-Object { " $_" }) | Set-Content -Encoding Ascii $definition
$exitCode = Invoke-Native $LibExe @("/nologo", "/machine:x64", "/def:$definition", "/out:$(Join-Path $importRoot "$Name.lib")")
if ($exitCode) { throw "Could not create the $Name import library." }
}
Get-VerifiedArchive $runtimeUrl $runtimeArchive $runtimeSha256
Get-VerifiedArchive $sourceUrl $sourceArchive $sourceSha256
if (!(Test-Path (Join-Path $runtimeRoot "bin\64bit\obs.dll"))) {
Remove-Item $runtimeRoot -Recurse -Force -ErrorAction SilentlyContinue
Expand-Archive $runtimeArchive $runtimeRoot
}
if (!(Test-Path (Join-Path $sourceRoot "libobs\obs-module.h"))) {
Remove-Item $sourceParent -Recurse -Force -ErrorAction SilentlyContinue
Expand-Archive $sourceArchive $sourceParent
}
$vswhere = Join-Path ${env:ProgramFiles(x86)} "Microsoft Visual Studio\Installer\vswhere.exe"
$vsRoot = if (Test-Path $vswhere) { & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath }
if (!$vsRoot) { $vsRoot = Join-Path ${env:ProgramFiles(x86)} "Microsoft Visual Studio\2022\BuildTools" }
if (!(Test-Path $vsRoot)) { throw "Visual Studio 2022 C++ Build Tools are required." }
$vcTools = Get-ChildItem (Join-Path $vsRoot "VC\Tools\MSVC") -Directory | Sort-Object { [version]$_.Name } | Select-Object -Last 1
$toolRoot = Join-Path $vcTools.FullName "bin\Hostx64\x64"
$dumpbin = Join-Path $toolRoot "dumpbin.exe"
$lib = Join-Path $toolRoot "lib.exe"
$cmakeCommand = Get-Command cmake.exe -ErrorAction SilentlyContinue
$cmake = if ($cmakeCommand) { $cmakeCommand.Source } else {
Get-ChildItem (Join-Path $env:APPDATA "Python") -Filter cmake.exe -File -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName
}
if (!$cmake) { throw "CMake 3.28 or newer is required." }
New-Item -ItemType Directory -Force -Path $importRoot | Out-Null
New-ImportLibrary (Join-Path $runtimeRoot "bin\64bit\obs.dll") "obs" $dumpbin $lib
New-ImportLibrary (Join-Path $runtimeRoot "bin\64bit\obs-frontend-api.dll") "obs-frontend-api" $dumpbin $lib
$configureArguments = @(
"-S", $nativeRoot,
"-B", $buildRoot,
"-G", "Visual Studio 17 2022",
"-A", "x64",
"-DOBS_SOURCE_DIR=$sourceRoot",
"-DOBS_IMPORT_DIR=$importRoot",
"-DLUMI_BRIDGE_VERSION=$BridgeVersion"
)
if ((Invoke-Native $cmake $configureArguments)) { throw "OBS bridge configuration failed." }
if ((Invoke-Native $cmake @("--build", $buildRoot, "--config", "Release"))) { throw "OBS bridge build failed." }
New-Item -ItemType Directory -Force -Path $componentRoot | Out-Null
$bridgeDll = Join-Path $buildRoot "Release\lumi-obs-bridge.dll"
Copy-Item $bridgeDll (Join-Path $componentRoot "lumi-obs-bridge.dll") -Force
Copy-Item (Join-Path $nativeRoot "data\locale\en-US.ini") (Join-Path $componentRoot "en-US.ini") -Force
$manifest = [ordered]@{
version = $BridgeVersion
sha256 = (Get-FileHash $bridgeDll -Algorithm SHA256).Hash.ToLowerInvariant()
obs_minimum_version = "31.0.0"
}
$manifestJson = $manifest | ConvertTo-Json
[IO.File]::WriteAllText((Join-Path $componentRoot "manifest.json"), $manifestJson, [Text.UTF8Encoding]::new($false))
Write-Host "Built OBS bridge $BridgeVersion at $componentRoot"