diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 823ec27c54..c6f0726d86 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,16 +1,19 @@
**Description of Change**
-
+
**Bugs Fixed**
-- Related to issue #
+- Fixes #
**API Changes**
+None.
+
**Behavioral Changes**
+None.
+
+**Required skia PR**
+
+None.
+
**PR Checklist**
- [ ] Has tests (if omitted, state reason in description)
- [ ] Rebased on top of main at time of PR
+- [ ] Merged related skia PRs
- [ ] Changes adhere to coding standard
- [ ] Updated documentation
diff --git a/scripts/azure-pipelines-complete.yml b/scripts/azure-pipelines-complete.yml
index c7ba12876e..ec1c1e6e43 100644
--- a/scripts/azure-pipelines-complete.yml
+++ b/scripts/azure-pipelines-complete.yml
@@ -11,8 +11,8 @@ pr:
parameters:
- name: buildExternals
displayName: 'The specific native artifacts to use for this build.'
- type: number
- default: 0
+ type: string
+ default: 'latest'
- name: VM_IMAGE_HOST
type: object
default:
diff --git a/scripts/azure-pipelines.yml b/scripts/azure-pipelines.yml
index 1a48f434ac..1bdd3839a5 100644
--- a/scripts/azure-pipelines.yml
+++ b/scripts/azure-pipelines.yml
@@ -11,8 +11,8 @@ pr:
parameters:
- name: buildExternals
displayName: 'The specific native artifacts to use for this build.'
- type: number
- default: 0
+ type: string
+ default: 'latest'
- name: VM_IMAGE_HOST
type: object
default:
@@ -25,33 +25,12 @@ parameters:
pool:
name: Azure Pipelines
vmImage: windows-2022
- - name: VM_IMAGE_MAC_NATIVE
+ - name: VM_IMAGE_MAC
type: object
default:
pool:
name: Azure Pipelines
vmImage: macos-11
- - name: VM_IMAGE_MAC
- type: object
- default:
- pool:
- name: VSEng-VSMac-Xamarin-Shared
- vmImage: VSEng-VSMac-Xamarin-Shared
- demands:
- - macOS.Name -equals Monterey
- - macOS.Architecture -equals x64
- - Agent.HasDevices -equals False
- - Agent.IsPaired -equals False
- variables:
- XCODE_VERSION: 13.3.0
- provisioningSteps:
- - task: xamops.azdevex.provisionator-task.provisionator@1
- displayName: 'Provision Xamarin'
- inputs:
- provisioning_script: ./scripts/provisionator.csx
- provisioning_extra_args: --force
- env:
- AUTH_TOKEN_GITHUB_COM: $(github--pat--vs-mobiletools-engineering-service2)
- name: VM_IMAGE_LINUX
type: object
default:
@@ -79,6 +58,6 @@ stages:
VM_IMAGE_WINDOWS: ${{ parameters.VM_IMAGE_WINDOWS }}
VM_IMAGE_WINDOWS_NATIVE: ${{ parameters.VM_IMAGE_WINDOWS }}
VM_IMAGE_MAC: ${{ parameters.VM_IMAGE_MAC }}
- VM_IMAGE_MAC_NATIVE: ${{ parameters.VM_IMAGE_MAC_NATIVE }}
+ VM_IMAGE_MAC_NATIVE: ${{ parameters.VM_IMAGE_MAC }}
VM_IMAGE_LINUX: ${{ parameters.VM_IMAGE_LINUX }}
VM_IMAGE_LINUX_NATIVE: ${{ parameters.VM_IMAGE_LINUX }}
diff --git a/scripts/azure-templates-bootstrapper.yml b/scripts/azure-templates-bootstrapper.yml
index b4b4f8defb..fbf24b8a1b 100644
--- a/scripts/azure-templates-bootstrapper.yml
+++ b/scripts/azure-templates-bootstrapper.yml
@@ -33,96 +33,302 @@ parameters:
tools: [] # any additional .net global tools
jobs:
- - ${{ if gt(parameters.buildExternals, 0) }}:
- - template: azure-templates-download.yml
- parameters:
- name: ${{ parameters.name }}
- displayName: ${{ parameters.displayName }}
- pool: ${{ parameters.vmImage.pool }}
- packages: ${{ parameters.packages }}
- target: ${{ parameters.target }}
- dependsOn: ${{ parameters.dependsOn }}
- variables:
- ${{ if ne(parameters.vmImage.variables, '') }}:
- ${{ parameters.vmImage.variables }}
- ${{ if ne(length(parameters.variables), 0) }}:
- ${{ parameters.variables }}
- requiredArtifacts: ${{ parameters.requiredArtifacts }}
- provisioningSteps:
- - ${{ if ne(parameters.vmImage.provisioningSteps, '') }}:
- - ${{ parameters.vmImage.provisioningSteps }}
- - ${{ if ne(length(parameters.provisioningSteps), 0) }}:
- - ${{ parameters.provisioningSteps }}
- preBuildSteps:
- - ${{ if ne(parameters.vmImage.preBuildSteps, '') }}:
- - ${{ parameters.vmImage.preBuildSteps }}
- - ${{ if ne(length(parameters.preBuildSteps), 0) }}:
- - ${{ parameters.preBuildSteps }}
- postBuildSteps: ${{ parameters.postBuildSteps }}
- initScript: ${{ parameters.initScript }}
- additionalArgs: ${{ parameters.additionalArgs }}
- retryCount: ${{ parameters.retryCount }}
- condition: ${{ parameters.condition }}
- shouldPublish: ${{ parameters.shouldPublish }}
- configuration: ${{ parameters.configuration }}
- buildExternals: ${{ parameters.buildExternals }}
- verbosity: ${{ parameters.verbosity }}
- docker: ${{ parameters.docker }}
- dockerArgs: ${{ parameters.dockerArgs }}
- installAndroidNdk: ${{ parameters.installAndroidNdk }}
- installAndroidSdk: ${{ parameters.installAndroidSdk }}
- installTizenSdk: ${{ parameters.installTizenSdk }}
- installWindowsSdk: ${{ parameters.installWindowsSdk }}
- installPreviewVs: ${{ parameters.installPreviewVs }}
- installDotNet: ${{ parameters.installDotNet }}
- installLlvm: ${{ parameters.installLlvm }}
- installEmsdk: ${{ parameters.installEmsdk }}
- artifactName: ${{ parameters.artifactName }}
- tools: ${{ parameters.tools }}
-
- - ${{ if not(gt(parameters.buildExternals, 0)) }}:
- - template: azure-templates-build.yml
- parameters:
- name: ${{ parameters.name }}
- displayName: ${{ parameters.displayName }}
- pool: ${{ parameters.vmImage.pool }}
- packages: ${{ parameters.packages }}
- target: ${{ parameters.target }}
- dependsOn: ${{ parameters.dependsOn }}
- variables:
- ${{ if ne(parameters.vmImage.variables, '') }}:
- ${{ parameters.vmImage.variables }}
- ${{ if ne(length(parameters.variables), 0) }}:
- ${{ parameters.variables }}
- requiredArtifacts: ${{ parameters.requiredArtifacts }}
- provisioningSteps:
- - ${{ if ne(parameters.vmImage.provisioningSteps, '') }}:
- - ${{ parameters.vmImage.provisioningSteps }}
- - ${{ if ne(length(parameters.provisioningSteps), 0) }}:
- - ${{ parameters.provisioningSteps }}
- preBuildSteps:
- - ${{ if ne(parameters.vmImage.preBuildSteps, '') }}:
- - ${{ parameters.vmImage.preBuildSteps }}
- - ${{ if ne(length(parameters.preBuildSteps), 0) }}:
- - ${{ parameters.preBuildSteps }}
- postBuildSteps: ${{ parameters.postBuildSteps }}
- initScript: ${{ parameters.initScript }}
- additionalArgs: ${{ parameters.additionalArgs }}
- retryCount: ${{ parameters.retryCount }}
- condition: ${{ parameters.condition }}
- shouldPublish: ${{ parameters.shouldPublish }}
- configuration: ${{ parameters.configuration }}
- buildPipelineType: ${{ parameters.buildPipelineType }}
- verbosity: ${{ parameters.verbosity }}
- docker: ${{ parameters.docker }}
- dockerArgs: ${{ parameters.dockerArgs }}
- installAndroidNdk: ${{ parameters.installAndroidNdk }}
- installAndroidSdk: ${{ parameters.installAndroidSdk }}
- installTizenSdk: ${{ parameters.installTizenSdk }}
- installWindowsSdk: ${{ parameters.installWindowsSdk }}
- installPreviewVs: ${{ parameters.installPreviewVs }}
- installDotNet: ${{ parameters.installDotNet }}
- installLlvm: ${{ parameters.installLlvm }}
- installEmsdk: ${{ parameters.installEmsdk }}
- artifactName: ${{ parameters.artifactName }}
- tools: ${{ parameters.tools }}
+ - job: ${{ parameters.name }}
+ displayName: ${{ parameters.displayName }}
+ timeoutInMinutes: 180
+ pool: ${{ parameters.vmImage.pool }}
+ dependsOn: ${{ parameters.dependsOn }}
+ condition: ${{ parameters.condition }}
+ variables:
+ ${{ if ne(parameters.vmImage.variables, '') }}:
+ ${{ parameters.vmImage.variables }}
+ ${{ if ne(length(parameters.variables), 0) }}:
+ ${{ parameters.variables }}
+ steps:
+ # prepare
+ - checkout: self
+ submodules: recursive
+ - template: azure-templates-variables.yml
+
+ # checkout required skia PR
+ - pwsh: .\scripts\checkout-skia.ps1
+ displayName: Checkout required skia PR
+ condition: eq(variables['Build.Reason'], 'PullRequest')
+
+ - ${{ if eq(parameters.buildPipelineType, 'tests') }}:
+ - template: azure-templates-github-status.yml
+ parameters:
+ state: 'pending'
+
+ # determine build type
+ - pwsh: .\scripts\get-build-type.ps1 -ExternalsBuildId '${{ parameters.buildExternals }}'
+ displayName: Determine build type
+
+ # provisioning steps
+ - ${{ if ne(parameters.vmImage.provisioningSteps, '') }}:
+ - ${{ parameters.vmImage.provisioningSteps }}
+ - ${{ if ne(length(parameters.provisioningSteps), 0) }}:
+ - ${{ parameters.provisioningSteps }}
+
+ # install any packages on linux
+ - ${{ if and(eq(parameters.docker, ''), endsWith(parameters.name, '_linux')) }}:
+ - bash: |
+ sudo apt update
+ sudo apt install -y ${{ parameters.packages }}
+ displayName: Install additional package dependencies
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''), ne('${{ parameters.packages }}', ''))
+
+ # make sure mono/msbuild is the correct version
+ - ${{ if and(ne(variables['MONO_VERSION_LINUX'], ''), eq(parameters.docker, ''), endsWith(parameters.name, '_linux')) }}:
+ - bash: ./scripts/install-mono.sh $(MONO_VERSION_LINUX)
+ displayName: Install Mono and MSBuild
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - ${{ if endsWith(parameters.name, '_macos') }}:
+ - bash: sudo ./scripts/select-xamarin.sh $(MONO_VERSION_MACOS)
+ displayName: Switch to the latest Xamarin SDK
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+
+ # install extra bits for the native builds
+ - ${{ if startsWith(parameters.name, 'native_') }}:
+ # switch to the correct Python version
+ - pwsh: .\scripts\install-python.ps1
+ displayName: Install Python
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - task: UsePythonVersion@0
+ displayName: Switch to the correct Python version
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ inputs:
+ versionSpec: '3.x'
+ architecture: 'x64'
+ - ${{ if not(contains(parameters.name, '_checks_')) }}:
+ # install android ndk
+ - ${{ if and(eq(parameters.installAndroidNdk, 'true'), contains(parameters.name, '_android_')) }}:
+ - pwsh: .\scripts\install-android-ndk.ps1
+ displayName: Install the Android NDK
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ # install tizen
+ - ${{ if and(eq(parameters.installTizenSdk, 'true'), contains(parameters.name, '_tizen_')) }}:
+ - pwsh: .\scripts\install-tizen.ps1
+ displayName: Install the Tizen SDK
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ # install llvm
+ - ${{ if and(eq(parameters.installLlvm, 'true'), contains(parameters.name, '_win32_')) }}:
+ - pwsh: .\scripts\install-7zip.ps1
+ displayName: Install 7-zip
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - pwsh: .\scripts\install-llvm.ps1
+ displayName: Install LLVM
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+
+ # install extra bits for the managed builds
+ - ${{ if and(not(startsWith(parameters.name, 'native_')), not(endsWith(parameters.name, '_linux'))) }}:
+ # install the bits needed for Android
+ - ${{ if eq(parameters.installAndroidSdk, 'true') }}:
+ # install the correct version of the JDK for .NET 6
+ - pwsh: |
+ if ("$env:JAVA_HOME_11_X64") {
+ echo "##vso[task.setvariable variable=JAVA_HOME]$env:JAVA_HOME_11_X64"
+ } else {
+ .\scripts\install-openjdk.ps1
+ }
+ displayName: Install OpenJDK
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ # install the correct version of the Android SDK
+ - pwsh: .\scripts\install-android-sdk.ps1
+ displayName: Install Android SDK
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ # install the required version of the Android Platforms
+ - pwsh: .\scripts\install-android-platform.ps1 -API 29
+ displayName: Install Android API 29 (v10)
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - pwsh: .\scripts\install-android-platform.ps1 -API 30
+ displayName: Install Android API 30 (v11)
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - pwsh: .\scripts\install-android-platform.ps1 -API 31
+ displayName: Install Android API 31 (v12)
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ # install the bits needed for .NET
+ - ${{ if eq(parameters.installDotNet, 'true') }}:
+ - ${{ if endsWith(parameters.name, '_macos') }}:
+ - pwsh: Remove-Item "$env:AGENT_TOOLSDIRECTORY/dotnet" -Recurse -Force -ErrorAction SilentlyContinue
+ displayName: Cleanup existing versions of .NET Core
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - task: UseDotNet@2
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ inputs:
+ packageType: 'sdk'
+ version: 3.1.x
+ displayName: Install .NET Core 3.1.x
+ - task: UseDotNet@2
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ inputs:
+ packageType: 'sdk'
+ version: 5.0.x
+ displayName: Install .NET Core 5.0.x
+ - task: UseDotNet@2
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ inputs:
+ packageType: 'sdk'
+ version: 6.0.x
+ displayName: Install .NET Core 6.0.x
+ # install the bits needed for .NET 6 builds
+ - pwsh: .\scripts\install-dotnet.ps1 -Version $env:DOTNET_VERSION_PREVIEW -InstallDir "$env:AGENT_TOOLSDIRECTORY/dotnet"
+ displayName: Install the preview version of .NET Core
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''), ne(variables.DOTNET_VERSION_PREVIEW, ''))
+ # display dotnet info
+ - pwsh: dotnet --info
+ displayName: Display all the .NET information
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ # install VS
+ - ${{ if endsWith(parameters.name, '_windows') }}:
+ - ${{ if eq(parameters.installPreviewVs, 'true') }}:
+ - pwsh: .\scripts\install-vs.ps1 -Version $(VISUAL_STUDIO_VERSION)
+ displayName: Install Visual Studio
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''), ne(variables.VISUAL_STUDIO_VERSION, ''))
+ # install workloads
+ - ${{ if not(endsWith(parameters.name, '_linux')) }}:
+ - pwsh: .\scripts\install-dotnet-workloads.ps1 -InstallDir "$env:AGENT_TOOLSDIRECTORY/dotnet" -SourceUrl "$env:DOTNET_WORKLOAD_SOURCE" -IsPreview $true
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''), ne(variables.DOTNET_VERSION_PREVIEW, ''))
+ displayName: Install the preview .NET Core workloads
+ - pwsh: .\scripts\install-dotnet-workloads.ps1 -InstallDir "$env:AGENT_TOOLSDIRECTORY/dotnet" -SourceUrl "$env:DOTNET_WORKLOAD_SOURCE" -IsPreview $false
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''), eq(variables.DOTNET_VERSION_PREVIEW, ''))
+ displayName: Install the .NET Core workloads
+
+ # select the correct/latest version of Visual Studio
+ - ${{ if endsWith(parameters.name, '_windows') }}:
+ - pwsh: .\scripts\select-vs.ps1
+ displayName: Select Visual Studio
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+
+ # install nuget
+ - ${{ if endsWith(parameters.name, '_windows') }}:
+ - pwsh: .\scripts\install-nuget.ps1
+ displayName: Install NuGet
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+
+ # install the mac tools
+ - ${{ if endsWith(parameters.name, '_macos') }}:
+ - bash: sudo ./scripts/select-xcode.sh $(XCODE_VERSION)
+ displayName: Switch to the latest Xcode
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+
+ # install the linux tools
+ - ${{ if and(eq(parameters.installEmsdk, 'true'), endsWith(parameters.name, '_linux')) }}:
+ - bash: ./scripts/install-emsdk.sh $(EMSCRIPTEN_VERSION)
+ displayName: Install the Emscripten SDK
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+
+ # install the Windows tools
+ - ${{ if endsWith(parameters.name, '_windows') }}:
+ - ${{ if not(contains(parameters.name, '_checks_')) }}:
+ # install the older Windows SDKs
+ - ${{ if eq(parameters.installWindowsSdk, 'true') }}:
+ - pwsh: .\scripts\install-winsdk.ps1 -LinkId 619296 -Version 10.0.10240.0
+ displayName: Install the Windows 10 SDK 10.0.10240
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - pwsh: .\scripts\install-winsdk.ps1 -LinkId 864422 -Version 10.0.16299.0
+ displayName: Install the Windows 10 SDK 10.0.16299
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - pwsh: .\scripts\install-winsdk.ps1 -LinkId 2083338 -Version 10.0.18362.0
+ displayName: Install the Windows 10 SDK 10.0.18362
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - pwsh: .\scripts\install-winsdk.ps1 -LinkId 2120843 -Version 10.0.19041.0
+ displayName: Install the Windows 10 SDK 10.0.19041
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+
+ # install any .NET Core global tools
+ - ${{ each tool in parameters.tools }}:
+ - pwsh: dotnet tool install -g ${{ tool }}
+ displayName: Install ${{ tool }}
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+
+ # download artifacts
+ - template: azure-templates-download-artifacts.yml
+ parameters:
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ artifacts: ${{ parameters.requiredArtifacts }}
+ - template: azure-templates-download-artifacts.yml
+ parameters:
+ condition: and(succeeded(), ne(variables['DOWNLOAD_EXTERNALS'], ''))
+ sourceBuildId: $(DOWNLOAD_EXTERNALS)
+ artifacts:
+ - name: ${{ parameters.name }}
+
+ # pre-build steps
+ - ${{ if ne(parameters.vmImage.preBuildSteps, '') }}:
+ - ${{ parameters.vmImage.preBuildSteps }}
+ - ${{ if ne(length(parameters.preBuildSteps), 0) }}:
+ - ${{ parameters.preBuildSteps }}
+
+ # build
+ - ${{ if eq(parameters.docker, '') }}:
+ - ${{ if endsWith(parameters.name, '_windows') }}:
+ - pwsh: |
+ dotnet tool restore
+ ${{ parameters.initScript }}
+ .\scripts\retry-command.ps1 -RetryCount ${{ parameters.retryCount }} {
+ dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }}
+ }
+ env:
+ JavaSdkDirectory: $(JAVA_HOME)
+ LLVM_HOME: $(LLVM_HOME)
+ # There seems to be a bug in some verions of mspdbcmf.exe. This looks to be fixed in a VS preview.
+ AppxSymbolPackageEnabled: false
+ displayName: Run the bootstrapper for ${{ parameters.target }}
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - ${{ if not(endsWith(parameters.name, '_windows')) }}:
+ - bash: |
+ dotnet tool restore
+ ${{ parameters.initScript }}
+ ./scripts/retry-command.sh ${{ parameters.retryCount }} \
+ dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }}
+ env:
+ JavaSdkDirectory: $(JAVA_HOME)
+ displayName: Run the bootstrapper for ${{ parameters.target }}
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - ${{ if ne(parameters.docker, '') }}:
+ - task: Docker@2
+ displayName: Build the Docker image for ${{ parameters.docker }}
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ inputs:
+ command: build
+ buildContext: ${{ parameters.docker }}
+ dockerfile: ${{ parameters.docker }}/Dockerfile
+ arguments: --tag skiasharp ${{ parameters.dockerArgs }}
+ - bash: |
+ echo dotnet tool restore > cmd.sh
+ echo dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }} >> cmd.sh
+ sed -i 's/--gnArgs=\" \"//' cmd.sh
+ docker run --rm --name skiasharp --volume $(pwd):/work skiasharp /bin/bash \
+ scripts/retry-command.sh ${{ parameters.retryCount }} \
+ /bin/bash /work/cmd.sh
+ displayName: Run the bootstrapper for ${{ parameters.target }} using the Docker image
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+
+ # post-build steps
+ - ${{ parameters.postBuildSteps }}
+
+ # publish artifacts
+ - task: PublishBuildArtifacts@1
+ displayName: Publish the ${{ parameters.name }} artifacts
+ condition: or(${{ parameters.shouldPublish }}, failed())
+ inputs:
+ artifactName: ${{ parameters.name }}
+ pathToPublish: 'output'
+ - ${{ if ne(parameters.artifactName, '') }}:
+ - task: PublishBuildArtifacts@1
+ displayName: Publish the combined ${{ parameters.artifactName }} artifacts
+ inputs:
+ artifactName: ${{ parameters.artifactName }}
+ pathToPublish: 'output'
+ - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}:
+ - task: ComponentGovernanceComponentDetection@0
+ displayName: Run component detection
+ condition: always()
+ inputs:
+ scanType: 'Register'
+ verbosity: 'Verbose'
+ alertWarningLevel: 'High'
+
+ - ${{ if eq(parameters.buildPipelineType, 'tests') }}:
+ - template: azure-templates-github-status.yml
diff --git a/scripts/azure-templates-build.yml b/scripts/azure-templates-build.yml
deleted file mode 100644
index 5a93f4088d..0000000000
--- a/scripts/azure-templates-build.yml
+++ /dev/null
@@ -1,275 +0,0 @@
-parameters:
- name: '' # in the form type_platform_host
- displayName: '' # the human name
- pool: '' # the agent pool
- packages: '' # any additional packages
- target: '' # the bootstrapper target
- dependsOn: [] # the dependiencies
- variables: [] # the job variables
- requiredArtifacts: [] # the artifacts that this build needs to download
- provisioningSteps: [] # any steps to run to provision the machine
- preBuildSteps: [] # any steps to run before the build
- postBuildSteps: [] # any additional steps to run after the build
- initScript: '' # any scripts to run before starting the bootstrapper
- additionalArgs: '' # any additional arguments to pass to the bootstrapper
- retryCount: 1 # the number of times to retry the bootstrapper
- condition: succeeded() # whether or not to run this template
- shouldPublish: true # whether or not to publish the artifacts
- configuration: $(CONFIGURATION) # the build configuration
- buildPipelineType: 'both' # the type of build pipeline setup
- verbosity: $(VERBOSITY) # the level of verbosity to use when building
- docker: '' # the Docker image to build and use
- dockerArgs: '' # any additional arguments to pass to docker build
- installAndroidNdk: true # whether or not to install the Android NDK
- installAndroidSdk: true # whether or not to install the Android SDK
- installTizenSdk: true # whether or not to install the Tizen SDK
- installWindowsSdk: true # whether or not to install the Windows SDK
- installPreviewVs: false # whether or not to install the preview VS
- installDotNet: true # whether or not to install the dotnet SDK
- installLlvm: true # whether or not to install the LLVM compiler
- installEmsdk: false # whether or not to install the Emscripten SDK
- artifactName: '' # the name of the artifact to merge this run into
-
-jobs:
- - job: ${{ parameters.name }}
- displayName: ${{ parameters.displayName }}
- timeoutInMinutes: 180
- pool: ${{ parameters.pool }}
- dependsOn: ${{ parameters.dependsOn }}
- condition: ${{ parameters.condition }}
- variables: ${{ parameters.variables }}
- steps:
- # prepare
- - checkout: self
- submodules: recursive
- - template: azure-templates-variables.yml
-
- - ${{ if eq(parameters.buildPipelineType, 'tests') }}:
- - template: azure-templates-github-status.yml
- parameters:
- state: 'pending'
-
- # provisioning steps
- - ${{ parameters.provisioningSteps }}
-
- # install any packages on linux
- - ${{ if and(eq(parameters.docker, ''), endsWith(parameters.name, '_linux')) }}:
- - bash: |
- sudo apt update
- sudo apt install -y ${{ parameters.packages }}
- displayName: Install additional package dependencies
- condition: and(succeeded(), ne('${{ parameters.packages }}', ''))
-
- # make sure mono/msbuild is the correct version
- - ${{ if and(ne(variables['MONO_VERSION_LINUX'], ''), eq(parameters.docker, ''), endsWith(parameters.name, '_linux')) }}:
- - bash: ./scripts/install-mono.sh $(MONO_VERSION_LINUX)
- displayName: Install Mono and MSBuild
- - ${{ if endsWith(parameters.name, '_macos') }}:
- - bash: sudo ./scripts/select-xamarin.sh $(MONO_VERSION_MACOS)
- displayName: Switch to the latest Xamarin SDK
-
- # install extra bits for the native builds
- - ${{ if startsWith(parameters.name, 'native_') }}:
- # switch to the correct Python version
- - pwsh: .\scripts\install-python.ps1
- displayName: Install Python
- - task: UsePythonVersion@0
- displayName: Switch to the correct Python version
- inputs:
- versionSpec: '3.x'
- architecture: 'x64'
- - ${{ if not(contains(parameters.name, '_checks_')) }}:
- # install android ndk
- - ${{ if and(eq(parameters.installAndroidNdk, 'true'), contains(parameters.name, '_android_')) }}:
- - pwsh: .\scripts\install-android-ndk.ps1
- displayName: Install the Android NDK
- # install tizen
- - ${{ if and(eq(parameters.installTizenSdk, 'true'), contains(parameters.name, '_tizen_')) }}:
- - pwsh: .\scripts\install-tizen.ps1
- displayName: Install the Tizen SDK
- # install llvm
- - ${{ if and(eq(parameters.installLlvm, 'true'), contains(parameters.name, '_win32_')) }}:
- - pwsh: .\scripts\install-7zip.ps1
- displayName: Install 7-zip
- - pwsh: .\scripts\install-llvm.ps1
- displayName: Install LLVM
-
- # install extra bits for the managed builds
- - ${{ if and(not(startsWith(parameters.name, 'native_')), not(endsWith(parameters.name, '_linux'))) }}:
- # install the bits needed for Android
- - ${{ if eq(parameters.installAndroidSdk, 'true') }}:
- # install the correct version of the JDK for .NET 6
- - pwsh: |
- if ("$env:JAVA_HOME_11_X64") {
- echo "##vso[task.setvariable variable=JAVA_HOME]$env:JAVA_HOME_11_X64"
- } else {
- .\scripts\install-openjdk.ps1
- }
- displayName: Install OpenJDK
- # install the correct version of the Android SDK
- - pwsh: .\scripts\install-android-sdk.ps1
- displayName: Install Android SDK
- # install the required version of the Android Platforms
- - pwsh: .\scripts\install-android-platform.ps1 -API 29
- displayName: Install Android API 29 (v10)
- - pwsh: .\scripts\install-android-platform.ps1 -API 30
- displayName: Install Android API 30 (v11)
- - pwsh: .\scripts\install-android-platform.ps1 -API 31
- displayName: Install Android API 31 (v12)
- # install the bits needed for .NET
- - ${{ if eq(parameters.installDotNet, 'true') }}:
- - ${{ if endsWith(parameters.name, '_macos') }}:
- - pwsh: Remove-Item "$env:AGENT_TOOLSDIRECTORY/dotnet" -Recurse -Force -ErrorAction SilentlyContinue
- displayName: Cleanup existing versions of .NET Core
- - task: UseDotNet@2
- inputs:
- packageType: 'sdk'
- version: 3.1.x
- displayName: Install .NET Core 3.1.x
- - task: UseDotNet@2
- inputs:
- packageType: 'sdk'
- version: 5.0.x
- displayName: Install .NET Core 5.0.x
- - task: UseDotNet@2
- inputs:
- packageType: 'sdk'
- version: 6.0.x
- displayName: Install .NET Core 6.0.x
- # install the bits needed for .NET 6 builds
- - pwsh: .\scripts\install-dotnet.ps1 -Version $env:DOTNET_VERSION_PREVIEW -InstallDir "$env:AGENT_TOOLSDIRECTORY/dotnet"
- displayName: Install the preview version of .NET Core
- condition: and(succeeded(), ne(variables.DOTNET_VERSION_PREVIEW, ''))
- # display dotnet info
- - pwsh: dotnet --info
- displayName: Display all the .NET information
- # install VS
- - ${{ if endsWith(parameters.name, '_windows') }}:
- - ${{ if eq(parameters.installPreviewVs, 'true') }}:
- - pwsh: .\scripts\install-vs.ps1 -Version $(VISUAL_STUDIO_VERSION)
- displayName: Install Visual Studio
- condition: ne(variables.VISUAL_STUDIO_VERSION, '')
- # install workloads
- - ${{ if not(endsWith(parameters.name, '_linux')) }}:
- - pwsh: .\scripts\install-dotnet-workloads.ps1 -InstallDir "$env:AGENT_TOOLSDIRECTORY/dotnet" -SourceUrl "$env:DOTNET_WORKLOAD_SOURCE" -IsPreview $true
- condition: and(succeeded(), ne(variables.DOTNET_VERSION_PREVIEW, ''))
- displayName: Install the preview .NET Core workloads
- - pwsh: .\scripts\install-dotnet-workloads.ps1 -InstallDir "$env:AGENT_TOOLSDIRECTORY/dotnet" -SourceUrl "$env:DOTNET_WORKLOAD_SOURCE" -IsPreview $false
- condition: and(succeeded(), eq(variables.DOTNET_VERSION_PREVIEW, ''))
- displayName: Install the .NET Core workloads
-
- # select the correct/latest version of Visual Studio
- - ${{ if endsWith(parameters.name, '_windows') }}:
- - pwsh: .\scripts\select-vs.ps1
- displayName: Select Visual Studio
-
- # install nuget
- - ${{ if endsWith(parameters.name, '_windows') }}:
- - pwsh: .\scripts\install-nuget.ps1
- displayName: Install NuGet
-
- # install the mac tools
- - ${{ if endsWith(parameters.name, '_macos') }}:
- - bash: sudo ./scripts/select-xcode.sh $(XCODE_VERSION)
- displayName: Switch to the latest Xcode
-
- # install the linux tools
- - ${{ if and(eq(parameters.installEmsdk, 'true'), endsWith(parameters.name, '_linux')) }}:
- - bash: ./scripts/install-emsdk.sh $(EMSCRIPTEN_VERSION)
- displayName: Install the Emscripten SDK
-
- # install the Windows tools
- - ${{ if endsWith(parameters.name, '_windows') }}:
- - ${{ if not(contains(parameters.name, '_checks_')) }}:
- # install the older Windows SDKs
- - ${{ if eq(parameters.installWindowsSdk, 'true') }}:
- - pwsh: .\scripts\install-winsdk.ps1 -LinkId 619296 -Version 10.0.10240.0
- displayName: Install the Windows 10 SDK 10.0.10240
- - pwsh: .\scripts\install-winsdk.ps1 -LinkId 864422 -Version 10.0.16299.0
- displayName: Install the Windows 10 SDK 10.0.16299
- - pwsh: .\scripts\install-winsdk.ps1 -LinkId 2083338 -Version 10.0.18362.0
- displayName: Install the Windows 10 SDK 10.0.18362
- - pwsh: .\scripts\install-winsdk.ps1 -LinkId 2120843 -Version 10.0.19041.0
- displayName: Install the Windows 10 SDK 10.0.19041
-
- # install any .NET Core global tools
- - ${{ each tool in parameters.tools }}:
- - pwsh: dotnet tool install -g ${{ tool }}
- displayName: Install ${{ tool }}
-
- # download artifacts
- - template: azure-templates-download-artifacts.yml
- parameters:
- artifacts: ${{ parameters.requiredArtifacts }}
-
- # pre-build steps
- - ${{ parameters.preBuildSteps }}
-
- # build
- - ${{ if eq(parameters.docker, '') }}:
- - ${{ if endsWith(parameters.name, '_windows') }}:
- - pwsh: |
- dotnet tool restore
- ${{ parameters.initScript }}
- .\scripts\retry-command.ps1 -RetryCount ${{ parameters.retryCount }} {
- dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }}
- }
- env:
- JavaSdkDirectory: $(JAVA_HOME)
- LLVM_HOME: $(LLVM_HOME)
- # There seems to be a bug in some verions of mspdbcmf.exe. This looks to be fixed in a VS preview.
- AppxSymbolPackageEnabled: false
- displayName: Run the bootstrapper for ${{ parameters.target }}
- - ${{ if not(endsWith(parameters.name, '_windows')) }}:
- - bash: |
- dotnet tool restore
- ${{ parameters.initScript }}
- ./scripts/retry-command.sh ${{ parameters.retryCount }} \
- dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }}
- env:
- JavaSdkDirectory: $(JAVA_HOME)
- displayName: Run the bootstrapper for ${{ parameters.target }}
- - ${{ if ne(parameters.docker, '') }}:
- - task: Docker@2
- displayName: Build the Docker image for ${{ parameters.docker }}
- inputs:
- command: build
- buildContext: ${{ parameters.docker }}
- dockerfile: ${{ parameters.docker }}/Dockerfile
- arguments: --tag skiasharp ${{ parameters.dockerArgs }}
- - bash: |
- echo dotnet tool restore > cmd.sh
- echo dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }} >> cmd.sh
- sed -i 's/--gnArgs=\" \"//' cmd.sh
- docker run --rm --name skiasharp --volume $(pwd):/work skiasharp /bin/bash \
- scripts/retry-command.sh ${{ parameters.retryCount }} \
- /bin/bash /work/cmd.sh
- displayName: Run the bootstrapper for ${{ parameters.target }} using the Docker image
-
- # post-build steps
- - ${{ parameters.postBuildSteps }}
-
- # publish artifacts
- - task: PublishBuildArtifacts@1
- displayName: Publish the ${{ parameters.name }} artifacts
- condition: or(${{ parameters.shouldPublish }}, failed())
- inputs:
- artifactName: ${{ parameters.name }}
- pathToPublish: 'output'
- - ${{ if ne(parameters.artifactName, '') }}:
- - task: PublishBuildArtifacts@1
- displayName: Publish the combined ${{ parameters.artifactName }} artifacts
- inputs:
- artifactName: ${{ parameters.artifactName }}
- pathToPublish: 'output'
- - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}:
- - task: ComponentGovernanceComponentDetection@0
- displayName: Run component detection
- condition: always()
- inputs:
- scanType: 'Register'
- verbosity: 'Verbose'
- alertWarningLevel: 'High'
-
- - ${{ if eq(parameters.buildPipelineType, 'tests') }}:
- - template: azure-templates-github-status.yml
diff --git a/scripts/azure-templates-download-artifacts.yml b/scripts/azure-templates-download-artifacts.yml
index 718c30e3ca..2af5bf528b 100644
--- a/scripts/azure-templates-download-artifacts.yml
+++ b/scripts/azure-templates-download-artifacts.yml
@@ -1,39 +1,57 @@
parameters:
sourceBuildId: ''
artifacts: [ ] # name, dir
+ condition: succeeded()
steps:
- - pwsh: |
- $buildId = "${{ parameters.sourceBuildId }}"
- if ($env:RESOURCES_PIPELINE_SKIASHARP_RUNID) {
- $buildId = $env:RESOURCES_PIPELINE_SKIASHARP_RUNID
- Write-Host "Using RESOURCES_PIPELINE_SKIASHARP_RUNID = '$env:RESOURCES_PIPELINE_SKIASHARP_RUNID'"
- }
- if (-not $buildId) {
- $buildId = $env:BUILD_BUILDID
- Write-Host "Using BUILD_BUILDID = '$env:BUILD_BUILDID'"
- }
- $pipelineId = "$env:SYSTEM_DEFINITIONID"
- if ($env:RESOURCES_PIPELINE_SKIASHARP_PIPELINEID) {
- $pipelineId = $env:RESOURCES_PIPELINE_SKIASHARP_PIPELINEID
- Write-Host "Using RESOURCES_PIPELINE_SKIASHARP_PIPELINEID = '$env:RESOURCES_PIPELINE_SKIASHARP_PIPELINEID'"
- }
- Write-Host "DOWNLOAD_BUILD_ID = '$buildId'"
- Write-Host "DOWNLOAD_PIPELINE_ID = '$pipelineId'"
- Write-Host "##vso[task.setvariable variable=DOWNLOAD_BUILD_ID]$buildId"
- Write-Host "##vso[task.setvariable variable=DOWNLOAD_PIPELINE_ID]$pipelineId"
- displayName: Ensure all the variables are set for the download
+ - ${{ if ne(length(parameters.artifacts), 0) }}:
+ - pwsh: |
+ $buildId = "${{ parameters.sourceBuildId }}"
+ if ($env:RESOURCES_PIPELINE_SKIASHARP_RUNID) {
+ $buildId = $env:RESOURCES_PIPELINE_SKIASHARP_RUNID
+ Write-Host "Using RESOURCES_PIPELINE_SKIASHARP_RUNID = '$env:RESOURCES_PIPELINE_SKIASHARP_RUNID'"
+ }
+ if (-not $buildId) {
+ $buildId = $env:BUILD_BUILDID
+ Write-Host "Using BUILD_BUILDID = '$env:BUILD_BUILDID'"
+ }
+ $versionType = 'specific'
+ if ($buildId -eq 'latest') {
+ $versionType = 'latestFromBranch'
+ }
+ $pipelineId = "$env:SYSTEM_DEFINITIONID"
+ if ($env:RESOURCES_PIPELINE_SKIASHARP_PIPELINEID) {
+ $pipelineId = $env:RESOURCES_PIPELINE_SKIASHARP_PIPELINEID
+ Write-Host "Using RESOURCES_PIPELINE_SKIASHARP_PIPELINEID = '$env:RESOURCES_PIPELINE_SKIASHARP_PIPELINEID'"
+ }
+ $branchName = "$env:BUILD_SOURCEBRANCH"
+ if ($env:SYSTEM_PULLREQUEST_TARGETBRANCH) {
+ $branchName = "refs/heads/$env:SYSTEM_PULLREQUEST_TARGETBRANCH"
+ }
+ Write-Host "DOWNLOAD_BUILD_ID = '$buildId'"
+ Write-Host "DOWNLOAD_PIPELINE_ID = '$pipelineId'"
+ Write-Host "DOWNLOAD_BRANCH = '$branchName'"
+ Write-Host "DOWNLOAD_VERSION_TYPE = '$versionType'"
+ Write-Host "##vso[task.setvariable variable=DOWNLOAD_BUILD_ID]$buildId"
+ Write-Host "##vso[task.setvariable variable=DOWNLOAD_PIPELINE_ID]$pipelineId"
+ Write-Host "##vso[task.setvariable variable=DOWNLOAD_BRANCH]$branchName"
+ Write-Host "##vso[task.setvariable variable=DOWNLOAD_VERSION_TYPE]$versionType"
+ displayName: Ensure all the variables are set for the download
+ condition: ${{ parameters.condition }}
- ${{ each artifact in parameters.artifacts }}:
- task: DownloadBuildArtifacts@0
displayName: Download the pre-built ${{ artifact.name }} artifacts
+ condition: ${{ parameters.condition }}
inputs:
buildType: 'specific'
project: '$(System.TeamProjectId)'
pipeline: '$(DOWNLOAD_PIPELINE_ID)'
- buildVersionToDownload: 'specific'
+ branchName: '$(DOWNLOAD_BRANCH)'
+ buildVersionToDownload: '$(DOWNLOAD_VERSION_TYPE)'
buildId: '$(DOWNLOAD_BUILD_ID)'
downloadType: 'single'
+ allowPartiallySucceededBuilds: true
artifactName: ${{ artifact.name }}
downloadPath: 'download-temp'
@@ -42,6 +60,8 @@ steps:
Get-ChildItem '.\download-temp\${{ artifact.name }}\' | Copy-Item -Destination '.\output\${{ artifact.dir }}\' -Recurse -Force
Remove-Item '.\download-temp\${{ artifact.name }}\' -Recurse -Force
displayName: Move the ${{ artifact.name }} artifacts to the ./output/${{ artifact.dir }} directory
+ condition: ${{ parameters.condition }}
- pwsh: Remove-Item ./output/logs/ -Recurse -Force -ErrorAction Ignore
displayName: Delete old logs
+ condition: ${{ parameters.condition }}
diff --git a/scripts/azure-templates-download.yml b/scripts/azure-templates-download.yml
deleted file mode 100644
index e9aaf69f9b..0000000000
--- a/scripts/azure-templates-download.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-parameters:
- name: '' # in the form type_platform_host
- displayName: '' # the human name
- pool: '' # the agent pool
- condition: succeeded() # whether or not to run this template
- buildExternals: '' # the build number to download externals from
- postBuildSteps: [] # any additional steps to run after the build
- artifactName: '' # the name of the artifact to merge this run into
-
-jobs:
- - job: ${{ parameters.name }}
- displayName: ${{ parameters.displayName }}
- pool: ${{ parameters.pool }}
- condition: ${{ parameters.condition }}
- variables: ${{ parameters.variables }}
- steps:
- - checkout: none
- - template: azure-templates-download-artifacts.yml
- parameters:
- sourceBuildId: ${{ parameters.buildExternals }}
- artifacts:
- - name: ${{ parameters.name }}
- - task: PublishBuildArtifacts@1
- displayName: Publish the ${{ parameters.name }} artifacts
- inputs:
- artifactName: ${{ parameters.name }}
- pathToPublish: 'output'
- - ${{ if ne(parameters.artifactName, '') }}:
- - task: PublishBuildArtifacts@1
- displayName: Publish the combined ${{ parameters.artifactName }} artifacts
- inputs:
- artifactName: ${{ parameters.artifactName }}
- pathToPublish: 'output'
- - ${{ parameters.postBuildSteps }}
diff --git a/scripts/azure-templates-stages.yml b/scripts/azure-templates-stages.yml
index d81d702cd0..cf90527bb5 100644
--- a/scripts/azure-templates-stages.yml
+++ b/scripts/azure-templates-stages.yml
@@ -3,8 +3,8 @@ parameters:
type: string
default: 'both'
- name: buildExternals
- type: number
- default: 0
+ type: string
+ default: 'latest'
- name: VM_IMAGE_HOST
type: object
- name: VM_IMAGE_WINDOWS
diff --git a/scripts/checkout-skia.ps1 b/scripts/checkout-skia.ps1
new file mode 100644
index 0000000000..b913c4b2ea
--- /dev/null
+++ b/scripts/checkout-skia.ps1
@@ -0,0 +1,33 @@
+$ErrorActionPreference = 'Stop'
+
+if (-not $env:SYSTEM_PULLREQUEST_PULLREQUESTNUMBER) {
+ Write-Host "Not a PR build."
+ exit 0
+}
+
+$json = curl `
+ -H "Accept: application/vnd.github.v3+json" `
+ https://api.github.com/repos/mono/SkiaSharp/pulls/$env:SYSTEM_PULLREQUEST_PULLREQUESTNUMBER | ConvertFrom-Json
+
+$regex = '\*\*Required\ skia\ PR\*\*[\\rn\s-]+https?\://github\.com/mono/skia/pull/(\d+)'
+
+$match = [regex]::Match($json.body, $regex, [System.Text.RegularExpressions.RegexOptions]::Singleline)
+
+if ((-not $match.Success) -or ($match.Groups.Count -ne 2)) {
+ Write-Host "No required skia PR specified."
+ exit 0
+}
+
+$skiaPR = $match.Groups[1].Value
+Write-Host "Found required skia PR: $skiaPR"
+
+try {
+ Push-Location externals/skia
+ git fetch --force --tags --prune --prune-tags --progress --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/pull/$skiaPR/merge:refs/remotes/pull/$skiaPR/merge
+ git checkout --progress --force refs/remotes/pull/$skiaPR/merge
+} finally {
+ Pop-Location
+}
+
+Write-Host "Requesting full build."
+Write-Host "##vso[task.setvariable variable=DOWNLOAD_EXTERNALS]required"
diff --git a/scripts/get-build-type.ps1 b/scripts/get-build-type.ps1
new file mode 100644
index 0000000000..da205d2eb0
--- /dev/null
+++ b/scripts/get-build-type.ps1
@@ -0,0 +1,54 @@
+param (
+ [string] $ExternalsBuildId = ''
+)
+
+$ErrorActionPreference = 'Stop'
+
+# some stage earlier requested a full build
+if ($env:DOWNLOAD_EXTERNALS -eq 'required') {
+ Write-Host "Full build explicitly requested."
+ Write-Host "##vso[task.setvariable variable=DOWNLOAD_EXTERNALS]"
+ exit 0
+}
+
+# this was explicit, so just us that
+$intBuildId = "$ExternalsBuildId" -as [int]
+if ($intBuildId -gt 0) {
+ Write-Host "Explicit managed-only build using $intBuildId."
+ Write-Host "##vso[task.setvariable variable=DOWNLOAD_EXTERNALS]$intBuildId"
+ exit 0
+}
+
+# if this is a PR and we are requesting last-build artifacts
+if (("$ExternalsBuildId" -eq 'latest') -and ("$env:BUILD_REASON" -eq 'PullRequest')) {
+ Write-Host "All changes:"
+ $all = (git diff-tree --no-commit-id --name-only -r HEAD~ HEAD)
+ foreach ($d in $all) {
+ Write-Host " - $d"
+ }
+
+ Write-Host "Matching changes:"
+ $matching = @(
+ 'cake',
+ 'externals',
+ 'native',
+ 'scripts',
+ '.gitmodules',
+ 'VERSIONS.txt'
+ )
+ $requiresFull = (git diff-tree --no-commit-id --name-only -r HEAD~ HEAD @matching)
+ foreach ($d in $requiresFull) {
+ Write-Host " - $d"
+ }
+
+ if (-not $requiresFull) {
+ Write-Host "Download-only build."
+ Write-Host "##vso[task.setvariable variable=DOWNLOAD_EXTERNALS]latest"
+ exit 0
+ }
+}
+
+# either not a PR, native files changed or explicit build-all
+Write-Host "Full build."
+Write-Host "##vso[task.setvariable variable=DOWNLOAD_EXTERNALS]"
+exit 0
diff --git a/source/SkiaSharp.Build.targets b/source/SkiaSharp.Build.targets
index b904632705..313f328b06 100644
--- a/source/SkiaSharp.Build.targets
+++ b/source/SkiaSharp.Build.targets
@@ -233,14 +233,15 @@ internal partial class VersionConstants {
$(IntermediateOutputPath)mdoc\
<_ShouldGenerateDocs Condition=" '$(MDocDocumentationDirectory)' != '' and Exists('$(MDocDocumentationDirectory)\index.xml') ">true
-
+
<_MDocInputs Include="$(MDocDocumentationDirectory)\**\*" />
-
+