[CmdletBinding()] param( [Parameter(Mandatory=$true)][string]$LibraryPath, [string]$ResultPath ) $ErrorActionPreference = 'Stop' $script:Root = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..')) $LibraryPath = [IO.Path]::GetFullPath($LibraryPath) if (-not (Test-Path -LiteralPath $LibraryPath -PathType Leaf)) { throw "Core library not found: $LibraryPath" } $VsBinRoots = @(Get-ChildItem -LiteralPath 'E:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC' -Directory -ErrorAction Stop | ForEach-Object { Join-Path $_.FullName 'bin\Hostx64\x64' } | Where-Object { Test-Path -LiteralPath (Join-Path $_ 'dumpbin.exe') }) if ($VsBinRoots.Count -eq 0) { throw 'dumpbin.exe was not found in the Visual Studio toolchain.' } $Dumpbin = Join-Path $VsBinRoots[-1] 'dumpbin.exe' # Build the forbidden set from the compatibility and copied Unreal-facing declarations so the # check covers the complete private type surface instead of a short hand-maintained example list. $ScanRoots = @( (Join-Path $script:Root 'Compat'), (Join-Path $script:Root 'Source'), (Join-Path $script:Root 'Core\src') ) $TypeNames = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) foreach ($ScanRoot in $ScanRoots) { foreach ($File in Get-ChildItem -LiteralPath $ScanRoot -Recurse -File -Include *.h,*.hpp,*.cpp) { foreach ($Match in [regex]::Matches([IO.File]::ReadAllText($File.FullName), '(?m)^\s*(?:class|struct|enum(?:\s+class)?|using)\s+([FTUE][A-Z][A-Za-z0-9_]*)\b')) { [void]$TypeNames.Add($Match.Groups[1].Value) } } } if ($TypeNames.Count -eq 0) { throw 'Could not derive Unreal-style type names from the copied implementation.' } $Dump = @(& $Dumpbin /SYMBOLS $LibraryPath 2>&1) if ($LASTEXITCODE -eq -1073741502) { throw 'dumpbin.exe exited with 0xC0000142; stopping as required.' } if ($LASTEXITCODE -ne 0) { throw "dumpbin.exe failed with exit code $LASTEXITCODE" } if ($Dump.Count -lt 1000) { throw "dumpbin returned only $($Dump.Count) lines; Core object symbols are not visible enough to verify." } $Violations = [Collections.Generic.List[string]]::new() $Alternation = ($TypeNames | Sort-Object { $_.Length } -Descending | ForEach-Object { [regex]::Escape($_) }) -join '|' $GlobalTypePattern = [regex]::new('(?