2018-12-19 20:55:42 +00:00
# Initialize variables if they aren't already defined.
# These may be defined as parameters of the importing script, or set after importing this script.
# CI mode - set to true on CI server for PR validation build or official build.
[ bool ] $ci = if ( Test-Path variable : ci ) { $ci } else { $false }
# Build configuration. Common values include 'Debug' and 'Release', but the repository may use other names.
2019-11-22 13:41:58 +00:00
[ string ] $configuration = if ( Test-Path variable : configuration ) { $configuration } else { 'Debug' }
2018-12-19 20:55:42 +00:00
2020-05-12 12:48:04 +00:00
# Set to true to opt out of outputting binary log while running in CI
[ bool ] $excludeCIBinarylog = if ( Test-Path variable : excludeCIBinarylog ) { $excludeCIBinarylog } else { $false }
2018-12-19 20:55:42 +00:00
# Set to true to output binary log from msbuild. Note that emitting binary log slows down the build.
2020-05-12 12:48:04 +00:00
[ bool ] $binaryLog = if ( Test-Path variable : binaryLog ) { $binaryLog } else { $ci -and ! $excludeCIBinarylog }
2018-12-19 20:55:42 +00:00
2019-05-09 12:24:48 +00:00
# Set to true to use the pipelines logger which will enable Azure logging output.
# https://github.com/Microsoft/azure-pipelines-tasks/blob/master/docs/authoring/commands.md
# This flag is meant as a temporary opt-opt for the feature while validate it across
# our consumers. It will be deleted in the future.
[ bool ] $pipelinesLog = if ( Test-Path variable : pipelinesLog ) { $pipelinesLog } else { $ci }
2018-12-19 20:55:42 +00:00
# Turns on machine preparation/clean up code that changes the machine state (e.g. kills build processes).
[ bool ] $prepareMachine = if ( Test-Path variable : prepareMachine ) { $prepareMachine } else { $false }
# True to restore toolsets and dependencies.
[ bool ] $restore = if ( Test-Path variable : restore ) { $restore } else { $true }
# Adjusts msbuild verbosity level.
2019-11-22 13:41:58 +00:00
[ string ] $verbosity = if ( Test-Path variable : verbosity ) { $verbosity } else { 'minimal' }
2018-12-19 20:55:42 +00:00
# Set to true to reuse msbuild nodes. Recommended to not reuse on CI.
[ bool ] $nodeReuse = if ( Test-Path variable : nodeReuse ) { $nodeReuse } else { ! $ci }
# Configures warning treatment in msbuild.
[ bool ] $warnAsError = if ( Test-Path variable : warnAsError ) { $warnAsError } else { $true }
# Specifies which msbuild engine to use for build: 'vs', 'dotnet' or unspecified (determined based on presence of tools.vs in global.json).
[ string ] $msbuildEngine = if ( Test-Path variable : msbuildEngine ) { $msbuildEngine } else { $null }
2019-06-08 12:08:27 +00:00
# True to attempt using .NET Core already that meets requirements specified in global.json
2018-12-19 20:55:42 +00:00
# installed on the machine instead of downloading one.
[ bool ] $useInstalledDotNetCli = if ( Test-Path variable : useInstalledDotNetCli ) { $useInstalledDotNetCli } else { $true }
2019-08-02 12:38:38 +00:00
# Enable repos to use a particular version of the on-line dotnet-install scripts.
2021-07-13 19:44:25 +00:00
# default URL: https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.ps1
2019-11-22 13:41:58 +00:00
[ string ] $dotnetInstallScriptVersion = if ( Test-Path variable : dotnetInstallScriptVersion ) { $dotnetInstallScriptVersion } else { 'v1' }
2019-08-02 12:38:38 +00:00
2018-12-19 20:55:42 +00:00
# True to use global NuGet cache instead of restoring packages to repository-local directory.
[ bool ] $useGlobalNuGetCache = if ( Test-Path variable : useGlobalNuGetCache ) { $useGlobalNuGetCache } else { ! $ci }
2021-05-06 13:01:50 +00:00
# True to exclude prerelease versions Visual Studio during build
[ bool ] $excludePrereleaseVS = if ( Test-Path variable : excludePrereleaseVS ) { $excludePrereleaseVS } else { $false }
2018-12-19 20:55:42 +00:00
# An array of names of processes to stop on script exit if prepareMachine is true.
2019-11-22 13:41:58 +00:00
$processesToStopOnExit = if ( Test-Path variable : processesToStopOnExit ) { $processesToStopOnExit } else { @ ( 'msbuild' , 'dotnet' , 'vbcscompiler' ) }
2018-10-22 05:07:26 +00:00
2019-10-24 22:05:36 +00:00
$disableConfigureToolsetImport = if ( Test-Path variable : disableConfigureToolsetImport ) { $disableConfigureToolsetImport } else { $null }
2018-10-22 05:07:26 +00:00
set-strictmode -version 2.0
2019-11-22 13:41:58 +00:00
$ErrorActionPreference = 'Stop'
2018-10-22 05:07:26 +00:00
[ Net.ServicePointManager ] :: SecurityProtocol = [ Net.SecurityProtocolType ] :: Tls12
2020-10-28 15:07:45 +00:00
# If specifies, provides an alternate path for getting .NET Core SDKs and Runtimes. This script will still try public sources first.
2020-08-26 13:09:20 +00:00
[ string ] $runtimeSourceFeed = if ( Test-Path variable : runtimeSourceFeed ) { $runtimeSourceFeed } else { $null }
# Base-64 encoded SAS token that has permission to storage container described by $runtimeSourceFeed
[ string ] $runtimeSourceFeedKey = if ( Test-Path variable : runtimeSourceFeedKey ) { $runtimeSourceFeedKey } else { $null }
2020-05-12 12:48:04 +00:00
function Create-Directory ( [ string[] ] $path ) {
New-Item -Path $path -Force -ItemType 'Directory' | Out-Null
2018-10-22 05:07:26 +00:00
}
2018-12-04 17:31:23 +00:00
function Unzip([string]$zipfile , [ string ] $outpath ) {
Add-Type -AssemblyName System . IO . Compression . FileSystem
[ System.IO.Compression.ZipFile ] :: ExtractToDirectory ( $zipfile , $outpath )
}
2018-12-19 20:55:42 +00:00
# This will exec a process using the console and return it's exit code.
# This will not throw when the process fails.
# Returns process exit code.
function Exec-Process([string]$command , [ string ] $commandArgs ) {
$startInfo = New-Object System . Diagnostics . ProcessStartInfo
$startInfo . FileName = $command
$startInfo . Arguments = $commandArgs
$startInfo . UseShellExecute = $false
$startInfo . WorkingDirectory = Get-Location
$process = New-Object System . Diagnostics . Process
$process . StartInfo = $startInfo
$process . Start ( ) | Out-Null
$finished = $false
try {
2019-06-08 12:08:27 +00:00
while ( -not $process . WaitForExit ( 100 ) ) {
2018-12-19 20:55:42 +00:00
# Non-blocking loop done to allow ctr-c interrupts
}
$finished = $true
return $global:LASTEXITCODE = $process . ExitCode
}
finally {
2019-07-11 12:25:27 +00:00
# If we didn't finish then an error occurred or the user hit ctrl-c. Either
2018-12-19 20:55:42 +00:00
# way kill the process
if ( -not $finished ) {
$process . Kill ( )
}
}
}
2021-07-15 14:32:48 +00:00
# Take the given block, print it, print what the block probably references from the current set of
# variables using low-effort string matching, then run the block.
#
# This is intended to replace the pattern of manually copy-pasting a command, wrapping it in quotes,
# and printing it using "Write-Host". The copy-paste method is more readable in build logs, but less
# maintainable and less reliable. It is easy to make a mistake and modify the command without
# properly updating the "Write-Host" line, resulting in misleading build logs. The probability of
# this mistake makes the pattern hard to trust when it shows up in build logs. Finding the bug in
# existing source code can also be difficult, because the strings are not aligned to each other and
# the line may be 300+ columns long.
#
# By removing the need to maintain two copies of the command, Exec-BlockVerbosely avoids the issues.
#
# In Bash (or any posix-like shell), "set -x" prints usable verbose output automatically.
# "Set-PSDebug" appears to be similar at first glance, but unfortunately, it isn't very useful: it
# doesn't print any info about the variables being used by the command, which is normally the
# interesting part to diagnose.
function Exec-BlockVerbosely([scriptblock ] $block ) {
Write-Host " --- Running script block: "
$blockString = $block . ToString ( ) . Trim ( )
Write-Host $blockString
Write-Host " --- List of variables that might be used: "
# For each variable x in the environment, check the block for a reference to x via simple "$x" or
# "@x" syntax. This doesn't detect other ways to reference variables ("${x}" nor "$variable:x",
# among others). It only catches what this function was originally written for: simple
# command-line commands.
$variableTable = Get-Variable |
Where-Object {
$blockString . Contains ( " `$ $( $_ . Name ) " ) -or $blockString . Contains ( " @ $( $_ . Name ) " )
} |
Format-Table -AutoSize -HideTableHeaders -Wrap |
Out-String
Write-Host $variableTable . Trim ( )
Write-Host " --- Executing: "
& $block
Write-Host " --- Done running script block! "
}
2019-12-17 13:31:15 +00:00
# createSdkLocationFile parameter enables a file being generated under the toolset directory
# which writes the sdk's location into. This is only necessary for cmd --> powershell invocations
# as dot sourcing isn't possible.
2019-12-12 13:30:39 +00:00
function InitializeDotNetCli([bool]$install , [ bool ] $createSdkLocationFile ) {
2018-12-19 20:55:42 +00:00
if ( Test-Path variable : global: _DotNetInstallDir ) {
return $global:_DotNetInstallDir
}
2018-10-22 05:07:26 +00:00
# Don't resolve runtime, shared framework, or SDK from other locations to ensure build determinism
$env:DOTNET_MULTILEVEL_LOOKUP = 0
2021-09-17 13:01:04 +00:00
# Disable first run since we do not need all ASP.NET packages restored.
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
2018-12-19 20:55:42 +00:00
# Disable telemetry on CI.
if ( $ci ) {
$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
}
2018-10-22 05:07:26 +00:00
# Source Build uses DotNetCoreSdkDir variable
if ( $env:DotNetCoreSdkDir -ne $null ) {
$env:DOTNET_INSTALL_DIR = $env:DotNetCoreSdkDir
}
# Find the first path on %PATH% that contains the dotnet.exe
2019-05-07 12:30:40 +00:00
if ( $useInstalledDotNetCli -and ( -not $globalJsonHasRuntimes ) -and ( $env:DOTNET_INSTALL_DIR -eq $null ) ) {
2020-05-30 12:44:29 +00:00
$dotnetExecutable = GetExecutableFileName 'dotnet'
$dotnetCmd = Get-Command $dotnetExecutable -ErrorAction SilentlyContinue
2018-12-19 20:55:42 +00:00
if ( $dotnetCmd -ne $null ) {
$env:DOTNET_INSTALL_DIR = Split-Path $dotnetCmd . Path -Parent
}
2018-10-22 05:07:26 +00:00
}
$dotnetSdkVersion = $GlobalJson . tools . dotnet
# Use dotnet installation specified in DOTNET_INSTALL_DIR if it contains the required SDK version,
# otherwise install the dotnet CLI and SDK to repo local .dotnet directory to avoid potential permission issues.
2021-03-03 14:01:31 +00:00
if ( ( -not $globalJsonHasRuntimes ) -and ( -not [ string ] :: IsNullOrEmpty ( $env:DOTNET_INSTALL_DIR ) ) -and ( Test-Path ( Join-Path $env:DOTNET_INSTALL_DIR " sdk\ $dotnetSdkVersion " ) ) ) {
2018-10-22 05:07:26 +00:00
$dotnetRoot = $env:DOTNET_INSTALL_DIR
} else {
2019-11-22 13:41:58 +00:00
$dotnetRoot = Join-Path $RepoRoot '.dotnet'
2018-10-22 05:07:26 +00:00
2018-12-19 20:55:42 +00:00
if ( -not ( Test-Path ( Join-Path $dotnetRoot " sdk\ $dotnetSdkVersion " ) ) ) {
2018-10-22 05:07:26 +00:00
if ( $install ) {
InstallDotNetSdk $dotnetRoot $dotnetSdkVersion
} else {
2019-11-22 13:41:58 +00:00
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message " Unable to find dotnet with SDK version ' $dotnetSdkVersion ' "
2018-10-22 05:07:26 +00:00
ExitWithExitCode 1
}
}
2018-12-19 20:55:42 +00:00
$env:DOTNET_INSTALL_DIR = $dotnetRoot
2019-12-17 13:31:15 +00:00
}
2019-12-12 13:30:39 +00:00
2019-12-17 13:31:15 +00:00
# Creates a temporary file under the toolset dir.
# The following code block is protecting against concurrent access so that this function can
# be called in parallel.
if ( $createSdkLocationFile ) {
2020-02-08 00:51:24 +00:00
do {
2019-12-17 13:31:15 +00:00
$sdkCacheFileTemp = Join-Path $ToolsetDir $ ( [ System.IO.Path ] :: GetRandomFileName ( ) )
2020-02-08 00:51:24 +00:00
}
2019-12-17 13:31:15 +00:00
until ( ! ( Test-Path $sdkCacheFileTemp ) )
Set-Content -Path $sdkCacheFileTemp -Value $dotnetRoot
2020-02-08 00:51:24 +00:00
2019-12-17 13:31:15 +00:00
try {
2021-02-26 13:51:15 +00:00
Move-Item -Force $sdkCacheFileTemp ( Join-Path $ToolsetDir 'sdk.txt' )
2019-12-17 13:31:15 +00:00
} catch {
# Somebody beat us
Remove-Item -Path $sdkCacheFileTemp
2019-12-12 13:30:39 +00:00
}
2018-10-22 05:07:26 +00:00
}
2018-12-19 20:55:42 +00:00
# Add dotnet to PATH. This prevents any bare invocation of dotnet in custom
# build steps from using anything other than what we've downloaded.
# It also ensures that VS msbuild will use the downloaded sdk targets.
$env:PATH = " $dotnetRoot ; $env:PATH "
2019-07-11 12:25:27 +00:00
# Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build
2019-05-31 12:10:52 +00:00
Write-PipelinePrependPath -Path $dotnetRoot
2019-09-13 12:37:37 +00:00
2019-05-31 12:10:52 +00:00
Write-PipelineSetVariable -Name 'DOTNET_MULTILEVEL_LOOKUP' -Value '0'
2021-09-17 13:01:04 +00:00
Write-PipelineSetVariable -Name 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE' -Value '1'
2019-01-11 13:12:40 +00:00
2018-12-19 20:55:42 +00:00
return $global:_DotNetInstallDir = $dotnetRoot
2018-10-22 05:07:26 +00:00
}
2021-06-12 12:58:31 +00:00
function Retry($downloadBlock , $maxRetries = 5 ) {
$retries = 1
while ( $true ) {
try {
& $downloadBlock
break
}
catch {
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_
}
if ( + + $retries -le $maxRetries ) {
$delayInSeconds = [ math ] :: Pow ( 2 , $retries ) - 1 # Exponential backoff
Write-Host " Retrying. Waiting for $delayInSeconds seconds before next attempt ( $retries of $maxRetries ). "
Start-Sleep -Seconds $delayInSeconds
}
else {
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message " Unable to download file in $maxRetries attempts. "
break
}
}
}
2018-10-22 05:07:26 +00:00
function GetDotNetInstallScript([string ] $dotnetRoot ) {
2019-11-22 13:41:58 +00:00
$installScript = Join-Path $dotnetRoot 'dotnet-install.ps1'
2018-10-22 05:07:26 +00:00
if ( ! ( Test-Path $installScript ) ) {
2020-10-28 15:07:45 +00:00
Create-Directory $dotnetRoot
$ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit
2021-07-13 19:44:25 +00:00
$uri = " https://dotnet.microsoft.com/download/dotnet/scripts/ $dotnetInstallScriptVersion /dotnet-install.ps1 "
2020-10-28 15:07:45 +00:00
2021-06-12 12:58:31 +00:00
Retry ( {
Write-Host " GET $uri "
Invoke-WebRequest $uri -OutFile $installScript
} )
2018-10-22 05:07:26 +00:00
}
2020-10-28 15:07:45 +00:00
2018-10-22 05:07:26 +00:00
return $installScript
}
2020-09-03 13:08:49 +00:00
function InstallDotNetSdk([string ] $dotnetRoot , [ string ] $version , [ string ] $architecture = '' , [ switch ] $noPath ) {
InstallDotNet $dotnetRoot $version $architecture '' $false $runtimeSourceFeed $runtimeSourceFeedKey -noPath: $noPath
2019-05-07 12:30:40 +00:00
}
2020-02-08 00:51:24 +00:00
function InstallDotNet([string ] $dotnetRoot ,
[ string ] $version ,
[ string ] $architecture = '' ,
[ string ] $runtime = '' ,
[ bool ] $skipNonVersionedFiles = $false ,
[ string ] $runtimeSourceFeed = '' ,
2020-09-03 13:08:49 +00:00
[ string ] $runtimeSourceFeedKey = '' ,
[ switch ] $noPath ) {
2019-10-24 22:05:36 +00:00
2023-05-06 12:33:43 +00:00
$dotnetVersionLabel = " 'sdk v $version ' "
if ( $runtime -ne '' -and $runtime -ne 'sdk' ) {
$runtimePath = $dotnetRoot
$runtimePath = $runtimePath + " \shared "
if ( $runtime -eq " dotnet " ) { $runtimePath = $runtimePath + " \Microsoft.NETCore.App " }
if ( $runtime -eq " aspnetcore " ) { $runtimePath = $runtimePath + " \Microsoft.AspNetCore.App " }
if ( $runtime -eq " windowsdesktop " ) { $runtimePath = $runtimePath + " \Microsoft.WindowsDesktop.App " }
$runtimePath = $runtimePath + " \ " + $version
$dotnetVersionLabel = " runtime toolset ' $runtime / $architecture v $version ' "
if ( Test-Path $runtimePath ) {
Write-Host " Runtime toolset ' $runtime / $architecture v $version ' already installed. "
$installSuccess = $true
Exit
}
}
2018-10-22 05:07:26 +00:00
$installScript = GetDotNetInstallScript $dotnetRoot
2019-05-07 12:30:40 +00:00
$installParameters = @ {
Version = $version
InstallDir = $dotnetRoot
}
if ( $architecture ) { $installParameters . Architecture = $architecture }
if ( $runtime ) { $installParameters . Runtime = $runtime }
if ( $skipNonVersionedFiles ) { $installParameters . SkipNonVersionedFiles = $skipNonVersionedFiles }
2020-09-03 13:08:49 +00:00
if ( $noPath ) { $installParameters . NoPath = $True }
2019-05-07 12:30:40 +00:00
2021-11-17 14:57:23 +00:00
$variations = @ ( )
$variations + = @ ( $installParameters )
2019-10-24 22:05:36 +00:00
2021-11-17 14:57:23 +00:00
$dotnetBuilds = $installParameters . Clone ( )
$dotnetbuilds . AzureFeed = " https://dotnetbuilds.azureedge.net/public "
$variations + = @ ( $dotnetBuilds )
2019-10-24 22:05:36 +00:00
2021-11-17 14:57:23 +00:00
if ( $runtimeSourceFeed ) {
$runtimeSource = $installParameters . Clone ( )
$runtimeSource . AzureFeed = $runtimeSourceFeed
if ( $runtimeSourceFeedKey ) {
$decodedBytes = [ System.Convert ] :: FromBase64String ( $runtimeSourceFeedKey )
$decodedString = [ System.Text.Encoding ] :: UTF8 . GetString ( $decodedBytes )
$runtimeSource . FeedCredential = $decodedString
}
$variations + = @ ( $runtimeSource )
}
$installSuccess = $false
foreach ( $variation in $variations ) {
if ( $variation | Get-Member AzureFeed ) {
$location = $variation . AzureFeed
2019-12-12 13:30:39 +00:00
} else {
2021-11-17 14:57:23 +00:00
$location = " public location " ;
}
2023-05-06 12:33:43 +00:00
Write-Host " Attempting to install $dotnetVersionLabel from $location . "
2021-11-17 14:57:23 +00:00
try {
& $installScript @variation
$installSuccess = $true
break
2019-10-24 22:05:36 +00:00
}
2021-11-17 14:57:23 +00:00
catch {
2023-05-06 12:33:43 +00:00
Write-Host " Failed to install $dotnetVersionLabel from $location . "
2021-11-17 14:57:23 +00:00
}
}
if ( -not $installSuccess ) {
2023-05-06 12:33:43 +00:00
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message " Failed to install $dotnetVersionLabel from any of the specified locations. "
2021-11-17 14:57:23 +00:00
ExitWithExitCode 1
2018-10-22 05:07:26 +00:00
}
}
2018-12-04 17:31:23 +00:00
#
2019-06-08 12:08:27 +00:00
# Locates Visual Studio MSBuild installation.
2018-12-04 17:31:23 +00:00
# The preference order for MSBuild to use is as follows:
#
# 1. MSBuild from an active VS command prompt
# 2. MSBuild from a compatible VS installation
# 3. MSBuild from the xcopy tool package
#
# Returns full path to msbuild.exe.
# Throws on failure.
#
2018-12-19 20:55:42 +00:00
function InitializeVisualStudioMSBuild([bool]$install , [ object ] $vsRequirements = $null ) {
2020-05-30 12:44:29 +00:00
if ( -not ( IsWindowsPlatform ) ) {
throw " Cannot initialize Visual Studio on non-Windows "
}
2018-12-19 20:55:42 +00:00
if ( Test-Path variable : global: _MSBuildExe ) {
return $global:_MSBuildExe
}
2020-09-21 16:22:30 +00:00
# Minimum VS version to require.
2023-10-17 15:07:15 +00:00
$vsMinVersionReqdStr = '17.7'
2020-06-02 12:45:27 +00:00
$vsMinVersionReqd = [ Version ] :: new ( $vsMinVersionReqdStr )
2020-09-21 16:22:30 +00:00
# If the version of msbuild is going to be xcopied,
# use this version. Version matches a package here:
2023-10-19 16:00:42 +00:00
# https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-eng/NuGet/RoslynTools.MSBuild/versions/17.8.1-2
$defaultXCopyMSBuildVersion = '17.8.1-2'
2020-09-21 16:22:30 +00:00
2022-08-11 12:40:33 +00:00
if ( ! $vsRequirements ) {
if ( Get-Member -InputObject $GlobalJson . tools -Name 'vs' ) {
$vsRequirements = $GlobalJson . tools . vs
}
else {
$vsRequirements = New-Object PSObject -Property @ { version = $vsMinVersionReqdStr }
}
}
2020-06-02 12:45:27 +00:00
$vsMinVersionStr = if ( $vsRequirements . version ) { $vsRequirements . version } else { $vsMinVersionReqdStr }
2019-06-08 12:08:27 +00:00
$vsMinVersion = [ Version ] :: new ( $vsMinVersionStr )
2018-12-04 17:31:23 +00:00
# Try msbuild command available in the environment.
if ( $env:VSINSTALLDIR -ne $null ) {
2019-11-22 13:41:58 +00:00
$msbuildCmd = Get-Command 'msbuild.exe' -ErrorAction SilentlyContinue
2018-12-04 17:31:23 +00:00
if ( $msbuildCmd -ne $null ) {
2019-05-22 12:11:57 +00:00
# Workaround for https://github.com/dotnet/roslyn/issues/35793
# Due to this issue $msbuildCmd.Version returns 0.0.0.0 for msbuild.exe 16.2+
2019-11-27 13:36:25 +00:00
$msbuildVersion = [ Version ] :: new ( ( Get-Item $msbuildCmd . Path ) . VersionInfo . ProductVersion . Split ( [ char[] ] @ ( '-' , '+' ) ) [ 0 ] )
2019-05-22 12:11:57 +00:00
if ( $msbuildVersion -ge $vsMinVersion ) {
2018-12-19 20:55:42 +00:00
return $global:_MSBuildExe = $msbuildCmd . Path
2018-12-04 17:31:23 +00:00
}
# Report error - the developer environment is initialized with incompatible VS version.
throw " Developer Command Prompt for VS $( $env:VisualStudioVersion ) is not recent enough. Please upgrade to $vsMinVersionStr or build from a plain CMD window "
}
2018-10-22 05:07:26 +00:00
}
2018-12-04 17:31:23 +00:00
# Locate Visual Studio installation or download x-copy msbuild.
2018-12-19 20:55:42 +00:00
$vsInfo = LocateVisualStudio $vsRequirements
2018-12-04 17:31:23 +00:00
if ( $vsInfo -ne $null ) {
2023-05-04 14:51:22 +00:00
# Ensure vsInstallDir has a trailing slash
$vsInstallDir = Join-Path $vsInfo . installationPath " \ "
2018-12-04 17:31:23 +00:00
$vsMajorVersion = $vsInfo . installationVersion . Split ( '.' ) [ 0 ]
InitializeVisualStudioEnvironmentVariables $vsInstallDir $vsMajorVersion
2019-02-13 19:39:26 +00:00
} else {
2018-10-22 05:07:26 +00:00
2019-11-22 13:41:58 +00:00
if ( Get-Member -InputObject $GlobalJson . tools -Name 'xcopy-msbuild' ) {
2018-12-04 17:31:23 +00:00
$xcopyMSBuildVersion = $GlobalJson . tools . 'xcopy-msbuild'
$vsMajorVersion = $xcopyMSBuildVersion . Split ( '.' ) [ 0 ]
} else {
2020-09-21 16:22:30 +00:00
#if vs version provided in global.json is incompatible (too low) then use the default version for xcopy msbuild download
2020-06-02 12:45:27 +00:00
if ( $vsMinVersion -lt $vsMinVersionReqd ) {
2020-09-21 16:22:30 +00:00
Write-Host " Using xcopy-msbuild version of $defaultXCopyMSBuildVersion since VS version $vsMinVersionStr provided in global.json is not compatible "
$xcopyMSBuildVersion = $defaultXCopyMSBuildVersion
2022-11-24 13:28:07 +00:00
$vsMajorVersion = $xcopyMSBuildVersion . Split ( '.' ) [ 0 ]
2020-06-02 12:45:27 +00:00
}
else {
2020-09-21 16:22:30 +00:00
# If the VS version IS compatible, look for an xcopy msbuild package
# with a version matching VS.
# Note: If this version does not exist, then an explicit version of xcopy msbuild
# can be specified in global.json. This will be required for pre-release versions of msbuild.
2020-06-02 12:45:27 +00:00
$vsMajorVersion = $vsMinVersion . Major
$vsMinorVersion = $vsMinVersion . Minor
2020-09-21 16:22:30 +00:00
$xcopyMSBuildVersion = " $vsMajorVersion . $vsMinorVersion .0 "
2020-06-02 12:45:27 +00:00
}
2018-12-04 17:31:23 +00:00
}
2020-02-08 00:51:24 +00:00
2019-12-12 13:30:39 +00:00
$vsInstallDir = $null
if ( $xcopyMSBuildVersion . Trim ( ) -ine " none " ) {
$vsInstallDir = InitializeXCopyMSBuild $xcopyMSBuildVersion $install
2020-09-21 16:22:30 +00:00
if ( $vsInstallDir -eq $null ) {
throw " Could not xcopy msbuild. Please check that package 'RoslynTools.MSBuild @ $xcopyMSBuildVersion ' exists on feed 'dotnet-eng'. "
}
2019-12-12 13:30:39 +00:00
}
2019-02-13 19:39:26 +00:00
if ( $vsInstallDir -eq $null ) {
2019-11-22 13:41:58 +00:00
throw 'Unable to find Visual Studio that has required version and components installed'
2019-02-13 19:39:26 +00:00
}
2018-12-04 17:31:23 +00:00
}
$msbuildVersionDir = if ( [ int ] $vsMajorVersion -lt 16 ) { " $vsMajorVersion .0 " } else { " Current " }
2021-06-25 13:21:59 +00:00
$local : BinFolder = Join-Path $vsInstallDir " MSBuild\ $msbuildVersionDir \Bin "
2021-06-29 14:45:44 +00:00
$local : Prefer64bit = if ( Get-Member -InputObject $vsRequirements -Name 'Prefer64bit' ) { $vsRequirements . Prefer64bit } else { $false }
2021-06-25 13:21:59 +00:00
if ( $local : Prefer64bit -and ( Test-Path ( Join-Path $local : BinFolder " amd64 " ) ) ) {
$global:_MSBuildExe = Join-Path $local : BinFolder " amd64\msbuild.exe "
} else {
$global:_MSBuildExe = Join-Path $local : BinFolder " msbuild.exe "
}
return $global:_MSBuildExe
2018-12-04 17:31:23 +00:00
}
2018-10-22 05:07:26 +00:00
2018-12-04 17:31:23 +00:00
function InitializeVisualStudioEnvironmentVariables([string ] $vsInstallDir , [ string ] $vsMajorVersion ) {
$env:VSINSTALLDIR = $vsInstallDir
Set-Item " env:VS $( $vsMajorVersion ) 0COMNTOOLS " ( Join-Path $vsInstallDir " Common7\Tools\ " )
2019-06-08 12:08:27 +00:00
2018-12-04 17:31:23 +00:00
$vsSdkInstallDir = Join-Path $vsInstallDir " VSSDK\ "
if ( Test-Path $vsSdkInstallDir ) {
Set-Item " env:VSSDK $( $vsMajorVersion ) 0Install " $vsSdkInstallDir
2018-10-22 05:07:26 +00:00
$env:VSSDKInstall = $vsSdkInstallDir
}
2018-12-04 17:31:23 +00:00
}
2019-02-13 19:39:26 +00:00
function InstallXCopyMSBuild([string]$packageVersion ) {
return InitializeXCopyMSBuild $packageVersion -install $true
}
function InitializeXCopyMSBuild([string]$packageVersion , [ bool ] $install ) {
2019-11-22 13:41:58 +00:00
$packageName = 'RoslynTools.MSBuild'
2018-12-04 17:31:23 +00:00
$packageDir = Join-Path $ToolsDir " msbuild\ $packageVersion "
$packagePath = Join-Path $packageDir " $packageName . $packageVersion .nupkg "
if ( ! ( Test-Path $packageDir ) ) {
2019-02-13 19:39:26 +00:00
if ( ! $install ) {
return $null
}
2018-12-04 17:31:23 +00:00
Create-Directory $packageDir
2021-06-12 12:58:31 +00:00
2018-12-04 17:31:23 +00:00
Write-Host " Downloading $packageName $packageVersion "
2019-08-28 12:37:30 +00:00
$ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit
2021-06-12 12:58:31 +00:00
Retry ( {
Invoke-WebRequest " https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/flat2/ $packageName / $packageVersion / $packageName . $packageVersion .nupkg " -OutFile $packagePath
} )
2018-12-04 17:31:23 +00:00
Unzip $packagePath $packageDir
}
2018-10-22 05:07:26 +00:00
2019-11-22 13:41:58 +00:00
return Join-Path $packageDir 'tools'
2018-10-22 05:07:26 +00:00
}
2018-12-04 17:31:23 +00:00
#
# Locates Visual Studio instance that meets the minimal requirements specified by tools.vs object in global.json.
#
# The following properties of tools.vs are recognized:
2019-06-08 12:08:27 +00:00
# "version": "{major}.{minor}"
2018-12-04 17:31:23 +00:00
# Two part minimal VS version, e.g. "15.9", "16.0", etc.
2019-06-08 12:08:27 +00:00
# "components": ["componentId1", "componentId2", ...]
2018-12-04 17:31:23 +00:00
# Array of ids of workload components that must be available in the VS instance.
# See e.g. https://docs.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-enterprise?view=vs-2017
#
2019-06-08 12:08:27 +00:00
# Returns JSON describing the located VS instance (same format as returned by vswhere),
2018-12-04 17:31:23 +00:00
# or $null if no instance meeting the requirements is found on the machine.
#
2018-12-19 20:55:42 +00:00
function LocateVisualStudio([object]$vsRequirements = $null ) {
2020-05-30 12:44:29 +00:00
if ( -not ( IsWindowsPlatform ) ) {
throw " Cannot run vswhere on non-Windows platforms. "
}
2019-11-22 13:41:58 +00:00
if ( Get-Member -InputObject $GlobalJson . tools -Name 'vswhere' ) {
2018-12-19 20:55:42 +00:00
$vswhereVersion = $GlobalJson . tools . vswhere
} else {
2019-11-22 13:41:58 +00:00
$vswhereVersion = '2.5.2'
2018-10-22 05:07:26 +00:00
}
2018-12-04 17:31:23 +00:00
$vsWhereDir = Join-Path $ToolsDir " vswhere\ $vswhereVersion "
2019-11-22 13:41:58 +00:00
$vsWhereExe = Join-Path $vsWhereDir 'vswhere.exe'
2018-10-22 05:07:26 +00:00
if ( ! ( Test-Path $vsWhereExe ) ) {
Create-Directory $vsWhereDir
2019-11-22 13:41:58 +00:00
Write-Host 'Downloading vswhere'
2021-06-12 12:58:31 +00:00
Retry ( {
Invoke-WebRequest " https://netcorenativeassets.blob.core.windows.net/resource-packages/external/windows/vswhere/ $vswhereVersion /vswhere.exe " -OutFile $vswhereExe
} )
2018-10-22 05:07:26 +00:00
}
2018-12-19 20:55:42 +00:00
if ( ! $vsRequirements ) { $vsRequirements = $GlobalJson . tools . vs }
2021-05-06 13:01:50 +00:00
$args = @ ( '-latest' , '-format' , 'json' , '-requires' , 'Microsoft.Component.MSBuild' , '-products' , '*' )
if ( ! $excludePrereleaseVS ) {
$args + = '-prerelease'
}
2019-06-08 12:08:27 +00:00
2019-11-22 13:41:58 +00:00
if ( Get-Member -InputObject $vsRequirements -Name 'version' ) {
$args + = '-version'
2018-12-19 20:55:42 +00:00
$args + = $vsRequirements . version
2018-12-04 17:31:23 +00:00
}
2019-11-22 13:41:58 +00:00
if ( Get-Member -InputObject $vsRequirements -Name 'components' ) {
2018-12-19 20:55:42 +00:00
foreach ( $component in $vsRequirements . components ) {
2019-11-22 13:41:58 +00:00
$args + = '-requires'
2018-12-04 17:31:23 +00:00
$args + = $component
2019-06-08 12:08:27 +00:00
}
2018-12-04 17:31:23 +00:00
}
$vsInfo = & $vsWhereExe $args | ConvertFrom-Json
2018-10-22 05:07:26 +00:00
if ( $lastExitCode -ne 0 ) {
2018-12-04 17:31:23 +00:00
return $null
2018-10-22 05:07:26 +00:00
}
# use first matching instance
return $vsInfo [ 0 ]
}
2018-12-19 20:55:42 +00:00
function InitializeBuildTool ( ) {
if ( Test-Path variable : global: _BuildTool ) {
2021-05-06 13:01:50 +00:00
# If the requested msbuild parameters do not match, clear the cached variables.
if ( $global:_BuildTool . Contains ( 'ExcludePrereleaseVS' ) -and $global:_BuildTool . ExcludePrereleaseVS -ne $excludePrereleaseVS ) {
2021-06-12 12:58:31 +00:00
Remove-Item variable : global: _BuildTool
2021-05-06 13:01:50 +00:00
Remove-Item variable : global: _MSBuildExe
} else {
return $global:_BuildTool
}
2018-10-22 05:07:26 +00:00
}
2018-12-19 20:55:42 +00:00
if ( -not $msbuildEngine ) {
$msbuildEngine = GetDefaultMSBuildEngine
}
2018-10-22 05:07:26 +00:00
# Initialize dotnet cli if listed in 'tools'
$dotnetRoot = $null
2019-11-22 13:41:58 +00:00
if ( Get-Member -InputObject $GlobalJson . tools -Name 'dotnet' ) {
2018-10-22 05:07:26 +00:00
$dotnetRoot = InitializeDotNetCli -install: $restore
}
2019-11-22 13:41:58 +00:00
if ( $msbuildEngine -eq 'dotnet' ) {
2018-10-22 05:07:26 +00:00
if ( ! $dotnetRoot ) {
2019-11-22 13:41:58 +00:00
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message " /global.json must specify 'tools.dotnet'. "
2018-10-22 05:07:26 +00:00
ExitWithExitCode 1
}
2020-05-30 12:44:29 +00:00
$dotnetPath = Join-Path $dotnetRoot ( GetExecutableFileName 'dotnet' )
2024-01-10 19:47:11 +00:00
# Use override if it exists - commonly set by source-build
if ( $null -eq $env:_OverrideArcadeInitializeBuildToolFramework ) {
$initializeBuildToolFramework = " net8.0 "
} else {
$initializeBuildToolFramework = $env:_OverrideArcadeInitializeBuildToolFramework
}
$buildTool = @ { Path = $dotnetPath ; Command = 'msbuild' ; Tool = 'dotnet' ; Framework = $initializeBuildToolFramework }
2018-10-22 05:07:26 +00:00
} elseif ( $msbuildEngine -eq " vs " ) {
2018-12-04 17:31:23 +00:00
try {
2018-12-19 20:55:42 +00:00
$msbuildPath = InitializeVisualStudioMSBuild -install: $restore
} catch {
2019-11-22 13:41:58 +00:00
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_
2018-12-04 17:31:23 +00:00
ExitWithExitCode 1
}
2018-12-19 20:55:42 +00:00
2021-05-06 13:01:50 +00:00
$buildTool = @ { Path = $msbuildPath ; Command = " " ; Tool = " vs " ; Framework = " net472 " ; ExcludePrereleaseVS = $excludePrereleaseVS }
2018-10-22 05:07:26 +00:00
} else {
2019-11-22 13:41:58 +00:00
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message " Unexpected value of -msbuildEngine: ' $msbuildEngine '. "
2018-10-22 05:07:26 +00:00
ExitWithExitCode 1
}
2018-12-19 20:55:42 +00:00
return $global:_BuildTool = $buildTool
}
function GetDefaultMSBuildEngine ( ) {
# Presence of tools.vs indicates the repo needs to build using VS msbuild on Windows.
2019-11-22 13:41:58 +00:00
if ( Get-Member -InputObject $GlobalJson . tools -Name 'vs' ) {
return 'vs'
2018-12-19 20:55:42 +00:00
}
2019-06-08 12:08:27 +00:00
2019-11-22 13:41:58 +00:00
if ( Get-Member -InputObject $GlobalJson . tools -Name 'dotnet' ) {
return 'dotnet'
2018-12-19 20:55:42 +00:00
}
2019-11-22 13:41:58 +00:00
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message " -msbuildEngine must be specified, or /global.json must specify 'tools.dotnet' or 'tools.vs'. "
2018-12-19 20:55:42 +00:00
ExitWithExitCode 1
}
function GetNuGetPackageCachePath ( ) {
if ( $env:NUGET_PACKAGES -eq $null ) {
2021-06-12 12:58:31 +00:00
# Use local cache on CI to ensure deterministic build.
[master] Update dependencies from dotnet/arcade (#8726)
* Update dependencies from https://github.com/dotnet/arcade build 20200924.4
Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Arcade.Sdk
From Version 5.0.0-beta.20471.1 -> To Version 5.0.0-beta.20474.4
Dependency coherency updates
Microsoft.WindowsDesktop.App.Ref,Microsoft.WindowsDesktop.App,Microsoft.AspNetCore.App.Ref,Microsoft.AspNetCore.App.Ref.Internal,Microsoft.AspNetCore.App.Runtime.win-x64,VS.Redist.Common.AspNetCore.TargetingPack.x64.5.0,dotnet-dev-certs,dotnet-user-secrets,dotnet-watch,Microsoft.Dotnet.WinForms.ProjectTemplates,Microsoft.WindowsDesktop.App.Runtime.win-x64,Microsoft.DotNet.Wpf.ProjectTemplates,Microsoft.FSharp.Compiler,Microsoft.NET.Test.Sdk,Microsoft.NET.ILLink.Tasks,Microsoft.Net.Compilers.Toolset,Microsoft.Build,NuGet.Build.Tasks
From Version 5.0.0-rc.2.20474.5 -> To Version 5.0.0-rc.1.20417.4 (parent: Microsoft.NET.Sdk
* Update dependencies from https://github.com/dotnet/arcade build 20200928.3
Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Arcade.Sdk
From Version 5.0.0-beta.20471.1 -> To Version 5.0.0-beta.20478.3
Dependency coherency updates
Microsoft.WindowsDesktop.App.Ref,Microsoft.WindowsDesktop.App,Microsoft.AspNetCore.App.Ref,Microsoft.AspNetCore.App.Ref.Internal,Microsoft.AspNetCore.App.Runtime.win-x64,VS.Redist.Common.AspNetCore.TargetingPack.x64.5.0,dotnet-dev-certs,dotnet-user-secrets,dotnet-watch,Microsoft.Dotnet.WinForms.ProjectTemplates,Microsoft.WindowsDesktop.App.Runtime.win-x64,Microsoft.DotNet.Wpf.ProjectTemplates,Microsoft.FSharp.Compiler,Microsoft.NET.Test.Sdk,Microsoft.NET.ILLink.Tasks,Microsoft.Net.Compilers.Toolset,Microsoft.Build,NuGet.Build.Tasks
From Version 5.0.0-rc.2.20474.5 -> To Version 5.0.0-rc.1.20417.4 (parent: Microsoft.NET.Sdk
* Update dependencies from https://github.com/dotnet/arcade build 20201006.7
Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Arcade.Sdk
From Version 5.0.0-beta.20471.1 -> To Version 5.0.0-beta.20506.7
Dependency coherency updates
Microsoft.WindowsDesktop.App.Ref,Microsoft.WindowsDesktop.App,Microsoft.AspNetCore.App.Ref,Microsoft.AspNetCore.App.Ref.Internal,Microsoft.AspNetCore.App.Runtime.win-x64,VS.Redist.Common.AspNetCore.TargetingPack.x64.5.0,dotnet-dev-certs,dotnet-user-secrets,dotnet-watch,Microsoft.Dotnet.WinForms.ProjectTemplates,Microsoft.WindowsDesktop.App.Runtime.win-x64,Microsoft.DotNet.Wpf.ProjectTemplates,Microsoft.FSharp.Compiler,Microsoft.NET.Test.Sdk,Microsoft.NET.ILLink.Tasks,Microsoft.Net.Compilers.Toolset,Microsoft.Build,NuGet.Build.Tasks,Microsoft.SourceLink.GitHub,XliffTasks
From Version 5.0.0-rc.2.20474.5 -> To Version 5.0.0-rc.1.20417.4 (parent: Microsoft.NET.Sdk
* Update dependencies from https://github.com/dotnet/arcade build 20201009.12
Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Arcade.Sdk
From Version 5.0.0-beta.20471.1 -> To Version 6.0.0-beta.20509.12
Dependency coherency updates
Microsoft.WindowsDesktop.App.Ref,Microsoft.WindowsDesktop.App,Microsoft.AspNetCore.App.Ref,Microsoft.AspNetCore.App.Ref.Internal,Microsoft.AspNetCore.App.Runtime.win-x64,VS.Redist.Common.AspNetCore.TargetingPack.x64.5.0,dotnet-dev-certs,dotnet-user-secrets,dotnet-watch,Microsoft.Dotnet.WinForms.ProjectTemplates,Microsoft.WindowsDesktop.App.Runtime.win-x64,Microsoft.DotNet.Wpf.ProjectTemplates,Microsoft.FSharp.Compiler,Microsoft.NET.Test.Sdk,Microsoft.NET.ILLink.Tasks,Microsoft.Net.Compilers.Toolset,Microsoft.Build,NuGet.Build.Tasks,Microsoft.SourceLink.GitHub,XliffTasks
From Version 5.0.0-rc.2.20474.5 -> To Version 5.0.0-rc.1.20417.4 (parent: Microsoft.NET.Sdk
* Update dependencies from https://github.com/dotnet/arcade build 20201020.8
Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Arcade.Sdk
From Version 5.0.0-beta.20471.1 -> To Version 6.0.0-beta.20520.8
Dependency coherency updates
Microsoft.SourceLink.GitHub,XliffTasks
From Version 1.1.0-beta-20464-02 -> To Version 1.1.0-beta-20519-02 (parent: Microsoft.DotNet.Arcade.Sdk
* Update FileInfoAssertions.cs
* Update FileInfoAssertions.cs
* Use tasks provided by Microsoft.DotNet.Build.Tasks.Installers when provided.
Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: Viktor Hofer <viktor.hofer@microsoft.com>
Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
2020-10-23 07:44:02 +00:00
# Avoid using the http cache as workaround for https://github.com/NuGet/Home/issues/3116
2018-12-19 20:55:42 +00:00
# use global cache in dev builds to avoid cost of downloading packages.
2020-04-24 17:34:25 +00:00
# For directory normalization, see also: https://github.com/NuGet/Home/issues/7968
2018-12-19 20:55:42 +00:00
if ( $useGlobalNuGetCache ) {
2020-04-24 17:34:25 +00:00
$env:NUGET_PACKAGES = Join-Path $env:UserProfile '.nuget\packages\'
2018-12-19 20:55:42 +00:00
} else {
2020-04-24 17:34:25 +00:00
$env:NUGET_PACKAGES = Join-Path $RepoRoot '.packages\'
[master] Update dependencies from dotnet/arcade (#8726)
* Update dependencies from https://github.com/dotnet/arcade build 20200924.4
Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Arcade.Sdk
From Version 5.0.0-beta.20471.1 -> To Version 5.0.0-beta.20474.4
Dependency coherency updates
Microsoft.WindowsDesktop.App.Ref,Microsoft.WindowsDesktop.App,Microsoft.AspNetCore.App.Ref,Microsoft.AspNetCore.App.Ref.Internal,Microsoft.AspNetCore.App.Runtime.win-x64,VS.Redist.Common.AspNetCore.TargetingPack.x64.5.0,dotnet-dev-certs,dotnet-user-secrets,dotnet-watch,Microsoft.Dotnet.WinForms.ProjectTemplates,Microsoft.WindowsDesktop.App.Runtime.win-x64,Microsoft.DotNet.Wpf.ProjectTemplates,Microsoft.FSharp.Compiler,Microsoft.NET.Test.Sdk,Microsoft.NET.ILLink.Tasks,Microsoft.Net.Compilers.Toolset,Microsoft.Build,NuGet.Build.Tasks
From Version 5.0.0-rc.2.20474.5 -> To Version 5.0.0-rc.1.20417.4 (parent: Microsoft.NET.Sdk
* Update dependencies from https://github.com/dotnet/arcade build 20200928.3
Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Arcade.Sdk
From Version 5.0.0-beta.20471.1 -> To Version 5.0.0-beta.20478.3
Dependency coherency updates
Microsoft.WindowsDesktop.App.Ref,Microsoft.WindowsDesktop.App,Microsoft.AspNetCore.App.Ref,Microsoft.AspNetCore.App.Ref.Internal,Microsoft.AspNetCore.App.Runtime.win-x64,VS.Redist.Common.AspNetCore.TargetingPack.x64.5.0,dotnet-dev-certs,dotnet-user-secrets,dotnet-watch,Microsoft.Dotnet.WinForms.ProjectTemplates,Microsoft.WindowsDesktop.App.Runtime.win-x64,Microsoft.DotNet.Wpf.ProjectTemplates,Microsoft.FSharp.Compiler,Microsoft.NET.Test.Sdk,Microsoft.NET.ILLink.Tasks,Microsoft.Net.Compilers.Toolset,Microsoft.Build,NuGet.Build.Tasks
From Version 5.0.0-rc.2.20474.5 -> To Version 5.0.0-rc.1.20417.4 (parent: Microsoft.NET.Sdk
* Update dependencies from https://github.com/dotnet/arcade build 20201006.7
Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Arcade.Sdk
From Version 5.0.0-beta.20471.1 -> To Version 5.0.0-beta.20506.7
Dependency coherency updates
Microsoft.WindowsDesktop.App.Ref,Microsoft.WindowsDesktop.App,Microsoft.AspNetCore.App.Ref,Microsoft.AspNetCore.App.Ref.Internal,Microsoft.AspNetCore.App.Runtime.win-x64,VS.Redist.Common.AspNetCore.TargetingPack.x64.5.0,dotnet-dev-certs,dotnet-user-secrets,dotnet-watch,Microsoft.Dotnet.WinForms.ProjectTemplates,Microsoft.WindowsDesktop.App.Runtime.win-x64,Microsoft.DotNet.Wpf.ProjectTemplates,Microsoft.FSharp.Compiler,Microsoft.NET.Test.Sdk,Microsoft.NET.ILLink.Tasks,Microsoft.Net.Compilers.Toolset,Microsoft.Build,NuGet.Build.Tasks,Microsoft.SourceLink.GitHub,XliffTasks
From Version 5.0.0-rc.2.20474.5 -> To Version 5.0.0-rc.1.20417.4 (parent: Microsoft.NET.Sdk
* Update dependencies from https://github.com/dotnet/arcade build 20201009.12
Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Arcade.Sdk
From Version 5.0.0-beta.20471.1 -> To Version 6.0.0-beta.20509.12
Dependency coherency updates
Microsoft.WindowsDesktop.App.Ref,Microsoft.WindowsDesktop.App,Microsoft.AspNetCore.App.Ref,Microsoft.AspNetCore.App.Ref.Internal,Microsoft.AspNetCore.App.Runtime.win-x64,VS.Redist.Common.AspNetCore.TargetingPack.x64.5.0,dotnet-dev-certs,dotnet-user-secrets,dotnet-watch,Microsoft.Dotnet.WinForms.ProjectTemplates,Microsoft.WindowsDesktop.App.Runtime.win-x64,Microsoft.DotNet.Wpf.ProjectTemplates,Microsoft.FSharp.Compiler,Microsoft.NET.Test.Sdk,Microsoft.NET.ILLink.Tasks,Microsoft.Net.Compilers.Toolset,Microsoft.Build,NuGet.Build.Tasks,Microsoft.SourceLink.GitHub,XliffTasks
From Version 5.0.0-rc.2.20474.5 -> To Version 5.0.0-rc.1.20417.4 (parent: Microsoft.NET.Sdk
* Update dependencies from https://github.com/dotnet/arcade build 20201020.8
Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Arcade.Sdk
From Version 5.0.0-beta.20471.1 -> To Version 6.0.0-beta.20520.8
Dependency coherency updates
Microsoft.SourceLink.GitHub,XliffTasks
From Version 1.1.0-beta-20464-02 -> To Version 1.1.0-beta-20519-02 (parent: Microsoft.DotNet.Arcade.Sdk
* Update FileInfoAssertions.cs
* Update FileInfoAssertions.cs
* Use tasks provided by Microsoft.DotNet.Build.Tasks.Installers when provided.
Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: Viktor Hofer <viktor.hofer@microsoft.com>
Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
2020-10-23 07:44:02 +00:00
$env:RESTORENOCACHE = $true
2018-12-19 20:55:42 +00:00
}
}
return $env:NUGET_PACKAGES
2018-10-22 05:07:26 +00:00
}
2019-02-05 13:42:55 +00:00
# Returns a full path to an Arcade SDK task project file.
function GetSdkTaskProject([string]$taskName ) {
return Join-Path ( Split-Path ( InitializeToolset ) -Parent ) " SdkTasks\ $taskName .proj "
}
2019-05-02 12:26:55 +00:00
function InitializeNativeTools ( ) {
2019-11-02 12:56:53 +00:00
if ( -Not ( Test-Path variable : DisableNativeToolsetInstalls ) -And ( Get-Member -InputObject $GlobalJson -Name " native-tools " ) ) {
2019-06-08 12:08:27 +00:00
$nativeArgs = @ { }
2019-05-02 12:26:55 +00:00
if ( $ci ) {
2019-06-08 12:08:27 +00:00
$nativeArgs = @ {
InstallDirectory = " $ToolsDir "
}
2019-05-02 12:26:55 +00:00
}
2022-07-05 12:38:53 +00:00
if ( $env:NativeToolsOnMachine ) {
2022-05-26 12:37:11 +00:00
Write-Host " Variable NativeToolsOnMachine detected, enabling native tool path promotion... "
$nativeArgs + = @ { PathPromotion = $true }
}
2019-06-08 12:08:27 +00:00
& " $PSScriptRoot /init-tools-native.ps1 " @nativeArgs
2019-05-02 12:26:55 +00:00
}
}
2023-08-15 16:26:32 +00:00
function Read-ArcadeSdkVersion ( ) {
return $GlobalJson . 'msbuild-sdks' . 'Microsoft.DotNet.Arcade.Sdk'
}
2018-12-19 20:55:42 +00:00
function InitializeToolset ( ) {
if ( Test-Path variable : global: _ToolsetBuildProj ) {
return $global:_ToolsetBuildProj
}
$nugetCache = GetNuGetPackageCachePath
2023-08-15 16:26:32 +00:00
$toolsetVersion = Read-ArcadeSdkVersion
2018-10-22 05:07:26 +00:00
$toolsetLocationFile = Join-Path $ToolsetDir " $toolsetVersion .txt "
if ( Test-Path $toolsetLocationFile ) {
$path = Get-Content $toolsetLocationFile -TotalCount 1
if ( Test-Path $path ) {
2018-12-19 20:55:42 +00:00
return $global:_ToolsetBuildProj = $path
2018-10-22 05:07:26 +00:00
}
}
if ( -not $restore ) {
2019-11-22 13:41:58 +00:00
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message " Toolset version $toolsetVersion has not been restored. "
2018-10-22 05:07:26 +00:00
ExitWithExitCode 1
}
2018-12-19 20:55:42 +00:00
$buildTool = InitializeBuildTool
2018-10-22 05:07:26 +00:00
2019-11-22 13:41:58 +00:00
$proj = Join-Path $ToolsetDir 'restore.proj'
$bl = if ( $binaryLog ) { '/bl:' + ( Join-Path $LogDir 'ToolsetRestore.binlog' ) } else { '' }
2019-02-15 13:37:10 +00:00
2018-10-22 05:07:26 +00:00
'<Project Sdk="Microsoft.DotNet.Arcade.Sdk"/>' | Set-Content $proj
2019-05-07 12:30:40 +00:00
2019-05-09 12:24:48 +00:00
MSBuild-Core $proj $bl / t: __WriteToolsetLocation / clp : ErrorsOnly ` ; NoSummary / p: __ToolsetLocationOutputFile = $toolsetLocationFile
2019-02-15 13:37:10 +00:00
2020-04-30 12:44:30 +00:00
$path = Get-Content $toolsetLocationFile -Encoding UTF8 -TotalCount 1
2018-10-22 05:07:26 +00:00
if ( ! ( Test-Path $path ) ) {
throw " Invalid toolset path: $path "
}
2019-02-15 13:37:10 +00:00
2018-12-19 20:55:42 +00:00
return $global:_ToolsetBuildProj = $path
2018-10-22 05:07:26 +00:00
}
function ExitWithExitCode([int ] $exitCode ) {
if ( $ci -and $prepareMachine ) {
Stop-Processes
}
exit $exitCode
}
2021-07-15 14:32:48 +00:00
# Check if $LASTEXITCODE is a nonzero exit code (NZEC). If so, print a Azure Pipeline error for
# diagnostics, then exit the script with the $LASTEXITCODE.
function Exit-IfNZEC([string ] $category = " General " ) {
Write-Host " Exit code $LASTEXITCODE "
if ( $LASTEXITCODE -ne 0 ) {
$message = " Last command failed with exit code $LASTEXITCODE . "
Write-PipelineTelemetryError -Force -Category $category -Message $message
ExitWithExitCode $LASTEXITCODE
}
}
2018-10-22 05:07:26 +00:00
function Stop-Processes ( ) {
2019-11-22 13:41:58 +00:00
Write-Host 'Killing running build processes...'
2018-12-19 20:55:42 +00:00
foreach ( $processName in $processesToStopOnExit ) {
Get-Process -Name $processName -ErrorAction SilentlyContinue | Stop-Process
}
}
#
# Executes msbuild (or 'dotnet msbuild') with arguments passed to the function.
# The arguments are automatically quoted.
# Terminates the script if the build fails.
#
function MSBuild ( ) {
2019-05-10 12:25:59 +00:00
if ( $pipelinesLog ) {
$buildTool = InitializeBuildTool
2019-09-13 12:37:37 +00:00
2019-11-22 13:41:58 +00:00
if ( $ci -and $buildTool . Tool -eq 'dotnet' ) {
2019-10-24 22:05:36 +00:00
$env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS = 20
$env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS = 20
Write-PipelineSetVariable -Name 'NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS' -Value '20'
Write-PipelineSetVariable -Name 'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value '20'
2019-09-13 12:37:37 +00:00
}
2021-09-21 13:13:52 +00:00
Enable-Nuget -EnhancedRetry
2021-09-07 19:27:33 +00:00
2019-05-09 12:24:48 +00:00
$toolsetBuildProject = InitializeToolset
2021-02-10 23:17:22 +00:00
$basePath = Split-Path -parent $toolsetBuildProject
$possiblePaths = @ (
# new scripts need to work with old packages, so we need to look for the old names/versions
( Join-Path $basePath ( Join-Path $buildTool . Framework 'Microsoft.DotNet.ArcadeLogging.dll' ) ) ,
( Join-Path $basePath ( Join-Path $buildTool . Framework 'Microsoft.DotNet.Arcade.Sdk.dll' ) ) ,
( Join-Path $basePath ( Join-Path netcoreapp2 . 1 'Microsoft.DotNet.ArcadeLogging.dll' ) ) ,
( Join-Path $basePath ( Join-Path netcoreapp2 . 1 'Microsoft.DotNet.Arcade.Sdk.dll' ) )
2021-09-07 19:27:33 +00:00
( Join-Path $basePath ( Join-Path netcoreapp3 . 1 'Microsoft.DotNet.ArcadeLogging.dll' ) ) ,
( Join-Path $basePath ( Join-Path netcoreapp3 . 1 'Microsoft.DotNet.Arcade.Sdk.dll' ) )
2023-01-18 10:18:03 +00:00
( Join-Path $basePath ( Join-Path net7 . 0 'Microsoft.DotNet.ArcadeLogging.dll' ) ) ,
( Join-Path $basePath ( Join-Path net7 . 0 'Microsoft.DotNet.Arcade.Sdk.dll' ) )
2021-02-10 23:17:22 +00:00
)
$selectedPath = $null
foreach ( $path in $possiblePaths ) {
if ( Test-Path $path -PathType Leaf ) {
$selectedPath = $path
break
}
}
if ( -not $selectedPath ) {
Write-PipelineTelemetryError -Category 'Build' -Message 'Unable to find arcade sdk logger assembly.'
ExitWithExitCode 1
2021-01-09 13:53:15 +00:00
}
2021-02-10 23:17:22 +00:00
$args + = " /logger: $selectedPath "
2019-05-09 12:24:48 +00:00
}
MSBuild-Core @args
}
#
# Executes msbuild (or 'dotnet msbuild') with arguments passed to the function.
# The arguments are automatically quoted.
# Terminates the script if the build fails.
#
function MSBuild-Core ( ) {
2018-12-19 20:55:42 +00:00
if ( $ci ) {
2020-05-12 12:48:04 +00:00
if ( ! $binaryLog -and ! $excludeCIBinarylog ) {
Write-PipelineTelemetryError -Category 'Build' -Message 'Binary log must be enabled in CI build, or explicitly opted-out from with the -excludeCIBinarylog switch.'
2019-06-14 12:10:56 +00:00
ExitWithExitCode 1
2018-12-19 20:55:42 +00:00
}
if ( $nodeReuse ) {
2019-11-22 13:41:58 +00:00
Write-PipelineTelemetryError -Category 'Build' -Message 'Node reuse must be disabled in CI build.'
2019-06-14 12:10:56 +00:00
ExitWithExitCode 1
2018-12-19 20:55:42 +00:00
}
}
2021-09-21 13:13:52 +00:00
Enable-Nuget -EnhancedRetry
2018-12-19 20:55:42 +00:00
$buildTool = InitializeBuildTool
2019-02-23 13:42:18 +00:00
$cmdArgs = " $( $buildTool . Command ) /m /nologo /clp:Summary /v: $verbosity /nr: $nodeReuse /p:ContinuousIntegrationBuild= $ci "
2018-12-19 20:55:42 +00:00
2019-06-08 12:08:27 +00:00
if ( $warnAsError ) {
2019-11-22 13:41:58 +00:00
$cmdArgs + = ' /warnaserror /p:TreatWarningsAsErrors=true'
2018-12-19 20:55:42 +00:00
}
2019-08-02 12:38:38 +00:00
else {
2019-11-22 13:41:58 +00:00
$cmdArgs + = ' /p:TreatWarningsAsErrors=false'
2019-08-02 12:38:38 +00:00
}
2018-12-19 20:55:42 +00:00
foreach ( $arg in $args ) {
2021-06-12 12:58:31 +00:00
if ( $null -ne $arg -and $arg . Trim ( ) -ne " " ) {
if ( $arg . EndsWith ( '\' ) ) {
$arg = $arg + " \ "
}
2018-12-19 20:55:42 +00:00
$cmdArgs + = " `" $arg `" "
}
}
2019-06-08 12:08:27 +00:00
2020-04-24 17:34:25 +00:00
$env:ARCADE_BUILD_TOOL_COMMAND = " $( $buildTool . Path ) $cmdArgs "
2018-12-19 20:55:42 +00:00
$exitCode = Exec-Process $buildTool . Path $cmdArgs
if ( $exitCode -ne 0 ) {
2020-12-09 03:11:38 +00:00
# We should not Write-PipelineTaskError here because that message shows up in the build summary
# The build already logged an error, that's the reason it failed. Producing an error here only adds noise.
Write-Host " Build failed with exit code $exitCode . Check errors above. " -ForegroundColor Red
2018-12-19 20:55:42 +00:00
$buildLog = GetMSBuildBinaryLogCommandLineArgument $args
2020-12-09 03:11:38 +00:00
if ( $null -ne $buildLog ) {
2019-06-08 12:08:27 +00:00
Write-Host " See log: $buildLog " -ForegroundColor DarkGray
2018-12-19 20:55:42 +00:00
}
2023-01-04 23:26:05 +00:00
# When running on Azure Pipelines, override the returned exit code to avoid double logging.
if ( $ci -and $env:SYSTEM_TEAMPROJECT -ne $null ) {
2020-12-09 03:11:38 +00:00
Write-PipelineSetResult -Result " Failed " -Message " msbuild execution failed. "
# Exiting with an exit code causes the azure pipelines task to log yet another "noise" error
# The above Write-PipelineSetResult will cause the task to be marked as failure without adding yet another error
ExitWithExitCode 0
} else {
ExitWithExitCode $exitCode
}
2018-12-19 20:55:42 +00:00
}
2018-10-22 05:07:26 +00:00
}
2019-06-08 12:08:27 +00:00
function GetMSBuildBinaryLogCommandLineArgument($arguments ) {
2018-12-19 20:55:42 +00:00
foreach ( $argument in $arguments ) {
if ( $argument -ne $null ) {
$arg = $argument . Trim ( )
2019-11-22 13:41:58 +00:00
if ( $arg . StartsWith ( '/bl:' , " OrdinalIgnoreCase " ) ) {
return $arg . Substring ( '/bl:' . Length )
2019-06-08 12:08:27 +00:00
}
2019-11-22 13:41:58 +00:00
if ( $arg . StartsWith ( '/binaryLogger:' , 'OrdinalIgnoreCase' ) ) {
return $arg . Substring ( '/binaryLogger:' . Length )
2018-12-19 20:55:42 +00:00
}
}
}
return $null
2018-10-22 05:07:26 +00:00
}
2020-05-30 12:44:29 +00:00
function GetExecutableFileName($baseName ) {
if ( IsWindowsPlatform ) {
return " $baseName .exe "
}
else {
return $baseName
}
}
function IsWindowsPlatform ( ) {
return [ environment ] :: OSVersion . Platform -eq [ PlatformID ] :: Win32NT
}
2020-09-05 12:49:59 +00:00
function Get-Darc($version ) {
$darcPath = " $TempDir \darc\ $( New-Guid ) "
if ( $version -ne $null ) {
& $PSScriptRoot \ darc-init . ps1 -toolpath $darcPath -darcVersion $version | Out-Host
} else {
& $PSScriptRoot \ darc-init . ps1 -toolpath $darcPath | Out-Host
}
return " $darcPath \darc.exe "
}
2019-06-14 12:10:56 +00:00
. $PSScriptRoot \ pipeline-logging -functions . ps1
2019-05-31 12:10:52 +00:00
2021-06-12 12:58:31 +00:00
$RepoRoot = Resolve-Path ( Join-Path $PSScriptRoot '..\..\' )
2019-11-22 13:41:58 +00:00
$EngRoot = Resolve-Path ( Join-Path $PSScriptRoot '..' )
$ArtifactsDir = Join-Path $RepoRoot 'artifacts'
$ToolsetDir = Join-Path $ArtifactsDir 'toolset'
$ToolsDir = Join-Path $RepoRoot '.tools'
$LogDir = Join-Path ( Join-Path $ArtifactsDir 'log' ) $configuration
$TempDir = Join-Path ( Join-Path $ArtifactsDir 'tmp' ) $configuration
$GlobalJson = Get-Content -Raw -Path ( Join-Path $RepoRoot 'global.json' ) | ConvertFrom-Json
2019-05-07 12:30:40 +00:00
# true if global.json contains a "runtimes" section
$globalJsonHasRuntimes = if ( $GlobalJson . tools . PSObject . Properties . Name -Match 'runtimes' ) { $true } else { $false }
2018-10-22 05:07:26 +00:00
Create-Directory $ToolsetDir
2018-12-19 20:55:42 +00:00
Create-Directory $TempDir
2018-10-22 05:07:26 +00:00
Create-Directory $LogDir
2019-05-31 12:10:52 +00:00
Write-PipelineSetVariable -Name 'Artifacts' -Value $ArtifactsDir
Write-PipelineSetVariable -Name 'Artifacts.Toolset' -Value $ToolsetDir
Write-PipelineSetVariable -Name 'Artifacts.Log' -Value $LogDir
Write-PipelineSetVariable -Name 'TEMP' -Value $TempDir
Write-PipelineSetVariable -Name 'TMP' -Value $TempDir
2019-10-24 22:05:36 +00:00
# Import custom tools configuration, if present in the repo.
# Note: Import in global scope so that the script set top-level variables without qualification.
if ( ! $disableConfigureToolsetImport ) {
2019-11-22 13:41:58 +00:00
$configureToolsetScript = Join-Path $EngRoot 'configure-toolset.ps1'
2019-10-24 22:05:36 +00:00
if ( Test-Path $configureToolsetScript ) {
2019-11-22 13:41:58 +00:00
. $configureToolsetScript
if ( ( Test-Path variable : failOnConfigureToolsetError ) -And $failOnConfigureToolsetError ) {
if ( ( Test-Path variable : LastExitCode ) -And ( $LastExitCode -ne 0 ) ) {
Write-PipelineTelemetryError -Category 'Build' -Message 'configure-toolset.ps1 returned a non-zero exit code'
ExitWithExitCode $LastExitCode
}
}
2019-10-24 22:05:36 +00:00
}
}
2021-08-19 13:02:51 +00:00
2021-09-21 13:13:52 +00:00
#
# If $ci flag is set, turn on (and log that we did) special environment variables for improved Nuget client retry logic.
#
function Enable-Nuget-EnhancedRetry ( ) {
if ( $ci ) {
Write-Host " Setting NUGET enhanced retry environment variables "
2023-03-17 12:22:11 +00:00
$env:NUGET_ENABLE_ENHANCED_HTTP_RETRY = 'true'
$env:NUGET_ENHANCED_MAX_NETWORK_TRY_COUNT = 6
$env:NUGET_ENHANCED_NETWORK_RETRY_DELAY_MILLISECONDS = 1000
$env:NUGET_RETRY_HTTP_429 = 'true'
Write-PipelineSetVariable -Name 'NUGET_ENABLE_ENHANCED_HTTP_RETRY' -Value 'true'
Write-PipelineSetVariable -Name 'NUGET_ENHANCED_MAX_NETWORK_TRY_COUNT' -Value '6'
Write-PipelineSetVariable -Name 'NUGET_ENHANCED_NETWORK_RETRY_DELAY_MILLISECONDS' -Value '1000'
Write-PipelineSetVariable -Name 'NUGET_RETRY_HTTP_429' -Value 'true'
2021-09-21 13:13:52 +00:00
}
}