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.
[ string ] $configuration = if ( Test-Path variable : configuration ) { $configuration } else { " Debug " }
# Set to true to output binary log from msbuild. Note that emitting binary log slows down the build.
# Binary log must be enabled on CI.
[ bool ] $binaryLog = if ( Test-Path variable : binaryLog ) { $binaryLog } else { $ci }
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.
[ string ] $verbosity = if ( Test-Path variable : verbosity ) { $verbosity } else { " minimal " }
# 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 }
# True to use global NuGet cache instead of restoring packages to repository-local directory.
[ bool ] $useGlobalNuGetCache = if ( Test-Path variable : useGlobalNuGetCache ) { $useGlobalNuGetCache } else { ! $ci }
# An array of names of processes to stop on script exit if prepareMachine is true.
$processesToStopOnExit = if ( Test-Path variable : processesToStopOnExit ) { $processesToStopOnExit } else { @ ( " msbuild " , " dotnet " , " vbcscompiler " ) }
2018-10-22 05:07:26 +00:00
set-strictmode -version 2.0
$ErrorActionPreference = " Stop "
[ Net.ServicePointManager ] :: SecurityProtocol = [ Net.SecurityProtocolType ] :: Tls12
function Create-Directory([string [ ] ] $path ) {
if ( ! ( Test-Path $path ) ) {
New-Item -path $path -force -itemType " Directory " | Out-Null
}
}
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 ( )
}
}
}
2018-10-22 05:07:26 +00:00
function InitializeDotNetCli([bool]$install ) {
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
# 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 ) ) {
2018-12-19 20:55:42 +00:00
$dotnetCmd = Get-Command " dotnet.exe " -ErrorAction SilentlyContinue
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.
2019-05-07 12:30:40 +00:00
if ( ( -not $globalJsonHasRuntimes ) -and ( $env:DOTNET_INSTALL_DIR -ne $null ) -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 {
$dotnetRoot = Join-Path $RepoRoot " .dotnet "
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-06-14 12:10:56 +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
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
Write-PipelineSetVariable -Name 'DOTNET_MULTILEVEL_LOOKUP' -Value '0'
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
}
function GetDotNetInstallScript([string ] $dotnetRoot ) {
2019-05-07 12:30:40 +00:00
$installScript = Join-Path $dotnetRoot " dotnet-install.ps1 "
2018-10-22 05:07:26 +00:00
if ( ! ( Test-Path $installScript ) ) {
Create-Directory $dotnetRoot
Invoke-WebRequest " https://dot.net/v1/dotnet-install.ps1 " -OutFile $installScript
}
return $installScript
}
2019-02-06 13:45:20 +00:00
function InstallDotNetSdk([string ] $dotnetRoot , [ string ] $version , [ string ] $architecture = " " ) {
2019-05-07 12:30:40 +00:00
InstallDotNet $dotnetRoot $version $architecture
}
2019-07-19 12:39:46 +00:00
function InstallDotNet([string ] $dotnetRoot , [ string ] $version , [ string ] $architecture = " " , [ string ] $runtime = " " , [ bool ] $skipNonVersionedFiles = $false ) {
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 }
& $installScript @installParameters
2018-10-22 05:07:26 +00:00
if ( $lastExitCode -ne 0 ) {
2019-06-14 12:10:56 +00:00
Write-PipelineTelemetryError -Category " InitializeToolset " -Message " Failed to install dotnet cli (exit code ' $lastExitCode '). "
2018-10-22 05:07:26 +00:00
ExitWithExitCode $lastExitCode
}
}
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 ) {
if ( Test-Path variable : global: _MSBuildExe ) {
return $global:_MSBuildExe
}
if ( ! $vsRequirements ) { $vsRequirements = $GlobalJson . tools . vs }
$vsMinVersionStr = if ( $vsRequirements . version ) { $vsRequirements . version } else { " 15.9 " }
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 ) {
$msbuildCmd = Get-Command " msbuild.exe " -ErrorAction SilentlyContinue
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+
$msbuildVersion = [ Version ] :: new ( ( Get-Item $msbuildCmd . Path ) . VersionInfo . ProductVersion . Split ( @ ( '-' , '+' ) ) [ 0 ] )
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 ) {
$vsInstallDir = $vsInfo . installationPath
$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
2018-12-04 17:31:23 +00:00
if ( Get-Member -InputObject $GlobalJson . tools -Name " xcopy-msbuild " ) {
$xcopyMSBuildVersion = $GlobalJson . tools . 'xcopy-msbuild'
$vsMajorVersion = $xcopyMSBuildVersion . Split ( '.' ) [ 0 ]
} else {
$vsMajorVersion = $vsMinVersion . Major
$xcopyMSBuildVersion = " $vsMajorVersion . $( $vsMinVersion . Minor ) .0-alpha "
}
2019-02-13 19:39:26 +00:00
$vsInstallDir = InitializeXCopyMSBuild $xcopyMSBuildVersion $install
if ( $vsInstallDir -eq $null ) {
throw " Unable to find Visual Studio that has required version and components installed "
}
2018-12-04 17:31:23 +00:00
}
$msbuildVersionDir = if ( [ int ] $vsMajorVersion -lt 16 ) { " $vsMajorVersion .0 " } else { " Current " }
2018-12-19 20:55:42 +00:00
return $global:_MSBuildExe = Join-Path $vsInstallDir " MSBuild\ $msbuildVersionDir \Bin\msbuild.exe "
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 ) {
2018-12-04 17:31:23 +00:00
$packageName = " RoslynTools.MSBuild "
$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
Write-Host " Downloading $packageName $packageVersion "
Invoke-WebRequest " https://dotnet.myget.org/F/roslyn-tools/api/v2/package/ $packageName / $packageVersion / " -OutFile $packagePath
Unzip $packagePath $packageDir
}
2018-10-22 05:07:26 +00:00
2018-12-04 17:31:23 +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 ) {
if ( Get-Member -InputObject $GlobalJson . tools -Name " vswhere " ) {
$vswhereVersion = $GlobalJson . tools . vswhere
} else {
2018-12-04 17:31:23 +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 "
2018-10-22 05:07:26 +00:00
$vsWhereExe = Join-Path $vsWhereDir " vswhere.exe "
if ( ! ( Test-Path $vsWhereExe ) ) {
Create-Directory $vsWhereDir
Write-Host " Downloading vswhere "
Invoke-WebRequest " https://github.com/Microsoft/vswhere/releases/download/ $vswhereVersion /vswhere.exe " -OutFile $vswhereExe
}
2018-12-19 20:55:42 +00:00
if ( ! $vsRequirements ) { $vsRequirements = $GlobalJson . tools . vs }
2019-06-13 12:10:50 +00:00
$args = @ ( " -latest " , " -prerelease " , " -format " , " json " , " -requires " , " Microsoft.Component.MSBuild " , " -products " , " * " )
2019-06-08 12:08:27 +00:00
2018-12-19 20:55:42 +00:00
if ( Get-Member -InputObject $vsRequirements -Name " version " ) {
2018-12-04 17:31:23 +00:00
$args + = " -version "
2018-12-19 20:55:42 +00:00
$args + = $vsRequirements . version
2018-12-04 17:31:23 +00:00
}
2018-12-19 20:55:42 +00:00
if ( Get-Member -InputObject $vsRequirements -Name " components " ) {
foreach ( $component in $vsRequirements . components ) {
2018-12-04 17:31:23 +00:00
$args + = " -requires "
$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 ) {
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
2018-12-19 20:55:42 +00:00
if ( Get-Member -InputObject $GlobalJson . tools -Name " dotnet " ) {
2018-10-22 05:07:26 +00:00
$dotnetRoot = InitializeDotNetCli -install: $restore
}
if ( $msbuildEngine -eq " dotnet " ) {
if ( ! $dotnetRoot ) {
2019-06-14 12:10:56 +00:00
Write-PipelineTelemetryError -Category " InitializeToolset " -Message " /global.json must specify 'tools.dotnet'. "
2018-10-22 05:07:26 +00:00
ExitWithExitCode 1
}
2019-05-10 12:25:59 +00:00
$buildTool = @ { Path = Join-Path $dotnetRoot " dotnet.exe " ; Command = " msbuild " ; Tool = " dotnet " ; Framework = " netcoreapp2.1 " }
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-06-14 12:10:56 +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
2019-05-10 12:25:59 +00:00
$buildTool = @ { Path = $msbuildPath ; Command = " " ; Tool = " vs " ; Framework = " net472 " }
2018-10-22 05:07:26 +00:00
} else {
2019-06-14 12:10:56 +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.
if ( Get-Member -InputObject $GlobalJson . tools -Name " vs " ) {
return " vs "
}
2019-06-08 12:08:27 +00:00
2018-12-19 20:55:42 +00:00
if ( Get-Member -InputObject $GlobalJson . tools -Name " dotnet " ) {
return " dotnet "
}
2019-06-14 12:10:56 +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 ) {
# Use local cache on CI to ensure deterministic build,
# use global cache in dev builds to avoid cost of downloading packages.
if ( $useGlobalNuGetCache ) {
$env:NUGET_PACKAGES = Join-Path $env:UserProfile " .nuget\packages "
} else {
$env:NUGET_PACKAGES = Join-Path $RepoRoot " .packages "
}
}
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 ( ) {
if ( 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
}
2019-06-08 12:08:27 +00:00
& " $PSScriptRoot /init-tools-native.ps1 " @nativeArgs
2019-05-02 12:26:55 +00:00
}
}
2018-12-19 20:55:42 +00:00
function InitializeToolset ( ) {
if ( Test-Path variable : global: _ToolsetBuildProj ) {
return $global:_ToolsetBuildProj
}
$nugetCache = GetNuGetPackageCachePath
2018-10-22 05:07:26 +00:00
$toolsetVersion = $GlobalJson . 'msbuild-sdks' . 'Microsoft.DotNet.Arcade.Sdk'
$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-06-14 12:10:56 +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
2018-12-19 20:55:42 +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
2018-10-22 05:07:26 +00:00
$path = Get-Content $toolsetLocationFile -TotalCount 1
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
}
function Stop-Processes ( ) {
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-05-09 12:24:48 +00:00
$toolsetBuildProject = InitializeToolset
$path = Split-Path -parent $toolsetBuildProject
2019-05-10 12:25:59 +00:00
$path = Join-Path $path ( Join-Path $buildTool . Framework " Microsoft.DotNet.Arcade.Sdk.dll " )
2019-05-09 12:24:48 +00:00
$args + = " /logger: $path "
}
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 ) {
if ( ! $binaryLog ) {
2019-06-14 12:10:56 +00:00
Write-PipelineTaskError -Message " Binary log must be enabled in CI build. "
ExitWithExitCode 1
2018-12-19 20:55:42 +00:00
}
if ( $nodeReuse ) {
2019-06-14 12:10:56 +00:00
Write-PipelineTaskError -Message " Node reuse must be disabled in CI build. "
ExitWithExitCode 1
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 ) {
$cmdArgs + = " /warnaserror /p:TreatWarningsAsErrors=true "
2018-12-19 20:55:42 +00:00
}
foreach ( $arg in $args ) {
if ( $arg -ne $null -and $arg . Trim ( ) -ne " " ) {
$cmdArgs + = " `" $arg `" "
}
}
2019-06-08 12:08:27 +00:00
2018-12-19 20:55:42 +00:00
$exitCode = Exec-Process $buildTool . Path $cmdArgs
if ( $exitCode -ne 0 ) {
2019-06-14 12:10:56 +00:00
Write-PipelineTaskError -Message " Build failed. "
2018-12-19 20:55:42 +00:00
$buildLog = GetMSBuildBinaryLogCommandLineArgument $args
2019-06-08 12:08:27 +00:00
if ( $buildLog -ne $null ) {
Write-Host " See log: $buildLog " -ForegroundColor DarkGray
2018-12-19 20:55:42 +00:00
}
ExitWithExitCode $exitCode
}
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 ( )
if ( $arg . StartsWith ( " /bl: " , " OrdinalIgnoreCase " ) ) {
return $arg . Substring ( " /bl: " . Length )
2019-06-08 12:08:27 +00:00
}
2018-12-19 20:55:42 +00:00
if ( $arg . StartsWith ( " /binaryLogger: " , " OrdinalIgnoreCase " ) ) {
return $arg . Substring ( " /binaryLogger: " . Length )
}
}
}
return $null
2018-10-22 05:07:26 +00:00
}
2019-06-14 12:10:56 +00:00
. $PSScriptRoot \ pipeline-logging -functions . ps1
2019-05-31 12:10:52 +00:00
2018-10-22 05:07:26 +00:00
$RepoRoot = Resolve-Path ( Join-Path $PSScriptRoot " ..\.. " )
$EngRoot = Resolve-Path ( Join-Path $PSScriptRoot " .. " )
$ArtifactsDir = Join-Path $RepoRoot " artifacts "
$ToolsetDir = Join-Path $ArtifactsDir " toolset "
2018-12-04 17:31:23 +00:00
$ToolsDir = Join-Path $RepoRoot " .tools "
2018-10-22 05:07:26 +00:00
$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