Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
build.psm14860 linesDownload Raw Back to PowerShell-master
1# Copyright (c) Microsoft Corporation.2# Licensed under the MIT License.3 4param(5    # Skips a check that prevents building PowerShell on unsupported Linux distributions.6    [parameter(Mandatory = $false)][switch]$SkipLinuxDistroCheck = $false7)8 9. "$PSScriptRoot\tools\buildCommon\startNativeExecution.ps1"10 11# CI runs with PowerShell 5.0, so don't use features like ?: && ||12Set-StrictMode -Version 3.013 14# On Unix paths is separated by colon.15# On Windows paths is separated by semicolon16$script:TestModulePathSeparator = [System.IO.Path]::PathSeparator17$script:Options = $null18 19$dotnetMetadata = Get-Content $PSScriptRoot/DotnetRuntimeMetadata.json | ConvertFrom-Json20$dotnetCLIChannel = $dotnetMetadata.Sdk.Channel21$dotnetCLIQuality = $dotnetMetadata.Sdk.Quality22# __DOTNET_RUNTIME_FEED and __DOTNET_RUNTIME_FEED_KEY are private variables used in release builds23$dotnetAzureFeed = if ([string]::IsNullOrWhiteSpace($env:__DOTNET_RUNTIME_FEED)) { $dotnetMetadata.Sdk.azureFeed } else { $env:__DOTNET_RUNTIME_FEED }24$dotnetAzureFeedSecret = $env:__DOTNET_RUNTIME_FEED_KEY25$dotnetSDKVersionOveride = $dotnetMetadata.Sdk.sdkImageOverride26$dotnetCLIRequiredVersion = $(Get-Content $PSScriptRoot/global.json | ConvertFrom-Json).Sdk.Version27 28# Track if tags have been sync'ed29$tagsUpToDate = $false30 31# Sync Tags32# When not using a branch in PowerShell/PowerShell, tags will not be fetched automatically33# Since code that uses Get-PSCommitID and Get-PSLatestTag assume that tags are fetched,34# This function can ensure that tags have been fetched.35# This function is used during the setup phase in tools/ci.psm136function Sync-PSTags37{38    <#39    .SYNOPSIS40        Syncs git tags from the PowerShell/PowerShell upstream remote.41    .DESCRIPTION42        Ensures that tags from the PowerShell/PowerShell upstream remote have been fetched.43        Functions like Get-PSCommitId and Get-PSLatestTag require tags to be current.44        This is called during the setup phase in tools/ci.psm1.45    .PARAMETER AddRemoteIfMissing46        If specified, adds the upstream remote automatically when it is not present.47    #>48    param(49        [Switch]50        $AddRemoteIfMissing51    )52 53    $powerShellRemoteUrls = @(54        'https://github.com/PowerShell/PowerShell'55        'git@github.com:PowerShell/PowerShell'56    )57    $defaultRemoteUrl = "$($powerShellRemoteUrls[0]).git"58 59    $upstreamRemoteDefaultName = 'upstream'60    $remotes = Start-NativeExecution {git --git-dir="$PSScriptRoot/.git" remote}61    $upstreamRemote = $null62    foreach($remote in $remotes)63    {64        $url = Start-NativeExecution {git --git-dir="$PSScriptRoot/.git" remote get-url $remote}65        if ($url.EndsWith('.git')) { $url = $url.Substring(0, $url.Length - 4) }66 67        if($url -in $powerShellRemoteUrls)68        {69            $upstreamRemote = $remote70            break71        }72    }73 74    if(!$upstreamRemote -and $AddRemoteIfMissing.IsPresent -and $remotes -notcontains $upstreamRemoteDefaultName)75    {76        $null = Start-NativeExecution {git --git-dir="$PSScriptRoot/.git" remote add $upstreamRemoteDefaultName $defaultRemoteUrl}77        $upstreamRemote = $upstreamRemoteDefaultName78    }79    elseif(!$upstreamRemote)80    {81        Write-Error "Please add a remote to PowerShell\PowerShell.  Example:  git remote add $upstreamRemoteDefaultName $defaultRemoteUrl" -ErrorAction Stop82    }83 84    $null = Start-NativeExecution {git --git-dir="$PSScriptRoot/.git" fetch --tags --quiet $upstreamRemote}85    $script:tagsUpToDate=$true86}87 88# Gets the latest tag for the current branch89function Get-PSLatestTag90{91    <#92    .SYNOPSIS93        Gets the latest git tag reachable from the current HEAD.94    .DESCRIPTION95        Returns the most recent annotated git tag. Run Sync-PSTags first to ensure tags96        are up to date; otherwise a warning is emitted.97    .OUTPUTS98        System.String. The latest tag string, e.g. 'v7.5.0'.99    #>100    [CmdletBinding()]101    param()102    # This function won't always return the correct value unless tags have been sync'ed103    # So, Write a warning to run Sync-PSTags104    if(!$tagsUpToDate)105    {106        Write-Warning "Run Sync-PSTags to update tags"107    }108 109    return (Start-NativeExecution {git --git-dir="$PSScriptRoot/.git" describe --abbrev=0})110}111 112function Get-PSVersion113{114    <#115    .SYNOPSIS116        Returns the PowerShell version string for the current commit.117    .DESCRIPTION118        Derives the version from the latest git tag, optionally omitting the commit-ID suffix.119    .PARAMETER OmitCommitId120        When specified, returns only the bare version (e.g. '7.5.0') from the latest tag,121        without the commit-count and hash suffix appended by git describe.122    .OUTPUTS123        System.String. A version string such as '7.5.0' or '7.5.0-15-gabcdef1234'.124    #>125    [CmdletBinding()]126    param(127        [switch]128        $OmitCommitId129    )130    if($OmitCommitId.IsPresent)131    {132        return (Get-PSLatestTag) -replace '^v'133    }134    else135    {136        return (Get-PSCommitId) -replace '^v'137    }138}139 140function Get-PSCommitId141{142    <#143    .SYNOPSIS144        Returns the PowerShell commit-ID string produced by git describe.145    .DESCRIPTION146        Returns the full git describe string including the tag, number of commits since147        the tag, and the abbreviated commit hash (e.g. 'v7.5.0-15-gabcdef1234567890').148        Run Sync-PSTags first; otherwise a warning is emitted.149    .OUTPUTS150        System.String. A git describe string such as 'v7.5.0-15-gabcdef1234567890'.151    #>152    [CmdletBinding()]153    param()154    # This function won't always return the correct value unless tags have been sync'ed155    # So, Write a warning to run Sync-PSTags156    if(!$tagsUpToDate)157    {158        Write-Warning "Run Sync-PSTags to update tags"159    }160 161    return (Start-NativeExecution {git --git-dir="$PSScriptRoot/.git" describe --dirty --abbrev=60})162}163 164function Get-EnvironmentInformation165{166    <#167    .SYNOPSIS168        Collects information about the current operating environment.169    .DESCRIPTION170        Returns a PSCustomObject containing OS-identity flags, architecture, admin status,171        NuGet package root paths, and Linux distribution details. The object is used172        throughout the build module to make platform-conditional decisions.173    .OUTPUTS174        System.Management.Automation.PSCustomObject. An object with properties such as175        IsWindows, IsLinux, IsMacOS, IsAdmin, OSArchitecture, and distribution-specific flags176        (IsUbuntu, IsDebian, IsRedHatFamily, etc.).177    #>178    param()179    $environment = @{'IsWindows' = [System.Environment]::OSVersion.Platform -eq [System.PlatformID]::Win32NT}180    # PowerShell will likely not be built on pre-1709 nanoserver181    if ('System.Management.Automation.Platform' -as [type]) {182        $environment += @{'IsCoreCLR' = [System.Management.Automation.Platform]::IsCoreCLR}183        $environment += @{'IsLinux' = [System.Management.Automation.Platform]::IsLinux}184        $environment += @{'IsMacOS' = [System.Management.Automation.Platform]::IsMacOS}185    } else {186        $environment += @{'IsCoreCLR' = $false}187        $environment += @{'IsLinux' = $false}188        $environment += @{'IsMacOS' = $false}189    }190 191    if ($environment.IsWindows)192    {193        $environment += @{'IsAdmin' = (New-Object Security.Principal.WindowsPrincipal ([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)}194        $environment += @{'nugetPackagesRoot' = "${env:USERPROFILE}\.nuget\packages", "${env:NUGET_PACKAGES}"}195        $environment += @{ 'OSArchitecture' = [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture }196    }197    else198    {199        $environment += @{'nugetPackagesRoot' = "${env:HOME}/.nuget/packages"}200    }201 202    if ($environment.IsMacOS) {203        $environment += @{'UsingHomebrew' = [bool](Get-Command brew -ErrorAction ignore)}204        $environment += @{'UsingMacports' = [bool](Get-Command port -ErrorAction ignore)}205 206        $environment += @{207            'OSArchitecture' = if ((uname -v) -match 'ARM64') { 'arm64' } else { 'x64' }208        }209 210        if (-not($environment.UsingHomebrew -or $environment.UsingMacports)) {211            throw "Neither Homebrew nor MacPorts is installed on this system, visit https://brew.sh/ or https://www.macports.org/ to continue"212        }213    }214 215    if ($environment.IsLinux) {216        $environment += @{ 'OSArchitecture' = [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture }217        $LinuxInfo = Get-Content /etc/os-release -Raw | ConvertFrom-StringData218        $lsb_release = Get-Command lsb_release -Type Application -ErrorAction Ignore | Select-Object -First 1219        if ($lsb_release) {220            $LinuxID = & $lsb_release -is221        }222        else {223            $LinuxID = ""224        }225 226        $environment += @{'LinuxInfo' = $LinuxInfo}227        $environment += @{'IsDebian' = $LinuxInfo.ID -match 'debian' -or $LinuxInfo.ID -match 'kali'}228        $environment += @{'IsDebian9' = $environment.IsDebian -and $LinuxInfo.VERSION_ID -match '9'}229        $environment += @{'IsDebian10' = $environment.IsDebian -and $LinuxInfo.VERSION_ID -match '10'}230        $environment += @{'IsDebian11' = $environment.IsDebian -and $LinuxInfo.PRETTY_NAME -match 'bullseye'}231        $environment += @{'IsUbuntu' = $LinuxInfo.ID -match 'ubuntu' -or $LinuxID -match 'Ubuntu'}232        $environment += @{'IsUbuntu16' = $environment.IsUbuntu -and $LinuxInfo.VERSION_ID -match '16.04'}233        $environment += @{'IsUbuntu18' = $environment.IsUbuntu -and $LinuxInfo.VERSION_ID -match '18.04'}234        $environment += @{'IsUbuntu20' = $environment.IsUbuntu -and $LinuxInfo.VERSION_ID -match '20.04'}235        $environment += @{'IsUbuntu22' = $environment.IsUbuntu -and $LinuxInfo.VERSION_ID -match '22.04'}236        $environment += @{'IsUbuntu24' = $environment.IsUbuntu -and $LinuxInfo.VERSION_ID -match '24.04'}237        $environment += @{'IsCentOS' = $LinuxInfo.ID -match 'centos' -and $LinuxInfo.VERSION_ID -match '7'}238        $environment += @{'IsFedora' = $LinuxInfo.ID -match 'fedora' -and $LinuxInfo.VERSION_ID -ge 24}239        $environment += @{'IsOpenSUSE' = $LinuxInfo.ID -match 'opensuse'}240        $environment += @{'IsSLES' = $LinuxInfo.ID -match 'sles'}241        $environment += @{'IsRedHat' = $LinuxInfo.ID -match 'rhel'}242        $environment += @{'IsRedHat7' = $environment.IsRedHat -and $LinuxInfo.VERSION_ID -match '7' }243        $environment += @{'IsOpenSUSE13' = $environment.IsOpenSUSE -and $LinuxInfo.VERSION_ID  -match '13'}244        $environment += @{'IsOpenSUSE42.1' = $environment.IsOpenSUSE -and $LinuxInfo.VERSION_ID  -match '42.1'}245        $environment += @{'IsDebianFamily' = $environment.IsDebian -or $environment.IsUbuntu}246        $environment += @{'IsRedHatFamily' = $environment.IsCentOS -or $environment.IsFedora -or $environment.IsRedHat}247        $environment += @{'IsSUSEFamily' = $environment.IsSLES -or $environment.IsOpenSUSE}248        $environment += @{'IsAlpine' = $LinuxInfo.ID -match 'alpine'}249        $environment += @{'IsMariner' = $LinuxInfo.ID -match 'mariner' -or $LinuxInfo.ID -match 'azurelinux'}250 251        # Workaround for temporary LD_LIBRARY_PATH hack for Fedora 24252        # https://github.com/PowerShell/PowerShell/issues/2511253        if ($environment.IsFedora -and (Test-Path ENV:\LD_LIBRARY_PATH)) {254            Remove-Item -Force ENV:\LD_LIBRARY_PATH255            Get-ChildItem ENV:256        }257 258        if( -not(259            $environment.IsDebian -or260            $environment.IsUbuntu -or261            $environment.IsRedHatFamily -or262            $environment.IsSUSEFamily -or263            $environment.IsAlpine -or264            $environment.IsMariner)265        ) {266            if ($SkipLinuxDistroCheck) {267                Write-Warning "The current OS : $($LinuxInfo.ID) is not supported for building PowerShell."268            } else {269                throw "The current OS : $($LinuxInfo.ID) is not supported for building PowerShell. Import this module with '-ArgumentList `$true' to bypass this check."270            }271        }272    }273 274    return [PSCustomObject] $environment275}276 277$environment = Get-EnvironmentInformation278 279# Autoload (in current session) temporary modules used in our tests280$TestModulePath = Join-Path $PSScriptRoot "test/tools/Modules"281if ( -not $env:PSModulePath.Contains($TestModulePath) ) {282    $env:PSModulePath = $TestModulePath+$TestModulePathSeparator+$($env:PSModulePath)283}284 285<#286    .Synopsis287        Tests if a version is preview288    .EXAMPLE289        Test-IsPreview -version '6.1.0-sometthing' # returns true290        Test-IsPreview -version '6.1.0' # returns false291#>292function Test-IsPreview293{294    param(295        [parameter(Mandatory)]296        [string]297        $Version,298 299        [switch]$IsLTS300    )301 302    if ($IsLTS.IsPresent) {303        ## If we are building a LTS package, then never consider it preview.304        return $false305    }306 307    return $Version -like '*-*'308}309 310<#311    .Synopsis312        Tests if a version is a Release Candidate313    .EXAMPLE314        Test-IsReleaseCandidate -version '6.1.0-sometthing' # returns false315        Test-IsReleaseCandidate -version '6.1.0-rc.1' # returns true316        Test-IsReleaseCandidate -version '6.1.0' # returns false317#>318function Test-IsReleaseCandidate319{320    param(321        [parameter(Mandatory)]322        [string]323        $Version324    )325 326    if ($Version -like '*-rc.*')327    {328        return $true329    }330 331    return $false332}333 334$optimizedFddRegex = 'fxdependent-(linux|win|win7|osx)-(x64|x86|arm64|arm)'335 336function Start-PSBuild {337    <#338    .SYNOPSIS339        Builds PowerShell from source using dotnet publish.340    .DESCRIPTION341        Compiles the PowerShell source tree for the specified runtime and configuration.342        Optionally restores NuGet packages, regenerates resources, generates the type catalog,343        and restores Gallery modules. Saves build options so subsequent commands can reuse them.344    .PARAMETER StopDevPowerShell345        Stops any running dev pwsh process before building to prevent file-in-use errors.346    .PARAMETER Restore347        Forces NuGet package restore even when packages already exist.348    .PARAMETER Output349        Path to the output directory. Defaults to the standard build location.350    .PARAMETER ResGen351        Regenerates C# bindings for resx resource files before building.352    .PARAMETER TypeGen353        Regenerates the CorePsTypeCatalog.cs type-catalog file before building.354    .PARAMETER Clean355        Runs 'git clean -fdX' to remove untracked and ignored files before building.356    .PARAMETER PSModuleRestore357        Restores PowerShell Gallery modules to the build output directory (legacy parameter set).358    .PARAMETER NoPSModuleRestore359        Skips restoring PowerShell Gallery modules to the build output directory.360    .PARAMETER CI361        Indicates a CI build; restores the Pester module to the output directory.362    .PARAMETER ForMinimalSize363        Produces a build optimized for minimal binary size (linux-x64, win7-x64, or osx-x64 only).364    .PARAMETER SkipExperimentalFeatureGeneration365        Skips the step that runs the built pwsh to produce the experimental-features list.366    .PARAMETER SMAOnly367        Rebuilds only System.Management.Automation.dll for rapid engine iteration.368    .PARAMETER UseNuGetOrg369        Uses nuget.org instead of the private PowerShell feed for package restore.370    .PARAMETER Runtime371        The .NET runtime identifier (RID) to target, e.g. 'win7-x64' or 'linux-x64'.372    .PARAMETER Configuration373        The build configuration: Debug, Release, CodeCoverage, or StaticAnalysis.374    .PARAMETER ReleaseTag375        A git tag in 'vX.Y.Z[-preview.N|-rc.N]' format to embed as the release version.376    .PARAMETER Detailed377        Passes '--verbosity d' to dotnet for detailed build output.378    .PARAMETER InteractiveAuth379        Passes '--interactive' to dotnet restore for interactive feed authentication.380    .PARAMETER SkipRoslynAnalyzers381        Skips Roslyn analyzer execution during the build.382    .PARAMETER PSOptionsPath383        When supplied, saves the resolved build options to this JSON file path.384    #>385    [CmdletBinding(DefaultParameterSetName="Default")]386    param(387        # When specified this switch will stops running dev powershell388        # to help avoid compilation error, because file are in use.389        [switch]$StopDevPowerShell,390 391        [switch]$Restore,392        # Accept a path to the output directory393        # When specified, --output <path> will be passed to dotnet394        [string]$Output,395        [switch]$ResGen,396        [switch]$TypeGen,397        [switch]$Clean,398        [Parameter(ParameterSetName="Legacy")]399        [switch]$PSModuleRestore,400        [Parameter(ParameterSetName="Default")]401        [switch]$NoPSModuleRestore,402        [switch]$CI,403        [switch]$ForMinimalSize,404 405        # Skips the step where the pwsh that's been built is used to create a configuration406        # Useful when changing parsing/compilation, since bugs there can mean we can't get past this step407        [switch]$SkipExperimentalFeatureGeneration,408 409        # this switch will re-build only System.Management.Automation.dll410        # it's useful for development, to do a quick changes in the engine411        [switch]$SMAOnly,412 413        # Use nuget.org instead of the PowerShell specific feed414        [switch]$UseNuGetOrg,415 416        # These runtimes must match those in project.json417        # We do not use ValidateScript since we want tab completion418        # If this parameter is not provided it will get determined automatically.419        [ValidateSet("linux-musl-x64",420                     "fxdependent",421                     "fxdependent-noopt-linux-musl-x64",422                     "fxdependent-linux-x64",423                     "fxdependent-linux-arm64",424                     "fxdependent-win-desktop",425                     "linux-arm",426                     "linux-arm64",427                     "linux-x64",428                     "osx-arm64",429                     "osx-x64",430                     "win-arm",431                     "win-arm64",432                     "win7-x64",433                     "win7-x86")]434        [string]$Runtime,435 436        [ValidateSet('Debug', 'Release', 'CodeCoverage', 'StaticAnalysis', '')] # We might need "Checked" as well437        [string]$Configuration,438 439        [ValidatePattern("^v\d+\.\d+\.\d+(-\w+(\.\d{1,2})?)?$")]440        [ValidateNotNullOrEmpty()]441        [string]$ReleaseTag,442        [switch]$Detailed,443        [switch]$InteractiveAuth,444        [switch]$SkipRoslynAnalyzers,445        [string]$PSOptionsPath446    )447 448    if ($ReleaseTag -and $ReleaseTag -notmatch "^v\d+\.\d+\.\d+(-(preview|rc)(\.\d{1,2})?)?$") {449        Write-Warning "Only preview or rc are supported for releasing pre-release version of PowerShell"450    }451 452    if ($PSCmdlet.ParameterSetName -eq "Default" -and !$NoPSModuleRestore)453    {454        $PSModuleRestore = $true455    }456 457    if ($Runtime -eq "linux-arm" -and $environment.IsLinux -and -not $environment.IsUbuntu -and -not $environment.IsMariner) {458        throw "Cross compiling for linux-arm is only supported on AzureLinux/Ubuntu environment"459    }460 461    if ("win-arm","win-arm64" -contains $Runtime -and -not $environment.IsWindows) {462        throw "Cross compiling for win-arm or win-arm64 is only supported on Windows environment"463    }464 465    if ($ForMinimalSize) {466        if ($Runtime -and "linux-x64", "win7-x64", "osx-x64" -notcontains $Runtime) {467            throw "Build for the minimal size is enabled only for following runtimes: 'linux-x64', 'win7-x64', 'osx-x64'"468        }469    }470 471    if ($UseNuGetOrg) {472        Switch-PSNugetConfig -Source Public473    } else {474        Write-Verbose -Message "Using default feeds which are Microsoft, use `-UseNuGetOrg` to switch to Public feeds" -Verbose475    }476 477    function Stop-DevPowerShell {478        Get-Process pwsh* |479            Where-Object {480                $_.Modules |481                Where-Object {482                    $_.FileName -eq (Resolve-Path $script:Options.Output).Path483                }484            } |485        Stop-Process -Verbose486    }487 488    if ($Clean) {489        Write-LogGroupStart -Title "Cleaning your working directory"490        Push-Location $PSScriptRoot491        try {492            # Excluded sqlite3 folder is due to this Roslyn issue: https://github.com/dotnet/roslyn/issues/23060493            # Excluded src/Modules/nuget.config as this is required for release build.494            # Excluded nuget.config as this is required for release build.495            git clean -fdX --exclude .vs/PowerShell/v16/Server/sqlite3 --exclude src/Modules/nuget.config  --exclude nuget.config496        } finally {497            Write-LogGroupEnd -Title "Cleaning your working directory"498            Pop-Location499        }500    }501 502    # Add .NET CLI tools to PATH503    Find-Dotnet504 505    # Verify we have git in place to do the build, and abort if the precheck failed506    $precheck = precheck 'git' "Build dependency 'git' not found in PATH. See <URL: https://docs.github.com/en/github/getting-started-with-github/set-up-git#setting-up-git >"507    if (-not $precheck) {508        return509    }510 511    # Verify we have .NET SDK in place to do the build, and abort if the precheck failed512    $precheck = precheck 'dotnet' "Build dependency 'dotnet' not found in PATH. Run Start-PSBootstrap. Also see <URL: https://dotnet.github.io/getting-started/ >"513    if (-not $precheck) {514        return515    }516 517    # Verify if the dotnet in-use is the required version518    $dotnetCLIInstalledVersion = Find-RequiredSDK $dotnetCLIRequiredVersion519 520    If ($dotnetCLIInstalledVersion -ne $dotnetCLIRequiredVersion) {521        Write-Warning @"522The currently installed .NET Command Line Tools is not the required version.523 524Installed version: $dotnetCLIInstalledVersion525Required version: $dotnetCLIRequiredVersion526 527Fix steps:528 5291. Remove the installed version from:530    - on windows '`$env:LOCALAPPDATA\Microsoft\dotnet'531    - on macOS and linux '`$env:HOME/.dotnet'5322. Run Start-PSBootstrap or Install-Dotnet5333. Start-PSBuild -Clean534`n535"@536        return537    }538 539    # set output options540    $OptionsArguments = @{541        Output=$Output542        Runtime=$Runtime543        Configuration=$Configuration544        Verbose=$true545        SMAOnly=[bool]$SMAOnly546        PSModuleRestore=$PSModuleRestore547        ForMinimalSize=$ForMinimalSize548    }549 550    $script:Options = New-PSOptions @OptionsArguments551 552    if ($StopDevPowerShell) {553        Stop-DevPowerShell554    }555 556    # setup arguments557    # adding ErrorOnDuplicatePublishOutputFiles=false due to .NET SDk issue: https://github.com/dotnet/sdk/issues/15748558    # removing --no-restore due to .NET SDK issue: https://github.com/dotnet/sdk/issues/18999559    # $Arguments = @("publish","--no-restore","/property:GenerateFullPaths=true", "/property:ErrorOnDuplicatePublishOutputFiles=false")560    $Arguments = @("publish","/property:GenerateFullPaths=true", "/property:ErrorOnDuplicatePublishOutputFiles=false")561    if ($Output -or $SMAOnly) {562        $Arguments += "--output", (Split-Path $Options.Output)563    }564 565    # Add --self-contained due to "warning NETSDK1179: One of '--self-contained' or '--no-self-contained' options are required when '--runtime' is used."566    if ($Options.Runtime -like 'fxdependent*') {567        $Arguments += "--no-self-contained"568        # The UseAppHost = true property creates ".exe" for the fxdependent packages.569        # We need this in the package as Start-Job needs it.570        $Arguments += "/property:UseAppHost=true"571    }572    else {573        $Arguments += "--self-contained"574    }575 576    if ($Options.Runtime -like 'win*') {577        # Starting in .NET 8, the .NET SDK won't recognize version-specific RIDs by default, such as win7-x64,578        # see https://learn.microsoft.com/dotnet/core/compatibility/sdk/8.0/rid-graph for details.579        # It will cause huge amount of changes in our build infrastructure because our building and packaging580        # scripts have the 'win7-xx' assumption regarding the target runtime.581        #582        # As a workaround, we use the old full RID graph during the build so that we can continue to use the583        # 'win7-x64' and 'win7-x86' RIDs.584        $Arguments += "/property:UseRidGraph=true"585    }586 587    if ($Options.Runtime -like 'win*' -or ($Options.Runtime -like 'fxdependent*' -and $environment.IsWindows)) {588        $Arguments += "/property:IsWindows=true"589        if(!$environment.IsWindows) {590            $Arguments += "/property:EnableWindowsTargeting=true"591        }592    }593    else {594        $Arguments += "/property:IsWindows=false"595    }596 597    # We pass in the AppDeployment property to indicate which type of deployment we are doing.598    # This allows the PowerShell.Common.props to set the correct properties for the build.599    $AppDeployment = if(($Options.Runtime -like 'fxdependent*' -or $ForMinimalSize) -and $Options.Runtime -notmatch $optimizedFddRegex) {600        # Global and zip files601        "FxDependent"602    }603    elseif($Options.Runtime -like 'fxdependent*' -and $Options.Runtime -match $optimizedFddRegex) {604        # These are Optimized and must come from the correct version of the runtime.605        # Global606        "FxDependentDeployment"607    }608    else {609        # The majority of our packages610        # AppLocal611        "SelfContained"612    }613 614    $Arguments += "/property:AppDeployment=$AppDeployment"615    $Arguments += "--configuration", $Options.Configuration616    $Arguments += "--framework", $Options.Framework617 618    if ($Detailed.IsPresent)619    {620        $Arguments += '--verbosity', 'd'621    }622 623    if (-not $SMAOnly -and $Options.Runtime -notlike 'fxdependent*') {624        # libraries should not have runtime625        $Arguments += "--runtime", $Options.Runtime626    } elseif ($Options.Runtime -match $optimizedFddRegex) {627        $runtime = $Options.Runtime -replace 'fxdependent-', ''628        $Arguments += "--runtime", $runtime629    }630 631    if ($ReleaseTag) {632        $ReleaseTagToUse = $ReleaseTag -Replace '^v'633        $Arguments += "/property:ReleaseTag=$ReleaseTagToUse"634    }635 636    if ($SkipRoslynAnalyzers) {637        $Arguments += "/property:RunAnalyzersDuringBuild=false"638    }639 640    # handle Restore641    Write-LogGroupStart -Title "Restore NuGet Packages"642    Restore-PSPackage -Options $Options -Force:$Restore -InteractiveAuth:$InteractiveAuth643    Write-LogGroupEnd -Title "Restore NuGet Packages"644 645    # handle ResGen646    # Heuristic to run ResGen on the fresh machine647    if ($ResGen -or -not (Test-Path "$PSScriptRoot/src/Microsoft.PowerShell.ConsoleHost/gen")) {648        Write-Log -message "Run ResGen (generating C# bindings for resx files)"649        Start-ResGen650    }651 652    # Handle TypeGen653    # .inc file name must be different for Windows and Linux to allow build on Windows and WSL.654    $runtime = $Options.Runtime655    if ($Options.Runtime -match $optimizedFddRegex) {656        $runtime = $Options.Runtime -replace 'fxdependent-', ''657    }658 659    $incFileName = "powershell_$runtime.inc"660    if ($TypeGen -or -not (Test-Path "$PSScriptRoot/src/TypeCatalogGen/$incFileName")) {661        Write-Log -message "Run TypeGen (generating CorePsTypeCatalog.cs)"662        Start-TypeGen -IncFileName $incFileName663    }664 665    # Get the folder path where pwsh.exe is located.666    if ((Split-Path $Options.Output -Leaf) -like "pwsh*") {667        $publishPath = Split-Path $Options.Output -Parent668    }669    else {670        $publishPath = $Options.Output671    }672 673    Write-LogGroupStart -Title "Build PowerShell"674    try {675        # Relative paths do not work well if cwd is not changed to project676        Push-Location $Options.Top677 678        if ($Options.Runtime -notlike 'fxdependent*' -or $Options.Runtime -match $optimizedFddRegex) {679            Write-Verbose "Building without shim" -Verbose680            $sdkToUse = 'Microsoft.NET.Sdk'681            if (($Options.Runtime -like 'win7-*' -or $Options.Runtime -eq 'win-arm64') -and !$ForMinimalSize) {682                ## WPF/WinForm and the PowerShell GraphicalHost assemblies are included683                ## when 'Microsoft.NET.Sdk.WindowsDesktop' is used.684                $sdkToUse = 'Microsoft.NET.Sdk.WindowsDesktop'685            }686 687            $Arguments += "/property:SDKToUse=$sdkToUse"688 689            Write-Log -message "Run dotnet $Arguments from $PWD"690            Start-NativeExecution { dotnet $Arguments }691            Write-Log -message "PowerShell output: $($Options.Output)"692        } else {693            Write-Verbose "Building with shim" -Verbose694            $globalToolSrcFolder = Resolve-Path (Join-Path $Options.Top "../Microsoft.PowerShell.GlobalTool.Shim") | Select-Object -ExpandProperty Path695 696            if ($Options.Runtime -eq 'fxdependent' -or $Options.Runtime -eq 'fxdependent-noopt-linux-musl-x64') {697                $Arguments += "/property:SDKToUse=Microsoft.NET.Sdk"698            } elseif ($Options.Runtime -eq 'fxdependent-win-desktop') {699                $Arguments += "/property:SDKToUse=Microsoft.NET.Sdk.WindowsDesktop"700            }701 702            Write-Log -message "Run dotnet $Arguments from $PWD"703            Start-NativeExecution { dotnet $Arguments }704            Write-Log -message "PowerShell output: $($Options.Output)"705 706            try {707                Push-Location $globalToolSrcFolder708 709                if ($Options.Runtime -like 'fxdependent*') {710                    if ($Arguments -contains '/property:UseAppHost=true') {711                        $Arguments = @($Arguments | Where-Object { $_ -notlike '/property:UseAppHost=true' })712                    }713                }714 715                if ($Arguments -notcontains '--output') {716                    $Arguments += "--output", $publishPath717                }718                Write-Log -message "Run dotnet $Arguments from $PWD to build global tool entry point"719                Start-NativeExecution { dotnet $Arguments }720            }721            finally {722                Pop-Location723            }724        }725    } finally {726        Pop-Location727    }728    Write-LogGroupEnd -Title "Build PowerShell"729 730    # No extra post-building task will run if '-SMAOnly' is specified, because its purpose is for a quick update of S.M.A.dll after full build.731    if ($SMAOnly) {732        return733    }734 735    # publish reference assemblies736    Write-LogGroupStart -Title "Publish Reference Assemblies"737    try {738        Push-Location "$PSScriptRoot/src/TypeCatalogGen"739        $refAssemblies = Get-Content -Path $incFileName | Where-Object { $_ -like "*microsoft.netcore.app*" } | ForEach-Object { $_.TrimEnd(';') }740        $refDestFolder = Join-Path -Path $publishPath -ChildPath "ref"741 742        if (Test-Path $refDestFolder -PathType Container) {743            Remove-Item $refDestFolder -Force -Recurse -ErrorAction Stop744        }745        New-Item -Path $refDestFolder -ItemType Directory -Force -ErrorAction Stop > $null746        Copy-Item -Path $refAssemblies -Destination $refDestFolder -Force -ErrorAction Stop747    } finally {748        Pop-Location749    }750    Write-LogGroupEnd -Title "Publish Reference Assemblies"751 752    if ($ReleaseTag) {753        $psVersion = $ReleaseTag754    }755    else {756        $psVersion = git --git-dir="$PSScriptRoot/.git" describe757    }758 759    if ($environment.IsLinux) {760        if ($environment.IsRedHatFamily -or $environment.IsDebian) {761            # Symbolic links added here do NOT affect packaging as we do not build on Debian.762            # add two symbolic links to system shared libraries that libmi.so is dependent on to handle763            # platform specific changes. This is the only set of platforms needed for this currently764            # as Ubuntu has these specific library files in the platform and macOS builds for itself765            # against the correct versions.766 767            if ($environment.IsDebian10 -or $environment.IsDebian11){768                $sslTarget = "/usr/lib/x86_64-linux-gnu/libssl.so.1.1"769                $cryptoTarget = "/usr/lib/x86_64-linux-gnu/libcrypto.so.1.1"770            }771            elseif ($environment.IsDebian9){772                # NOTE: Debian 8 doesn't need these symlinks773                $sslTarget = "/usr/lib/x86_64-linux-gnu/libssl.so.1.0.2"774                $cryptoTarget = "/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.2"775            }776            else { #IsRedHatFamily777                $sslTarget = "/lib64/libssl.so.10"778                $cryptoTarget = "/lib64/libcrypto.so.10"779            }780 781            if ( ! (Test-Path "$publishPath/libssl.so.1.0.0")) {782                $null = New-Item -Force -ItemType SymbolicLink -Target $sslTarget -Path "$publishPath/libssl.so.1.0.0" -ErrorAction Stop783            }784            if ( ! (Test-Path "$publishPath/libcrypto.so.1.0.0")) {785                $null = New-Item -Force -ItemType SymbolicLink -Target $cryptoTarget -Path "$publishPath/libcrypto.so.1.0.0" -ErrorAction Stop786            }787        }788    }789 790    # download modules from powershell gallery.791    #   - PowerShellGet, PackageManagement, Microsoft.PowerShell.Archive792    if ($PSModuleRestore) {793        Write-LogGroupStart -Title "Restore PowerShell Modules"794        Restore-PSModuleToBuild -PublishPath $publishPath795        Write-LogGroupEnd -Title "Restore PowerShell Modules"796    }797 798    # publish powershell.config.json799    Write-LogGroupStart -Title "Generate PowerShell Configuration"800    $config = [ordered]@{}801 802    if ($Options.Runtime -like "*win*") {803        # Execution Policy and WinCompat feature are only supported on Windows.804        $config.Add("Microsoft.PowerShell:ExecutionPolicy", "RemoteSigned")805        $config.Add("WindowsPowerShellCompatibilityModuleDenyList", @("PSScheduledJob", "BestPractices", "UpdateServices"))806    }807 808    if (-not $SkipExperimentalFeatureGeneration -and809        (Test-IsPreview $psVersion) -and810        -not (Test-IsReleaseCandidate $psVersion)811    ) {812        if ((Test-ShouldGenerateExperimentalFeatures -Runtime $Options.Runtime)) {813            Write-Verbose "Build experimental feature list by running 'Get-ExperimentalFeature'" -Verbose814            $json = & $publishPath\pwsh -noprofile -command {815                $expFeatures = Get-ExperimentalFeature | ForEach-Object -MemberName Name816                ConvertTo-Json $expFeatures817            }818        } else {819            Write-Verbose "Build experimental feature list by using the pre-generated JSON files" -Verbose820            $ExperimentalFeatureJsonFilePath = if ($Options.Runtime -like "*win*") {821                "$PSScriptRoot/experimental-feature-windows.json"822            } else {823                "$PSScriptRoot/experimental-feature-linux.json"824            }825 826            if (-not (Test-Path $ExperimentalFeatureJsonFilePath)) {827                throw "ExperimentalFeatureJsonFilePath: $ExperimentalFeatureJsonFilePath does not exist"828            }829 830            $json = Get-Content -Raw $ExperimentalFeatureJsonFilePath831        }832 833        $config.Add('ExperimentalFeatures', [string[]]($json | ConvertFrom-Json));834 835    } else {836        Write-Warning -Message "Experimental features are not enabled in powershell.config.json file"837    }838 839    if ($config.Count -gt 0) {840        $configPublishPath = Join-Path -Path $publishPath -ChildPath "powershell.config.json"841        Set-Content -Path $configPublishPath -Value ($config | ConvertTo-Json) -Force -ErrorAction Stop842    } else {843        Write-Warning "No powershell.config.json generated for $publishPath"844    }845    Write-LogGroupEnd -Title "Generate PowerShell Configuration"846 847    # Restore the Pester module848    if ($CI) {849        Write-LogGroupStart -Title "Restore Pester Module"850        Restore-PSPester -Destination (Join-Path $publishPath "Modules")851        Write-LogGroupEnd -Title "Restore Pester Module"852    }853 854    Clear-NativeDependencies -PublishFolder $publishPath855 856    if ($PSOptionsPath) {857        $resolvedPSOptionsPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($PSOptionsPath)858        $parent = Split-Path -Path $resolvedPSOptionsPath859        if (!(Test-Path $parent)) {860            $null = New-Item -ItemType Directory -Path $parent861        }862        Save-PSOptions -PSOptionsPath $PSOptionsPath -Options $Options863    }864}865 866function Switch-PSNugetConfig {867    <#868    .SYNOPSIS869        Switches the NuGet configuration between public, private, and NuGet.org-only sources.870    .DESCRIPTION871        Regenerates nuget.config files in the repository root, src/Modules, and test/tools/Modules872        to point to the specified feed source. Optionally stores authenticated credentials.873    .PARAMETER Source874        The feed set to activate: 'Public' (nuget.org + dotnet feed), 'Private' (PowerShell ADO875        feed), or 'NuGetOnly' (nuget.org only).876    .PARAMETER UserName877        Username for authenticated private feed access.878    .PARAMETER ClearTextPAT879        Personal access token in clear text for authenticated private feed access.880    #>881    param(882        [Parameter(Mandatory = $true, ParameterSetName = 'user')]883        [Parameter(Mandatory = $true, ParameterSetName = 'nouser')]884        [ValidateSet('Public', 'Private', 'NuGetOnly')]885        [string] $Source,886 887        [Parameter(Mandatory = $true, ParameterSetName = 'user')]888        [string] $UserName,889 890        [Parameter(Mandatory = $true, ParameterSetName = 'user')]891        [string] $ClearTextPAT892    )893 894    Clear-PipelineNugetAuthentication895 896    $extraParams = @()897    if ($UserName) {898        $extraParams = @{899            UserName     = $UserName900            ClearTextPAT = $ClearTextPAT901        }902    }903 904    $dotnetSdk = [NugetPackageSource] @{Url = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v2'; Name = 'dotnet' }905    $gallery = [NugetPackageSource] @{Url = 'https://www.powershellgallery.com/api/v2/'; Name = 'psgallery' }906    $nugetorg = [NugetPackageSource] @{Url = 'https://api.nuget.org/v3/index.json'; Name = 'nuget.org' }907    if ( $Source -eq 'Public') {908        New-NugetConfigFile -NugetPackageSource $nugetorg, $dotnetSdk   -Destination "$PSScriptRoot/" @extraParams909        New-NugetConfigFile -NugetPackageSource $gallery                -Destination "$PSScriptRoot/src/Modules/" @extraParams910        New-NugetConfigFile -NugetPackageSource $gallery                -Destination "$PSScriptRoot/test/tools/Modules/" @extraParams911    } elseif ( $Source -eq 'NuGetOnly') {912        New-NugetConfigFile -NugetPackageSource $nugetorg   -Destination "$PSScriptRoot/" @extraParams913        New-NugetConfigFile -NugetPackageSource $gallery                -Destination "$PSScriptRoot/src/Modules/" @extraParams914        New-NugetConfigFile -NugetPackageSource $gallery                -Destination "$PSScriptRoot/test/tools/Modules/" @extraParams915    } elseif ( $Source -eq 'Private') {916        $powerShellPackages = [NugetPackageSource] @{Url = 'https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/PowerShell/nuget/v3/index.json'; Name = 'powershell' }917 918        New-NugetConfigFile -NugetPackageSource $powerShellPackages -Destination "$PSScriptRoot/" @extraParams919        New-NugetConfigFile -NugetPackageSource $powerShellPackages -Destination "$PSScriptRoot/src/Modules/" @extraParams920        New-NugetConfigFile -NugetPackageSource $powerShellPackages -Destination "$PSScriptRoot/test/tools/Modules/" @extraParams921    } else {922        throw "Unknown source: $Source"923    }924 925    if ($UserName -or $ClearTextPAT) {926        Set-PipelineNugetAuthentication927    }928}929 930function Test-ShouldGenerateExperimentalFeatures931{932    <#933    .SYNOPSIS934        Determines whether experimental-feature JSON files should be generated on this host.935    .DESCRIPTION936        Returns $true only when the current runtime identifier matches the host OS and937        architecture, the build is not a release build (PS_RELEASE_BUILD not set), and the938        runtime is not fxdependent.939    .PARAMETER Runtime940        The .NET runtime identifier (RID) being targeted by the build.941    .OUTPUTS942        System.Boolean. $true if the experimental-feature list should be generated.943    #>944    param(945        [Parameter(Mandatory)]946        $Runtime947    )948 949    if ($env:PS_RELEASE_BUILD) {950        return $false951    }952 953    if ($Runtime -like 'fxdependent*') {954        return $false955    }956 957    $runtimePattern = 'unknown-'958    if ($environment.IsWindows) {959        $runtimePattern = '^win.*-'960    }961 962    if ($environment.IsMacOS) {963        $runtimePattern = '^osx.*-'964    }965 966    if ($environment.IsLinux) {967        $runtimePattern = '^linux.*-'968    }969 970    $runtimePattern += $environment.OSArchitecture.ToString()971    Write-Verbose "runtime pattern check: $Runtime -match $runtimePattern" -Verbose972    if ($Runtime -match $runtimePattern) {973        Write-Verbose "Generating experimental feature list" -Verbose974        return $true975    }976 977    Write-Verbose "Skipping generating experimental feature list" -Verbose978    return $false979}980 981function Restore-PSPackage982{983    <#984    .SYNOPSIS985        Restores NuGet packages for the PowerShell project directories.986    .DESCRIPTION987        Runs 'dotnet restore' on the main PowerShell project directories with up to five988        retries on transient failures. Honors the target runtime identifier and build verbosity.989    .PARAMETER ProjectDirs990        Explicit list of project directories to restore. Defaults to the standard PS project set.991    .PARAMETER Options992        PSOptions object specifying runtime and configuration. Defaults to Get-PSOptions.993    .PARAMETER Force994        Forces restore even when project.assets.json already exists.995    .PARAMETER InteractiveAuth996        Passes '--interactive' to dotnet restore for interactive feed authentication.997    .PARAMETER PSModule998        Restores in PSModule mode, omitting the runtime argument.999    #>1000    [CmdletBinding()]1001    param(1002        [ValidateNotNullOrEmpty()]1003        [Parameter()]1004        [string[]] $ProjectDirs,1005 1006        [ValidateNotNullOrEmpty()]1007        [Parameter()]1008        $Options = (Get-PSOptions -DefaultToNew),1009 1010        [switch] $Force,1011 1012        [switch] $InteractiveAuth,1013 1014        [switch] $PSModule1015    )1016 1017    if (-not $ProjectDirs)1018    {1019        $ProjectDirs = @($Options.Top, "$PSScriptRoot/src/TypeCatalogGen", "$PSScriptRoot/src/ResGen", "$PSScriptRoot/src/Modules", "$PSScriptRoot/tools/wix")1020 1021        if ($Options.Runtime -like 'fxdependent*') {1022            $ProjectDirs += "$PSScriptRoot/src/Microsoft.PowerShell.GlobalTool.Shim"1023        }1024    }1025 1026    if ($Force -or (-not (Test-Path "$($Options.Top)/obj/project.assets.json"))) {1027 1028        if ($Options.Runtime -eq 'fxdependent-win-desktop') {1029            $sdkToUse = 'Microsoft.NET.Sdk.WindowsDesktop'1030        }1031        else {1032            $sdkToUse = 'Microsoft.NET.Sdk'1033            if (($Options.Runtime -like 'win7-*' -or $Options.Runtime -eq 'win-arm64') -and !$Options.ForMinimalSize) {1034                $sdkToUse = 'Microsoft.NET.Sdk.WindowsDesktop'1035            }1036        }1037 1038        if ($PSModule.IsPresent) {1039            $RestoreArguments = @("--verbosity")1040        }1041        elseif ($Options.Runtime -notlike 'fxdependent*') {1042            $RestoreArguments = @("--runtime", $Options.Runtime, "/property:SDKToUse=$sdkToUse", "--verbosity")1043        } else {1044            $RestoreArguments = @("/property:SDKToUse=$sdkToUse", "--verbosity")1045        }1046 1047        if ($VerbosePreference -eq 'Continue') {1048            $RestoreArguments += "detailed"1049        } else {1050            $RestoreArguments += "quiet"1051        }1052 1053        if ($Options.Runtime -like 'win*') {1054            $RestoreArguments += "/property:EnableWindowsTargeting=True"1055            $RestoreArguments += "/property:UseRidGraph=True"1056        }1057 1058        if ($InteractiveAuth) {1059            $RestoreArguments += "--interactive"1060        }1061 1062        if ($env:ENABLE_MSBUILD_BINLOGS -eq 'true') {1063            $RestoreArguments += '-bl'1064        }1065 1066        $ProjectDirs | ForEach-Object {1067            $project = $_1068            Write-Log -message "Run dotnet restore $project $RestoreArguments"1069            $retryCount = 01070            $maxTries = 51071            while($retryCount -lt $maxTries)1072            {1073                try1074                {1075                    Start-NativeExecution { dotnet restore $project $RestoreArguments }1076                }1077                catch1078                {1079                    Write-Log -message "Failed to restore $project, retrying..."1080                    $retryCount++1081                    if($retryCount -ge $maxTries)1082                    {1083                        if ($env:ENABLE_MSBUILD_BINLOGS -eq 'true') {1084                            if ( Test-Path ./msbuild.binlog ) {1085                                if (!(Test-Path $env:OB_OUTPUTDIRECTORY -PathType Container)) {1086                                    $null = New-Item -path $env:OB_OUTPUTDIRECTORY -ItemType Directory -Force -Verbose1087                                }1088 1089                                $projectName = Split-Path -Leaf -Path $project1090                                $binlogFileName = "${projectName}.msbuild.binlog"1091                                if ($IsMacOS) {1092                                    $resolvedPath = (Resolve-Path -Path ./msbuild.binlog).ProviderPath1093                                    Write-Host "##vso[artifact.upload containerfolder=$binLogFileName;artifactname=$binLogFileName]$resolvedPath"1094                                } else {1095                                    Copy-Item -Path ./msbuild.binlog -Destination "$env:OB_OUTPUTDIRECTORY/${projectName}.msbuild.binlog" -Verbose1096                                }1097                            }1098                        }1099 1100                        throw1101                    }1102                    continue1103                }1104 1105                Write-Log -message "Done restoring $project"1106                break1107            }1108        }1109    }1110}1111 1112function Restore-PSModuleToBuild1113{1114    <#1115    .SYNOPSIS1116        Copies PowerShell Gallery modules from the NuGet cache into the build output Modules folder.1117    .DESCRIPTION1118        Resolves Gallery module packages referenced in PSGalleryModules.csproj and copies1119        them to the Modules subdirectory of the specified publish path. Also removes1120        .nupkg.metadata files left behind by the restore.1121    .PARAMETER PublishPath1122        The PowerShell build output directory whose Modules sub-folder receives the modules.1123    #>1124    param(1125        [Parameter(Mandatory)]1126        [string]1127        $PublishPath1128    )1129 1130    Write-Log -message "Restore PowerShell modules to $publishPath"1131    $modulesDir = Join-Path -Path $publishPath -ChildPath "Modules"1132    Copy-PSGalleryModules -Destination $modulesDir -CsProjPath "$PSScriptRoot\src\Modules\PSGalleryModules.csproj"1133 1134    # Remove .nupkg.metadata files1135    Get-ChildItem $PublishPath -Filter '.nupkg.metadata' -Recurse | ForEach-Object { Remove-Item $_.FullName -ErrorAction SilentlyContinue -Force }1136}1137 1138function Restore-PSPester1139{1140    <#1141    .SYNOPSIS1142        Downloads and saves the Pester module (v4.x) from the PowerShell Gallery.1143    .DESCRIPTION1144        Uses Save-Module to install Pester up to version 4.99 into the target directory.1145    .PARAMETER Destination1146        Directory to save Pester into. Defaults to the Modules folder of the current build output.1147    #>1148    param(1149        [ValidateNotNullOrEmpty()]1150        [string] $Destination = ([IO.Path]::Combine((Split-Path (Get-PSOptions -DefaultToNew).Output), "Modules"))1151    )1152    Save-Module -Name Pester -Path $Destination -Repository PSGallery -MaximumVersion 4.991153}1154 1155function Compress-TestContent {1156    <#1157    .SYNOPSIS1158        Compresses the test directory into a zip archive for distribution.1159    .DESCRIPTION1160        Publishes PSTestTools and then zips the entire test/ directory to the given1161        destination path using System.IO.Compression.ZipFile.1162    .PARAMETER Destination1163        The path of the output zip file to create.1164    #>1165    [CmdletBinding()]1166    param(1167        $Destination1168    )1169 1170    $null = Publish-PSTestTools1171    $powerShellTestRoot =  Join-Path $PSScriptRoot 'test'1172    Add-Type -AssemblyName System.IO.Compression.FileSystem1173 1174    $resolvedPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Destination)1175    [System.IO.Compression.ZipFile]::CreateFromDirectory($powerShellTestRoot, $resolvedPath)1176}1177 1178function New-PSOptions {1179    <#1180    .SYNOPSIS1181        Creates a new PSOptions hashtable describing a PowerShell build configuration.1182    .DESCRIPTION1183        Computes the output path, project directory, and framework for a PowerShell build1184        based on the supplied runtime and configuration. The resulting hashtable is consumed1185        by Start-PSBuild, Restore-PSPackage, and related functions.1186    .PARAMETER Configuration1187        The build configuration: Debug (default), Release, CodeCoverage, or StaticAnalysis.1188    .PARAMETER Framework1189        The target .NET framework moniker. Defaults to 'net11.0'.1190    .PARAMETER Runtime1191        The .NET runtime identifier (RID). Detected automatically via 'dotnet --info' if omitted.1192    .PARAMETER Output1193        Optional path to the output directory. The executable name is appended automatically.1194    .PARAMETER SMAOnly1195        Targets only the System.Management.Automation project rather than the full host.1196    .PARAMETER PSModuleRestore1197        Indicates whether Start-PSBuild should restore PowerShell Gallery modules.1198    .PARAMETER ForMinimalSize1199        Produces a build targeting minimal binary size.1200    .OUTPUTS

Showing the first 1,200 of 4860 lines. Download the file for the rest.