| 1 | # Shared build job template for x64 and arm64 platforms. |
| 2 | # Parameterized by platform, with optional test artifact and CodeQL support. |
| 3 | |
| 4 | parameters: |
| 5 | - name: platform |
| 6 | type: string |
| 7 | |
| 8 | - name: isRelease |
| 9 | type: boolean |
| 10 | |
| 11 | - name: isNightly |
| 12 | type: boolean |
| 13 | |
| 14 | - name: packageVersion |
| 15 | type: string |
| 16 | |
| 17 | - name: traceLoggingConfig |
| 18 | type: string |
| 19 | default: '' |
| 20 | |
| 21 | - name: targets |
| 22 | type: object |
| 23 | |
| 24 | - name: pool |
| 25 | type: string |
| 26 | default: '' |
| 27 | |
| 28 | - name: vsoOrg |
| 29 | type: string |
| 30 | |
| 31 | - name: vsoProject |
| 32 | type: string |
| 33 | |
| 34 | - name: artifactSuffix |
| 35 | type: string |
| 36 | |
| 37 | - name: esrp |
| 38 | type: object |
| 39 | |
| 40 | # x64-only features |
| 41 | - name: includeTestArtifacts |
| 42 | type: boolean |
| 43 | default: false |
| 44 | |
| 45 | - name: includeCodeQL |
| 46 | type: boolean |
| 47 | default: false |
| 48 | |
| 49 | - name: dependsOn |
| 50 | type: string |
| 51 | default: '' |
| 52 | |
| 53 | jobs: |
| 54 | - job: build_${{ parameters.platform }} |
| 55 | displayName: "Build WSL package (${{ parameters.platform }})" |
| 56 | timeoutInMinutes: 120 |
| 57 | ${{ if ne(parameters.dependsOn, '') }}: |
| 58 | dependsOn: ${{ parameters.dependsOn }} |
| 59 | |
| 60 | ${{ if eq(parameters.pool, '') }}: |
| 61 | pool: {'type': 'windows'} |
| 62 | |
| 63 | ${{ else }}: |
| 64 | pool: ${{ parameters.pool }} |
| 65 | |
| 66 | variables: |
| 67 | NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS: 60 |
| 68 | NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS: 60 |
| 69 | ob_outputDirectory: '$(Build.SourcesDirectory)\out' |
| 70 | ob_artifactBaseName: 'drop_wsl' |
| 71 | ob_artifactSuffix: '${{ parameters.artifactSuffix }}' |
| 72 | packageStagingDir: '$(Build.SourcesDirectory)\packageStagingDir' |
| 73 | ob_sdl_codeSignValidation_excludes: -|**\*.ps1;-|**\testbin\** |
| 74 | ${{ if parameters.includeCodeQL }}: |
| 75 | Codeql.PublishDatabaseLog: true |
| 76 | Codeql.SourceRoot: src |
| 77 | ${{ if eq(parameters.isRelease, true) }}: |
| 78 | packageInputDirArg: '-DPACKAGE_INPUT_DIR=$(packageStagingDir)' |
| 79 | ${{ else }}: |
| 80 | packageInputDirArg: '' |
| 81 | |
| 82 | steps: |
| 83 | |
| 84 | - ${{ if parameters.includeCodeQL }}: |
| 85 | - task: CodeQL3000Init@0 |
| 86 | inputs: |
| 87 | Enabled: ${{ and(parameters.isNightly, eq(variables['Build.SourceBranch'], 'refs/heads/main'))}} |
| 88 | |
| 89 | - ${{ if eq(parameters.isRelease, true) }}: |
| 90 | - task: UseDotNet@2 |
| 91 | displayName: Install .NET Core SDK (required by EsrpCodeSigning) |
| 92 | inputs: |
| 93 | packageType: "sdk" |
| 94 | |
| 95 | - task: PowerShell@2 |
| 96 | displayName: Set trace logging configuration |
| 97 | condition: ne('${{ parameters.traceLoggingConfig }}', '') |
| 98 | inputs: |
| 99 | targetType: 'inline' |
| 100 | script: 'Set-Content -Path src/windows/inc/traceloggingconfig.h -Value $env:config.replace("\n", "`n")' |
| 101 | env: |
| 102 | config: '${{ parameters.traceLoggingConfig }}' |
| 103 | |
| 104 | - task: PowerShell@2 |
| 105 | displayName: "Compute package version" |
| 106 | name: version |
| 107 | inputs: |
| 108 | targetType: inline |
| 109 | ${{ if eq(parameters.packageVersion, '') }}: |
| 110 | script: | |
| 111 | $gitversion_version = (Select-Xml -Path packages.config -XPath '/packages/package[@id=''GitVersion.CommandLine'']/@version').Node.Value |
| 112 | $env:path = "packages/GitVersion.CommandLine.$gitversion_version/tools;$env:path" |
| 113 | . .\tools\devops\version_functions.ps1 |
| 114 | $version = Get-VersionInfo -Nightly $${{ parameters.isNightly }} |
| 115 | Write-Host "##vso[task.setvariable variable=WSL_PACKAGE_VERSION;isOutput=true]$($version.MsixVersion)" |
| 116 | Write-Host "##vso[task.setvariable variable=WSL_NUGET_PACKAGE_VERSION;isOutput=true]$($version.NugetVersion)" |
| 117 | |
| 118 | ${{ else }}: |
| 119 | script: | |
| 120 | Write-Host "##vso[task.setvariable variable=WSL_PACKAGE_VERSION;isOutput=true]$([string]('${{ parameters.packageVersion }}' + '.0'))" |
| 121 | Write-Host "##vso[task.setvariable variable=WSL_NUGET_PACKAGE_VERSION;isOutput=true]$([string]('${{ parameters.packageVersion }}'))" |
| 122 | |
| 123 | - task: CMake@1 |
| 124 | displayName: "CMake ${{ parameters.platform }}" |
| 125 | inputs: |
| 126 | workingDirectory: "." |
| 127 | cmakeArgs: . --fresh -A ${{ parameters.platform }} -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_VERSION=10.0.26100.0 -DPACKAGE_VERSION=$(version.WSL_PACKAGE_VERSION) -DWSL_NUGET_PACKAGE_VERSION=$(version.WSL_NUGET_PACKAGE_VERSION) -DSKIP_PACKAGE_SIGNING=${{ parameters.isRelease }} -DOFFICIAL_BUILD=${{ parameters.isRelease }} -DINCLUDE_PACKAGE_STAGE=${{ or(parameters.isRelease, parameters.isNightly) }} -DPIPELINE_BUILD_ID=$(Build.BuildId) -DVSO_ORG=${{ parameters.vsoOrg }} -DVSO_PROJECT=${{ parameters.vsoProject }} -DWSL_BUILD_WSL_SETTINGS=true -DWSL_INCLUDE_SDK_CSHARP=true -DWSL_UNITY_BATCH_SIZE=4 $(packageInputDirArg)\${{ parameters.platform }} |
| 128 | |
| 129 | # Workaround for WSL Settings NuGet restore authentication issue |
| 130 | - script: _deps\nuget.exe restore -NonInteractive |
| 131 | |
| 132 | - ${{ each target in parameters.targets }}: |
| 133 | - script: cmake --build . --config Release --target ${{ target.target }} -- -m |
| 134 | displayName: "Build ${{ target.target }} (${{ parameters.platform }})" |
| 135 | |
| 136 | - ${{ if eq(parameters.isRelease, true) }}: |
| 137 | - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5 |
| 138 | displayName: "Sign ${{ target.target }} (${{ parameters.platform }})" |
| 139 | inputs: |
| 140 | ConnectedServiceName: ${{ parameters.esrp.ConnectedServiceName}} |
| 141 | signConfigType: ${{ parameters.esrp.signConfigType }} |
| 142 | SessionTimeout: ${{ parameters.esrp.SessionTimeout }} |
| 143 | MaxConcurrency: ${{ parameters.esrp.MaxConcurrency }} |
| 144 | MaxRetryAttempts: ${{ parameters.esrp.MaxRetryAttempts }} |
| 145 | ServiceEndpointUrl: ${{ parameters.esrp.ServiceEndpointUrl }} |
| 146 | AuthAKVName: ${{ parameters.esrp.AuthAKVName }} |
| 147 | AuthSignCertName: ${{ parameters.esrp.AuthSignCertName }} |
| 148 | AppRegistrationClientId: ${{ parameters.esrp.AppRegistrationClientId }} |
| 149 | AppRegistrationTenantId: ${{ parameters.esrp.AppRegistrationTenantId }} |
| 150 | FolderPath: "bin\\${{ parameters.platform }}\\Release" |
| 151 | Pattern: "${{ target.pattern }}" |
| 152 | UseMSIAuthentication: true |
| 153 | EsrpClientId: ${{ parameters.esrp.EsrpClientId }} |
| 154 | inlineOperation: | |
| 155 | [ |
| 156 | { |
| 157 | "KeyCode": "CP-230012", |
| 158 | "OperationCode": "SigntoolSign", |
| 159 | "Parameters" : { |
| 160 | "OpusName" : "Microsoft", |
| 161 | "OpusInfo" : "http://www.microsoft.com", |
| 162 | "FileDigest" : "/fd \"SHA256\"", |
| 163 | "PageHash" : "/NPH", |
| 164 | "TimeStamp" : "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" |
| 165 | }, |
| 166 | "ToolName" : "sign", |
| 167 | "ToolVersion" : "1.0" |
| 168 | }, |
| 169 | { |
| 170 | "KeyCode" : "CP-230012", |
| 171 | "OperationCode" : "SigntoolVerify", |
| 172 | "Parameters" : {}, |
| 173 | "ToolName" : "sign", |
| 174 | "ToolVersion" : "1.0" |
| 175 | } |
| 176 | ] |
| 177 | |
| 178 | - task: PowerShell@2 |
| 179 | displayName: "Copy signed ${{ target.target }} to staging (${{ parameters.platform }})" |
| 180 | inputs: |
| 181 | targetType: inline |
| 182 | script: | |
| 183 | $arch = '${{ parameters.platform }}' |
| 184 | $pattern = '${{ target.pattern }}' |
| 185 | $inputDir = "bin\$arch\Release" |
| 186 | $outputDir = "$(packageStagingDir)\$arch" |
| 187 | New-Item -ItemType Directory -Path "$outputDir\wslsettings" -Force |
| 188 | foreach ($file in $pattern.Split(',')) { |
| 189 | $sourcePath = Join-Path $inputDir $file |
| 190 | if (Test-Path $sourcePath) { |
| 191 | $destPath = Join-Path $outputDir $file |
| 192 | Write-Host "Copying signed file: $sourcePath -> $destPath" |
| 193 | Copy-Item -Path $sourcePath -Destination $destPath -Force |
| 194 | } else { |
| 195 | Write-Warning "File not found: $sourcePath" |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | - script: cmake --build . --config Release -- -m |
| 200 | displayName: "Build remaining targets (${{ parameters.platform }})" |
| 201 | |
| 202 | - task: PowerShell@2 |
| 203 | displayName: "Stage MSI and installer msix (${{ parameters.platform }})" |
| 204 | inputs: |
| 205 | targetType: inline |
| 206 | script: | |
| 207 | New-Item -ItemType Directory -Path "$(ob_outputDirectory)\bundle" -Force |
| 208 | New-Item -ItemType Directory -Path "$(ob_outputDirectory)\installer" -Force |
| 209 | Copy-Item -Path "bin\${{ parameters.platform }}\release\wsl.msi" -Destination "$(ob_outputDirectory)\bundle\wsl.$(version.WSL_PACKAGE_VERSION).${{ parameters.platform }}.msi" |
| 210 | Copy-Item -Path "bin\${{ parameters.platform }}\release\installer.msix" -Destination "$(ob_outputDirectory)\installer\installer.${{ parameters.platform }}.msix" |
| 211 | if (Test-Path "generated\dev-cert.pfx") { Copy-Item "generated\dev-cert.pfx" "$(ob_outputDirectory)\installer\dev-cert.pfx" } |
| 212 | New-Item -ItemType Directory -Path "$(ob_outputDirectory)\sdk\${{ parameters.platform }}" -Force |
| 213 | Copy-Item -Path "bin\${{ parameters.platform }}\release\wslcsdk.lib" -Destination "$(ob_outputDirectory)\sdk\${{ parameters.platform }}\wslcsdk.lib" |
| 214 | if ('${{ parameters.isRelease }}' -eq 'True') { |
| 215 | Copy-Item -Path "$(packageStagingDir)\${{ parameters.platform }}\wslcsdk.dll" -Destination "$(ob_outputDirectory)\sdk\${{ parameters.platform }}\wslcsdk.dll" |
| 216 | Copy-Item -Path "$(packageStagingDir)\${{ parameters.platform }}\wslcsdkcs.dll" -Destination "$(ob_outputDirectory)\sdk\${{ parameters.platform }}\wslcsdkcs.dll" |
| 217 | Copy-Item -Path "$(packageStagingDir)\${{ parameters.platform }}\Microsoft.WSL.Containers.winmd" -Destination "$(ob_outputDirectory)\sdk\${{ parameters.platform }}\Microsoft.WSL.Containers.winmd" |
| 218 | } else { |
| 219 | Copy-Item -Path "bin\${{ parameters.platform }}\release\wslcsdk.dll" -Destination "$(ob_outputDirectory)\sdk\${{ parameters.platform }}\wslcsdk.dll" |
| 220 | Copy-Item -Path "bin\${{ parameters.platform }}\release\wslcsdkcs.dll" -Destination "$(ob_outputDirectory)\sdk\${{ parameters.platform }}\wslcsdkcs.dll" |
| 221 | Copy-Item -Path "bin\${{ parameters.platform }}\release\Microsoft.WSL.Containers.winmd" -Destination "$(ob_outputDirectory)\sdk\${{ parameters.platform }}\Microsoft.WSL.Containers.winmd" |
| 222 | } |
| 223 | |
| 224 | - task: PowerShell@2 |
| 225 | displayName: "Create CAB from ${{ parameters.platform }} installer msi" |
| 226 | inputs: |
| 227 | targetType: inline |
| 228 | script: | |
| 229 | $arch = '${{ parameters.platform }}' |
| 230 | $bundleDir = "$(ob_outputDirectory)\bundle" |
| 231 | $msiPath = Join-Path $bundleDir "wsl.$(version.WSL_PACKAGE_VERSION).$arch.msi" |
| 232 | $cabPath = Join-Path $bundleDir "wsl.$(version.WSL_PACKAGE_VERSION).$arch.cab" |
| 233 | |
| 234 | if (-not (Test-Path -Path $msiPath)) { |
| 235 | throw "Input MSI not found for architecture '$arch': $msiPath" |
| 236 | } |
| 237 | |
| 238 | Write-Host "Creating CAB from MSI: $msiPath -> $cabPath" |
| 239 | & makecab.exe $msiPath $cabPath |
| 240 | |
| 241 | if ($LASTEXITCODE -ne 0) { |
| 242 | throw "makecab.exe failed with exit code $LASTEXITCODE for architecture '$arch'." |
| 243 | } |
| 244 | |
| 245 | if (-not (Test-Path -Path $cabPath)) { |
| 246 | throw "CAB file was not created at expected path: $cabPath" |
| 247 | } |
| 248 | |
| 249 | - ${{ if eq(parameters.isRelease, true) }}: |
| 250 | - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5 |
| 251 | displayName: "Sign CAB (${{ parameters.platform }})" |
| 252 | inputs: |
| 253 | ConnectedServiceName: ${{ parameters.esrp.ConnectedServiceName}} |
| 254 | signConfigType: ${{ parameters.esrp.signConfigType }} |
| 255 | SessionTimeout: ${{ parameters.esrp.SessionTimeout }} |
| 256 | MaxConcurrency: ${{ parameters.esrp.MaxConcurrency }} |
| 257 | MaxRetryAttempts: ${{ parameters.esrp.MaxRetryAttempts }} |
| 258 | ServiceEndpointUrl: ${{ parameters.esrp.ServiceEndpointUrl }} |
| 259 | AuthAKVName: ${{ parameters.esrp.AuthAKVName }} |
| 260 | AuthSignCertName: ${{ parameters.esrp.AuthSignCertName }} |
| 261 | AppRegistrationClientId: ${{ parameters.esrp.AppRegistrationClientId }} |
| 262 | AppRegistrationTenantId: ${{ parameters.esrp.AppRegistrationTenantId }} |
| 263 | FolderPath: "$(ob_outputDirectory)\\bundle" |
| 264 | Pattern: "*.cab" |
| 265 | UseMSIAuthentication: true |
| 266 | EsrpClientId: ${{ parameters.esrp.EsrpClientId }} |
| 267 | inlineOperation: | |
| 268 | [ |
| 269 | { |
| 270 | "KeyCode": "CP-230012", |
| 271 | "OperationCode": "SigntoolSign", |
| 272 | "Parameters" : { |
| 273 | "OpusName" : "Microsoft", |
| 274 | "OpusInfo" : "http://www.microsoft.com", |
| 275 | "FileDigest" : "/fd \"SHA256\"", |
| 276 | "PageHash" : "/NPH", |
| 277 | "TimeStamp" : "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" |
| 278 | }, |
| 279 | "ToolName" : "sign", |
| 280 | "ToolVersion" : "1.0" |
| 281 | }, |
| 282 | { |
| 283 | "KeyCode" : "CP-230012", |
| 284 | "OperationCode" : "SigntoolVerify", |
| 285 | "Parameters" : {}, |
| 286 | "ToolName" : "sign", |
| 287 | "ToolVersion" : "1.0" |
| 288 | } |
| 289 | ] |
| 290 | |
| 291 | - powershell: | |
| 292 | $binFolder = ".\bin\${{ parameters.platform }}\Release" |
| 293 | $pdbFolder = Join-Path $(ob_outputDirectory) "pdb\${{ parameters.platform }}\Release" |
| 294 | mkdir $pdbFolder |
| 295 | foreach ($filter in @("*.pdb", "*.debug")) |
| 296 | { |
| 297 | foreach ($e in (Get-ChildItem -Recurse -Path $binFolder -Filter $filter)) {Move-Item -Path $e.fullname -Destination (Join-Path $pdbFolder $e.name)} |
| 298 | } |
| 299 | displayName: Collect symbols (${{ parameters.platform }}) |
| 300 | |
| 301 | # Test artifacts (x64 only) |
| 302 | - ${{ if parameters.includeTestArtifacts }}: |
| 303 | - powershell: | |
| 304 | $taefVersion = (Select-Xml -Path packages.config -XPath '/packages/package[@id=''Microsoft.Taef'']/@version').Node.Value |
| 305 | New-Item -ItemType Directory -Path "$(ob_outputDirectory)\bundle" -Force |
| 306 | mkdir $(ob_outputDirectory)\testbin\x64\release |
| 307 | |
| 308 | Copy-Item -Path "bin\x64\release\wsltests.dll" -Destination "$(ob_outputDirectory)\testbin\x64\release\wsltests.dll" |
| 309 | Copy-Item -Path "bin\x64\release\testplugin.dll" -Destination "$(ob_outputDirectory)\testbin\x64\release\testplugin.dll" |
| 310 | Copy-Item -Path "bin\x64\release\wslcsdk.dll" -Destination "$(ob_outputDirectory)\testbin\x64\release\wslcsdk.dll" |
| 311 | Copy-Item -Path "bin\x64\release\installer.msix" -Destination "$(ob_outputDirectory)\testbin\x64\release\installer.msix" |
| 312 | Move-Item -Path "packages\Microsoft.Taef.$taefVersion\build\Binaries\x64" -Destination "$(ob_outputDirectory)\testbin\x64\release\taef" |
| 313 | |
| 314 | Move-Item -Path "bin\x64\cloudtest" -Destination "$(ob_outputDirectory)\testbin\x64\cloudtest" |
| 315 | |
| 316 | Move-Item -Path "tools\test\test-setup.ps1" -Destination "$(ob_outputDirectory)\testbin\test-setup.ps1" |
| 317 | Move-Item -Path "tools\test\CloudTest-Setup.bat" -Destination "$(ob_outputDirectory)\testbin\CloudTest-Setup.bat" |
| 318 | Move-Item -Path "diagnostics\wsl.wprp" -Destination "$(ob_outputDirectory)\testbin\wsl.wprp" |
| 319 | Move-Item -Path "test\linux\unit_tests" -Destination "$(ob_outputDirectory)\testbin\unit_tests" |
| 320 | |
| 321 | $TestDistroVersion = (Select-Xml -Path packages.config -XPath '/packages/package[@id=''Microsoft.WSL.TestDistro'']/@version').Node.Value |
| 322 | Copy-Item "packages\Microsoft.WSL.TestDistro.$TestDistroVersion\x64\test_distro.tar.xz" "$(ob_outputDirectory)\testbin\x64" |
| 323 | |
| 324 | $TestDataVersion = (Select-Xml -Path packages.config -XPath '/packages/package[@id=''Microsoft.WSL.TestData'']/@version').Node.Value |
| 325 | Copy-Item "packages\Microsoft.WSL.TestData.$TestDataVersion\x64" "$(ob_outputDirectory)\testbin\x64\test_data" -Recurse -Force |
| 326 | |
| 327 | displayName: Stage test artifacts |
| 328 | |
| 329 | - task: PublishSymbols@2 |
| 330 | displayName: Publish symbols (${{ parameters.platform }}) |
| 331 | inputs: |
| 332 | SymbolServerType: "TeamServices" |
| 333 | TreatNotIndexedAsWarning: true |
| 334 | SymbolsProduct: WSL |
| 335 | SymbolsVersion: $(version.WSL_PACKAGE_VERSION) |
| 336 | SearchPattern: | |
| 337 | $(ob_outputDirectory)/pdb/**/*.pdb |
| 338 | bin/**/*.exe |
| 339 | bin/**/*.dll |
| 340 | |
| 341 | - ${{ if ne(parameters.pool, '') }}: |
| 342 | - task: PublishPipelineArtifact@1 |
| 343 | inputs: |
| 344 | targetPath: $(ob_outputDirectory) |
| 345 | artifactName: $(ob_artifactBaseName)$(ob_artifactSuffix) |
| 346 | |
| 347 | - ${{ if parameters.includeCodeQL }}: |
| 348 | - task: CodeQL3000Finalize@0 |
| 349 | condition: ${{ and(parameters.isNightly, eq(variables['Build.SourceBranch'], 'refs/heads/main'))}} |