FEMM/scripts/windows/_toolchain.ps1

120 lines
4.6 KiB
PowerShell

# Toolchain detection. Picks a backend appropriate for the host arch:
# x64 host -> MSVC (x64) or MinGW (x86_64), Rust target = host default or x86_64-pc-windows-gnu
# ARM64 host -> CLANGARM64 (msys2) or MinGW (x86_64, emulated, warned), Rust target = aarch64-pc-windows-gnullvm
# Dot-source this file: . "$PSScriptRoot\_toolchain.ps1"
$ErrorActionPreference = 'Stop'
function Get-HostArch {
if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64' -or $env:PROCESSOR_ARCHITEW6432 -eq 'ARM64') { return 'arm64' }
return 'x64'
}
function Initialize-VsEnv {
param([string]$VcVars)
$tmp = New-TemporaryFile
try {
cmd /c "`"$VcVars`" x64 >NUL && set" | Out-File -FilePath $tmp -Encoding ascii
foreach ($line in Get-Content $tmp) {
if ($line -match '^([^=]+)=(.*)$') {
Set-Item -Path "env:$($Matches[1])" -Value $Matches[2]
}
}
} finally {
Remove-Item $tmp -Force -ErrorAction SilentlyContinue
}
}
function Find-VsInstall {
$vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe'
if (-not (Test-Path $vswhere)) {
$vswhere = Join-Path $env:ProgramFiles 'Microsoft Visual Studio\Installer\vswhere.exe'
}
if (-not (Test-Path $vswhere)) { return $null }
$install = & $vswhere -latest -products * `
-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
-property installationPath 2>$null
if (-not $install) { return $null }
$vcvars = Join-Path $install 'VC\Auxiliary\Build\vcvars64.bat'
if (Test-Path $vcvars) { return $vcvars }
return $null
}
function Find-MingwBin {
if ($env:MINGW_PREFIX -and (Test-Path (Join-Path $env:MINGW_PREFIX 'g++.exe'))) {
return $env:MINGW_PREFIX
}
$gxx = Get-Command g++.exe -ErrorAction SilentlyContinue
if ($gxx) { return (Split-Path $gxx.Source -Parent) }
foreach ($p in @(
'C:\msys64\mingw64\bin',
'C:\msys64\ucrt64\bin',
'C:\mingw64\bin',
'C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin'
)) {
if (Test-Path (Join-Path $p 'g++.exe')) { return $p }
}
return $null
}
function Find-ClangArm64Bin {
if ($env:CLANGARM64_PREFIX -and (Test-Path (Join-Path $env:CLANGARM64_PREFIX 'clang++.exe'))) {
return $env:CLANGARM64_PREFIX
}
foreach ($p in @('C:\msys64\clangarm64\bin')) {
if (Test-Path (Join-Path $p 'clang++.exe')) { return $p }
}
return $null
}
function Get-Toolchain {
$hostArch = Get-HostArch
if ($hostArch -eq 'arm64') {
$clangBin = Find-ClangArm64Bin
if ($clangBin) {
return [pscustomobject]@{
Kind = 'clangarm64'
Ready = $true
Bin = $clangBin
CargoTarget = 'aarch64-pc-windows-gnullvm'
}
}
$mingw = Find-MingwBin
if ($mingw) {
Write-Warning "ARM64 host but only x86_64 MinGW found; resulting binaries will run under emulation and may crash at startup. Install msys2 CLANGARM64 (pacman -S mingw-w64-clang-aarch64-toolchain)."
return [pscustomobject]@{ Kind = 'mingw'; Ready = $true; MingwBin = $mingw; CargoTarget = 'x86_64-pc-windows-gnu' }
}
throw "No ARM64 C++ toolchain found. Install msys2 CLANGARM64 (pacman -S mingw-w64-clang-aarch64-toolchain) or Visual Studio ARM64 C++ tools."
}
if (Get-Command cl.exe -ErrorAction SilentlyContinue) {
return [pscustomobject]@{ Kind = 'msvc'; Ready = $true; VcVars = $null; CargoTarget = '' }
}
$vcvars = Find-VsInstall
if ($vcvars) {
return [pscustomobject]@{ Kind = 'msvc'; Ready = $false; VcVars = $vcvars; CargoTarget = '' }
}
$mingw = Find-MingwBin
if ($mingw) {
return [pscustomobject]@{ Kind = 'mingw'; Ready = $true; MingwBin = $mingw; CargoTarget = 'x86_64-pc-windows-gnu' }
}
throw "No C++ toolchain found. Install Visual Studio Build Tools (with the C++ workload) or MinGW-w64."
}
function Initialize-Toolchain {
param([pscustomobject]$Toolchain)
if ($Toolchain.Kind -eq 'msvc' -and -not $Toolchain.Ready) {
Write-Host "Importing MSVC environment from $($Toolchain.VcVars)"
Initialize-VsEnv -VcVars $Toolchain.VcVars
}
if ($Toolchain.Kind -eq 'mingw' -and $Toolchain.MingwBin -and ($env:PATH -notlike "*$($Toolchain.MingwBin)*")) {
$env:PATH = "$($Toolchain.MingwBin);$env:PATH"
}
if ($Toolchain.Kind -eq 'clangarm64' -and $Toolchain.Bin -and ($env:PATH -notlike "*$($Toolchain.Bin)*")) {
$env:PATH = "$($Toolchain.Bin);$env:PATH"
}
}