Okay,

With the new MSVC compiler flag Andres mentioned (/arch:armv9.4) I only
had to update the S_UNLOCK() macro, the compiler did the rest correctly
AFAICT.  So, a much smaller patch (v2) attached. FWIW I'm using Visual
Studio 2026 (18) to build, other platform information below [1].

The white space/formatting issues seem to have been due to my ineptitude
on Windows running pgindent, or maybe I can blame Perl.  I'll try to dig
if I get a minute to figure out what was the cause and if I need to
patch something.

Also attached is a file with some notes on how I build. The build farm
section isn't finished yet, but there is value in the rest for anyone
doing similar work.  If you're wondering how I learned PowerShell, I
didn't.  I used AI, forgive me.  Eventually I'll have a build animal to
add to the "farm" and update a wiki page somewhere when this solidifies
a bit more. :)

best.

-greg

[1] OS Name     Microsoft Windows 11 Pro
Version 10.0.26100 Build 26100
Other OS Description    Not Available
OS Manufacturer Microsoft Corporation
System Name     SANTORINI
System Manufacturer     Microsoft Corporation
System Model    Windows Dev Kit 2023
System Type     ARM64-based PC
System SKU      2043
Processor       Snapdragon Compute Platform, 2995 Mhz, 8 Core(s), 8 Logical 
Processor(s)
BIOS Version/Date       Microsoft Corporation 13.42.235, 11/13/2024

Attachment: v2-0001-Address-build-issues-for-ARM64-using-MSVC.patch
Description: Binary data

Attachment: v2-0002-Fix-Win11-MSVC-ARM64-atomic-intrinsics.patch
Description: Binary data

My goal was to be able to:
  a) develop PostgreSQL on Win11/ARM64 using either GCC or MSVC/Visual Studio
  b) setup my host as a "build farm animal"

Why?  I'm not a "Windows super-fan", I just saw that the Win11/ARM64/MSVC combo
was not covered by the build farm as yet, so I wanted to address that.  If you
have a sick animal you should be able to diagnose and fix it.  Hence, my two
goals.

I started with Dave Cramer's work on a GitHub workflow for this combo, that was
very helpful.
https://github.com/davecramer/vcpkg/blob/main/.github/workflows/vcpkg_windows_arm.yml

NOTE: ... someday figure out how to run the workflow on the host.


Steps I took (YMMV) to accomplish (a) development/testing on Win11/ARM64/MSVC
================================================================================================

* I decided to create a directory c:\tools rather than litter things around,
  you can put the things I placed in that directory anywhere you'd like, but
  adjust your PATH accordingly.

* install Chocolatey (a package manager)
  https://docs.chocolatey.org/

* use Chocolatey to install some packages
  choco install make cmake flex bison openssl python3 diffutils gzip sed 
strawberryperl winflexbison

  NOTE: the only viable Perl is "strawberryperl" and it is only available as an
  x86_64 build.  This works for scripts used to build Postgres, but it you
  can't link it into your arm64 binary so there is no way to support plperl.

* install Git
  https://git-scm.com/install/windows

  NOTE: This gives you a nice bash shell and some coreutils too.

* use Git to install vcpkg (https://github.com/microsoft/vcpkg)
  cd c:\tools
  git clone --depth 1 --branch 2025.10.17 https://github.com/microsoft/vcpkg.git
  .\bootstrap-vcpkg.bat
  ensure that the path to "vcpkg.bat" is in your PATH

* use vcpkg to install some libraries
  cd c:\tools
  vcpkg install --triplet=arm64-windows --debug icu libiconv libxml2 libxslt 
lz4 openssl pkgconf readline vcpkg-cmake vcpkg-make vcpkg-tool-meson zlib zstd


* install meson/ninja
  python -m pip install --upgrade pip
  python -m pip install meson==1.9.1
  python -m pip install ninja==1.13.0

  NOTE: I'm not sure if I've now installed meson twice, once via vcpkg and once
  using python... oh well.

* install cURL
  https://curl.se/windows/

* install Visual Studio Community
  https://visualstudio.microsoft.com/downloads/

  ls "C:\Program Files\Microsoft Visual Studio\18\Community\"

* set some environment variables

  PATH=
    $env:PATH
    $env:VCPKG_ROOT
    c:\tools
    c:\tools\curl\bin
    c:\tools\vcpkg\installed\arm64-windows\bin
    "%AppData%\Python\Python314\Scripts"
    "%LocalAppData%\Programs\Microsoft VS Code\bin"
    "%ProgramData%\chocolatey\bin"
    "%ProgramFiles(x86)%\Windows Kits\10\Windows Performance Toolkit"
    "%ProgramFiles%\Git\cmd"
    "C:\Strawberry\c\bin"
    "C:\Strawberry\perl\site\bin"
    "C:\Strawberry\perl\bin"

PKG_CONFIG_PATH=
  c:\tools\vcpkg\installed\arm64-windows\lib\pkgconfig

VCPKG_ROOT=
  c:\tools\vcpkg

* until the fixes are in the tree, apply patches
  git am .\0001-patch-for-arm.patch
  git am .\0002-patch-meson.patch
  git am .\0003...patch

* configure environment
.\env_setup.ps1

* setup meson build
  .\setup.bat

  See below what I get when I run setup.bat

* build
  ninja -v -C build

* test
  meson test -q --print-errorlogs -C build

  NOTE: When builds fail frequently there are postgres.exe and/or cmd.exe
  processes lingering about that are holding "handles" on things and when you
  try to build again or test again or remove the build directory you'll run
  into issues.  Below is a script that finds and kills those processes.

Not required, but useful for sanity... YMMV
================================================================================================
* update PowerShell
  
https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows
  winget install --id Microsoft.PowerShell --source winget

* emacs or vi/vim/nvim
  choco install emacs nvim

* Zed Editor
  https://zed.dev/

* Sublime Merge/Text
  https://www.sublimetext.com/download
  https://www.sublimemerge.com/download

* sysinternals
 https://learn.microsoft.com/en-us/sysinternals/
 - https://live.sysinternals.com/handle.exe
 - https://live.sysinternals.com/ctrl2cap.exe

* Windows Subsystem for Linux (WSL)
  from an admin cmd.exe: wsl --install

* install Windows Terminal
  https://learn.microsoft.com/en-us/windows/terminal/install

* Docker Desktop
  https://apps.microsoft.com/detail/xp8cbj40xlbwkx
  https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-containers


CloseFileHandles.ps1
================================================================================================
PS C:\> Unblock-File C:\tools\CloseFileHandles.ps1

<SNIP>
<#
.SYNOPSIS
    Finds and terminates processes holding open handles to files in a directory.

.DESCRIPTION
    Recursively identifies all files in a specified directory that have open 
handles,
    determines which processes hold those handles, and forcefully terminates 
those processes.

.PARAMETER Path
    The directory path to scan for files with open handles. Required.

.PARAMETER WhatIf
    If specified, shows what actions would be taken without actually performing 
them.

.EXAMPLE
    .\CloseFileHandles.ps1 -Path "C:\Temp"
    .\CloseFileHandles.ps1 -Path "C:\Temp" -Verbose
    .\CloseFileHandles.ps1 -Path "C:\Temp" -WhatIf
    .\CloseFileHandles.ps1 -Path "C:\Temp" -Verbose -WhatIf
.REQUIRES
    https://live.sysinternals.com/handle.exe
#>

[CmdletBinding(SupportsShouldProcess=$true)]
param(
    [Parameter(Mandatory=$true, HelpMessage="Path to scan for open file 
handles")]
    [string]$Path
)

# Set error action preference to stop on errors
$ErrorActionPreference = "Stop"

# Initialize variables
$processesKilled = @()
$processesFailed = @()

function Write-Error-Custom {
    param([string]$Message)
    Write-Host "[ERROR] $Message" -ForegroundColor Red
}

function Write-Success-Custom {
    param([string]$Message)
    Write-Host "[SUCCESS] $Message" -ForegroundColor Green
}

function Write-WhatIf-Custom {
    param([string]$Message)
    Write-Host "[WHATIF] $Message" -ForegroundColor Yellow
}

try {
    # Validate path exists
    Write-Verbose "Validating path: $Path"
    if (-not (Test-Path -Path $Path -PathType Container)) {
        Write-Error-Custom "Path does not exist or is not a directory: $Path"
        exit 1
    }

    # Check if handle.exe exists
    Write-Verbose "Checking for handle.exe availability"
    $handlePath = "handle.exe"

    try {
        $null = & $handlePath -? 2>&1
    }
    catch {
        Write-Error-Custom "handle.exe not found. Please ensure Sysinternals 
handle.exe is in PATH or current directory."
        Write-Host "Download from: https://live.sysinternals.com/handle.exe";
        exit 1
    }

    # Get all files recursively in the path
    Write-Verbose "Scanning directory recursively: $Path"
    $files = Get-ChildItem -Path $Path -File -Recurse -ErrorAction 
SilentlyContinue

    if ($files.Count -eq 0) {
        Write-Verbose "No files found in directory"
        Write-Host "No files found in the specified directory."
        exit 0
    }

    Write-Verbose "Found $($files.Count) files to check"

    # Track unique processes to avoid duplicate kills
    $uniqueProcesses = @{}

    # Process each file
    foreach ($file in $files) {
        Write-Verbose "Checking file: $($file.FullName)"

        try {
            # Run handle.exe to find processes with open handles to this file
            $handleOutput = & $handlePath -p * $file.FullName 2>&1

            if ($handleOutput -and $handleOutput -match '\w+\s+pid:\s+(\d+)') {
                # Parse process IDs from handle.exe output
                $pidMatches = [regex]::Matches($handleOutput, 'pid:\s+(\d+)')

                foreach ($match in $pidMatches) {
                    $pid = [int]$match.Groups[1].Value

                    # Store unique processes
                    if (-not $uniqueProcesses.ContainsKey($pid)) {
                        $uniqueProcesses[$pid] = $file.FullName
                        Write-Verbose "Found process with PID $pid holding 
handle to: $($file.FullName)"
                    }
                }
            }
        }
        catch {
            Write-Verbose "Could not check handles for file $($file.FullName): 
$_"
        }
    }

    if ($uniqueProcesses.Count -eq 0) {
        Write-Success-Custom "No processes with open handles found."
        exit 0
    }

    Write-Host "`nFound $($uniqueProcesses.Count) process(es) holding open 
handles:`n"

    # Kill each unique process
    foreach ($pid in $uniqueProcesses.Keys) {
        try {
            $process = Get-Process -Id $pid -ErrorAction SilentlyContinue

            if ($null -ne $process) {
                $processName = $process.Name
                $processFile = $uniqueProcesses[$pid]

                if ($PSCmdlet.ShouldProcess("Process $processName (PID: $pid)", 
"Terminate")) {
                    Write-Verbose "Attempting to kill process: $processName 
(PID: $pid)"
                    Stop-Process -Id $pid -Force -ErrorAction Stop
                    $processesKilled += @{ Name = $processName; PID = $pid; 
File = $processFile }
                    Write-Success-Custom "Killed process: $processName (PID: 
$pid)"
                }
            }
            else {
                Write-Verbose "Process with PID $pid no longer exists"
            }
        }
        catch {
            $processesFailed += @{ PID = $pid; Error = $_.Exception.Message }
            Write-Error-Custom "Failed to kill process with PID $pid : $_"
        }
    }

    # Summary
    Write-Host "`n--- Summary ---"
    Write-Host "Processes to be killed: $($uniqueProcesses.Count)"

    if (-not $PSCmdlet.ShouldProcess("dummy", "dummy")) {
        # WhatIf mode was active
        Write-WhatIf-Custom "No processes were actually terminated (WhatIf 
mode)"
        exit 0
    }
    else {
        Write-Success-Custom "Successfully killed: $($processesKilled.Count) 
process(es)"

        if ($processesFailed.Count -gt 0) {
            Write-Error-Custom "Failed to kill: $($processesFailed.Count) 
process(es)"
            foreach ($failed in $processesFailed) {
                Write-Host "  - PID $($failed.PID): $($failed.Error)"
            }
            exit 1
        }

        if ($processesKilled.Count -gt 0 -and $processesFailed.Count -eq 0) {
            exit 0
        }
    }
}
catch {
    Write-Error-Custom "Script error: $_"
    exit 1
}
</SNIP>


Build Farm Animal Setup
================================================================================================

emacs -nw .\build-farm.conf
perl -cw .\run_build.pl
emacs -nw .\build-farm.conf
perl .\run_build.pl --test --nosend --verbose
more .\CHANGEME-test.lastrun-logs\
more .\CHANGEME-test.lastrun-logs\ns-githead.log
more .\CHANGEME-test.lastrun-logs\SCM-checkout.log


NOTES
================================================================================================
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Get-ExecutionPolicy -Scope CurrentUser
$env:PATH
# Core variables
$env:VCPKG_ROOT
$env:PATH | ForEach-Object { $_.Split(';') | Select-Object -First 20 }
# MSVC paths
$env:INCLUDE
$env:LIB
$env:LIBPATH
# Verify Python
python --version
python -c "import struct; print(f'Python is {struct.calcsize(\"P\") * 8}-bit')"
# Verify Perl location (should be empty or ARM64)
perl --version 2>&1 | Select-Object -First 5
# Meson/build configuration
$env:MESON_PREFIX_PATH
$env:CMAKE_PREFIX_PATH
$env:PKG_CONFIG_PATH
$env:LIB.Split(';') | ForEach-Object { Write-Host $_ }
cat (Get-PSReadlineOption).HistorySavePath


Last bit of output from setup.bat/meson reconfigure/setup
================================================================================================

postgresql 19devel

  Data layout
    data block size        : 8 kB
    WAL block size         : 8 kB
    segment size           : 1 GB

  System
    host system            : windows aarch64
    build system           : windows aarch64

  Compiler
    linker                 : link
    C compiler             : msvc 19.50.35718

  Compiler Flags
    CPP FLAGS              : /DWIN32 /DWINDOWS /D__WINDOWS__ /D__WIN32__ 
/D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
    C FLAGS, functional    : /std:c11
    C FLAGS, warnings      : /wd4090 /wd4244 /wd4018 /wd4101 /wd4267 /w24062 
/w24102 /w24777
    C FLAGS, modules       :
    C FLAGS, user specified:
    LD FLAGS               : /INCREMENTAL:NO /STACK:4194304 /NOEXP

  Programs
    bison                  : C:\ProgramData\chocolatey\bin\win_bison.EXE 2.7
    dtrace                 : NO
    flex                   : C:\ProgramData\chocolatey\bin\win_flex.EXE 2.6.3

  External libraries
    bonjour                : NO
    bsd_auth               : NO
    docs                   : NO
    docs_pdf               : NO
    gss                    : NO
    icu                    : YES 78.1
    ldap                   : YES
    libcurl                : NO
    libnuma                : NO
    liburing               : NO
    libxml                 : YES 2.15.0
    libxslt                : YES 1.1.43
    llvm                   : NO
    lz4                    : YES 1.10.0
    nls                    : NO
    openssl                : YES 3.6.0
    pam                    : NO
    plperl                 : NO
    plpython               : NO
    pltcl                  : NO
    readline               : NO
    selinux                : NO
    systemd                : NO
    uuid                   : NO
    zlib                   : YES 1.3.1
    zstd                   : YES 1.5.7

  User defined options
    backend                : ninja
    buildtype              : debugoptimized
    extra_include_dirs     :
    extra_lib_dirs         :
    pkg_config_path        : 
C:\tools\vcpkg\installed\arm64-windows\lib\pkgconfig
    prefix                 : C:\Program Files\postgresql

Found ninja-1.13.0.git.kitware.jobserver-pipe-1 at 
C:\Users\gregb\AppData\Roaming\Python\Python314\Scripts\ninja.EXE


ConfigMSVC.ps1
================================================================================================


# ARM64 Development Environment Setup with Auto-Detection
# Configures environment variables and runs Meson setup

# ============================================
# Visual Studio and MSVC Auto-Detection
# ============================================

function Find-VisualStudioPath {
    <#
    .SYNOPSIS
    Locates the Visual Studio installation directory using vswhere
    Works with Visual Studio 2022, 2026, and later
    #>

    # vswhere.exe is always in ProgramFiles(x86)
    $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual 
Studio\Installer\vswhere.exe"

    if (Test-Path $vswhere) {
        try {
            # Get the latest version of Visual Studio
            $vsPath = & $vswhere -latest -property installationPath 2>$null

            if ($vsPath -and (Test-Path $vsPath)) {
                Write-Host "Found Visual Studio at: $vsPath" -ForegroundColor 
Green
                return $vsPath
            }
        }
        catch {
            Write-Warning "vswhere.exe found but failed to execute: $_"
        }
    }

    # Fallback: Scan the entire Visual Studio directory tree
    $vsRoot = "${env:ProgramFiles}\Microsoft Visual Studio"
    if (Test-Path $vsRoot) {
        Write-Host "Searching for Visual Studio installations in $vsRoot" 
-ForegroundColor Yellow

        # Get year directories sorted by newest first (17 = 2022, 18 = 2026, 
etc.)
        $yearDirs = Get-ChildItem -Path $vsRoot -Directory -ErrorAction 
SilentlyContinue | Sort-Object Name -Descending

        foreach ($yearDir in $yearDirs) {
            # Get edition directories (Community, Professional, Enterprise)
            $editions = Get-ChildItem -Path $yearDir.FullName -Directory 
-ErrorAction SilentlyContinue
            foreach ($edition in $editions) {
                # Check if it has the VC tools
                if (Test-Path (Join-Path $edition.FullName "VC\Tools\MSVC")) {
                    Write-Host "Found Visual Studio at: $($edition.FullName)" 
-ForegroundColor Green
                    return $edition.FullName
                }
            }
        }
    }

    Write-Error "Visual Studio installation not found."
    Write-Error "Checked: $vswhere (vswhere.exe)"
    Write-Error "Checked: ${env:ProgramFiles}\Microsoft Visual Studio\"
    exit 1
}

function Find-MSVCPath {
    <#
    .SYNOPSIS
    Locates the MSVC compiler toolset and returns the latest version path
    #>
    param([string]$VSPath)

    $msvRoot = Join-Path $VSPath "VC\Tools\MSVC"

    if (-not (Test-Path $msvRoot)) {
        Write-Error "MSVC toolset not found at $msvRoot"
        exit 1
    }

    # Get the latest MSVC version folder
    $msvVersions = Get-ChildItem -Path $msvRoot -Directory | Sort-Object Name 
-Descending

    if ($msvVersions.Count -eq 0) {
        Write-Error "No MSVC versions found in $msvRoot"
        exit 1
    }

    return Join-Path $msvRoot $msvVersions[0].Name
}

function Find-WindowsSDKVersion {
    <#
    .SYNOPSIS
    Detects the Windows SDK version from the registry
    #>
    $regPath = "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots"

    if (Test-Path $regPath) {
        $sdkRoot = Get-ItemProperty -Path $regPath -Name KitsRoot10
        $sdkRoot = $sdkRoot.KitsRoot10

        if (Test-Path (Join-Path $sdkRoot "Include")) {
            # Get the latest SDK version folder
            $versions = Get-ChildItem -Path (Join-Path $sdkRoot "Include") 
-Directory |
                        Where-Object { $_.Name -match '^\d+\.\d+\.\d+\.\d+$' } |
                        Sort-Object Name -Descending

            if ($versions.Count -gt 0) {
                return @{
                    Version = $versions[0].Name
                    Path = $sdkRoot
                }
            }
        }
    }

    Write-Error "Windows SDK not found"
    exit 1
}

# ============================================
# Main Setup
# ============================================

Write-Host "=== Detecting Visual Studio Installation ===" -ForegroundColor Cyan
$vsPath = Find-VisualStudioPath
Write-Host "Found Visual Studio at: $vsPath" -ForegroundColor Green

Write-Host "`n=== Detecting MSVC Toolset ===" -ForegroundColor Cyan
$msvPath = Find-MSVCPath -VSPath $vsPath
Write-Host "Found MSVC at: $msvPath" -ForegroundColor Green

Write-Host "`n=== Detecting Windows SDK ===" -ForegroundColor Cyan
$sdkInfo = Find-WindowsSDKVersion
$winKitVersion = $sdkInfo.Version
$winKitPath = $sdkInfo.Path
Write-Host "Found Windows SDK $winKitVersion at: $winKitPath" -ForegroundColor 
Green

# ============================================
# Initialize MSVC Environment with vcvarsarm64.bat
# ============================================

Write-Host "`n=== Initializing MSVC Environment ===" -ForegroundColor Cyan

$vcvarsPath = Join-Path $vsPath "VC\Auxiliary\Build\vcvarsarm64.bat"

if (-not (Test-Path $vcvarsPath)) {
    Write-Error "vcvarsarm64.bat not found at $vcvarsPath"
    exit 1
}

# Detect Visual Studio version from path
$vsVersion = (Split-Path $vsPath -Parent | Split-Path -Leaf)
Write-Host "Detected Visual Studio version: $vsVersion" -ForegroundColor Yellow

# Map VS directory to version number (17=2022, 18=2026, etc.)
$versionMap = @{
    "17" = "17.0"
    "18" = "18.0"
    "19" = "19.0"
}
$visualStudioVersion = $versionMap[$vsVersion]
if (-not $visualStudioVersion) {
    $visualStudioVersion = "$vsVersion.0"
}

Write-Host "Executing: `"$vcvarsPath`"" -ForegroundColor Yellow
$output = cmd /c """$vcvarsPath"" && set"

# Parse and set all environment variables from vcvarsarm64.bat
foreach ($line in $output) {
    if ($line -match "^([^=]+)=(.*)$") {
        $varName = $matches[1].Trim()
        $varValue = $matches[2].Trim()

        if ($varName -and $varValue) {
            Set-Item -Force -Path "ENV:\$varName" -Value $varValue 2>$null
        }
    }
}

# Explicitly set required variables for Meson
$env:VSINSTALLDIR = $vsPath
$env:VisualStudioVersion = $visualStudioVersion
$env:VCINSTALLDIR = $msvPath

# Verify critical variables
$requiredVars = @{
    "VSINSTALLDIR" = $vsPath
    "VisualStudioVersion" = $visualStudioVersion
    "VCINSTALLDIR" = $msvPath
}

Write-Host "`nEnvironment variables set:" -ForegroundColor Green
foreach ($var in $requiredVars.GetEnumerator()) {
    $value = Get-Item -Path "ENV:\$($var.Key)" -ErrorAction SilentlyContinue
    if ($value) {
        Write-Host "  $($var.Key) = $($value.Value)" -ForegroundColor Green
    }
    else {
        Write-Warning "  $($var.Key) not set!"
    }
}

Write-Host "MSVC environment initialized" -ForegroundColor Green

# ============================================
# Configure Include Paths
# ============================================

Write-Host "`n=== Configuring Include Paths ===" -ForegroundColor Cyan

$includeList = @(
    "$msvPath\include",
    "$winKitPath\Include\$winKitVersion\ucrt",
    "$winKitPath\Include\$winKitVersion\um",
    "$winKitPath\Include\$winKitVersion\shared"
    "$vcpkgRoot\installed\arm64-windows\include"
)

$env:INCLUDE = $includeList -join ";"
Write-Host "INCLUDE path configured" -ForegroundColor Green

# Dump INCLUDE
#$env:INCLUDE | ForEach-Object { $_.Split(';') | Select-Object -First 20 }

# ============================================
# Configure Library Paths
# ============================================

Write-Host "`n=== Configuring Library Paths ===" -ForegroundColor Cyan

$libList = @(
    "$msvPath\lib\arm64",
    "$winKitPath\Lib\$winKitVersion\ucrt\arm64",
    "$winKitPath\Lib\$winKitVersion\um\arm64"
    "$vcpkgRoot\installed\arm64-windows\lib"
)

$env:LIB = $libList -join ";"
$env:LIBPATH = $env:LIB
Write-Host "LIB and LIBPATH configured" -ForegroundColor Green

# Dump LIB
#$env:LIB | ForEach-Object { $_.Split(';') | Select-Object -First 20 }

# ============================================
# Configure PATH
# ============================================

Write-Host "`n=== Configuring System PATH ===" -ForegroundColor Cyan

$pythonPath = "C:\Python314"
#$pythonPath = Join-Path $env:LocalAppData "Programs\Python\Python314"
$pythonScripts = Join-Path $pythonPath "Scripts"
$pythonUserScripts = Join-Path $env:AppData "Python\Python314\Scripts"

$vcpkgRoot = "C:\tools\vcpkg"
$codeInsiders = Join-Path $env:LocalAppData "Programs\Microsoft VS Code 
Insiders\bin"
$vsCode = Join-Path $env:LocalAppData "Programs\Microsoft VS Code\bin"

# Perl paths - try Strawberry Perl first, then ActivePerl
$perlPath = $null
$perlCandidates = @(
    "C:\Strawberry\perl\bin",
    "${env:ProgramFiles}\Strawberry\perl\bin",
    "${env:ProgramFiles(x86)}\Strawberry\perl\bin",
    "C:\Perl\bin",
    "${env:ProgramFiles}\ActivePerl\bin"
)

foreach ($candidate in $perlCandidates) {
    if (Test-Path $candidate) {
        $perlPath = $candidate
        Write-Host "Found Perl at: $perlPath" -ForegroundColor Green
        break
    }
}

if (-not $perlPath) {
    Write-Warning "Perl not found in standard locations. PostgreSQL build may 
fail."
    Write-Warning "Install Strawberry Perl from https://strawberryperl.com/";
}

$pathArray = @(
    # ARM64 MSVC compiler
    "$msvPath\bin\HostARM64\ARM64",

    # ARM64 Python (BEFORE system Python or other tools)
    $pythonPath,
    $pythonScripts,
    $pythonUserScripts,

    # Add Perl to PATH
    $perlPath,

    # ARM64 vcpkg
    "$vcpkgRoot\installed\arm64-windows\bin",
    
    # Windows Kits ARM64
    "$winKitPath\bin\$winKitVersion\arm64",

    # System paths
    "$env:SystemRoot\system32",
    "$env:SystemRoot",
    "$env:SystemRoot\System32\Wbem",
    "$env:SystemRoot\System32\WindowsPowerShell\v1.0",
    $codeInsiders,
    $vsCode,

    # Optional tools (but keep at end)
    "${env:ProgramFiles}\Git\cmd",
    "${env:ProgramFiles}\Neovim\bin",
    "${env:ProgramFiles(x86)}\Windows Kits\10\Windows Performance Toolkit",
    "${env:ProgramData}\chocolatey\bin",
    "${env:ProgramFiles}\CMake\bin",
    "C:\tools"
)

# Filter out null/empty entries and non-existent paths
$env:PATH = ($pathArray | Where-Object { $_ -and (Test-Path $_) }) -join ";"
Write-Host "PATH configured" -ForegroundColor Green

# Dump PATH
#$env:PATH | ForEach-Object { $_.Split(';') | Select-Object -First 20 }


# ============================================
# Configure vcpkg and CMake
# ============================================

Write-Host "`n=== Configuring vcpkg and CMake ===" -ForegroundColor Cyan

if (Test-Path $vcpkgRoot) {
    $env:VCPKG_ROOT = $vcpkgRoot
    $env:CMAKE_PREFIX_PATH = "$vcpkgRoot\installed\arm64-windows"

    # Set PKG_CONFIG_PATH for Meson to find vcpkg dependencies
    $env:PKG_CONFIG_PATH = "$vcpkgRoot\installed\arm64-windows\lib\pkgconfig"

    # Add vcpkg tools to PATH (includes pkg-config, ninja from 
vcpkg-tool-meson, etc.)
    $vcpkgBinPath = "$vcpkgRoot\installed\arm64-windows\bin"
    $vcpkgToolsPath = "$vcpkgRoot\tools"

    if ($vcpkgBinPath -notin $env:PATH.Split(";")) {
        $env:PATH = "$vcpkgBinPath;$env:PATH"
    }

    if ($vcpkgToolsPath -notin $env:PATH.Split(";")) {
        $env:PATH = "$vcpkgToolsPath;$env:PATH"
    }

    Write-Host "vcpkg configured:" -ForegroundColor Green
    Write-Host "  VCPKG_ROOT = $env:VCPKG_ROOT" -ForegroundColor Green
    Write-Host "  CMAKE_PREFIX_PATH = $env:CMAKE_PREFIX_PATH" -ForegroundColor 
Green
    Write-Host "  PKG_CONFIG_PATH = $env:PKG_CONFIG_PATH" -ForegroundColor Green
    Write-Host "  Added to PATH: $vcpkgBinPath" -ForegroundColor Green
}
else {
    Write-Warning "vcpkg not found at $vcpkgRoot - skipping vcpkg configuration"
}

# ============================================
# Run Meson Setup
# ============================================

Write-Host "`n=== Running Meson Setup ===" -ForegroundColor Cyan

$mesonBuildDir = "build"
$mesonPrefix = "${env:ProgramFiles}\postgresql"

# Use ninja backend instead of vs, which works better with newer MSVC
$mesonArgs = @(
    "setup"
    $mesonBuildDir
    "--reconfigure"
#    "--vsenv"
#    "--backend", "vs"
    "--backend", "ninja"
    "--prefix=$mesonPrefix"
    "--buildtype=debugoptimized"
    "-Dplperl=disabled"
    "-Dextra_lib_dirs=$extraLibDir"
    "-Dextra_include_dirs=$extraIncludeDir"
    "-Dpkg_config_path=$env:PKG_CONFIG_PATH"
)

Write-Host "Executing: meson $($mesonArgs -join ' ')" -ForegroundColor Yellow
meson @mesonArgs

Reply via email to