[CmdletBinding()] param( [ValidateSet("Debug", "Release")] [string]$Configuration = "Debug" ) $ErrorActionPreference = "Stop" $ProjectRoot = Split-Path -Parent $PSScriptRoot function Require-Command { param([Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][string]$InstallHint) $command = Get-Command $Name -ErrorAction SilentlyContinue if (-not $command) { throw "Required command '$Name' was not found. $InstallHint" } return $command } function Invoke-Checked { param([Parameter(Mandatory)][string]$Command, [Parameter(ValueFromRemainingArguments)][string[]]$Arguments) & $Command @Arguments if ($LASTEXITCODE -ne 0) { throw "Command failed with exit code ${LASTEXITCODE}: $Command $($Arguments -join ' ')" } } Require-Command git "Install Git for Windows and add it to PATH." | Out-Null Require-Command cmake "Install CMake 4.3 or newer and add it to PATH." | Out-Null Require-Command vcpkg "Install vcpkg and add it to PATH." | Out-Null $cmakeVersionText = (& cmake --version | Select-Object -First 1) if ($cmakeVersionText -notmatch '(\d+)\.(\d+)\.(\d+)') { throw "Could not determine the CMake version from: $cmakeVersionText" } $cmakeVersion = [Version]::new([int]$Matches[1], [int]$Matches[2], [int]$Matches[3]) if ($cmakeVersion -lt [Version]'4.3.0') { throw "CMake 4.3 or newer is required; found $cmakeVersion." } $vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe' if (-not (Test-Path $vswhere)) { throw "vswhere.exe was not found. Install Visual Studio 2026 with the Desktop development with C++ workload." } $vsPath = & $vswhere -latest -products * -version '[18.0,19.0)' ` -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath if (-not $vsPath) { throw "Visual Studio 2026 with the MSVC x64 toolchain was not found. Add the Desktop development with C++ workload." } $vcpkgConfig = (& vcpkg z-print-config | ConvertFrom-Json) $env:VCPKG_ROOT = $vcpkgConfig.'vcpkg-root' $toolchain = Join-Path $env:VCPKG_ROOT 'scripts\buildsystems\vcpkg.cmake' if (-not (Test-Path $toolchain)) { throw "The vcpkg CMake toolchain was not found at $toolchain." } Push-Location $ProjectRoot try { if (-not (Test-Path 'third_party\mcpc\mcpc\mcpc.h')) { Invoke-Checked git submodule update --init --recursive } # mcpc tracks both a top-level LICENSE file and a license/ directory. # They collide on Windows' case-insensitive filesystem. Preserve the # license/ directory used by the project and suppress only the impossible # top-level checkout entry in the local submodule index. $licenseStatus = & git -C third_party/mcpc status --porcelain -- LICENSE 2>$null if ($LASTEXITCODE -eq 0 -and $licenseStatus -match '^ D LICENSE$') { & git -C third_party/mcpc update-index --skip-worktree LICENSE if ($LASTEXITCODE -ne 0) { Write-Warning "Could not suppress mcpc's Windows LICENSE case collision; the build can continue, but the submodule may appear dirty." } } Invoke-Checked cmake --preset windows-vs2026 $preset = "windows-vs2026-$($Configuration.ToLowerInvariant())" Invoke-Checked cmake --build --preset $preset Invoke-Checked ctest --preset $preset } finally { Pop-Location } Write-Host "tiny-convmem-mcp $Configuration build and smoke test completed successfully."