228 lines
11 KiB
PowerShell
228 lines
11 KiB
PowerShell
#requires -Version 7
|
|
# Per-engine static archives for mag/elec/heat/curr.
|
|
# MSVC: cl /c + lib /OUT (no inter-engine symbol localization yet).
|
|
# MinGW: g++ -c + ld -r + objcopy --keep-global-symbols + ar — mirrors scripts/macos/build_ffi.sh.
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$Root = Resolve-Path (Join-Path $PSScriptRoot '..\..')
|
|
$Build = if ($env:BUILD) { $env:BUILD } else { Join-Path $Root 'build\ffi' }
|
|
|
|
. (Join-Path $PSScriptRoot '_toolchain.ps1')
|
|
$tc = Get-Toolchain
|
|
Initialize-Toolchain $tc
|
|
|
|
$buildProfile = if ($env:PROFILE) { $env:PROFILE } else { 'release' }
|
|
|
|
foreach ($d in @('fkn','liblua','belasolv','csolv','hsolv','ffi','exports')) {
|
|
New-Item -ItemType Directory -Force -Path (Join-Path $Build $d) | Out-Null
|
|
}
|
|
|
|
function Compile-Many {
|
|
param(
|
|
[string[]]$Includes,
|
|
[string]$OutDir,
|
|
[string[]]$Sources
|
|
)
|
|
foreach ($src in $Sources) {
|
|
$base = [IO.Path]::GetFileNameWithoutExtension($src)
|
|
if ($tc.Kind -eq 'msvc') {
|
|
$obj = Join-Path $OutDir "$base.obj"
|
|
$cxxflags = if ($buildProfile -eq 'release') {
|
|
@('/nologo','/std:c++17','/EHs-c-','/GR-','/O2','/DNDEBUG','/W0','/D_CRT_SECURE_NO_WARNINGS')
|
|
} else {
|
|
@('/nologo','/std:c++17','/EHs-c-','/GR-','/Od','/Zi','/W0','/D_CRT_SECURE_NO_WARNINGS')
|
|
}
|
|
$incFlags = $Includes | ForEach-Object { "/I$_" }
|
|
& cl.exe @cxxflags @incFlags /c $src "/Fo:$obj" | Out-Null
|
|
if ($LASTEXITCODE -ne 0) { throw "cl.exe failed on $src ($LASTEXITCODE)" }
|
|
} else {
|
|
$obj = Join-Path $OutDir "$base.o"
|
|
$cxxflags = if ($buildProfile -eq 'release') {
|
|
@('-std=c++17','-fno-exceptions','-fno-rtti','-fpermissive','-O3','-DNDEBUG','-w')
|
|
} else {
|
|
@('-std=c++17','-fno-exceptions','-fno-rtti','-fpermissive','-O0','-g','-w')
|
|
}
|
|
$incFlags = $Includes | ForEach-Object { "-I$_" }
|
|
$cxx = if ($tc.Kind -eq 'clangarm64') { Join-Path $tc.Bin 'clang++.exe' } else { 'g++.exe' }
|
|
& $cxx @cxxflags @incFlags -c $src -o $obj
|
|
if ($LASTEXITCODE -ne 0) { throw "$cxx failed on $src ($LASTEXITCODE)" }
|
|
}
|
|
}
|
|
}
|
|
|
|
# liblua — compiled against fkn's complex.h
|
|
Compile-Many `
|
|
-Includes @((Join-Path $Root 'fkn'), (Join-Path $Root 'liblua'), (Join-Path $Root 'compat')) `
|
|
-OutDir (Join-Path $Build 'liblua') `
|
|
-Sources @(
|
|
(Join-Path $Root 'liblua\lapi.cpp'),
|
|
(Join-Path $Root 'liblua\lauxlib.cpp'),
|
|
(Join-Path $Root 'liblua\lbaselib.cpp'),
|
|
(Join-Path $Root 'liblua\lcode.cpp'),
|
|
(Join-Path $Root 'liblua\ldblib.cpp'),
|
|
(Join-Path $Root 'liblua\ldebug.cpp'),
|
|
(Join-Path $Root 'liblua\ldo.cpp'),
|
|
(Join-Path $Root 'liblua\lfunc.cpp'),
|
|
(Join-Path $Root 'liblua\lgc.cpp'),
|
|
(Join-Path $Root 'liblua\liolib.cpp'),
|
|
(Join-Path $Root 'liblua\llex.cpp'),
|
|
(Join-Path $Root 'liblua\lmathlib.cpp'),
|
|
(Join-Path $Root 'liblua\lmem.cpp'),
|
|
(Join-Path $Root 'liblua\lobject.cpp'),
|
|
(Join-Path $Root 'liblua\lparser.cpp'),
|
|
(Join-Path $Root 'liblua\lstate.cpp'),
|
|
(Join-Path $Root 'liblua\lstring.cpp'),
|
|
(Join-Path $Root 'liblua\lstrlib.cpp'),
|
|
(Join-Path $Root 'liblua\ltable.cpp'),
|
|
(Join-Path $Root 'liblua\ltests.cpp'),
|
|
(Join-Path $Root 'liblua\ltm.cpp'),
|
|
(Join-Path $Root 'liblua\lundump.cpp'),
|
|
(Join-Path $Root 'liblua\lvm.cpp'),
|
|
(Join-Path $Root 'liblua\lzio.cpp')
|
|
)
|
|
|
|
Compile-Many `
|
|
-Includes @((Join-Path $Root 'fkn'), (Join-Path $Root 'compat')) `
|
|
-OutDir (Join-Path $Build 'fkn') `
|
|
-Sources @(
|
|
(Join-Path $Root 'fkn\complex.cpp'),
|
|
(Join-Path $Root 'fkn\cspars.cpp'),
|
|
(Join-Path $Root 'fkn\cuthill.cpp'),
|
|
(Join-Path $Root 'fkn\femmedoccore.cpp'),
|
|
(Join-Path $Root 'fkn\fullmatrix.cpp'),
|
|
(Join-Path $Root 'fkn\matprop.cpp'),
|
|
(Join-Path $Root 'fkn\prob1big.cpp'),
|
|
(Join-Path $Root 'fkn\prob2big.cpp'),
|
|
(Join-Path $Root 'fkn\prob3big.cpp'),
|
|
(Join-Path $Root 'fkn\prob4big.cpp'),
|
|
(Join-Path $Root 'fkn\spars.cpp')
|
|
)
|
|
|
|
Compile-Many `
|
|
-Includes @((Join-Path $Root 'belasolv'), (Join-Path $Root 'compat')) `
|
|
-OutDir (Join-Path $Build 'belasolv') `
|
|
-Sources @(
|
|
(Join-Path $Root 'belasolv\cuthill.cpp'),
|
|
(Join-Path $Root 'belasolv\femmedoccore.cpp'),
|
|
(Join-Path $Root 'belasolv\prob1big.cpp'),
|
|
(Join-Path $Root 'belasolv\spars.cpp')
|
|
)
|
|
|
|
Compile-Many `
|
|
-Includes @((Join-Path $Root 'csolv'), (Join-Path $Root 'compat')) `
|
|
-OutDir (Join-Path $Build 'csolv') `
|
|
-Sources @(
|
|
(Join-Path $Root 'csolv\complex.cpp'),
|
|
(Join-Path $Root 'csolv\cspars.cpp'),
|
|
(Join-Path $Root 'csolv\CUTHILL.CPP'),
|
|
(Join-Path $Root 'csolv\femmedoccore.cpp'),
|
|
(Join-Path $Root 'csolv\PROB1BIG.CPP')
|
|
)
|
|
|
|
Compile-Many `
|
|
-Includes @((Join-Path $Root 'hsolv'), (Join-Path $Root 'compat')) `
|
|
-OutDir (Join-Path $Build 'hsolv') `
|
|
-Sources @(
|
|
(Join-Path $Root 'hsolv\complex.cpp'),
|
|
(Join-Path $Root 'hsolv\CUTHILL.CPP'),
|
|
(Join-Path $Root 'hsolv\hsolvdoc.cpp'),
|
|
(Join-Path $Root 'hsolv\prob1big.cpp'),
|
|
(Join-Path $Root 'hsolv\SPARS.CPP')
|
|
)
|
|
|
|
# ffi shims — one TU per engine, plus the liblua complex-op shim.
|
|
Compile-Many -Includes @((Join-Path $Root 'fkn'), (Join-Path $Root 'compat')) -OutDir (Join-Path $Build 'ffi') -Sources @((Join-Path $Root 'ffi\femm_mag.cpp'))
|
|
Compile-Many -Includes @((Join-Path $Root 'belasolv'), (Join-Path $Root 'compat')) -OutDir (Join-Path $Build 'ffi') -Sources @((Join-Path $Root 'ffi\femm_elec.cpp'))
|
|
Compile-Many -Includes @((Join-Path $Root 'hsolv'), (Join-Path $Root 'compat')) -OutDir (Join-Path $Build 'ffi') -Sources @((Join-Path $Root 'ffi\femm_heat.cpp'))
|
|
Compile-Many -Includes @((Join-Path $Root 'csolv'), (Join-Path $Root 'compat')) -OutDir (Join-Path $Build 'ffi') -Sources @((Join-Path $Root 'ffi\femm_curr.cpp'))
|
|
Compile-Many -Includes @((Join-Path $Root 'liblua'), (Join-Path $Root 'compat')) -OutDir (Join-Path $Build 'ffi') -Sources @((Join-Path $Root 'ffi\femm_lua_complex_ops.cpp'))
|
|
|
|
if ($tc.Kind -eq 'msvc') {
|
|
# MSVC: bundle objects per engine via lib.exe. Note: inter-engine internal-symbol collisions
|
|
# (cuthill / femmedoccore / prob1big / spars all repeat across engines) are not localized here —
|
|
# if the Rust link step trips LNK2005, we'll need to merge to DLLs or namespace the C++ sources.
|
|
function Pack-Lib {
|
|
param([string]$Name, [string[]]$Objs)
|
|
$out = Join-Path $Build "$Name.lib"
|
|
if (Test-Path $out) { Remove-Item $out -Force }
|
|
& lib.exe /NOLOGO "/OUT:$out" @Objs | Out-Null
|
|
if ($LASTEXITCODE -ne 0) { throw "lib.exe failed for $Name ($LASTEXITCODE)" }
|
|
}
|
|
Pack-Lib 'femm_mag' ((Get-ChildItem (Join-Path $Build 'fkn\*.obj') | ForEach-Object FullName) +
|
|
(Get-ChildItem (Join-Path $Build 'liblua\*.obj') | ForEach-Object FullName) +
|
|
@((Join-Path $Build 'ffi\femm_mag.obj'),
|
|
(Join-Path $Build 'ffi\femm_lua_complex_ops.obj')))
|
|
Pack-Lib 'femm_elec' ((Get-ChildItem (Join-Path $Build 'belasolv\*.obj') | ForEach-Object FullName) +
|
|
@((Join-Path $Build 'ffi\femm_elec.obj')))
|
|
Pack-Lib 'femm_heat' ((Get-ChildItem (Join-Path $Build 'hsolv\*.obj') | ForEach-Object FullName) +
|
|
@((Join-Path $Build 'ffi\femm_heat.obj')))
|
|
Pack-Lib 'femm_curr' ((Get-ChildItem (Join-Path $Build 'csolv\*.obj') | ForEach-Object FullName) +
|
|
@((Join-Path $Build 'ffi\femm_curr.obj')))
|
|
|
|
Write-Host 'built:'
|
|
Get-ChildItem (Join-Path $Build 'femm_*.lib') | ForEach-Object { Write-Host " $($_.FullName) ($([math]::Round($_.Length/1KB)) KB)" }
|
|
} else {
|
|
$binDir = if ($tc.Kind -eq 'clangarm64') { $tc.Bin } else { $tc.MingwBin }
|
|
$nmExe = Join-Path $binDir 'nm.exe'
|
|
$arExe = Join-Path $binDir 'ar.exe'
|
|
$objcopyExe = if ($tc.Kind -eq 'clangarm64') {
|
|
Join-Path $binDir 'llvm-objcopy.exe'
|
|
} else {
|
|
Join-Path $binDir 'objcopy.exe'
|
|
}
|
|
foreach ($p in @($nmExe, $arExe, $objcopyExe)) {
|
|
if (-not (Test-Path $p)) { throw "missing binutil: $p" }
|
|
}
|
|
|
|
function Pack-Engine {
|
|
param([string]$Prefix, [string[]]$Objs)
|
|
|
|
$publicRx = "^femm_${Prefix}_"
|
|
$renameSet = [System.Collections.Generic.HashSet[string]]::new()
|
|
foreach ($obj in $Objs) {
|
|
$lines = & $nmExe --defined-only -g $obj
|
|
if ($LASTEXITCODE -ne 0) { throw "nm failed on $obj" }
|
|
foreach ($line in $lines) {
|
|
if ($line -match '^\s*(?:[0-9a-fA-F]+\s+)?([A-Z])\s+(\S+)\s*$') {
|
|
$sym = $Matches[2]
|
|
if ($sym -notmatch $publicRx) { $null = $renameSet.Add($sym) }
|
|
}
|
|
}
|
|
}
|
|
$renameFile = Join-Path $Build "exports\${Prefix}_rename.txt"
|
|
(($renameSet | Sort-Object | ForEach-Object { "$_ __femm_${Prefix}__$_" }) -join "`n") | Set-Content -Path $renameFile -Encoding ascii
|
|
|
|
$engineDir = Join-Path $Build "engines\$Prefix"
|
|
if (Test-Path $engineDir) { Remove-Item $engineDir -Recurse -Force }
|
|
New-Item -ItemType Directory -Force -Path $engineDir | Out-Null
|
|
$renamedObjs = foreach ($obj in $Objs) {
|
|
$base = [IO.Path]::GetFileName($obj)
|
|
$newPath = Join-Path $engineDir "${Prefix}_${base}"
|
|
Copy-Item $obj $newPath -Force
|
|
& $objcopyExe "--redefine-syms=$renameFile" $newPath $newPath
|
|
if ($LASTEXITCODE -ne 0) { throw "objcopy failed on $newPath ($LASTEXITCODE)" }
|
|
$newPath
|
|
}
|
|
|
|
$archive = Join-Path $Build "libfemm_${Prefix}.a"
|
|
if (Test-Path $archive) { Remove-Item $archive -Force }
|
|
& $arExe rcs $archive @renamedObjs
|
|
if ($LASTEXITCODE -ne 0) { throw "ar failed for $Prefix ($LASTEXITCODE)" }
|
|
}
|
|
|
|
Pack-Engine 'mag' ((Get-ChildItem (Join-Path $Build 'fkn\*.o') | ForEach-Object FullName) +
|
|
(Get-ChildItem (Join-Path $Build 'liblua\*.o') | ForEach-Object FullName) +
|
|
@((Join-Path $Build 'ffi\femm_mag.o'),
|
|
(Join-Path $Build 'ffi\femm_lua_complex_ops.o')))
|
|
Pack-Engine 'elec' ((Get-ChildItem (Join-Path $Build 'belasolv\*.o') | ForEach-Object FullName) +
|
|
@((Join-Path $Build 'ffi\femm_elec.o')))
|
|
Pack-Engine 'heat' ((Get-ChildItem (Join-Path $Build 'hsolv\*.o') | ForEach-Object FullName) +
|
|
@((Join-Path $Build 'ffi\femm_heat.o')))
|
|
Pack-Engine 'curr' ((Get-ChildItem (Join-Path $Build 'csolv\*.o') | ForEach-Object FullName) +
|
|
@((Join-Path $Build 'ffi\femm_curr.o')))
|
|
|
|
Write-Host 'built:'
|
|
Get-ChildItem (Join-Path $Build 'libfemm_*.a') | ForEach-Object { Write-Host " $($_.FullName) ($([math]::Round($_.Length/1KB)) KB)" }
|
|
}
|