param( [string]$ObsVersion = "31.1.1", [string]$BridgeVersion = "0.1.0-experimental.5", [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" $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 & $LibExe /nologo /machine:x64 "/def:$definition" "/out:$(Join-Path $importRoot "$Name.lib")" if ($LASTEXITCODE) { 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`"") $configured = Start-Process -FilePath $cmake -ArgumentList $configureArguments -NoNewWindow -Wait -PassThru if ($configured.ExitCode) { throw "OBS bridge configuration failed." } $built = Start-Process -FilePath $cmake -ArgumentList @("--build", "`"$buildRoot`"", "--config", "Release") -NoNewWindow -Wait -PassThru if ($built.ExitCode) { 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"