From e01d713909e4905643b33c4f7fb261bb90e80b3d Mon Sep 17 00:00:00 2001
From: Nate McMaster <natemcmaster@users.noreply.github.com>
Date: Thu, 23 May 2019 15:35:49 -0700
Subject: [PATCH] Use Microsoft.Net.Compilers.Toolset (#10415)

---
 Directory.Build.props                        |  10 +-
 build/sources.props                          |   1 +
 eng/Version.Details.xml                      |  12 +-
 eng/Versions.props                           |   6 +-
 eng/common/PublishToPackageFeed.proj         |   1 +
 eng/common/build.ps1                         |   4 +
 eng/common/build.sh                          |   5 +
 eng/common/cross/arm64/sources.list.buster   |  11 ++
 eng/common/cross/arm64/sources.list.stretch  |  12 ++
 eng/common/cross/build-rootfs.sh             |  17 ++-
 eng/common/darc-init.ps1                     |  11 +-
 eng/common/darc-init.sh                      |  15 ++-
 eng/common/dotnet-install.ps1                |  11 +-
 eng/common/templates/steps/send-to-helix.yml |   3 +
 eng/common/tools.ps1                         |   6 +-
 eng/common/tools.sh                          | 115 +++++++++++++++++--
 global.json                                  |   4 +-
 17 files changed, 212 insertions(+), 32 deletions(-)
 create mode 100644 eng/common/cross/arm64/sources.list.buster
 create mode 100644 eng/common/cross/arm64/sources.list.stretch

diff --git a/Directory.Build.props b/Directory.Build.props
index 8b002c635e8..8a8ef6d27d7 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,6 +1,15 @@
 <Project>
   <Import Project="version.props" />
 
+  <!--
+    These imports look funny.
+    Eventually they will be replaced by a simplified import that brings in
+    the entire Arcade SDK. For now, we're moving onto Arcade one piece at a time.
+  -->
+  <Import Project="../tools/DefaultVersions.Generated.props" Sdk="Microsoft.DotNet.Arcade.Sdk" />
+  <Import Project="eng\Versions.props" />
+  <Import Project="../tools/Compiler.props" Sdk="Microsoft.DotNet.Arcade.Sdk" Condition="'$(UsingToolMicrosoftNetCompilers)' == 'true'"/>
+
   <PropertyGroup>
     <Product>Microsoft ASP.NET Core</Product>
 
@@ -121,7 +130,6 @@
     <OutDirName Condition="'$(IsReferenceAssemblyProject)' == 'true'">$(MSBuildProjectName)-ref</OutDirName>
   </PropertyGroup>
 
-  <Import Project="eng\Versions.props" />
   <Import Project="build\sources.props" />
 
   <!-- Artifacts layout -->
diff --git a/build/sources.props b/build/sources.props
index 26d8be66778..b561688d1f3 100644
--- a/build/sources.props
+++ b/build/sources.props
@@ -14,6 +14,7 @@
       https://dotnetfeed.blob.core.windows.net/aspnet-entityframeworkcore/index.json;
       https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore-tooling/index.json;
       https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json;
+      https://dotnet.myget.org/F/roslyn/api/v3/index.json;
       https://grpc.jfrog.io/grpc/api/nuget/v3/grpc-nuget-dev;
       https://api.nuget.org/v3/index.json;
     </RestoreSources>
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index fc32cbe01a9..11b8454994a 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -384,13 +384,17 @@
       <Uri>https://github.com/aspnet/Extensions</Uri>
       <Sha>8dfb4ece7ca9a6dea14264dafc38a0c953874559</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.DotNet.GenAPI" Version="1.0.0-beta.19270.1">
+    <Dependency Name="Microsoft.DotNet.GenAPI" Version="1.0.0-beta.19272.13">
       <Uri>https://github.com/dotnet/arcade</Uri>
-      <Sha>e913fb3b02d4089a91ff91c041c5f6e7c29038b0</Sha>
+      <Sha>86e674361bdcefecbd8199ab62d0b1a6cb25703d</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="2.0.0-beta.19270.1">
+    <Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="1.0.0-beta.19272.13">
       <Uri>https://github.com/dotnet/arcade</Uri>
-      <Sha>e913fb3b02d4089a91ff91c041c5f6e7c29038b0</Sha>
+      <Sha>86e674361bdcefecbd8199ab62d0b1a6cb25703d</Sha>
+    </Dependency>
+    <Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="2.0.0-beta.19272.13">
+      <Uri>https://github.com/dotnet/arcade</Uri>
+      <Sha>86e674361bdcefecbd8199ab62d0b1a6cb25703d</Sha>
     </Dependency>
     <Dependency Name="Microsoft.AspNetCore.Testing" Version="3.0.0-preview6.19265.2" CoherentParentDependency="Microsoft.CodeAnalysis.Razor">
       <Uri>https://github.com/aspnet/Extensions</Uri>
diff --git a/eng/Versions.props b/eng/Versions.props
index 10a317d4415..108f3ea38a1 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -5,6 +5,10 @@
 
 -->
 <Project>
+  <PropertyGroup Label="Arcade settings">
+    <!-- Opt-in to using the version of the Roslyn compiler bundled with Arcade. -->
+    <UsingToolMicrosoftNetCompilers Condition="'$(MSBuildProjectExtension)' == '.csproj' or '$(MSBuildProjectExtension)' == '.fsproj' or '$(MSBuildProjectExtension)' == '.vbproj'">true</UsingToolMicrosoftNetCompilers>
+  </PropertyGroup>
   <!--
 
     These versions should ONLY be updated by automation.
@@ -17,7 +21,7 @@
   -->
   <PropertyGroup Label="Automated">
     <!-- Packages from dotnet/arcade -->
-    <MicrosoftDotNetGenAPIPackageVersion>1.0.0-beta.19270.1</MicrosoftDotNetGenAPIPackageVersion>
+    <MicrosoftDotNetGenAPIPackageVersion>1.0.0-beta.19272.13</MicrosoftDotNetGenAPIPackageVersion>
     <!-- Packages from dotnet/core-setup -->
     <MicrosoftExtensionsDependencyModelPackageVersion>3.0.0-preview6-27714-15</MicrosoftExtensionsDependencyModelPackageVersion>
     <MicrosoftNETCoreAppPackageVersion>3.0.0-preview6-27714-15</MicrosoftNETCoreAppPackageVersion>
diff --git a/eng/common/PublishToPackageFeed.proj b/eng/common/PublishToPackageFeed.proj
index e17f72644e3..9120b2d2129 100644
--- a/eng/common/PublishToPackageFeed.proj
+++ b/eng/common/PublishToPackageFeed.proj
@@ -53,6 +53,7 @@
       <TargetStaticFeed Condition="'$(ArtifactsCategory.ToUpper())' == 'TOOLSET'">https://dotnetfeed.blob.core.windows.net/dotnet-toolset/index.json</TargetStaticFeed>
       <TargetStaticFeed Condition="'$(ArtifactsCategory.ToUpper())' == 'WINDOWSDESKTOP'">https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json</TargetStaticFeed>
       <TargetStaticFeed Condition="'$(ArtifactsCategory.ToUpper())' == 'NUGETCLIENT'">https://dotnetfeed.blob.core.windows.net/nuget-nugetclient/index.json</TargetStaticFeed>
+      <TargetStaticFeed Condition="'$(ArtifactsCategory.ToUpper())' == 'ASPNETENTITYFRAMEWORK6'">https://dotnetfeed.blob.core.windows.net/aspnet-entityframework6/index.json</TargetStaticFeed>
     </PropertyGroup>
 
     <Error 
diff --git a/eng/common/build.ps1 b/eng/common/build.ps1
index d7e3799ebd9..67046a43f8c 100644
--- a/eng/common/build.ps1
+++ b/eng/common/build.ps1
@@ -1,6 +1,7 @@
 [CmdletBinding(PositionalBinding=$false)]
 Param(
   [string][Alias('c')]$configuration = "Debug",
+  [string]$platform = $null,
   [string] $projects,
   [string][Alias('v')]$verbosity = "minimal",
   [string] $msbuildEngine = $null,
@@ -29,6 +30,7 @@ Param(
 function Print-Usage() {
     Write-Host "Common settings:"
     Write-Host "  -configuration <value>  Build configuration: 'Debug' or 'Release' (short: -c)"
+    Write-Host "  -platform <value>       Platform configuration: 'x86', 'x64' or any valid Platform value to pass to msbuild"
     Write-Host "  -verbosity <value>      Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] (short: -v)"
     Write-Host "  -binaryLog              Output binary log (short: -bl)"
     Write-Host "  -help                   Print help and exit"
@@ -77,6 +79,7 @@ function Build {
   InitializeCustomToolset
 
   $bl = if ($binaryLog) { "/bl:" + (Join-Path $LogDir "Build.binlog") } else { "" }
+  $platformArg = if ($platform) { "/p:Platform=$platform" } else { "" }
 
   if ($projects) {
     # Re-assign properties to a new variable because PowerShell doesn't let us append properties directly for unclear reasons.
@@ -88,6 +91,7 @@ function Build {
 
   MSBuild $toolsetBuildProj `
     $bl `
+    $platformArg `
     /p:Configuration=$configuration `
     /p:RepoRoot=$RepoRoot `
     /p:Restore=$restore `
diff --git a/eng/common/build.sh b/eng/common/build.sh
index ce846d888df..6236fc4d38c 100755
--- a/eng/common/build.sh
+++ b/eng/common/build.sh
@@ -66,6 +66,7 @@ ci=false
 warn_as_error=true
 node_reuse=true
 binary_log=false
+pipelines_log=false
 
 projects=''
 configuration='Debug'
@@ -92,6 +93,9 @@ while [[ $# > 0 ]]; do
     -binarylog|-bl)
       binary_log=true
       ;;
+    -pipelineslog|-pl)
+      pipelines_log=true
+      ;;
     -restore|-r)
       restore=true
       ;;
@@ -146,6 +150,7 @@ while [[ $# > 0 ]]; do
 done
 
 if [[ "$ci" == true ]]; then
+  pipelines_log=true
   binary_log=true
   node_reuse=false
 fi
diff --git a/eng/common/cross/arm64/sources.list.buster b/eng/common/cross/arm64/sources.list.buster
new file mode 100644
index 00000000000..7194ac64a96
--- /dev/null
+++ b/eng/common/cross/arm64/sources.list.buster
@@ -0,0 +1,11 @@
+deb http://deb.debian.org/debian buster main
+deb-src http://deb.debian.org/debian buster main
+
+deb http://deb.debian.org/debian-security/ buster/updates main
+deb-src http://deb.debian.org/debian-security/ buster/updates main
+
+deb http://deb.debian.org/debian buster-updates main
+deb-src http://deb.debian.org/debian buster-updates main
+
+deb http://deb.debian.org/debian buster-backports main contrib non-free
+deb-src http://deb.debian.org/debian buster-backports main contrib non-free
diff --git a/eng/common/cross/arm64/sources.list.stretch b/eng/common/cross/arm64/sources.list.stretch
new file mode 100644
index 00000000000..0e121577436
--- /dev/null
+++ b/eng/common/cross/arm64/sources.list.stretch
@@ -0,0 +1,12 @@
+deb http://deb.debian.org/debian stretch main
+deb-src http://deb.debian.org/debian stretch main
+
+deb http://deb.debian.org/debian-security/ stretch/updates main
+deb-src http://deb.debian.org/debian-security/ stretch/updates main
+
+deb http://deb.debian.org/debian stretch-updates main
+deb-src http://deb.debian.org/debian stretch-updates main
+
+deb http://deb.debian.org/debian stretch-backports main contrib non-free
+deb-src http://deb.debian.org/debian stretch-backports main contrib non-free
+
diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh
index 83ec39195cd..34d3d2ba1fe 100755
--- a/eng/common/cross/build-rootfs.sh
+++ b/eng/common/cross/build-rootfs.sh
@@ -2,7 +2,7 @@
 
 usage()
 {
-    echo "Usage: $0 [BuildArch] [LinuxCodeName] [lldbx.y] [--skipunmount] --rootfs <directory>]"
+    echo "Usage: $0 [BuildArch] [LinuxCodeName] [lldbx.y] [--skipunmount] --rootfsdir <directory>]"
     echo "BuildArch can be: arm(default), armel, arm64, x86"
     echo "LinuxCodeName - optional, Code name for Linux, can be: trusty, xenial(default), zesty, bionic, alpine. If BuildArch is armel, LinuxCodeName is jessie(default) or tizen."
     echo "lldbx.y - optional, LLDB version, can be: lldb3.9(default), lldb4.0, lldb5.0, lldb6.0 no-lldb. Ignored for alpine"
@@ -113,12 +113,12 @@ while :; do
                 __LinuxCodeName=trusty
             fi
             ;;
-        xenial) # Ubunry 16.04
+        xenial) # Ubuntu 16.04
             if [ "$__LinuxCodeName" != "jessie" ]; then
                 __LinuxCodeName=xenial
             fi
             ;;
-        zesty) # Ununtu 17.04
+        zesty) # Ubuntu 17.04
             if [ "$__LinuxCodeName" != "jessie" ]; then
                 __LinuxCodeName=zesty
             fi
@@ -132,7 +132,16 @@ while :; do
             __LinuxCodeName=jessie
             __UbuntuRepo="http://ftp.debian.org/debian/"
             ;;
-        # TBD Stretch -> Debian 9, Buster -> Debian 10
+        stretch) # Debian 9
+            __LinuxCodeName=stretch
+            __UbuntuRepo="http://ftp.debian.org/debian/"
+            __LLDB_Package="liblldb-6.0-dev"
+            ;;
+        buster) # Debian 10
+            __LinuxCodeName=buster
+            __UbuntuRepo="http://ftp.debian.org/debian/"
+            __LLDB_Package="liblldb-6.0-dev"
+            ;;
         tizen)
             if [ "$__BuildArch" != "armel" ]; then
                 echo "Tizen is available only for armel."
diff --git a/eng/common/darc-init.ps1 b/eng/common/darc-init.ps1
index 81ffd16779c..dea7cdd903b 100644
--- a/eng/common/darc-init.ps1
+++ b/eng/common/darc-init.ps1
@@ -1,5 +1,6 @@
 param (
-    $darcVersion = $null
+    $darcVersion = $null,
+    $versionEndpoint = "https://maestro-prod.westus2.cloudapp.azure.com/api/assets/darc-version?api-version=2019-01-16"
 )
 
 $verbosity = "m"
@@ -16,13 +17,13 @@ function InstallDarcCli ($darcVersion) {
     Invoke-Expression "& `"$dotnet`" tool uninstall $darcCliPackageName -g"
   }
 
-  # Until we can anonymously query the BAR API for the latest arcade-services
-  # build applied to the PROD channel, this is hardcoded.
+  # If the user didn't explicitly specify the darc version,
+  # query the Maestro API for the correct version of darc to install.
   if (-not $darcVersion) {
-    $darcVersion = '1.1.0-beta.19205.4'
+    $darcVersion = $(Invoke-WebRequest -Uri $versionEndpoint -UseBasicParsing).Content
   }
   
-  $arcadeServicesSource = 'https://dotnetfeed.blob.core.windows.net/dotnet-arcade/index.json'
+  $arcadeServicesSource = 'https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json'
 
   Write-Host "Installing Darc CLI version $darcVersion..."
   Write-Host "You may need to restart your command window if this is the first dotnet tool you have installed."
diff --git a/eng/common/darc-init.sh b/eng/common/darc-init.sh
index bd7eb463986..abdd0bc05a1 100755
--- a/eng/common/darc-init.sh
+++ b/eng/common/darc-init.sh
@@ -1,7 +1,8 @@
 #!/usr/bin/env bash
 
 source="${BASH_SOURCE[0]}"
-darcVersion="1.1.0-beta.19205.4"
+darcVersion=''
+versionEndpoint="https://maestro-prod.westus2.cloudapp.azure.com/api/assets/darc-version?api-version=2019-01-16"
 
 while [[ $# > 0 ]]; do
   opt="$(echo "$1" | awk '{print tolower($0)}')"
@@ -10,6 +11,10 @@ while [[ $# > 0 ]]; do
       darcVersion=$2
       shift
       ;;
+    --versionendpoint)
+      versionEndpoint=$2
+      shift
+      ;;
     *)
       echo "Invalid argument: $1"
       usage
@@ -33,6 +38,10 @@ verbosity=m
 
 . "$scriptroot/tools.sh"
 
+if [ -z "$darcVersion" ]; then
+  darcVersion=$(curl -X GET "$versionEndpoint" -H "accept: text/plain")
+fi
+
 function InstallDarcCli {
   local darc_cli_package_name="microsoft.dotnet.darc"
 
@@ -45,9 +54,9 @@ function InstallDarcCli {
     echo $($dotnet_root/dotnet tool uninstall $darc_cli_package_name -g)
   fi
 
-  local arcadeServicesSource="https://dotnetfeed.blob.core.windows.net/dotnet-arcade/index.json"
+  local arcadeServicesSource="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json"
 
-  echo "Installing Darc CLI version $toolset_version..."
+  echo "Installing Darc CLI version $darcVersion..."
   echo "You may need to restart your command shell if this is the first dotnet tool you have installed."
   echo $($dotnet_root/dotnet tool install $darc_cli_package_name --version $darcVersion --add-source "$arcadeServicesSource" -v $verbosity -g)
 }
diff --git a/eng/common/dotnet-install.ps1 b/eng/common/dotnet-install.ps1
index 5987943fd6f..0b629b8301a 100644
--- a/eng/common/dotnet-install.ps1
+++ b/eng/common/dotnet-install.ps1
@@ -8,9 +8,14 @@ Param(
 
 . $PSScriptRoot\tools.ps1
 
+$dotnetRoot = Join-Path $RepoRoot ".dotnet"
+
+$installdir = $dotnetRoot
 try {
-  $dotnetRoot = Join-Path $RepoRoot ".dotnet"
-  InstallDotNet $dotnetRoot $version $architecture $runtime $true
+    if ($architecture -and $architecture.Trim() -eq "x86") {
+        $installdir = Join-Path $installdir "x86"
+    }
+   InstallDotNet $installdir $version $architecture $runtime $true
 } 
 catch {
   Write-Host $_
@@ -19,4 +24,4 @@ catch {
   ExitWithExitCode 1
 }
 
-ExitWithExitCode 0
\ No newline at end of file
+ExitWithExitCode 0
diff --git a/eng/common/templates/steps/send-to-helix.yml b/eng/common/templates/steps/send-to-helix.yml
index d1ce577db5b..05df886f55f 100644
--- a/eng/common/templates/steps/send-to-helix.yml
+++ b/eng/common/templates/steps/send-to-helix.yml
@@ -5,6 +5,7 @@ parameters:
   HelixBuild: $(Build.BuildNumber)       # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number
   HelixTargetQueues: ''                  # required -- semicolon delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues
   HelixAccessToken: ''                   # required -- access token to make Helix API requests; should be provided by the appropriate variable group
+  HelixConfiguration: ''                 # optional -- additional property attached to a job
   HelixPreCommands: ''                   # optional -- commands to run before Helix work item execution
   HelixPostCommands: ''                  # optional -- commands to run after Helix work item execution
   WorkItemDirectory: ''                  # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects
@@ -35,6 +36,7 @@ steps:
       HelixSource: ${{ parameters.HelixSource }}
       HelixType: ${{ parameters.HelixType }}
       HelixBuild: ${{ parameters.HelixBuild }}
+      HelixConfiguration:  ${{ parameters.HelixConfiguration }}
       HelixTargetQueues: ${{ parameters.HelixTargetQueues }}
       HelixAccessToken: ${{ parameters.HelixAccessToken }}
       HelixPreCommands: ${{ parameters.HelixPreCommands }}
@@ -64,6 +66,7 @@ steps:
       HelixSource: ${{ parameters.HelixSource }}
       HelixType: ${{ parameters.HelixType }}
       HelixBuild: ${{ parameters.HelixBuild }}
+      HelixConfiguration:  ${{ parameters.HelixConfiguration }}
       HelixTargetQueues: ${{ parameters.HelixTargetQueues }}
       HelixAccessToken: ${{ parameters.HelixAccessToken }}
       HelixPreCommands: ${{ parameters.HelixPreCommands }}
diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1
index 9ca177b82a3..9cea610a27f 100644
--- a/eng/common/tools.ps1
+++ b/eng/common/tools.ps1
@@ -213,7 +213,11 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements =
   if ($env:VSINSTALLDIR -ne $null) {
     $msbuildCmd = Get-Command "msbuild.exe" -ErrorAction SilentlyContinue
     if ($msbuildCmd -ne $null) {
-      if ($msbuildCmd.Version -ge $vsMinVersion) {
+      # 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) {
         return $global:_MSBuildExe = $msbuildCmd.Path
       }
 
diff --git a/eng/common/tools.sh b/eng/common/tools.sh
index df3eb8bce07..34a23e9476d 100755
--- a/eng/common/tools.sh
+++ b/eng/common/tools.sh
@@ -1,8 +1,20 @@
+#!/usr/bin/env bash
+
 # Initialize variables if they aren't already defined.
 
 # CI mode - set to true on CI server for PR validation build or official build.
 ci=${ci:-false}
 
+# 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.
+if [[ "$ci" == true ]]; then
+  pipelines_log=${pipelines_log:-true}
+else
+  pipelines_log=${pipelines_log:-false}
+fi
+
 # Build configuration. Common values include 'Debug' and 'Release', but the repository may use other names.
 configuration=${configuration:-'Debug'}
 
@@ -40,6 +52,78 @@ else
   use_global_nuget_cache=${use_global_nuget_cache:-true}
 fi
 
+function EmitError {
+  if [[ "$ci" != true ]]; then
+    echo "$@" >&2
+    return
+  fi
+
+  message_type="error"
+  sourcepath=''
+  linenumber=''
+  columnnumber=''
+  error_code=''
+
+  while [[ $# -gt 0 ]]; do
+    opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')"
+    case "$opt" in
+      -type|-t)
+        message_type=$2
+        shift
+        ;;
+      -sourcepath|-s)
+        sourcepath=$2
+        shift
+        ;;
+      -linenumber|-l)
+        linenumber=$2
+        shift
+        ;;
+      -columnnumber|-col)
+        columnnumber=$2
+        shift
+        ;;
+      -code|-c)
+        error_code=$2
+        shift
+        ;;
+      *)
+        break
+        ;;
+    esac
+
+    shift
+  done
+
+  message='##vso[task.logissue'
+
+  message="$message type=$message_type"
+
+  if [ -n "$sourcepath" ]; then
+    message="$message;sourcepath=$sourcepath"
+  else
+    message="$message;sourcepath=${BASH_SOURCE[1]}"
+  fi
+
+  if [ -n "$linenumber" ]; then
+    message="$message;linenumber=$linenumber"
+  else
+    message="$message;linenumber=${BASH_LINENO[0]}"
+  fi
+
+  if [ -n "$columnnumber" ]; then
+    message="$message;columnnumber=$columnnumber"
+  fi
+
+  if [ -n "$error_code" ]; then
+    message="$message;code=$error_code"
+  fi
+
+  message="$message]$*"
+
+  echo "$message"
+}
+
 # Resolve any symlinks in the given path.
 function ResolvePath {
   local path=$1
@@ -65,7 +149,7 @@ function ReadGlobalVersion {
   local pattern="\"$key\" *: *\"(.*)\""
 
   if [[ ! $line =~ $pattern ]]; then
-    echo "Error: Cannot find \"$key\" in $global_json_file" >&2
+    EmitError "Error: Cannot find \"$key\" in $global_json_file"
     ExitWithExitCode 1
   fi
 
@@ -126,7 +210,7 @@ function InitializeDotNetCli {
       if [[ "$install" == true ]]; then
         InstallDotNetSdk "$dotnet_root" "$dotnet_sdk_version"
       else
-        echo "Unable to find dotnet with SDK version '$dotnet_sdk_version'" >&2
+        EmitError "Unable to find dotnet with SDK version '$dotnet_sdk_version'"
         ExitWithExitCode 1
       fi
     fi
@@ -179,7 +263,7 @@ function InstallDotNet {
   fi
   bash "$install_script" --version $version --install-dir "$root" $archArg $runtimeArg $skipNonVersionedFilesArg || {
     local exit_code=$?
-    echo "Failed to install dotnet SDK (exit code '$exit_code')." >&2
+    EmitError "Failed to install dotnet SDK (exit code '$exit_code')."
     ExitWithExitCode $exit_code
   }
 }
@@ -216,6 +300,7 @@ function InitializeBuildTool {
   # return values
   _InitializeBuildTool="$_InitializeDotNetCli/dotnet"  
   _InitializeBuildToolCommand="msbuild"
+  _InitializeBuildToolFramework="netcoreapp2.1"
 }
 
 function GetNuGetPackageCachePath {
@@ -264,7 +349,7 @@ function InitializeToolset {
   fi
 
   if [[ "$restore" != true ]]; then
-    echo "Toolset version $toolsetVersion has not been restored." >&2
+    EmitError "Toolset version $toolsetVersion has not been restored."
     ExitWithExitCode 2
   fi
 
@@ -276,12 +361,12 @@ function InitializeToolset {
   fi
   
   echo '<Project Sdk="Microsoft.DotNet.Arcade.Sdk"/>' > "$proj"
-  MSBuild "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file"
+  MSBuild-Core "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file"
 
   local toolset_build_proj=`cat "$toolset_location_file"`
 
   if [[ ! -a "$toolset_build_proj" ]]; then
-    echo "Invalid toolset path: $toolset_build_proj" >&2
+    EmitError "Invalid toolset path: $toolset_build_proj"
     ExitWithExitCode 3
   fi
 
@@ -304,14 +389,26 @@ function StopProcesses {
 }
 
 function MSBuild {
+  args=$@
+  if [[ "$pipelines_log" == true ]]; then
+    InitializeBuildTool
+    InitializeToolset
+    _toolset_dir="${_InitializeToolset%/*}"
+    _loggerPath="$_toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.Arcade.Sdk.dll"
+    args=( "${args[@]}" "-logger:$_loggerPath" )
+  fi
+  MSBuild-Core ${args[@]}
+}
+
+function MSBuild-Core {
   if [[ "$ci" == true ]]; then
     if [[ "$binary_log" != true ]]; then
-      echo "Binary log must be enabled in CI build." >&2
+      EmitError "Binary log must be enabled in CI build."
       ExitWithExitCode 1
     fi
 
     if [[ "$node_reuse" == true ]]; then
-      echo "Node reuse must be disabled in CI build." >&2
+      EmitError "Node reuse must be disabled in CI build."
       ExitWithExitCode 1
     fi
   fi
@@ -325,7 +422,7 @@ function MSBuild {
 
   "$_InitializeBuildTool" "$_InitializeBuildToolCommand" /m /nologo /clp:Summary /v:$verbosity /nr:$node_reuse $warnaserror_switch /p:TreatWarningsAsErrors=$warn_as_error /p:ContinuousIntegrationBuild=$ci "$@" || {
     local exit_code=$?
-    echo "Build failed (exit code '$exit_code')." >&2
+    EmitError "Build failed (exit code '$exit_code')."
     ExitWithExitCode $exit_code
   }
 }
diff --git a/global.json b/global.json
index 30db777b992..e4c42b3c603 100644
--- a/global.json
+++ b/global.json
@@ -3,10 +3,12 @@
     "version": "3.0.100-preview5-011568"
   },
   "tools": {
+    "dotnet": "3.0.100-preview5-011568",
     "jdk": "11.0.3"
   },
   "msbuild-sdks": {
     "Yarn.MSBuild": "1.15.2",
-    "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19270.1"
+    "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19272.13",
+    "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19272.13"
   }
 }
-- 
GitLab