From 6508b75d7d2b74f9b64cb53aef5a2178db35b731 Mon Sep 17 00:00:00 2001 From: Leonard Grey Date: Tue, 16 Sep 2025 18:01:33 -0400 Subject: [PATCH 1/3] build.ps1: make time summary hierarchical --- utils/build.ps1 | 128 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 96 insertions(+), 32 deletions(-) diff --git a/utils/build.ps1 b/utils/build.ps1 index 76951ed1392a5..bd9bcfcb17c4d 100644 --- a/utils/build.ps1 +++ b/utils/build.ps1 @@ -581,6 +581,7 @@ $WindowsSDKBuilds = @($WindowsSDKArchitectures | ForEach-Object { ## Helpers for logging and timing build steps. $TimingData = New-Object System.Collections.Generic.List[System.Object] +$CurrentOperation = $null function Add-TimingData { param @@ -589,16 +590,86 @@ function Add-TimingData { [Hashtable] $Platform, [Parameter(Mandatory)] [string] $BuildStep, - [Parameter(Mandatory)] - [System.TimeSpan] $ElapsedTime + [PSCustomObject] $Parent = $null ) - $TimingData.Add([PSCustomObject]@{ + $TimingEntry = [PSCustomObject]@{ Arch = $Platform.Architecture.LLVMName Platform = $Platform.OS.ToString() "Build Step" = $BuildStep - "Elapsed Time" = $ElapsedTime - }) + "Elapsed Time" = [TimeSpan]::Zero + "Child Time" = [TimeSpan]::Zero + Parent = $Parent + Children = @() + } + + if ($Parent) { + $Parent.Children += $TimingEntry + } + + $TimingData.Add($TimingEntry) + return $TimingEntry +} + +function Record-OperationTime { + param + ( + [Parameter(Mandatory)] + [Hashtable] $Platform, + [Parameter(Mandatory)] + [string] $BuildStep, + [Parameter(Mandatory)] + [ScriptBlock] $ScriptBlock + ) + if (!$Summary) { + & $ScriptBlock + return + } + + $Stopwatch = [Diagnostics.Stopwatch]::StartNew() + $TimingEntry = Add-TimingData $Platform $BuildStep $script:CurrentOperation + $script:CurrentOperation = $TimingEntry + + try { + & $ScriptBlock + } finally { + $Stopwatch.Stop() + $TimingEntry."Elapsed Time" = $Stopwatch.Elapsed + if ($TimingEntry.Parent) { + $TimingEntry.Parent."Child Time" = $TimingEntry.Parent."Child Time".Add($Stopwatch.Elapsed) + } + $script:CurrentOperation = $TimingEntry.Parent + } +} + +function Flatten-TimingEntry { + param( + [Parameter(Mandatory)] + [PSCustomObject] $Entry, + [Parameter(Mandatory)] + [TimeSpan] $TotalTime, + [int] $Depth = 0 + ) + + $Indent = " " * $Depth + $Percentage = [math]::Round(($Entry."Elapsed Time".TotalSeconds / $TotalTime.TotalSeconds) * 100, 1) + $FormattedTime = "{0:hh\:mm\:ss\.ff}" -f $Entry."Elapsed Time" + $SelfTime = $Entry."Elapsed Time".Subtract($Entry."Child Time") + $FormattedSelfTime = "{0:hh\:mm\:ss\.ff}" -f $SelfTime + + [PSCustomObject]@{ + "Total Time" = $FormattedTime + "Self Time" = $FormattedSelfTime + "%" = "$Percentage%" + "Build Step" = "$Indent$($Entry.'Build Step')" + Platform = $Entry.Platform + Arch = $Entry.Arch + } + + $SortedChildren = $Entry.Children | Sort-Object -Descending -Property "Elapsed Time" + foreach ($Child in $SortedChildren) { + Flatten-TimingEntry $Child $TotalTime ($Depth + 1) + } } function Write-Summary { @@ -611,31 +682,27 @@ function Write-Summary { $TotalTime = [TimeSpan]::Zero foreach ($Entry in $TimingData) { - $TotalTime = $TotalTime.Add($Entry."Elapsed Time") - } - - $SortedData = $TimingData | ForEach-Object { - $Percentage = [math]::Round(($_.("Elapsed Time").TotalSeconds / $TotalTime.TotalSeconds) * 100, 1) - $FormattedTime = "{0:hh\:mm\:ss\.ff}" -f $_."Elapsed Time" - [PSCustomObject]@{ - "Build Step" = $_."Build Step" - Platform = $_.Platform - Arch = $_.Arch - "Elapsed Time" = $FormattedTime - "%" = "$Percentage%" + if (-not $Entry.Parent) { + $TotalTime = $TotalTime.Add($Entry."Elapsed Time") } - } | Sort-Object -Descending -Property "Elapsed Time" + } + + $RootEntries = $TimingData | Where-Object { -not $_.Parent } | Sort-Object -Descending -Property "Elapsed Time" + $Result = foreach ($RootEntry in $RootEntries) { + Flatten-TimingEntry $RootEntry $TotalTime + } $FormattedTotalTime = "{0:hh\:mm\:ss\.ff}" -f $TotalTime $TotalRow = [PSCustomObject]@{ + "Total Time" = $FormattedTotalTime + "Self Time" = $FormattedTotalTime + "%" = "100.0%" "Build Step" = "TOTAL" Platform = "" Arch = "" - "Elapsed Time" = $FormattedTotalTime - "%" = "100.0%" } - @($SortedData) + $TotalRow | Format-Table -AutoSize + @($Result) + $TotalRow | Format-Table -AutoSize } function Get-AndroidNDK { @@ -720,10 +787,6 @@ function Invoke-BuildStep { [Object[]] $RemainingArgs ) - if ($Summary) { - $Stopwatch = [Diagnostics.Stopwatch]::StartNew() - } - $SplatArgs = @{} if ($RemainingArgs) { $Enumerator = $RemainingArgs.GetEnumerator() @@ -750,10 +813,8 @@ function Invoke-BuildStep { } } - & $Name $Platform @SplatArgs - - if ($Summary) { - Add-TimingData $Platform $Name $Stopwatch.Elapsed + Record-OperationTime $Platform $Name { + & $Name $Platform @SplatArgs } } @@ -1044,7 +1105,7 @@ function Invoke-VsDevShell([Hashtable] $Platform) { } } -function Get-Dependencies { +function Get-Dependencies-Impl { Write-Host "[$([DateTime]::Now.ToString("yyyy-MM-dd HH:mm:ss"))] Get-Dependencies ..." -ForegroundColor Cyan $ProgressPreference = "SilentlyContinue" @@ -1285,8 +1346,11 @@ function Get-Dependencies { Write-Host -ForegroundColor Cyan "[$([DateTime]::Now.ToString("yyyy-MM-dd HH:mm:ss"))] Get-Dependencies took $($Stopwatch.Elapsed)" Write-Host "" } - if ($Summary) { - Add-TimingData $BuildPlatform "Get-Dependencies" $Stopwatch.Elapsed +} + +function Get-Dependencies { + Record-OperationTime $BuildPlatform "Get-Dependencies" { + Get-Dependencies-Impl } } From e8d11a506815651d01aa2874f52626a46f6ec48e Mon Sep 17 00:00:00 2001 From: Leonard Grey Date: Wed, 17 Sep 2025 17:58:44 -0400 Subject: [PATCH 2/3] Revert report ordering --- utils/build.ps1 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/utils/build.ps1 b/utils/build.ps1 index bd9bcfcb17c4d..7e9cee6dd654b 100644 --- a/utils/build.ps1 +++ b/utils/build.ps1 @@ -658,12 +658,12 @@ function Flatten-TimingEntry { $FormattedSelfTime = "{0:hh\:mm\:ss\.ff}" -f $SelfTime [PSCustomObject]@{ - "Total Time" = $FormattedTime - "Self Time" = $FormattedSelfTime - "%" = "$Percentage%" "Build Step" = "$Indent$($Entry.'Build Step')" Platform = $Entry.Platform Arch = $Entry.Arch + "Total Time" = $FormattedTime + "Self Time" = $FormattedSelfTime + "%" = "$Percentage%" } $SortedChildren = $Entry.Children | Sort-Object -Descending -Property "Elapsed Time" @@ -694,12 +694,12 @@ function Write-Summary { $FormattedTotalTime = "{0:hh\:mm\:ss\.ff}" -f $TotalTime $TotalRow = [PSCustomObject]@{ - "Total Time" = $FormattedTotalTime - "Self Time" = $FormattedTotalTime - "%" = "100.0%" "Build Step" = "TOTAL" Platform = "" Arch = "" + "Total Time" = $FormattedTotalTime + "Self Time" = $FormattedTotalTime + "%" = "100.0%" } @($Result) + $TotalRow | Format-Table -AutoSize From 203f66987476f155f3c0b2b4ed68e487cc65c25b Mon Sep 17 00:00:00 2001 From: Leonard Grey Date: Wed, 17 Sep 2025 20:03:27 -0400 Subject: [PATCH 3/3] Remove self/total time split; don't indirect Get-Dependencies --- utils/build.ps1 | 406 +++++++++++++++++++++++------------------------- 1 file changed, 197 insertions(+), 209 deletions(-) diff --git a/utils/build.ps1 b/utils/build.ps1 index 7e9cee6dd654b..4aaac2821c4b5 100644 --- a/utils/build.ps1 +++ b/utils/build.ps1 @@ -598,7 +598,6 @@ function Add-TimingData { Platform = $Platform.OS.ToString() "Build Step" = $BuildStep "Elapsed Time" = [TimeSpan]::Zero - "Child Time" = [TimeSpan]::Zero Parent = $Parent Children = @() } @@ -635,9 +634,6 @@ function Record-OperationTime { } finally { $Stopwatch.Stop() $TimingEntry."Elapsed Time" = $Stopwatch.Elapsed - if ($TimingEntry.Parent) { - $TimingEntry.Parent."Child Time" = $TimingEntry.Parent."Child Time".Add($Stopwatch.Elapsed) - } $script:CurrentOperation = $TimingEntry.Parent } } @@ -654,15 +650,12 @@ function Flatten-TimingEntry { $Indent = " " * $Depth $Percentage = [math]::Round(($Entry."Elapsed Time".TotalSeconds / $TotalTime.TotalSeconds) * 100, 1) $FormattedTime = "{0:hh\:mm\:ss\.ff}" -f $Entry."Elapsed Time" - $SelfTime = $Entry."Elapsed Time".Subtract($Entry."Child Time") - $FormattedSelfTime = "{0:hh\:mm\:ss\.ff}" -f $SelfTime [PSCustomObject]@{ "Build Step" = "$Indent$($Entry.'Build Step')" Platform = $Entry.Platform Arch = $Entry.Arch - "Total Time" = $FormattedTime - "Self Time" = $FormattedSelfTime + "Elapsed Time" = $FormattedTime "%" = "$Percentage%" } @@ -697,8 +690,7 @@ function Write-Summary { "Build Step" = "TOTAL" Platform = "" Arch = "" - "Total Time" = $FormattedTotalTime - "Self Time" = $FormattedTotalTime + "Elapsed Time" = $FormattedTotalTime "%" = "100.0%" } @@ -1105,252 +1097,248 @@ function Invoke-VsDevShell([Hashtable] $Platform) { } } -function Get-Dependencies-Impl { - Write-Host "[$([DateTime]::Now.ToString("yyyy-MM-dd HH:mm:ss"))] Get-Dependencies ..." -ForegroundColor Cyan - $ProgressPreference = "SilentlyContinue" - - $WebClient = New-Object Net.WebClient +function Get-Dependencies { + Record-OperationTime $BuildPlatform "Get-Dependencies" { + Write-Host "[$([DateTime]::Now.ToString("yyyy-MM-dd HH:mm:ss"))] Get-Dependencies ..." -ForegroundColor Cyan + $ProgressPreference = "SilentlyContinue" - function DownloadAndVerify($URL, $Destination, $Hash) { - if (Test-Path $Destination) { - return - } + $WebClient = New-Object Net.WebClient - Write-Output "$Destination not found. Downloading ..." - if ($ToBatch) { - Write-Output "md `"$(Split-Path -Path $Destination -Parent)`"" - Write-Output "curl.exe -sL $URL -o $Destination" - Write-Output "(certutil -HashFile $Destination SHA256) == $Hash || (exit /b)" - } else { - New-Item -ItemType Directory (Split-Path -Path $Destination -Parent) -ErrorAction Ignore | Out-Null - $WebClient.DownloadFile($URL, $Destination) - $SHA256 = Get-FileHash -Path $Destination -Algorithm SHA256 - if ($SHA256.Hash -ne $Hash) { - throw "SHA256 mismatch ($($SHA256.Hash) vs $Hash)" + function DownloadAndVerify($URL, $Destination, $Hash) { + if (Test-Path $Destination) { + return } - } - } - - function Expand-ZipFile { - param - ( - [string]$ZipFileName, - [string]$BinaryCache, - [string]$ExtractPath, - [bool]$CreateExtractPath = $true - ) - $source = Join-Path -Path $BinaryCache -ChildPath $ZipFileName - $destination = Join-Path -Path $BinaryCache -ChildPath $ExtractPath - - # Check if the extracted directory already exists and is up to date. - if (Test-Path $destination) { - $zipLastWriteTime = (Get-Item $source).LastWriteTime - $extractedLastWriteTime = (Get-Item $destination).LastWriteTime - # Compare the last write times - if ($zipLastWriteTime -le $extractedLastWriteTime) { - Write-Output "'$ZipFileName' is already extracted and up to date." - return + Write-Output "$Destination not found. Downloading ..." + if ($ToBatch) { + Write-Output "md `"$(Split-Path -Path $Destination -Parent)`"" + Write-Output "curl.exe -sL $URL -o $Destination" + Write-Output "(certutil -HashFile $Destination SHA256) == $Hash || (exit /b)" + } else { + New-Item -ItemType Directory (Split-Path -Path $Destination -Parent) -ErrorAction Ignore | Out-Null + $WebClient.DownloadFile($URL, $Destination) + $SHA256 = Get-FileHash -Path $Destination -Algorithm SHA256 + if ($SHA256.Hash -ne $Hash) { + throw "SHA256 mismatch ($($SHA256.Hash) vs $Hash)" } + } } - $destination = if ($CreateExtractPath) { $destination } else { $BinaryCache } - - Write-Output "Extracting '$ZipFileName' ..." - New-Item -ItemType Directory -ErrorAction Ignore -Path $BinaryCache | Out-Null - Expand-Archive -Path $source -DestinationPath $destination -Force - } - - function Extract-Toolchain { - param - ( - [string]$InstallerExeName, - [string]$BinaryCache, - [string]$ToolchainName - ) + function Expand-ZipFile { + param + ( + [string]$ZipFileName, + [string]$BinaryCache, + [string]$ExtractPath, + [bool]$CreateExtractPath = $true + ) + + $source = Join-Path -Path $BinaryCache -ChildPath $ZipFileName + $destination = Join-Path -Path $BinaryCache -ChildPath $ExtractPath + + # Check if the extracted directory already exists and is up to date. + if (Test-Path $destination) { + $zipLastWriteTime = (Get-Item $source).LastWriteTime + $extractedLastWriteTime = (Get-Item $destination).LastWriteTime + # Compare the last write times + if ($zipLastWriteTime -le $extractedLastWriteTime) { + Write-Output "'$ZipFileName' is already extracted and up to date." + return + } + } - $source = Join-Path -Path $BinaryCache -ChildPath $InstallerExeName - $destination = Join-Path -Path $BinaryCache -ChildPath toolchains\$ToolchainName + $destination = if ($CreateExtractPath) { $destination } else { $BinaryCache } - # Check if the extracted directory already exists and is up to date. - if (Test-Path $destination) { - $installerWriteTime = (Get-Item $source).LastWriteTime - $extractedWriteTime = (Get-Item $destination).LastWriteTime - if ($installerWriteTime -le $extractedWriteTime) { - Write-Output "'$InstallerExeName' is already extracted and up to date." - return - } + Write-Output "Extracting '$ZipFileName' ..." + New-Item -ItemType Directory -ErrorAction Ignore -Path $BinaryCache | Out-Null + Expand-Archive -Path $source -DestinationPath $destination -Force } - Write-Output "Extracting '$InstallerExeName' ..." + function Extract-Toolchain { + param + ( + [string]$InstallerExeName, + [string]$BinaryCache, + [string]$ToolchainName + ) + + $source = Join-Path -Path $BinaryCache -ChildPath $InstallerExeName + $destination = Join-Path -Path $BinaryCache -ChildPath toolchains\$ToolchainName + + # Check if the extracted directory already exists and is up to date. + if (Test-Path $destination) { + $installerWriteTime = (Get-Item $source).LastWriteTime + $extractedWriteTime = (Get-Item $destination).LastWriteTime + if ($installerWriteTime -le $extractedWriteTime) { + Write-Output "'$InstallerExeName' is already extracted and up to date." + return + } + } + + Write-Output "Extracting '$InstallerExeName' ..." - # The new runtime MSI is built to expand files into the immediate directory. So, setup the installation location. - New-Item -ItemType Directory -ErrorAction Ignore $BinaryCache\toolchains\$ToolchainName\LocalApp\Programs\Swift\Runtimes\$(Get-PinnedToolchainVersion)\usr\bin | Out-Null - Invoke-Program "$($WiX.Path)\wix.exe" -- burn extract $BinaryCache\$InstallerExeName -out $BinaryCache\toolchains\ -outba $BinaryCache\toolchains\ - Get-ChildItem "$BinaryCache\toolchains\WixAttachedContainer" -Filter "*.msi" | ForEach-Object { - $LogFile = [System.IO.Path]::ChangeExtension($_.Name, "log") - $TARGETDIR = if ($_.Name -eq "rtl.msi") { "$BinaryCache\toolchains\$ToolchainName\LocalApp\Programs\Swift\Runtimes\$(Get-PinnedToolchainVersion)\usr\bin" } else { "$BinaryCache\toolchains\$ToolchainName" } - Invoke-Program -OutNull msiexec.exe /lvx! $BinaryCache\toolchains\$LogFile /qn /a $BinaryCache\toolchains\WixAttachedContainer\$($_.Name) ALLUSERS=0 TARGETDIR=$TARGETDIR + # The new runtime MSI is built to expand files into the immediate directory. So, setup the installation location. + New-Item -ItemType Directory -ErrorAction Ignore $BinaryCache\toolchains\$ToolchainName\LocalApp\Programs\Swift\Runtimes\$(Get-PinnedToolchainVersion)\usr\bin | Out-Null + Invoke-Program "$($WiX.Path)\wix.exe" -- burn extract $BinaryCache\$InstallerExeName -out $BinaryCache\toolchains\ -outba $BinaryCache\toolchains\ + Get-ChildItem "$BinaryCache\toolchains\WixAttachedContainer" -Filter "*.msi" | ForEach-Object { + $LogFile = [System.IO.Path]::ChangeExtension($_.Name, "log") + $TARGETDIR = if ($_.Name -eq "rtl.msi") { "$BinaryCache\toolchains\$ToolchainName\LocalApp\Programs\Swift\Runtimes\$(Get-PinnedToolchainVersion)\usr\bin" } else { "$BinaryCache\toolchains\$ToolchainName" } + Invoke-Program -OutNull msiexec.exe /lvx! $BinaryCache\toolchains\$LogFile /qn /a $BinaryCache\toolchains\WixAttachedContainer\$($_.Name) ALLUSERS=0 TARGETDIR=$TARGETDIR + } } - } - if ($IncludeSBoM) { - $syft = Get-Syft - DownloadAndVerify $syft.URL "$BinaryCache\syft-$SyftVersion.zip" $syft.SHA256 - Expand-ZipFile syft-$SyftVersion.zip $BinaryCache syft-$SyftVersion - } + if ($IncludeSBoM) { + $syft = Get-Syft + DownloadAndVerify $syft.URL "$BinaryCache\syft-$SyftVersion.zip" $syft.SHA256 + Expand-ZipFile syft-$SyftVersion.zip $BinaryCache syft-$SyftVersion + } - if ($SkipBuild -and $SkipPackaging) { return } + if ($SkipBuild -and $SkipPackaging) { return } - $Stopwatch = [Diagnostics.Stopwatch]::StartNew() - if ($ToBatch) { - Write-Host -ForegroundColor Cyan "[$([DateTime]::Now.ToString("yyyy-MM-dd HH:mm:ss"))] Get-Dependencies..." - } + $Stopwatch = [Diagnostics.Stopwatch]::StartNew() + if ($ToBatch) { + Write-Host -ForegroundColor Cyan "[$([DateTime]::Now.ToString("yyyy-MM-dd HH:mm:ss"))] Get-Dependencies..." + } - DownloadAndVerify $WiX.URL "$BinaryCache\WiX-$($WiX.Version).zip" $WiX.SHA256 - Expand-ZipFile WiX-$($WiX.Version).zip $BinaryCache WiX-$($WiX.Version) + DownloadAndVerify $WiX.URL "$BinaryCache\WiX-$($WiX.Version).zip" $WiX.SHA256 + Expand-ZipFile WiX-$($WiX.Version).zip $BinaryCache WiX-$($WiX.Version) - if ($SkipBuild) { return } + if ($SkipBuild) { return } - if ($EnableCaching) { - $SCCache = Get-SCCache - DownloadAndVerify $SCCache.URL "$BinaryCache\sccache-$SCCacheVersion.zip" $SCCache.SHA256 - Expand-ZipFile sccache-$SCCacheVersion.zip $BinaryCache sccache-$SCCacheVersion - } + if ($EnableCaching) { + $SCCache = Get-SCCache + DownloadAndVerify $SCCache.URL "$BinaryCache\sccache-$SCCacheVersion.zip" $SCCache.SHA256 + Expand-ZipFile sccache-$SCCacheVersion.zip $BinaryCache sccache-$SCCacheVersion + } - DownloadAndVerify $PinnedBuild "$BinaryCache\$PinnedToolchain.exe" $PinnedSHA256 + DownloadAndVerify $PinnedBuild "$BinaryCache\$PinnedToolchain.exe" $PinnedSHA256 - if ($Test -contains "lldb") { - # The make tool isn't part of MSYS - $GnuWin32MakeURL = "https://downloads.sourceforge.net/project/ezwinports/make-4.4.1-without-guile-w32-bin.zip" - $GnuWin32MakeHash = "fb66a02b530f7466f6222ce53c0b602c5288e601547a034e4156a512dd895ee7" - DownloadAndVerify $GnuWin32MakeURL "$BinaryCache\GnuWin32Make-4.4.1.zip" $GnuWin32MakeHash - Expand-ZipFile GnuWin32Make-4.4.1.zip $BinaryCache GnuWin32Make-4.4.1 - } + if ($Test -contains "lldb") { + # The make tool isn't part of MSYS + $GnuWin32MakeURL = "https://downloads.sourceforge.net/project/ezwinports/make-4.4.1-without-guile-w32-bin.zip" + $GnuWin32MakeHash = "fb66a02b530f7466f6222ce53c0b602c5288e601547a034e4156a512dd895ee7" + DownloadAndVerify $GnuWin32MakeURL "$BinaryCache\GnuWin32Make-4.4.1.zip" $GnuWin32MakeHash + Expand-ZipFile GnuWin32Make-4.4.1.zip $BinaryCache GnuWin32Make-4.4.1 + } - # TODO(compnerd) stamp/validate that we need to re-extract - New-Item -ItemType Directory -ErrorAction Ignore $BinaryCache\toolchains | Out-Null - Extract-Toolchain "$PinnedToolchain.exe" $BinaryCache $PinnedToolchain.TrimStart("swift-").TrimEnd("-a-windows10") + # TODO(compnerd) stamp/validate that we need to re-extract + New-Item -ItemType Directory -ErrorAction Ignore $BinaryCache\toolchains | Out-Null + Extract-Toolchain "$PinnedToolchain.exe" $BinaryCache $PinnedToolchain.TrimStart("swift-").TrimEnd("-a-windows10") - function Get-KnownPython([string] $ArchName) { - if (-not $KnownPythons.ContainsKey($PythonVersion)) { - throw "Unknown python version: $PythonVersion" + function Get-KnownPython([string] $ArchName) { + if (-not $KnownPythons.ContainsKey($PythonVersion)) { + throw "Unknown python version: $PythonVersion" + } + return $KnownPythons[$PythonVersion].$ArchName } - return $KnownPythons[$PythonVersion].$ArchName - } - function Install-Python([string] $ArchName) { - $Python = Get-KnownPython $ArchName - DownloadAndVerify $Python.URL "$BinaryCache\Python$ArchName-$PythonVersion.zip" $Python.SHA256 - if (-not $ToBatch) { - Expand-ZipFile Python$ArchName-$PythonVersion.zip "$BinaryCache" Python$ArchName-$PythonVersion + function Install-Python([string] $ArchName) { + $Python = Get-KnownPython $ArchName + DownloadAndVerify $Python.URL "$BinaryCache\Python$ArchName-$PythonVersion.zip" $Python.SHA256 + if (-not $ToBatch) { + Expand-ZipFile Python$ArchName-$PythonVersion.zip "$BinaryCache" Python$ArchName-$PythonVersion + } } - } - function Install-PIPIfNeeded() { - try { - Invoke-Program -Silent "$(Get-PythonExecutable)" -m pip - } catch { - Write-Output "Installing pip ..." - Invoke-Program -OutNull "$(Get-PythonExecutable)" '-I' -m ensurepip -U --default-pip - } finally { - Write-Output "pip installed." + function Install-PIPIfNeeded() { + try { + Invoke-Program -Silent "$(Get-PythonExecutable)" -m pip + } catch { + Write-Output "Installing pip ..." + Invoke-Program -OutNull "$(Get-PythonExecutable)" '-I' -m ensurepip -U --default-pip + } finally { + Write-Output "pip installed." + } } - } - function Test-PythonModuleInstalled([string] $ModuleName) { - try { - Invoke-Program -Silent "$(Get-PythonExecutable)" -c "import $ModuleName" - return $true; - } catch { - return $false; + function Test-PythonModuleInstalled([string] $ModuleName) { + try { + Invoke-Program -Silent "$(Get-PythonExecutable)" -c "import $ModuleName" + return $true; + } catch { + return $false; + } } - } - function Install-PythonModule([string] $ModuleName) { - if (Test-PythonModuleInstalled $ModuleName) { - Write-Output "$ModuleName already installed." - return; - } - $TempRequirementsTxt = New-TemporaryFile - $Module = $PythonModules[$ModuleName] - $Dependencies = $Module["Dependencies"] - Write-Output "$ModuleName==$($Module.Version) --hash=`"sha256:$($Module.SHA256)`"" >> $TempRequirementsTxt - for ($i = 0; $i -lt $Dependencies.Length; $i++) { - $Dependency = $PythonModules[$Dependencies[$i]] - Write-Output "$($Dependencies[$i])==$($Dependency.Version) --hash=`"sha256:$($Dependency.SHA256)`"" >> $TempRequirementsTxt + function Install-PythonModule([string] $ModuleName) { + if (Test-PythonModuleInstalled $ModuleName) { + Write-Output "$ModuleName already installed." + return; + } + $TempRequirementsTxt = New-TemporaryFile + $Module = $PythonModules[$ModuleName] + $Dependencies = $Module["Dependencies"] + Write-Output "$ModuleName==$($Module.Version) --hash=`"sha256:$($Module.SHA256)`"" >> $TempRequirementsTxt + for ($i = 0; $i -lt $Dependencies.Length; $i++) { + $Dependency = $PythonModules[$Dependencies[$i]] + Write-Output "$($Dependencies[$i])==$($Dependency.Version) --hash=`"sha256:$($Dependency.SHA256)`"" >> $TempRequirementsTxt + } + Invoke-Program -OutNull "$(Get-PythonExecutable)" '-I' -m pip install -r $TempRequirementsTxt --require-hashes --no-binary==:all: --disable-pip-version-check + Write-Output "$ModuleName installed." } - Invoke-Program -OutNull "$(Get-PythonExecutable)" '-I' -m pip install -r $TempRequirementsTxt --require-hashes --no-binary==:all: --disable-pip-version-check - Write-Output "$ModuleName installed." - } - function Install-PythonModules() { - Install-PIPIfNeeded - Install-PythonModule "packaging" # For building LLVM 18+ - Install-PythonModule "setuptools" # Required for SWIG support - if ($Test -contains "lldb") { - Install-PythonModule "psutil" # Required for testing LLDB + function Install-PythonModules() { + Install-PIPIfNeeded + Install-PythonModule "packaging" # For building LLVM 18+ + Install-PythonModule "setuptools" # Required for SWIG support + if ($Test -contains "lldb") { + Install-PythonModule "psutil" # Required for testing LLDB + } } - } - Install-Python $HostArchName - if ($IsCrossCompiling) { - Install-Python $BuildArchName - } + Install-Python $HostArchName + if ($IsCrossCompiling) { + Install-Python $BuildArchName + } - # Ensure Python modules that are required as host build tools - Install-PythonModules + # Ensure Python modules that are required as host build tools + Install-PythonModules - if ($Android) { - $NDK = Get-AndroidNDK - DownloadAndVerify $NDK.URL "$BinaryCache\android-ndk-$AndroidNDKVersion-windows.zip" $NDK.SHA256 - Expand-ZipFile -ZipFileName "android-ndk-$AndroidNDKVersion-windows.zip" -BinaryCache $BinaryCache -ExtractPath "android-ndk-$AndroidNDKVersion" -CreateExtractPath $false - } + if ($Android) { + $NDK = Get-AndroidNDK + DownloadAndVerify $NDK.URL "$BinaryCache\android-ndk-$AndroidNDKVersion-windows.zip" $NDK.SHA256 + Expand-ZipFile -ZipFileName "android-ndk-$AndroidNDKVersion-windows.zip" -BinaryCache $BinaryCache -ExtractPath "android-ndk-$AndroidNDKVersion" -CreateExtractPath $false + } - if ($IncludeDS2) { - $WinFlexBisonVersion = "2.5.25" - $WinFlexBisonURL = "https://github.com/lexxmark/winflexbison/releases/download/v$WinFlexBisonVersion/win_flex_bison-$WinFlexBisonVersion.zip" - $WinFlexBisonHash = "8D324B62BE33604B2C45AD1DD34AB93D722534448F55A16CA7292DE32B6AC135" - DownloadAndVerify $WinFlexBisonURL "$BinaryCache\win_flex_bison-$WinFlexBisonVersion.zip" $WinFlexBisonHash + if ($IncludeDS2) { + $WinFlexBisonVersion = "2.5.25" + $WinFlexBisonURL = "https://github.com/lexxmark/winflexbison/releases/download/v$WinFlexBisonVersion/win_flex_bison-$WinFlexBisonVersion.zip" + $WinFlexBisonHash = "8D324B62BE33604B2C45AD1DD34AB93D722534448F55A16CA7292DE32B6AC135" + DownloadAndVerify $WinFlexBisonURL "$BinaryCache\win_flex_bison-$WinFlexBisonVersion.zip" $WinFlexBisonHash - Expand-ZipFile -ZipFileName "win_flex_bison-$WinFlexBisonVersion.zip" -BinaryCache $BinaryCache -ExtractPath "win_flex_bison" - } + Expand-ZipFile -ZipFileName "win_flex_bison-$WinFlexBisonVersion.zip" -BinaryCache $BinaryCache -ExtractPath "win_flex_bison" + } - if ($WinSDKVersion) { - try { - # Check whether VsDevShell can already resolve the requested Windows SDK Version - Invoke-IsolatingEnvVars { Invoke-VsDevShell $HostPlatform } - } catch { - $Package = Microsoft.Windows.SDK.CPP + if ($WinSDKVersion) { + try { + # Check whether VsDevShell can already resolve the requested Windows SDK Version + Invoke-IsolatingEnvVars { Invoke-VsDevShell $HostPlatform } + } catch { + $Package = Microsoft.Windows.SDK.CPP - Write-Output "Windows SDK $WinSDKVersion not found. Downloading from nuget.org ..." - Invoke-Program nuget install $Package -Version $WinSDKVersion -OutputDirectory $NugetRoot + Write-Output "Windows SDK $WinSDKVersion not found. Downloading from nuget.org ..." + Invoke-Program nuget install $Package -Version $WinSDKVersion -OutputDirectory $NugetRoot - # Set to script scope so Invoke-VsDevShell can read it. - $script:CustomWinSDKRoot = "$NugetRoot\$Package.$WinSDKVersion\c" + # Set to script scope so Invoke-VsDevShell can read it. + $script:CustomWinSDKRoot = "$NugetRoot\$Package.$WinSDKVersion\c" - # Install each required architecture package and move files under the base /lib directory. - $Builds = $WindowsSDKBuilds.Clone() - if (-not ($HostPlatform -in $Builds)) { - $Builds += $HostPlatform - } + # Install each required architecture package and move files under the base /lib directory. + $Builds = $WindowsSDKBuilds.Clone() + if (-not ($HostPlatform -in $Builds)) { + $Builds += $HostPlatform + } - foreach ($Build in $Builds) { - Invoke-Program nuget install $Package.$($Build.Architecture.ShortName) -Version $WinSDKVersion -OutputDirectory $NugetRoot - Copy-Directory "$NugetRoot\$Package.$($Build.Architecture.ShortName).$WinSDKVersion\c\*" "$CustomWinSDKRoot\lib\$WinSDKVersion" + foreach ($Build in $Builds) { + Invoke-Program nuget install $Package.$($Build.Architecture.ShortName) -Version $WinSDKVersion -OutputDirectory $NugetRoot + Copy-Directory "$NugetRoot\$Package.$($Build.Architecture.ShortName).$WinSDKVersion\c\*" "$CustomWinSDKRoot\lib\$WinSDKVersion" + } } } - } - - if (-not $ToBatch) { - Write-Host -ForegroundColor Cyan "[$([DateTime]::Now.ToString("yyyy-MM-dd HH:mm:ss"))] Get-Dependencies took $($Stopwatch.Elapsed)" - Write-Host "" - } -} -function Get-Dependencies { - Record-OperationTime $BuildPlatform "Get-Dependencies" { - Get-Dependencies-Impl + if (-not $ToBatch) { + Write-Host -ForegroundColor Cyan "[$([DateTime]::Now.ToString("yyyy-MM-dd HH:mm:ss"))] Get-Dependencies took $($Stopwatch.Elapsed)" + Write-Host "" + } } }