You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
7.8 KiB
PowerShell
251 lines
7.8 KiB
PowerShell
param(
|
|
[string]$RunRoot = "",
|
|
[string]$LibPackRoot = "",
|
|
[string]$OcctRoot = "",
|
|
[string]$RuntimeRoot = "",
|
|
[switch]$SkipRuntimeJson
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
function Resolve-NormalizedPath {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Path
|
|
)
|
|
|
|
return [System.IO.Path]::GetFullPath($Path)
|
|
}
|
|
|
|
function Resolve-ConfiguredPath {
|
|
param(
|
|
[string]$ConfiguredPath,
|
|
[string[]]$EnvironmentVariableNames
|
|
)
|
|
|
|
if (-not [string]::IsNullOrWhiteSpace($ConfiguredPath)) {
|
|
return Resolve-NormalizedPath -Path $ConfiguredPath
|
|
}
|
|
|
|
foreach ($variableName in $EnvironmentVariableNames) {
|
|
$value = [Environment]::GetEnvironmentVariable($variableName)
|
|
if (-not [string]::IsNullOrWhiteSpace($value)) {
|
|
return Resolve-NormalizedPath -Path $value
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
function Ensure-Directory {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Path
|
|
)
|
|
|
|
if (-not (Test-Path -LiteralPath $Path)) {
|
|
New-Item -ItemType Directory -Path $Path | Out-Null
|
|
}
|
|
}
|
|
|
|
function Copy-MatchingFiles {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$SourceDir,
|
|
[Parameter(Mandatory = $true)]
|
|
[string[]]$Patterns,
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$DestinationDir
|
|
)
|
|
|
|
if (-not (Test-Path -LiteralPath $SourceDir)) {
|
|
return
|
|
}
|
|
|
|
foreach ($pattern in $Patterns) {
|
|
Get-ChildItem -LiteralPath $SourceDir -Filter $pattern -File -ErrorAction SilentlyContinue | ForEach-Object {
|
|
Copy-Item -LiteralPath $_.FullName -Destination (Join-Path $DestinationDir $_.Name) -Force
|
|
}
|
|
}
|
|
}
|
|
|
|
function Copy-PluginDirectory {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$SourceDir,
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$DestinationDir
|
|
)
|
|
|
|
if (-not (Test-Path -LiteralPath $SourceDir)) {
|
|
return
|
|
}
|
|
|
|
Ensure-Directory -Path $DestinationDir
|
|
Get-ChildItem -LiteralPath $SourceDir -Force | ForEach-Object {
|
|
Copy-Item -LiteralPath $_.FullName -Destination $DestinationDir -Recurse -Force
|
|
}
|
|
}
|
|
|
|
function Resolve-RuntimeRoot {
|
|
param([string]$ConfiguredRoot)
|
|
|
|
if (-not [string]::IsNullOrWhiteSpace($ConfiguredRoot)) {
|
|
return Resolve-NormalizedPath -Path $ConfiguredRoot
|
|
}
|
|
|
|
$localAppData = [Environment]::GetEnvironmentVariable("LOCALAPPDATA")
|
|
if ([string]::IsNullOrWhiteSpace($localAppData)) {
|
|
throw "LOCALAPPDATA is not available."
|
|
}
|
|
|
|
return Resolve-NormalizedPath -Path (Join-Path $localAppData "QETDeps")
|
|
}
|
|
|
|
function Read-ExistingRuntimeJson {
|
|
param([string]$RuntimeConfigPath)
|
|
|
|
if (-not (Test-Path -LiteralPath $RuntimeConfigPath)) {
|
|
return $null
|
|
}
|
|
|
|
return Get-Content -LiteralPath $RuntimeConfigPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
}
|
|
|
|
function Resolve-OcctRoot {
|
|
param(
|
|
[string]$ConfiguredRoot,
|
|
$ExistingRuntime
|
|
)
|
|
|
|
$resolvedConfiguredRoot = Resolve-ConfiguredPath -ConfiguredPath $ConfiguredRoot -EnvironmentVariableNames @(
|
|
"FREECAD_OCCT_ROOT",
|
|
"QET_OCCT_ROOT"
|
|
)
|
|
if (-not [string]::IsNullOrWhiteSpace($resolvedConfiguredRoot)) {
|
|
return $resolvedConfiguredRoot
|
|
}
|
|
|
|
if ($null -ne $ExistingRuntime -and $ExistingRuntime.PSObject.Properties.Name -contains "occt_root") {
|
|
$existingOcctRoot = [string]$ExistingRuntime.occt_root
|
|
if (-not [string]::IsNullOrWhiteSpace($existingOcctRoot) -and (Test-Path -LiteralPath $existingOcctRoot)) {
|
|
return Resolve-NormalizedPath -Path $existingOcctRoot
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
$resolvedRunRoot = Resolve-ConfiguredPath -ConfiguredPath $RunRoot -EnvironmentVariableNames @(
|
|
"FREECAD_RUN_ROOT",
|
|
"QET_FREECAD_RUN_ROOT"
|
|
)
|
|
if ([string]::IsNullOrWhiteSpace($resolvedRunRoot)) {
|
|
throw "RunRoot is required. Pass -RunRoot or set FREECAD_RUN_ROOT / QET_FREECAD_RUN_ROOT."
|
|
}
|
|
|
|
$resolvedLibPackRoot = Resolve-ConfiguredPath -ConfiguredPath $LibPackRoot -EnvironmentVariableNames @(
|
|
"FREECAD_LIBPACK_ROOT",
|
|
"QET_FREECAD_LIBPACK_ROOT"
|
|
)
|
|
if ([string]::IsNullOrWhiteSpace($resolvedLibPackRoot)) {
|
|
throw "LibPackRoot is required. Pass -LibPackRoot or set FREECAD_LIBPACK_ROOT / QET_FREECAD_LIBPACK_ROOT."
|
|
}
|
|
|
|
$runBinDir = Join-Path $resolvedRunRoot "bin"
|
|
|
|
if (-not (Test-Path -LiteralPath $runBinDir)) {
|
|
throw "Run directory bin folder was not found: $runBinDir"
|
|
}
|
|
|
|
if (-not (Test-Path -LiteralPath $resolvedLibPackRoot)) {
|
|
throw "LibPack root was not found: $resolvedLibPackRoot"
|
|
}
|
|
|
|
$copySpecs = @(
|
|
@{ Source = (Join-Path $resolvedLibPackRoot "bin"); Patterns = @("*.dll") },
|
|
@{ Source = (Join-Path $resolvedLibPackRoot "lib"); Patterns = @("*.dll") },
|
|
@{ Source = (Join-Path $resolvedLibPackRoot "bin"); Patterns = @("python.exe", "pythonw.exe", "py.exe", "python*.zip") },
|
|
@{ Source = (Join-Path $resolvedLibPackRoot "bin\Lib\site-packages\shiboken6"); Patterns = @("*.dll", "*.pyd") },
|
|
@{ Source = (Join-Path $resolvedLibPackRoot "bin\Lib\site-packages\PySide6"); Patterns = @("*.dll", "*.pyd") }
|
|
)
|
|
|
|
foreach ($copySpec in $copySpecs) {
|
|
Copy-MatchingFiles -SourceDir $copySpec.Source -Patterns $copySpec.Patterns -DestinationDir $runBinDir
|
|
}
|
|
|
|
$pluginRoot = Join-Path $resolvedLibPackRoot "bin\Lib\site-packages\PySide6\plugins"
|
|
$pluginDirs = @(
|
|
"platforms",
|
|
"imageformats",
|
|
"iconengines",
|
|
"platformthemes",
|
|
"styles"
|
|
)
|
|
|
|
foreach ($pluginDir in $pluginDirs) {
|
|
Copy-PluginDirectory `
|
|
-SourceDir (Join-Path $pluginRoot $pluginDir) `
|
|
-DestinationDir (Join-Path $runBinDir $pluginDir)
|
|
}
|
|
|
|
Copy-PluginDirectory `
|
|
-SourceDir (Join-Path $resolvedLibPackRoot "bin\Lib") `
|
|
-DestinationDir (Join-Path $runBinDir "Lib")
|
|
|
|
Copy-PluginDirectory `
|
|
-SourceDir (Join-Path $resolvedLibPackRoot "bin\DLLs") `
|
|
-DestinationDir (Join-Path $runBinDir "DLLs")
|
|
|
|
if (-not $SkipRuntimeJson) {
|
|
$resolvedRuntimeRoot = Resolve-RuntimeRoot -ConfiguredRoot $RuntimeRoot
|
|
Ensure-Directory -Path $resolvedRuntimeRoot
|
|
|
|
$runtimeConfigPath = Join-Path $resolvedRuntimeRoot "runtime.json"
|
|
$diagnosticLogPath = Join-Path $resolvedRuntimeRoot "bootstrap.log"
|
|
$existingRuntime = Read-ExistingRuntimeJson -RuntimeConfigPath $runtimeConfigPath
|
|
$resolvedOcctRoot = Resolve-OcctRoot -ConfiguredRoot $OcctRoot -ExistingRuntime $existingRuntime
|
|
|
|
$resolvedFreeCadPython = ""
|
|
$pythonCandidate = Join-Path $runBinDir "python.exe"
|
|
if (Test-Path -LiteralPath $pythonCandidate) {
|
|
$resolvedFreeCadPython = $pythonCandidate
|
|
}
|
|
|
|
$resolvedFreeCadCmd = ""
|
|
$cmdCandidate = Join-Path $runBinDir "FreeCADCmd.exe"
|
|
if (Test-Path -LiteralPath $cmdCandidate) {
|
|
$resolvedFreeCadCmd = $cmdCandidate
|
|
}
|
|
|
|
$qet3dPython = if (-not [string]::IsNullOrWhiteSpace($resolvedFreeCadPython)) {
|
|
$resolvedFreeCadPython
|
|
} else {
|
|
$resolvedFreeCadCmd
|
|
}
|
|
|
|
$runtimeObject = [ordered]@{
|
|
schema_version = 1
|
|
runtime_root = $resolvedRuntimeRoot
|
|
runtime_config = $runtimeConfigPath
|
|
diagnostic_log = $diagnosticLogPath
|
|
occt_root = $resolvedOcctRoot
|
|
freecad_root = $resolvedRunRoot
|
|
freecad_lib = $runBinDir
|
|
freecad_python = $resolvedFreeCadPython
|
|
freecad_cmd = $resolvedFreeCadCmd
|
|
qet_3d_python = $qet3dPython
|
|
path_prefix = @($runBinDir)
|
|
}
|
|
|
|
($runtimeObject | ConvertTo-Json -Depth 5) | Set-Content -LiteralPath $runtimeConfigPath -Encoding UTF8
|
|
}
|
|
|
|
Write-Host "FreeCAD runtime deployment completed."
|
|
Write-Host (" Run root: {0}" -f $resolvedRunRoot)
|
|
Write-Host (" LibPack root: {0}" -f $resolvedLibPackRoot)
|
|
if (-not $SkipRuntimeJson) {
|
|
Write-Host (" runtime.json: {0}" -f (Join-Path (Resolve-RuntimeRoot -ConfiguredRoot $RuntimeRoot) "runtime.json"))
|
|
}
|