1 # Initialize variables if they aren't already defined.
2 # These may be defined as parameters of the importing script, or set after importing this script.
4 # CI mode - set to true on CI server for PR validation build or official build.
5 [bool
]$ci = if (Test-Path variable
:ci
) { $ci } else { $false }
7 # Build configuration. Common values include 'Debug' and 'Release', but the repository may use other names.
8 [string
]$configuration = if (Test-Path variable
:configuration
) { $configuration } else { 'Debug' }
10 # Set to true to output binary log from msbuild. Note that emitting binary log slows down the build.
11 # Binary log must be enabled on CI.
12 [bool
]$binaryLog = if (Test-Path variable
:binaryLog
) { $binaryLog } else { $ci }
14 # Set to true to use the pipelines logger which will enable Azure logging output.
15 # https://github.com/Microsoft/azure-pipelines-tasks/blob/master/docs/authoring/commands.md
16 # This flag is meant as a temporary opt-opt for the feature while validate it across
17 # our consumers. It will be deleted in the future.
18 [bool
]$pipelinesLog = if (Test-Path variable
:pipelinesLog
) { $pipelinesLog } else { $ci }
20 # Turns on machine preparation/clean up code that changes the machine state (e.g. kills build processes).
21 [bool
]$prepareMachine = if (Test-Path variable
:prepareMachine
) { $prepareMachine } else { $false }
23 # True to restore toolsets and dependencies.
24 [bool
]$restore = if (Test-Path variable
:restore
) { $restore } else { $true }
26 # Adjusts msbuild verbosity level.
27 [string
]$verbosity = if (Test-Path variable
:verbosity
) { $verbosity } else { 'minimal' }
29 # Set to true to reuse msbuild nodes. Recommended to not reuse on CI.
30 [bool
]$nodeReuse = if (Test-Path variable
:nodeReuse
) { $nodeReuse } else { !$ci }
32 # Configures warning treatment in msbuild.
33 [bool
]$warnAsError = if (Test-Path variable
:warnAsError
) { $warnAsError } else { $true }
35 # Specifies which msbuild engine to use for build: 'vs', 'dotnet' or unspecified (determined based on presence of tools.vs in global.json).
36 [string
]$msbuildEngine = if (Test-Path variable
:msbuildEngine
) { $msbuildEngine } else { $null }
38 # True to attempt using .NET Core already that meets requirements specified in global.json
39 # installed on the machine instead of downloading one.
40 [bool
]$useInstalledDotNetCli = if (Test-Path variable
:useInstalledDotNetCli
) { $useInstalledDotNetCli } else { $true }
42 # Enable repos to use a particular version of the on-line dotnet-install scripts.
43 # default URL: https://dot.net/v1/dotnet-install.ps1
44 [string
]$dotnetInstallScriptVersion = if (Test-Path variable
:dotnetInstallScriptVersion
) { $dotnetInstallScriptVersion } else { 'v1' }
46 # True to use global NuGet cache instead of restoring packages to repository-local directory.
47 [bool
]$useGlobalNuGetCache = if (Test-Path variable
:useGlobalNuGetCache
) { $useGlobalNuGetCache } else { !$ci }
49 # An array of names of processes to stop on script exit if prepareMachine is true.
50 $processesToStopOnExit = if (Test-Path variable
:processesToStopOnExit
) { $processesToStopOnExit } else { @
('msbuild', 'dotnet', 'vbcscompiler') }
52 $disableConfigureToolsetImport = if (Test-Path variable
:disableConfigureToolsetImport
) { $disableConfigureToolsetImport } else { $null }
54 set-strictmode
-version
2.0
55 $ErrorActionPreference = 'Stop'
56 [Net
.ServicePointManager
]::SecurityProtocol
= [Net
.SecurityProtocolType
]::Tls12
58 function Create-Directory
([string
[]] $path) {
59 if (!(Test-Path $path)) {
60 New-Item -path
$path -force
-itemType
'Directory' | Out-Null
64 function Unzip
([string
]$zipfile, [string
]$outpath) {
65 Add-Type
-AssemblyName System
.IO
.Compression
.FileSystem
66 [System
.IO
.Compression
.ZipFile
]::ExtractToDirectory
($zipfile, $outpath)
69 # This will exec a process using the console and return it's exit code.
70 # This will not throw when the process fails.
71 # Returns process exit code.
72 function Exec-Process
([string
]$command, [string
]$commandArgs) {
73 $startInfo = New-Object System
.Diagnostics
.ProcessStartInfo
74 $startInfo.FileName
= $command
75 $startInfo.Arguments
= $commandArgs
76 $startInfo.UseShellExecute
= $false
77 $startInfo.WorkingDirectory
= Get-Location
79 $process = New-Object System
.Diagnostics
.Process
80 $process.StartInfo
= $startInfo
81 $process.Start
() | Out-Null
85 while (-not
$process.WaitForExit
(100)) {
86 # Non-blocking loop done to allow ctr-c interrupts
90 return $global:LASTEXITCODE
= $process.ExitCode
93 # If we didn't finish then an error occurred or the user hit ctrl-c. Either
94 # way kill the process
101 # createSdkLocationFile parameter enables a file being generated under the toolset directory
102 # which writes the sdk's location into. This is only necessary for cmd --> powershell invocations
103 # as dot sourcing isn't possible.
104 function InitializeDotNetCli
([bool
]$install, [bool
]$createSdkLocationFile) {
105 if (Test-Path variable
:global
:_DotNetInstallDir
) {
106 return $global:_DotNetInstallDir
109 # Don't resolve runtime, shared framework, or SDK from other locations to ensure build determinism
110 $env:DOTNET_MULTILEVEL_LOOKUP
=0
112 # Disable first run since we do not need all ASP.NET packages restored.
113 $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE
=1
115 # Disable telemetry on CI.
117 $env:DOTNET_CLI_TELEMETRY_OPTOUT
=1
120 # Source Build uses DotNetCoreSdkDir variable
121 if ($env:DotNetCoreSdkDir
-ne
$null) {
122 $env:DOTNET_INSTALL_DIR
= $env:DotNetCoreSdkDir
125 # Find the first path on %PATH% that contains the dotnet.exe
126 if ($useInstalledDotNetCli -and
(-not
$globalJsonHasRuntimes) -and
($env:DOTNET_INSTALL_DIR
-eq
$null)) {
127 $dotnetCmd = Get-Command 'dotnet.exe' -ErrorAction SilentlyContinue
128 if ($dotnetCmd -ne
$null) {
129 $env:DOTNET_INSTALL_DIR
= Split-Path $dotnetCmd.Path
-Parent
133 $dotnetSdkVersion = $GlobalJson.tools
.dotnet
135 # Use dotnet installation specified in DOTNET_INSTALL_DIR if it contains the required SDK version,
136 # otherwise install the dotnet CLI and SDK to repo local .dotnet directory to avoid potential permission issues.
137 if ((-not
$globalJsonHasRuntimes) -and
($env:DOTNET_INSTALL_DIR
-ne
$null) -and
(Test-Path(Join-Path $env:DOTNET_INSTALL_DIR
"sdk\$dotnetSdkVersion"))) {
138 $dotnetRoot = $env:DOTNET_INSTALL_DIR
140 $dotnetRoot = Join-Path $RepoRoot '.dotnet'
142 if (-not
(Test-Path(Join-Path $dotnetRoot "sdk\$dotnetSdkVersion"))) {
144 InstallDotNetSdk
$dotnetRoot $dotnetSdkVersion
146 Write-PipelineTelemetryError
-Category
'InitializeToolset' -Message
"Unable to find dotnet with SDK version '$dotnetSdkVersion'"
151 $env:DOTNET_INSTALL_DIR
= $dotnetRoot
154 # Creates a temporary file under the toolset dir.
155 # The following code block is protecting against concurrent access so that this function can
156 # be called in parallel.
157 if ($createSdkLocationFile) {
159 $sdkCacheFileTemp = Join-Path $ToolsetDir $([System.IO.Path]::GetRandomFileName()
)
161 until
(!(Test-Path $sdkCacheFileTemp))
162 Set-Content -Path
$sdkCacheFileTemp -Value
$dotnetRoot
165 Rename-Item -Force
-Path
$sdkCacheFileTemp 'sdk.txt'
168 Remove-Item -Path
$sdkCacheFileTemp
172 # Add dotnet to PATH. This prevents any bare invocation of dotnet in custom
173 # build steps from using anything other than what we've downloaded.
174 # It also ensures that VS msbuild will use the downloaded sdk targets.
175 $env:PATH
= "$dotnetRoot;$env:PATH"
177 # Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build
178 Write-PipelinePrependPath
-Path
$dotnetRoot
180 Write-PipelineSetVariable
-Name
'DOTNET_MULTILEVEL_LOOKUP' -Value
'0'
181 Write-PipelineSetVariable
-Name
'DOTNET_SKIP_FIRST_TIME_EXPERIENCE' -Value
'1'
183 return $global:_DotNetInstallDir
= $dotnetRoot
186 function GetDotNetInstallScript
([string
] $dotnetRoot) {
187 $installScript = Join-Path $dotnetRoot 'dotnet-install.ps1'
188 if (!(Test-Path $installScript)) {
189 Create-Directory
$dotnetRoot
190 $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit
191 Invoke-WebRequest
"https://dot.net/$dotnetInstallScriptVersion/dotnet-install.ps1" -OutFile
$installScript
194 return $installScript
197 function InstallDotNetSdk
([string
] $dotnetRoot, [string
] $version, [string
] $architecture = '') {
198 InstallDotNet
$dotnetRoot $version $architecture
201 function InstallDotNet
([string
] $dotnetRoot,
203 [string
] $architecture = '',
204 [string
] $runtime = '',
205 [bool
] $skipNonVersionedFiles = $false,
206 [string
] $runtimeSourceFeed = '',
207 [string
] $runtimeSourceFeedKey = '') {
209 $installScript = GetDotNetInstallScript
$dotnetRoot
210 $installParameters = @
{
212 InstallDir
= $dotnetRoot
215 if ($architecture) { $installParameters.Architecture
= $architecture }
216 if ($runtime) { $installParameters.Runtime
= $runtime }
217 if ($skipNonVersionedFiles) { $installParameters.SkipNonVersionedFiles
= $skipNonVersionedFiles }
220 & $installScript @installParameters
223 Write-PipelineTelemetryError
-Category
'InitializeToolset' -Message
"Failed to install dotnet runtime '$runtime' from public location."
225 # Only the runtime can be installed from a custom [private] location.
226 if ($runtime -and
($runtimeSourceFeed -or
$runtimeSourceFeedKey)) {
227 if ($runtimeSourceFeed) { $installParameters.AzureFeed
= $runtimeSourceFeed }
229 if ($runtimeSourceFeedKey) {
230 $decodedBytes = [System
.Convert
]::FromBase64String
($runtimeSourceFeedKey)
231 $decodedString = [System
.Text
.Encoding
]::UTF8
.GetString
($decodedBytes)
232 $installParameters.FeedCredential
= $decodedString
236 & $installScript @installParameters
239 Write-PipelineTelemetryError
-Category
'InitializeToolset' -Message
"Failed to install dotnet runtime '$runtime' from custom location '$runtimeSourceFeed'."
249 # Locates Visual Studio MSBuild installation.
250 # The preference order for MSBuild to use is as follows:
252 # 1. MSBuild from an active VS command prompt
253 # 2. MSBuild from a compatible VS installation
254 # 3. MSBuild from the xcopy tool package
256 # Returns full path to msbuild.exe.
259 function InitializeVisualStudioMSBuild
([bool
]$install, [object
]$vsRequirements = $null) {
260 if (Test-Path variable
:global
:_MSBuildExe
) {
261 return $global:_MSBuildExe
264 if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools
.vs
}
265 $vsMinVersionStr = if ($vsRequirements.version
) { $vsRequirements.version
} else { '15.9' }
266 $vsMinVersion = [Version
]::new
($vsMinVersionStr)
268 # Try msbuild command available in the environment.
269 if ($env:VSINSTALLDIR
-ne
$null) {
270 $msbuildCmd = Get-Command 'msbuild.exe' -ErrorAction SilentlyContinue
271 if ($msbuildCmd -ne
$null) {
272 # Workaround for https://github.com/dotnet/roslyn/issues/35793
273 # Due to this issue $msbuildCmd.Version returns 0.0.0.0 for msbuild.exe 16.2+
274 $msbuildVersion = [Version
]::new
((Get-Item $msbuildCmd.Path
).VersionInfo
.ProductVersion
.Split
([char
[]]@
('-', '+'))[0])
276 if ($msbuildVersion -ge
$vsMinVersion) {
277 return $global:_MSBuildExe
= $msbuildCmd.Path
280 # Report error - the developer environment is initialized with incompatible VS version.
281 throw "Developer Command Prompt for VS $($env:VisualStudioVersion) is not recent enough. Please upgrade to $vsMinVersionStr or build from a plain CMD window"
285 # Locate Visual Studio installation or download x-copy msbuild.
286 $vsInfo = LocateVisualStudio
$vsRequirements
287 if ($vsInfo -ne
$null) {
288 $vsInstallDir = $vsInfo.installationPath
289 $vsMajorVersion = $vsInfo.installationVersion
.Split
('.')[0]
291 InitializeVisualStudioEnvironmentVariables
$vsInstallDir $vsMajorVersion
294 if (Get-Member -InputObject
$GlobalJson.tools
-Name
'xcopy-msbuild') {
295 $xcopyMSBuildVersion = $GlobalJson.tools
.'xcopy-msbuild'
296 $vsMajorVersion = $xcopyMSBuildVersion.Split
('.')[0]
298 $vsMajorVersion = $vsMinVersion.Major
299 $xcopyMSBuildVersion = "$vsMajorVersion.$($vsMinVersion.Minor).0-alpha"
302 $vsInstallDir = $null
303 if ($xcopyMSBuildVersion.Trim
() -ine
"none") {
304 $vsInstallDir = InitializeXCopyMSBuild
$xcopyMSBuildVersion $install
306 if ($vsInstallDir -eq
$null) {
307 throw 'Unable to find Visual Studio that has required version and components installed'
311 $msbuildVersionDir = if ([int
]$vsMajorVersion -lt
16) { "$vsMajorVersion.0" } else { "Current" }
312 return $global:_MSBuildExe
= Join-Path $vsInstallDir "MSBuild\$msbuildVersionDir\Bin\msbuild.exe"
315 function InitializeVisualStudioEnvironmentVariables
([string
] $vsInstallDir, [string
] $vsMajorVersion) {
316 $env:VSINSTALLDIR
= $vsInstallDir
317 Set-Item "env:VS$($vsMajorVersion)0COMNTOOLS" (Join-Path $vsInstallDir "Common7\Tools\")
319 $vsSdkInstallDir = Join-Path $vsInstallDir "VSSDK\"
320 if (Test-Path $vsSdkInstallDir) {
321 Set-Item "env:VSSDK$($vsMajorVersion)0Install" $vsSdkInstallDir
322 $env:VSSDKInstall
= $vsSdkInstallDir
326 function InstallXCopyMSBuild
([string
]$packageVersion) {
327 return InitializeXCopyMSBuild
$packageVersion -install
$true
330 function InitializeXCopyMSBuild
([string
]$packageVersion, [bool
]$install) {
331 $packageName = 'RoslynTools.MSBuild'
332 $packageDir = Join-Path $ToolsDir "msbuild\$packageVersion"
333 $packagePath = Join-Path $packageDir "$packageName.$packageVersion.nupkg"
335 if (!(Test-Path $packageDir)) {
340 Create-Directory
$packageDir
341 Write-Host "Downloading $packageName $packageVersion"
342 $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit
343 Invoke-WebRequest
"https://dotnet.myget.org/F/roslyn-tools/api/v2/package/$packageName/$packageVersion/" -OutFile
$packagePath
344 Unzip
$packagePath $packageDir
347 return Join-Path $packageDir 'tools'
351 # Locates Visual Studio instance that meets the minimal requirements specified by tools.vs object in global.json.
353 # The following properties of tools.vs are recognized:
354 # "version": "{major}.{minor}"
355 # Two part minimal VS version, e.g. "15.9", "16.0", etc.
356 # "components": ["componentId1", "componentId2", ...]
357 # Array of ids of workload components that must be available in the VS instance.
358 # See e.g. https://docs.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-enterprise?view=vs-2017
360 # Returns JSON describing the located VS instance (same format as returned by vswhere),
361 # or $null if no instance meeting the requirements is found on the machine.
363 function LocateVisualStudio
([object
]$vsRequirements = $null){
364 if (Get-Member -InputObject
$GlobalJson.tools
-Name
'vswhere') {
365 $vswhereVersion = $GlobalJson.tools
.vswhere
367 $vswhereVersion = '2.5.2'
370 $vsWhereDir = Join-Path $ToolsDir "vswhere\$vswhereVersion"
371 $vsWhereExe = Join-Path $vsWhereDir 'vswhere.exe'
373 if (!(Test-Path $vsWhereExe)) {
374 Create-Directory
$vsWhereDir
375 Write-Host 'Downloading vswhere'
376 Invoke-WebRequest
"https://github.com/Microsoft/vswhere/releases/download/$vswhereVersion/vswhere.exe" -OutFile
$vswhereExe
379 if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools
.vs
}
380 $args = @
('-latest', '-prerelease', '-format', 'json', '-requires', 'Microsoft.Component.MSBuild', '-products', '*')
382 if (Get-Member -InputObject
$vsRequirements -Name
'version') {
384 $args += $vsRequirements.version
387 if (Get-Member -InputObject
$vsRequirements -Name
'components') {
388 foreach ($component in $vsRequirements.components
) {
394 $vsInfo =& $vsWhereExe $args | ConvertFrom-Json
396 if ($lastExitCode -ne
0) {
400 # use first matching instance
404 function InitializeBuildTool
() {
405 if (Test-Path variable
:global
:_BuildTool
) {
406 return $global:_BuildTool
409 if (-not
$msbuildEngine) {
410 $msbuildEngine = GetDefaultMSBuildEngine
413 # Initialize dotnet cli if listed in 'tools'
415 if (Get-Member -InputObject
$GlobalJson.tools
-Name
'dotnet') {
416 $dotnetRoot = InitializeDotNetCli
-install
:$restore
419 if ($msbuildEngine -eq
'dotnet') {
421 Write-PipelineTelemetryError
-Category
'InitializeToolset' -Message
"/global.json must specify 'tools.dotnet'."
424 $buildTool = @
{ Path
= Join-Path $dotnetRoot 'dotnet.exe'; Command
= 'msbuild'; Tool
= 'dotnet'; Framework
= 'netcoreapp2.1' }
425 } elseif
($msbuildEngine -eq
"vs") {
427 $msbuildPath = InitializeVisualStudioMSBuild
-install
:$restore
429 Write-PipelineTelemetryError
-Category
'InitializeToolset' -Message
$_
433 $buildTool = @
{ Path
= $msbuildPath; Command
= ""; Tool
= "vs"; Framework
= "net472" }
435 Write-PipelineTelemetryError
-Category
'InitializeToolset' -Message
"Unexpected value of -msbuildEngine: '$msbuildEngine'."
439 return $global:_BuildTool
= $buildTool
442 function GetDefaultMSBuildEngine
() {
443 # Presence of tools.vs indicates the repo needs to build using VS msbuild on Windows.
444 if (Get-Member -InputObject
$GlobalJson.tools
-Name
'vs') {
448 if (Get-Member -InputObject
$GlobalJson.tools
-Name
'dotnet') {
452 Write-PipelineTelemetryError
-Category
'InitializeToolset' -Message
"-msbuildEngine must be specified, or /global.json must specify 'tools.dotnet' or 'tools.vs'."
456 function GetNuGetPackageCachePath
() {
457 if ($env:NUGET_PACKAGES
-eq
$null) {
458 # Use local cache on CI to ensure deterministic build,
459 # use global cache in dev builds to avoid cost of downloading packages.
460 if ($useGlobalNuGetCache) {
461 $env:NUGET_PACKAGES
= Join-Path $env:UserProfile
'.nuget\packages'
463 $env:NUGET_PACKAGES
= Join-Path $RepoRoot '.packages'
467 return $env:NUGET_PACKAGES
470 # Returns a full path to an Arcade SDK task project file.
471 function GetSdkTaskProject
([string
]$taskName) {
472 return Join-Path (Split-Path (InitializeToolset
) -Parent
) "SdkTasks\$taskName.proj"
475 function InitializeNativeTools
() {
476 if (-Not
(Test-Path variable
:DisableNativeToolsetInstalls
) -And
(Get-Member -InputObject
$GlobalJson -Name
"native-tools")) {
480 InstallDirectory
= "$ToolsDir"
483 & "$PSScriptRoot/init-tools-native.ps1" @nativeArgs
487 function InitializeToolset
() {
488 if (Test-Path variable
:global
:_ToolsetBuildProj
) {
489 return $global:_ToolsetBuildProj
492 $nugetCache = GetNuGetPackageCachePath
494 $toolsetVersion = $GlobalJson.'msbuild-sdks'.'Microsoft.DotNet.Arcade.Sdk'
495 $toolsetLocationFile = Join-Path $ToolsetDir "$toolsetVersion.txt"
497 if (Test-Path $toolsetLocationFile) {
498 $path = Get-Content $toolsetLocationFile -TotalCount
1
499 if (Test-Path $path) {
500 return $global:_ToolsetBuildProj
= $path
505 Write-PipelineTelemetryError
-Category
'InitializeToolset' -Message
"Toolset version $toolsetVersion has not been restored."
509 $buildTool = InitializeBuildTool
511 $proj = Join-Path $ToolsetDir 'restore.proj'
512 $bl = if ($binaryLog) { '/bl:' + (Join-Path $LogDir 'ToolsetRestore.binlog') } else { '' }
514 '<Project Sdk="Microsoft.DotNet.Arcade.Sdk"/>' | Set-Content $proj
516 MSBuild-Core
$proj $bl /t
:__WriteToolsetLocation
/clp:ErrorsOnly`
;NoSummary
/p
:__ToolsetLocationOutputFile
=$toolsetLocationFile
518 $path = Get-Content $toolsetLocationFile -TotalCount
1
519 if (!(Test-Path $path)) {
520 throw "Invalid toolset path: $path"
523 return $global:_ToolsetBuildProj
= $path
526 function ExitWithExitCode
([int
] $exitCode) {
527 if ($ci -and
$prepareMachine) {
533 function Stop-Processes
() {
534 Write-Host 'Killing running build processes...'
535 foreach ($processName in $processesToStopOnExit) {
536 Get-Process -Name
$processName -ErrorAction SilentlyContinue
| Stop-Process
541 # Executes msbuild (or 'dotnet msbuild') with arguments passed to the function.
542 # The arguments are automatically quoted.
543 # Terminates the script if the build fails.
547 $buildTool = InitializeBuildTool
549 # Work around issues with Azure Artifacts credential provider
550 # https://github.com/dotnet/arcade/issues/3932
551 if ($ci -and
$buildTool.Tool
-eq
'dotnet') {
552 dotnet nuget locals http-cache
-c
554 $env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS
= 20
555 $env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS
= 20
556 Write-PipelineSetVariable
-Name
'NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS' -Value
'20'
557 Write-PipelineSetVariable
-Name
'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value
'20'
560 $toolsetBuildProject = InitializeToolset
561 $path = Split-Path -parent
$toolsetBuildProject
562 $path = Join-Path $path (Join-Path $buildTool.Framework
'Microsoft.DotNet.Arcade.Sdk.dll')
563 $args += "/logger:$path"
570 # Executes msbuild (or 'dotnet msbuild') with arguments passed to the function.
571 # The arguments are automatically quoted.
572 # Terminates the script if the build fails.
574 function MSBuild-Core
() {
577 Write-PipelineTelemetryError
-Category
'Build' -Message
'Binary log must be enabled in CI build.'
582 Write-PipelineTelemetryError
-Category
'Build' -Message
'Node reuse must be disabled in CI build.'
587 $buildTool = InitializeBuildTool
589 $cmdArgs = "$($buildTool.Command) /m /nologo /clp:Summary /v:$verbosity /nr:$nodeReuse /p:ContinuousIntegrationBuild=$ci"
592 $cmdArgs += ' /warnaserror /p:TreatWarningsAsErrors=true'
595 $cmdArgs += ' /p:TreatWarningsAsErrors=false'
598 foreach ($arg in $args) {
599 if ($arg -ne
$null -and
$arg.Trim
() -ne
"") {
600 $cmdArgs += " `"$arg`
""
604 $exitCode = Exec-Process
$buildTool.Path
$cmdArgs
606 if ($exitCode -ne
0) {
607 Write-PipelineTelemetryError Category
'Build' -Message
'Build failed.'
609 $buildLog = GetMSBuildBinaryLogCommandLineArgument
$args
610 if ($buildLog -ne
$null) {
611 Write-Host "See log: $buildLog" -ForegroundColor DarkGray
614 ExitWithExitCode
$exitCode
618 function GetMSBuildBinaryLogCommandLineArgument
($arguments) {
619 foreach ($argument in $arguments) {
620 if ($argument -ne
$null) {
621 $arg = $argument.Trim
()
622 if ($arg.StartsWith
('/bl:', "OrdinalIgnoreCase")) {
623 return $arg.Substring
('/bl:'.Length
)
626 if ($arg.StartsWith
('/binaryLogger:', 'OrdinalIgnoreCase')) {
627 return $arg.Substring
('/binaryLogger:'.Length
)
635 . $PSScriptRoot\pipeline-logging-functions
.ps1
637 $RepoRoot = Resolve-Path (Join-Path $PSScriptRoot '..\..')
638 $EngRoot = Resolve-Path (Join-Path $PSScriptRoot '..')
639 $ArtifactsDir = Join-Path $RepoRoot 'artifacts'
640 $ToolsetDir = Join-Path $ArtifactsDir 'toolset'
641 $ToolsDir = Join-Path $RepoRoot '.tools'
642 $LogDir = Join-Path (Join-Path $ArtifactsDir 'log') $configuration
643 $TempDir = Join-Path (Join-Path $ArtifactsDir 'tmp') $configuration
644 $GlobalJson = Get-Content -Raw
-Path
(Join-Path $RepoRoot 'global.json') | ConvertFrom-Json
645 # true if global.json contains a "runtimes" section
646 $globalJsonHasRuntimes = if ($GlobalJson.tools
.PSObject
.Properties
.Name
-Match
'runtimes') { $true } else { $false }
648 Create-Directory
$ToolsetDir
649 Create-Directory
$TempDir
650 Create-Directory
$LogDir
652 Write-PipelineSetVariable
-Name
'Artifacts' -Value
$ArtifactsDir
653 Write-PipelineSetVariable
-Name
'Artifacts.Toolset' -Value
$ToolsetDir
654 Write-PipelineSetVariable
-Name
'Artifacts.Log' -Value
$LogDir
655 Write-PipelineSetVariable
-Name
'TEMP' -Value
$TempDir
656 Write-PipelineSetVariable
-Name
'TMP' -Value
$TempDir
661 # Import custom tools configuration, if present in the repo.
662 # Note: Import in global scope so that the script set top-level variables without qualification.
663 if (!$disableConfigureToolsetImport) {
664 $configureToolsetScript = Join-Path $EngRoot 'configure-toolset.ps1'
665 if (Test-Path $configureToolsetScript) {
666 . $configureToolsetScript
667 if ((Test-Path variable
:failOnConfigureToolsetError
) -And
$failOnConfigureToolsetError) {
668 if ((Test-Path variable
:LastExitCode
) -And
($LastExitCode -ne
0)) {
669 Write-PipelineTelemetryError
-Category
'Build' -Message
'configure-toolset.ps1 returned a non-zero exit code'
670 ExitWithExitCode
$LastExitCode