aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/azure-pipelines/analyze-test-results.ps1374
-rwxr-xr-xscripts/azure-pipelines/generate-skip-list.ps111
-rw-r--r--scripts/azure-pipelines/linux/azure-pipelines.yml8
-rw-r--r--scripts/azure-pipelines/osx/azure-pipelines.yml8
-rwxr-xr-xscripts/azure-pipelines/test-modified-ports.ps122
-rw-r--r--scripts/azure-pipelines/windows/azure-pipelines.yml8
-rw-r--r--scripts/ci.baseline.txt166
-rw-r--r--toolsrc/include/vcpkg/base/files.h2
-rw-r--r--toolsrc/include/vcpkg/binarycaching.h2
-rw-r--r--toolsrc/include/vcpkg/build.h51
-rw-r--r--toolsrc/include/vcpkg/install.h1
-rw-r--r--toolsrc/include/vcpkg/vcpkgpaths.h2
-rw-r--r--toolsrc/src/vcpkg/base/files.cpp25
-rw-r--r--toolsrc/src/vcpkg/binarycaching.cpp92
-rw-r--r--toolsrc/src/vcpkg/build.cpp65
-rw-r--r--toolsrc/src/vcpkg/commands.buildexternal.cpp1
-rw-r--r--toolsrc/src/vcpkg/commands.ci.cpp132
-rw-r--r--toolsrc/src/vcpkg/commands.edit.cpp5
-rw-r--r--toolsrc/src/vcpkg/commands.setinstalled.cpp14
-rw-r--r--toolsrc/src/vcpkg/commands.upgrade.cpp14
-rw-r--r--toolsrc/src/vcpkg/export.cpp14
-rw-r--r--toolsrc/src/vcpkg/install.cpp105
-rw-r--r--toolsrc/src/vcpkg/postbuildlint.cpp11
-rw-r--r--toolsrc/src/vcpkg/vcpkgpaths.cpp11
24 files changed, 362 insertions, 782 deletions
diff --git a/scripts/azure-pipelines/analyze-test-results.ps1 b/scripts/azure-pipelines/analyze-test-results.ps1
index 9e6d09d20..5bebe985c 100755
--- a/scripts/azure-pipelines/analyze-test-results.ps1
+++ b/scripts/azure-pipelines/analyze-test-results.ps1
@@ -15,24 +15,11 @@ Then, uploads the logs from any unexpected failures.
.PARAMETER logDir
Directory of xml test logs to analyze.
-.PARAMETER failurelogDir
-Path to the failure logs that need to be published to azure for inspection.
-
-.PARAMETER outputDir
-Where to write out the results of the analysis.
-
.PARAMETER allResults
Include tests that have no change from the baseline in the output.
-.PARAMETER errorOnRegression
-Output an error on test regressions.
-This will give a clean message in the build pipeline.
-
-.PARAMETER noTable
-Don't create or upload the markdown table of results
-
-.PARAMETER triplets
-A list of triplets to analyze; defaults to all triplets.
+.PARAMETER triplet
+The triplet to analyze.
.PARAMETER baselineFile
The path to the ci.baseline.txt file in the vcpkg repository.
@@ -41,14 +28,9 @@ The path to the ci.baseline.txt file in the vcpkg repository.
Param(
[Parameter(Mandatory = $true)]
[string]$logDir,
- [Parameter(Mandatory = $true)]
- [string]$failurelogDir,
- [Parameter(Mandatory = $true)]
- [string]$outputDir,
[switch]$allResults,
- [switch]$errorOnRegression,
- [switch]$noTable,
- [string[]]$triplets = @(),
+ [Parameter(Mandatory = $true)]
+ [string]$triplet,
[Parameter(Mandatory = $true)]
[string]$baselineFile
)
@@ -59,25 +41,6 @@ if ( -not (Test-Path $logDir) ) {
[System.Console]::Error.WriteLine("Log directory does not exist: $logDir")
exit
}
-if ( -not (Test-Path $outputDir) ) {
- [System.Console]::Error.WriteLine("output directory does not exist: $outputDir")
- exit
-}
-
-if ( $triplets.Count -eq 0 ) {
- $triplets = @(
- "x64-linux",
- "x64-osx",
- "arm-uwp",
- "arm64-windows",
- "x64-osx",
- "x64-uwp",
- "x64-windows-static",
- "x64-windows",
- "x86-windows"
- )
-}
-
<#
.SYNOPSIS
@@ -402,260 +365,6 @@ function combine_results {
<#
.SYNOPSIS
-Takes the combined results object and writes it to an xml file.
-
-.DESCRIPTION
-write_xunit_results takes the results object from combine_results, and writes the
-results XML file to the correct location for the CI system to pick it up.
-
-.PARAMETER combined_results
-The results object from combine_results.
-#>
-function write_xunit_results {
- [CmdletBinding()]
- Param(
- $combined_results
- )
- $allTests = $combined_results.allTests
- $triplet = $combined_results.collectionName
-
- $filePath = "$outputDir\$triplet.xml"
- if (Test-Path $filePath) {
- Write-Verbose "removing old file $filepath"
- rm $filePath
- }
- Write-Verbose "output filename: $filepath"
-
- $xmlWriter = New-Object System.Xml.XmlTextWriter($filePath, $Null)
- $xmlWriter.Formatting = "Indented"
- $xmlWriter.IndentChar = "`t"
-
- $xmlWriter.WriteStartDocument()
- $xmlWriter.WriteStartElement("assemblies")
- $xmlWriter.WriteStartElement("assembly")
- $xmlWriter.WriteAttributeString("name", $combined_results.assemblyName)
- $xmlWriter.WriteAttributeString("run-date", $combined_results.assemblyStartDate)
- $xmlWriter.WriteAttributeString("run-time", $combined_results.assemblyStartTime)
- $xmlWriter.WriteAttributeString("time", $combined_results.assemblyTime)
-
- $xmlWriter.WriteStartElement("collection")
- $xmlWriter.WriteAttributeString("name", $triplet)
- $xmlWriter.WriteAttributeString("time", $combined_results.collectionTime)
-
- foreach ($testName in $allTests.Keys) {
- $test = $allTests[$testName]
-
- $xmlWriter.WriteStartElement("test")
-
- $fullTestName = "$($testName):$triplet"
- $xmlWriter.WriteAttributeString("name", $fullTestName)
- $xmlWriter.WriteAttributeString("method", $fullTestName)
- $xmlWriter.WriteAttributeString("time", $test.time)
- $xmlWriter.WriteAttributeString("result", $test.result)
-
- switch ($test.result) {
- "Pass" { } # Do nothing
- "Fail" {
- $xmlWriter.WriteStartElement("failure")
- $xmlWriter.WriteStartElement("message")
- $xmlWriter.WriteCData($test.message)
- $xmlWriter.WriteEndElement() #message
- $xmlWriter.WriteEndElement() #failure
- }
- "Skip" {
- $xmlWriter.WriteStartElement("reason")
- $xmlWriter.WriteCData($test.message)
- $xmlWriter.WriteEndElement() #reason
- }
- }
-
- $xmlWriter.WriteEndElement() # test
- }
-
-
- $xmlWriter.WriteEndElement() # collection
- $xmlWriter.WriteEndElement() # assembly
- $xmlWriter.WriteEndElement() # assemblies
- $xmlWriter.WriteEndDocument()
- $xmlWriter.Flush()
- $xmlWriter.Close()
-}
-
-<#
-.SYNOPSIS
-Saves the failure logs, and prints information to the screen for CI.
-
-.DESCRIPTION
-save_failure_logs takes the combined_results object, saves the failure
-logs to the correct location for the CI to pick them up, and writes pretty
-information to the screen for the CI logs, so that one knows what's wrong.
-
-.PARAMETER combined_results
-The results object from combine_results.
-#>
-function save_failure_logs {
- [CmdletBinding()]
- Param(
- $combined_results
- )
- $triplet = $combined_results.collectionName
- $allTests = $combined_results.allTests
-
- # abi_tags of missing results (if any exist)
- $missing_results = @()
-
- foreach ($testName in $allTests.Keys) {
- $test = $allTests[$testName]
- if ($test.result -eq "Fail") {
- $path_to_failure_Logs = Join-Path "$outputDir" "failureLogs"
- if ( -not (Test-Path $path_to_failure_Logs)) {
- mkdir $path_to_failure_Logs | Out-Null
- }
- $path_to_triplet_Logs = Join-Path $path_to_failure_Logs "$triplet"
- if ( -not (Test-Path $path_to_triplet_Logs)) {
- mkdir $path_to_triplet_Logs | Out-Null
- }
-
- $abi_tag = $test.abi_tag
- $sourceDirectory = Join-Path "$failurelogDir" "$($abi_tag.substring(0,2))"
- $sourceFilename = Join-Path $sourceDirectory "$abi_tag.zip"
- Write-Verbose "searching for $sourceFilename"
-
- if ( Test-Path $sourceFilename) {
- Write-Verbose "found failure log file"
-
- Write-Verbose "Uncompressing $sourceFilename to $outputDir\failureLogs\$triplet\"
- Write-Host "Uncompressing $sourceFilename to $outputDir\failureLogs\$triplet\"
-
- $destination = Join-Path (Join-Path "$outputDir" "failureLogs") "$triplet"
-
- Expand-Archive -Path $sourceFilename -Destination $destination -Force
- }
- elseif ($test.currentState -eq "Pass") {
- # The port is building, but is marked as expected to fail. There are no failure logs.
- # Write a log with instructions how to fix it.
- Write-Verbose "The port is building but marked as expected to fail, adding readme.txt with fixit instructions"
-
- $out_filename = Join-Path (Join-Path (Join-Path (Join-Path "$outputDir" "failureLogs") "$triplet") "$($test.name)") "readme.txt"
-
- $message = "Congradulations! The port $($test.name) builds for $triplet!`n"
- $message += "For the CI tests to recognize this, please update ci.baseline.txt in your PR.`n"
- $message += "Remove the line that looks like this:`n"
- $message += " $($test.name):$triplet=fail`n"
- $message | Out-File $out_filename -Encoding ascii
- }
- else {
- $missing_results += $test.abi_tag
- Write-Verbose "Missing failure logs for $($test.name)"
- Join-Path (Join-Path (Join-Path "$outputDir" "failureLogs") "$triplet" ) "$($test.name)" | % { mkdir $_ } | Out-Null
- }
-
-
-
- if ((Convert-Path "$outputDir\failureLogs\$triplet\$($test.name)" | Get-ChildItem).count -eq 0) {
- Write-Verbose "The logs are empty, adding readme.txt"
-
- $readme_path = Join-Path (Join-Path (Join-Path (Join-Path "$outputDir" "failureLogs") "$triplet") "$($test.name)") "readme.txt"
-
- $message = "There are no build logs for $($test.name) build.`n"
- $message += "This is usually because the build failed early and outside of a task that is logged.`n"
- $message += "See the console output logs from vcpkg for more information on the failure.`n"
- $message += "If the console output of the $($test.name) is missing you can trigger a rebuild`n"
- $message += "in the test system by making any whitespace change to one of the files under`n"
- $message += "the ports/$($test.name) directory or by asking a member of the vcpkg team to remove the`n"
- $message += "tombstone for abi tag $abi_tag`n"
- $message | Out-File $readme_path -Encoding ascii
- }
- }
- }
-
- if ($missing_results.count -ne 0) {
- $missing_tag_filename = Join-Path (Join-Path (Join-Path "$outputDir" "failureLogs") "$triplet") "missing_abi_tags.txt"
- $missing_results | Out-File -FilePath $missing_tag_filename -Encoding ascii
- }
- Write-Verbose "$triplet logs saved: $(Get-ChildItem $outputDir\failureLogs\$triplet\ -ErrorAction Ignore)"
-
-}
-
-<#
-.SYNOPSIS
-Writes a pretty summary table to the CI log.
-
-.DESCRIPTION
-Takes a hashtable which maps triplets to objects returned by the combine_results
-cmdlet, and a list of missing triplets, and prints a really pretty summary table
-to the CI logs.
-
-.PARAMETER complete_results
-A hashtable which maps triplets to combine_results objects.
-
-.PARAMETER missing_triplets
-A list of missing triplets.
-#>
-function write_summary_table {
- [CmdletBinding()]
- Param(
- $complete_results,
- $missing_triplets
- )
-
- $table = ""
-
- foreach ($triplet in $complete_results.Keys) {
- $triplet_results = $complete_results[$triplet]
-
- if ($triplet_results.allTests.count -eq 0) {
- $table += "$triplet CI build test results are clean`n`n"
- }
- else {
- $portWidth = $triplet.length
- #calculate the width of the first column
- foreach ($testName in $triplet_results.allTests.Keys) {
- $test = $triplet_results.allTests[$testName]
- if ($portWidth -lt $test.name.length) {
- $portWidth = $test.name.length
- }
- }
-
- # the header
- $table += "|{0,-$portWidth}|result|features|notes`n" -f $triplet
- $table += "|{0}|----|--------|-----`n" -f ("-" * $portWidth)
-
- # add each port results
- foreach ($testName in $triplet_results.allTests.Keys | Sort-Object) {
- $test = $triplet_results.allTests[$testName]
- $notes = ""
- if ($test.result -eq 'Fail') {
- $notes = "**Regression**"
- }
- elseif ($test.result -eq 'Skip') {
- if ($test.currentResult -eq 'Fail') {
- $notes = "Previously skipped, not a regression"
- }
- else {
- $notes = "Missing port dependency"
- }
- }
- $notes = $test.message
- $table += "|{0,-$portWidth}|{1,-4}|{2}|{3}`n" -f $test.name, $test.currentResult, $test.features, $notes
- }
- $table += "`n"
- }
- if ($triplet_results.ignored.Count -ne 0) {
- $table += "The following build failures were ignored: $($triplet_results.ignored)`n"
- }
- }
-
- # Add list of missing triplets to the table
- foreach ($triplet in $missing_triplets.Keys) {
- $table += "$triplet results are inconclusive because it is missing logs from test run`n`n"
- }
-
- $table
-}
-
-<#
-.SYNOPSIS
Writes short errors to the CI logs.
.DESCRIPTION
@@ -705,74 +414,27 @@ function write_errors_for_summary {
$complete_results = @{ }
-$missing_triplets = @{ }
-foreach ( $triplet in $triplets) {
- Write-Verbose "looking for $triplet logs"
+Write-Verbose "looking for $triplet logs"
- # The standard name for logs is:
- # <triplet>.xml
- # for example:
- # x64-linux.xml
+# The standard name for logs is:
+# <triplet>.xml
+# for example:
+# x64-linux.xml
- $current_test_hash = build_test_results( Convert-Path "$logDir\$($triplet).xml" )
- $baseline_results = build_baseline_results -baselineFile $baselineFile -triplet $triplet
+$current_test_hash = build_test_results( Convert-Path "$logDir\$($triplet).xml" )
+$baseline_results = build_baseline_results -baselineFile $baselineFile -triplet $triplet
- if ($current_test_hash -eq $null) {
- [System.Console]::Error.WriteLine("Missing $triplet test results in current test run")
- $missing_triplets[$triplet] = "test"
- }
- else {
- Write-Verbose "combining results..."
- $complete_results[$triplet] = combine_results -baseline $baseline_results -current $current_test_hash
- }
-}
-
-Write-Verbose "done analizing results"
-
-# If there is only one triplet, add the triplet name to the result table file
-if ($triplets.Count -eq 1) {
- $result_table_name = $triplets[0]
+if ($current_test_hash -eq $null) {
+ [System.Console]::Error.WriteLine("Missing $triplet test results in current test run")
+ $missing_triplets[$triplet] = "test"
}
else {
- $result_table_name = ""
-}
-
-if (-not $noTable) {
- $table_path = Join-Path "$outputDir" "result_table$result_table_name.md"
-
- write_summary_table -complete_results $complete_results -missing_triplets $missing_triplets | Out-File -FilePath $table_path -Encoding ascii
-
- Write-Host ""
- cat $table_path
-
- Write-Host "##vso[task.addattachment type=Distributedtask.Core.Summary;name=$result_table_name issue summary;]$table_path"
-}
-
-foreach ( $triplet in $complete_results.Keys) {
- $combined_results = $complete_results[$triplet]
- if ( $failurelogDir -ne "") {
- save_failure_logs -combined_results $combined_results
- }
-
- write_xunit_results -combined_results $combined_results
+ Write-Verbose "combining results..."
+ $complete_results[$triplet] = combine_results -baseline $baseline_results -current $current_test_hash
}
+Write-Verbose "done analyzing results"
# emit error last. Unlike the table output this is going to be seen in the "status" section of the pipeline
# and needs to be formatted for a single line.
-if ($errorOnRegression) {
- write_errors_for_summary -complete_results $complete_results
-
- if ($missing_triplets.Count -ne 0) {
- $regression_log_directory = Join-Path "$outputDir" "failureLogs"
- if ( -not (Test-Path $regression_log_directory)) {
- mkdir $regression_log_directory | Out-Null
- }
- $file_path = Join-Path $regression_log_directory "missing_test_results.txt"
- $message = "Test logs are missing for the following triplets: $($hash.Keys | %{"$($_)($($hash[$_]))"})`n"
- $message += "Without this information the we are unable to determine if the build has regressions. `n"
- $message += "Missing test logs are sometimes the result of failures in the pipeline infrastructure. `n"
- $message += "If you beleave this is the case please alert a member of the vcpkg team to investigate. `n"
- $message | Out-File $file_path -Encoding ascii
- }
-}
+write_errors_for_summary -complete_results $complete_results
diff --git a/scripts/azure-pipelines/generate-skip-list.ps1 b/scripts/azure-pipelines/generate-skip-list.ps1
index 11980d7ad..84b78b338 100755
--- a/scripts/azure-pipelines/generate-skip-list.ps1
+++ b/scripts/azure-pipelines/generate-skip-list.ps1
@@ -19,7 +19,8 @@ The path to the ci.baseline.txt file.
[CmdletBinding()]
Param(
[string]$Triplet,
- [string]$BaselineFile
+ [string]$BaselineFile,
+ [switch]$SkipFailures = $false
)
$ErrorActionPreference = 'Stop'
@@ -70,7 +71,13 @@ foreach ($port in $baselineForTriplet | ForEach-Object { $_ -replace ":.*$" }) {
}
# Format the skip list for the command line
+if ($SkipFailures) {
+ $targetRegex = "=(?:skip|fail)$"
+} else {
+ $targetRegex = "=skip$"
+}
+
$skip_list = $baselineForTriplet `
- | Where-Object { $_ -match "=skip$" } `
+ | Where-Object { $_ -match $targetRegex } `
| ForEach-Object { $_ -replace ":.*$" }
[string]::Join(",", $skip_list)
diff --git a/scripts/azure-pipelines/linux/azure-pipelines.yml b/scripts/azure-pipelines/linux/azure-pipelines.yml
index 77842437f..65d6d3f1d 100644
--- a/scripts/azure-pipelines/linux/azure-pipelines.yml
+++ b/scripts/azure-pipelines/linux/azure-pipelines.yml
@@ -37,11 +37,7 @@ jobs:
inputs:
failOnStderr: true
filePath: 'scripts/azure-pipelines/test-modified-ports.ps1'
- arguments: '-Triplet x64-linux -BuildReason $(Build.Reason) -ArchivesRoot /archives -WorkingRoot /mnt/vcpkg-ci -ArtifactStagingDirectory $(Build.ArtifactStagingDirectory) -ArtifactsDirectory $(System.ArtifactsDirectory)'
- - task: PublishTestResults@2
- inputs:
- testResultsFiles: '$(System.ArtifactsDirectory)/xml-results/x64-linux.xml'
- condition: always()
+ arguments: '-Triplet x64-linux -BuildReason $(Build.Reason) -ArchivesRoot /archives -WorkingRoot /mnt/vcpkg-ci -ArtifactsDirectory $(System.ArtifactsDirectory)'
- bash: |
df -h
displayName: 'Report on Disk Space After Build'
@@ -49,6 +45,6 @@ jobs:
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: x86-linux Build Failure Logs'
inputs:
- PathtoPublish: '$(Build.ArtifactStagingDirectory)/failureLogs'
+ PathtoPublish: '$(System.ArtifactsDirectory)/failure-logs'
ArtifactName: 'x64-linux port build failure logs'
condition: failed()
diff --git a/scripts/azure-pipelines/osx/azure-pipelines.yml b/scripts/azure-pipelines/osx/azure-pipelines.yml
index 8008df45f..33685fd6b 100644
--- a/scripts/azure-pipelines/osx/azure-pipelines.yml
+++ b/scripts/azure-pipelines/osx/azure-pipelines.yml
@@ -41,11 +41,7 @@ jobs:
inputs:
failOnStderr: true
filePath: 'scripts/azure-pipelines/test-modified-ports.ps1'
- arguments: '-Triplet x64-osx -BuildReason $(Build.Reason) -ArchivesRoot /Users/vagrant/Data/archives -WorkingRoot /Users/vagrant/Data -ArtifactStagingDirectory $(Build.ArtifactStagingDirectory) -ArtifactsDirectory $(System.ArtifactsDirectory)'
- - task: PublishTestResults@2
- inputs:
- testResultsFiles: '$(System.ArtifactsDirectory)/xml-results/x64-osx.xml'
- condition: always()
+ arguments: '-Triplet x64-osx -BuildReason $(Build.Reason) -ArchivesRoot /Users/vagrant/Data/archives -WorkingRoot /Users/vagrant/Data -ArtifactsDirectory $(System.ArtifactsDirectory)'
- bash: |
df -h
displayName: 'Report on Disk Space After Build'
@@ -53,6 +49,6 @@ jobs:
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: x64-osx port build failure logs'
inputs:
- PathtoPublish: '$(Build.ArtifactStagingDirectory)/failureLogs'
+ PathtoPublish: '$(System.ArtifactsDirectory)/failure-logs'
ArtifactName: 'x64-osx port build failure logs'
condition: failed()
diff --git a/scripts/azure-pipelines/test-modified-ports.ps1 b/scripts/azure-pipelines/test-modified-ports.ps1
index d6b59364e..9a30321b4 100755
--- a/scripts/azure-pipelines/test-modified-ports.ps1
+++ b/scripts/azure-pipelines/test-modified-ports.ps1
@@ -15,9 +15,6 @@ The location where the binary caching archives are stored. Shared across runs of
.PARAMETER WorkingRoot
The location used as scratch space for 'installed', 'packages', and 'buildtrees' vcpkg directories.
-.PARAMETER ArtifactStagingDirectory
-The Azure Pipelines artifact staging directory. If not supplied, defaults to the current directory.
-
.PARAMETER ArtifactsDirectory
The Azure Pipelines artifacts directory. If not supplied, defaults to the current directory.
@@ -38,8 +35,6 @@ Param(
[ValidateNotNullOrEmpty()]
$WorkingRoot,
[ValidateNotNullOrEmpty()]
- $ArtifactStagingDirectory = '.',
- [ValidateNotNullOrEmpty()]
$ArtifactsDirectory = '.',
$BuildReason = $null
)
@@ -61,11 +56,13 @@ $commonArgs = @(
)
$binaryCachingMode = 'readwrite'
+$skipFailures = $false
if ([string]::IsNullOrWhiteSpace($BuildReason)) {
Write-Host 'Build reason not specified, defaulting to using binary caching in read write mode.'
}
elseif ($BuildReason -eq 'PullRequest') {
- Write-Host 'Build reason was Pull Request, using binary caching in read write mode.'
+ Write-Host 'Build reason was Pull Request, using binary caching in read write mode, skipping failures.'
+ $skipFailures = $true
}
else {
Write-Host "Build reason was $BuildReason, using binary caching in write only mode."
@@ -89,8 +86,13 @@ $xmlResults = Join-Path $ArtifactsDirectory 'xml-results'
mkdir $xmlResults
$xmlFile = Join-Path $xmlResults "$Triplet.xml"
+$failureLogs = Join-Path $ArtifactsDirectory 'failure-logs'
+
& "./vcpkg$executableExtension" x-ci-clean @commonArgs
-$skipList = . "$PSScriptRoot/generate-skip-list.ps1" -Triplet $Triplet -BaselineFile "$PSScriptRoot/../ci.baseline.txt"
+$skipList = . "$PSScriptRoot/generate-skip-list.ps1" `
+ -Triplet $Triplet `
+ -BaselineFile "$PSScriptRoot/../ci.baseline.txt" `
+ -SkipFailures:$skipFailures
# WORKAROUND: the x86-windows flavors of these are needed for all cross-compilation, but they are not auto-installed.
# Install them so the CI succeeds:
@@ -98,7 +100,7 @@ if ($Triplet -in @('x64-uwp', 'arm64-windows', 'arm-uwp')) {
.\vcpkg.exe install protobuf:x86-windows boost-build:x86-windows sqlite3:x86-windows @commonArgs
}
-& "./vcpkg$executableExtension" ci $Triplet --x-xunit=$xmlFile --exclude=$skipList @commonArgs
-& "$PSScriptRoot/analyze-test-results.ps1" -logDir $xmlResults -outputDir $ArtifactStagingDirectory `
- -failureLogDir (Join-Path $ArchivesRoot 'fail') -triplets $Triplet -errorOnRegression `
+& "./vcpkg$executableExtension" ci $Triplet --x-xunit=$xmlFile --exclude=$skipList --failure-logs=$failureLogs @commonArgs
+& "$PSScriptRoot/analyze-test-results.ps1" -logDir $xmlResults `
+ -triplet $Triplet `
-baselineFile .\scripts\ci.baseline.txt
diff --git a/scripts/azure-pipelines/windows/azure-pipelines.yml b/scripts/azure-pipelines/windows/azure-pipelines.yml
index a20ee23bb..d7f34b3c7 100644
--- a/scripts/azure-pipelines/windows/azure-pipelines.yml
+++ b/scripts/azure-pipelines/windows/azure-pipelines.yml
@@ -49,11 +49,7 @@ jobs:
inputs:
failOnStderr: true
filePath: 'scripts/azure-pipelines/test-modified-ports.ps1'
- arguments: '-Triplet ${{ parameters.triplet }} -BuildReason $(Build.Reason) -ArchivesRoot W:\ -WorkingRoot D:\ -ArtifactStagingDirectory $(Build.ArtifactStagingDirectory) -ArtifactsDirectory $(System.ArtifactsDirectory)'
- - task: PublishTestResults@2
- inputs:
- testResultsFiles: '$(System.ArtifactsDirectory)/xml-results/${{ parameters.triplet }}.xml'
- condition: always()
+ arguments: '-Triplet ${{ parameters.triplet }} -BuildReason $(Build.Reason) -ArchivesRoot W:\ -WorkingRoot D:\ -ArtifactsDirectory $(System.ArtifactsDirectory)'
- task: PowerShell@2
displayName: 'Report on Disk Space After Build'
condition: always()
@@ -62,6 +58,6 @@ jobs:
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: ${{ parameters.triplet }} port build failure logs'
inputs:
- PathtoPublish: '$(Build.ArtifactStagingDirectory)\failureLogs'
+ PathtoPublish: '$(System.ArtifactsDirectory)\failure-logs'
ArtifactName: '${{ parameters.triplet }} port build failure logs'
condition: failed()
diff --git a/scripts/ci.baseline.txt b/scripts/ci.baseline.txt
index ab8ea0e60..4ae2000d5 100644
--- a/scripts/ci.baseline.txt
+++ b/scripts/ci.baseline.txt
@@ -13,9 +13,6 @@
## This is added to ports that may be flaky or conflict with other
## ports. Please comment for why a port is skipped so it can be
## removed when the issue is resolved.
-## ignore - attempt to build the port, but do not fail the CI test if the
-## port does not build. Any ignored build failures will be reported
-## in the test summary.
##
##
## CI tested triplets:
@@ -38,7 +35,7 @@
3fd:x64-osx=fail
3fd:x64-windows=fail
3fd:x64-windows-static=fail
-3fd:x86-windows=ignore
+3fd:x86-windows=fail
7zip:arm64-windows=fail
7zip:arm-uwp=fail
7zip:x64-linux=fail
@@ -64,9 +61,6 @@ angelscript:arm64-windows=fail
angelscript:arm-uwp=fail
antlr4:arm-uwp=fail
antlr4:x64-uwp=fail
-anyrpc:arm-uwp=ignore
-anyrpc:x86-windows=ignore
-anyrpc:x64-windows-static=ignore
apr:arm-uwp=fail
apr:x64-uwp=fail
# Cross compiling CI machine cannot run gen_test_char to generate apr_escape_test_char.h
@@ -107,10 +101,8 @@ aws-lambda-cpp:x64-windows=fail
aws-lambda-cpp:x64-windows-static=fail
aws-lambda-cpp:x86-windows=fail
aws-lambda-cpp:x64-osx=fail
-aws-sdk-cpp:x64-linux=ignore
azure-c-shared-utility:arm-uwp=fail
azure-c-shared-utility:x64-uwp=fail
-basisu:x64-linux=ignore
bde:arm64-windows=fail
bde:arm-uwp=fail
bde:x64-uwp=fail
@@ -151,7 +143,6 @@ boost-fiber:arm-uwp=fail
boost-fiber:arm64-windows=fail
boost-fiber:x64-osx=fail
boost-fiber:x64-uwp=fail
-boost-fiber:x64-linux=ignore
boost-filesystem:arm-uwp=fail
boost-filesystem:x64-uwp=fail
boost-iostreams:arm-uwp=fail
@@ -175,11 +166,9 @@ breakpad:arm64-windows=fail
bullet3:arm64-windows=fail
bullet3:arm-uwp=fail
bullet3:x64-uwp=fail
-butteraugli:x64-linux=ignore
caf:arm-uwp=fail
caf:arm64-windows=fail
caf:x64-uwp=fail
-caf:x64-linux=ignore
caffe2:x86-windows=fail
caffe2:arm64-windows=fail
cairomm:x64-linux=fail
@@ -238,7 +227,6 @@ civetweb:arm-uwp = skip
civetweb:x64-uwp = skip
clapack:x64-uwp=fail
clblas:arm64-windows=fail
-clblast:x64-osx=ignore
clblast:x64-linux=fail
clblast:x64-windows-static=fail
clockutils:x64-linux=fail
@@ -270,15 +258,11 @@ cppcms:x64-osx=fail
cppcms:x64-windows-static=fail
cppfs:arm-uwp=fail
cppfs:x64-uwp=fail
-cppgraphqlgen:arm-uwp=ignore
-cppgraphqlgen:x64-uwp=ignore
-cppkafka:x64-linux=ignore
cppmicroservices:arm64-windows=fail
cppmicroservices:arm-uwp=fail
cppmicroservices:x64-uwp=fail
cpp-netlib:arm-uwp=fail
cpp-netlib:x64-uwp=fail
-cpp-netlib:x64-linux=ignore
cpp-taskflow:x64-osx=fail
cppcoro:x64-linux=fail
cppcoro:arm-uwp=fail
@@ -288,8 +272,7 @@ cppunit:arm-uwp=fail
cppunit:x64-linux=fail
cppunit:x64-osx=fail
cppunit:x64-uwp=fail
-cpr:x64-linux=ignore
-cpuinfo:arm64-windows=ignore
+cpuinfo:arm64-windows=fail
crashpad:arm64-windows=fail
crashpad:arm-uwp=fail
crashpad:x64-linux=fail
@@ -344,10 +327,10 @@ dlfcn-win32:x64-linux=fail
dlfcn-win32:x64-osx=fail
dlfcn-win32:x64-uwp=fail
dmlc:arm-uwp=fail
-dmlc:arm64-windows=ignore
+dmlc:arm64-windows=fail
dmlc:x64-uwp=fail
-dmlc:x64-windows-static=ignore
-dmlc:x86-windows=ignore
+dmlc:x64-windows-static=fail
+dmlc:x86-windows=fail
dpdk:arm-uwp=fail
dpdk:arm64-windows=fail
dpdk:x64-linux=fail
@@ -457,11 +440,11 @@ fmi4cpp:arm-uwp=fail
fmi4cpp:x64-uwp=fail
fmilib:arm64-windows=fail
fmilib:arm-uwp=fail
-fmilib:x64-linux=ignore
+fmilib:x64-linux=fail
fmilib:x64-uwp=fail
-fmilib:x64-windows=ignore
-fmilib:x64-windows-static=ignore
-fmilib:x86-windows=ignore
+fmilib:x64-windows=fail
+fmilib:x64-windows-static=fail
+fmilib:x86-windows=fail
foonathan-memory:arm64-windows=fail
foonathan-memory:arm-uwp=fail
foonathan-memory:x64-uwp=fail
@@ -480,11 +463,11 @@ freetds:x64-osx=fail
freetds:x64-uwp=fail
freetype-gl:x64-uwp=fail
freexl:arm-uwp=fail
-freexl:arm64-windows=ignore
+freexl:arm64-windows=fail
freexl:x64-uwp=fail
-freexl:x86-windows=ignore
-freexl:x64-windows=ignore
-freexl:x64-windows-static=ignore
+freexl:x86-windows=fail
+freexl:x64-windows=fail
+freexl:x64-windows-static=fail
fribidi:arm64-windows=fail
fribidi:arm-uwp=fail
fribidi:x64-linux=fail
@@ -508,7 +491,6 @@ gasol:arm-uwp=fail
gasol:x64-uwp=fail
gdcm:arm64-windows=fail
gdcm:x64-linux = skip
-geographiclib:x64-linux=ignore
geos:arm-uwp=fail
geos:x64-uwp=fail
getopt:arm-uwp=fail
@@ -540,7 +522,6 @@ glfw3:x64-uwp=fail
glib:x64-uwp=fail
glib:x64-windows-static=fail
glib:x64-osx=fail
-globjects:x64-linux=ignore
gmmlib:arm64-windows=fail
gmmlib:arm-uwp=fail
gmmlib:x64-osx=fail
@@ -570,7 +551,6 @@ gsoap:x64-linux=fail
gsoap:x64-osx=fail
gsoap:x64-uwp=fail
gtk:x64-linux=fail
-gtk:x86-windows=ignore
guetzli:x64-osx=fail
h3:arm64-windows=fail
h3:arm-uwp=fail
@@ -598,7 +578,6 @@ hpx:x64-linux=fail
hwloc:arm64-windows=fail
hwloc:arm-uwp=fail
hwloc:x64-uwp=fail
-hyperscan:x64-linux=ignore
# hypre has a conflict with 'superlu' port
hypre:x64-linux=skip
hypre:x64-osx=skip
@@ -616,7 +595,6 @@ ignition-msgs5:arm64-windows=fail
ignition-msgs5:arm-uwp=fail
ignition-msgs5:x64-uwp=fail
ignition-msgs5:x64-osx=skip
-imgui-sfml:x64-linux=ignore
intel-ipsec:arm64-windows=fail
intel-ipsec:arm-uwp=fail
intel-ipsec:x64-osx=fail
@@ -649,7 +627,6 @@ isal:x86-windows=fail
itk:x64-windows=fail
itk:x64-windows-static=fail
itk:x86-windows=fail
-ixwebsocket:x64-linux=ignore
jack2:arm-uwp=fail
jack2:x64-uwp=fail
jaeger-client-cpp:arm64-windows=fail
@@ -739,10 +716,9 @@ libfabric:arm-uwp=fail
libfabric:x64-linux=fail
libfabric:x64-osx=fail
libfabric:x64-uwp=fail
-libfabric:x64-windows=ignore
+libfabric:x64-windows=fail
libfabric:x64-windows-static=fail
libfreenect2:arm64-windows=fail
-libgd:x64-linux=ignore
libgit2:arm-uwp=fail
libgit2:x64-uwp=fail
libgo:arm-uwp=fail
@@ -824,9 +800,6 @@ libmupdf:x64-osx=fail
libmysql:x86-windows=fail
libnice:x64-linux=fail
libnice:x64-osx=fail
-libodb-boost:x64-linux=ignore
-libodb-pgsql:x64-linux=ignore
-libodb-pgsql:x64-windows=ignore
libopenmpt:x64-linux=fail
libopenmpt:x64-osx=fail
libopusenc:arm-uwp=fail
@@ -876,7 +849,6 @@ libpq:x64-uwp=fail
libqcow:arm-uwp=fail
libqcow:x64-uwp=fail
libqcow:x64-windows-static=fail
-librabbitmq:x64-linux=ignore
libraqm:x64-windows-static=fail
librdkafka:arm-uwp=fail
librdkafka:x64-uwp=fail
@@ -974,7 +946,6 @@ libxslt:x64-osx=fail
libxslt:x64-uwp=fail
libyuv:arm-uwp=fail
libyuv:x64-uwp=fail
-libzippp:x64-linux=ignore
licensepp:arm-uwp=fail
licensepp:x64-uwp=fail
linenoise-ng:arm-uwp=fail
@@ -1022,7 +993,6 @@ marl:arm-uwp=fail
marl:x64-uwp=fail
mathgl:x64-osx=fail
mathgl:x64-uwp=fail
-mathgl:x64-linux=ignore
matio:x64-linux=fail
matio:x64-osx=fail
mbedtls:arm-uwp=fail
@@ -1060,7 +1030,7 @@ mhook:x64-osx=fail
mhook:x64-uwp=fail
milerius-sfml-imgui:x64-osx=fail
milerius-sfml-imgui:x64-windows-static=fail
-milerius-sfml-imgui:x64-linux=ignore
+milerius-sfml-imgui:x64-linux=fail
mimalloc:arm64-windows=fail
mimalloc:arm-uwp=fail
mimalloc:x64-uwp=fail
@@ -1116,13 +1086,13 @@ monkeys-audio:x64-uwp=fail
monkeys-audio:x64-windows-static=fail
moos-core:arm-uwp=fail
moos-core:x64-uwp=fail
-moos-core:x64-windows=ignore
+moos-core:x64-windows=fail
moos-core:x64-windows-static=fail
-moos-core:x86-windows=ignore
+moos-core:x86-windows=fail
moos-essential:arm64-windows=fail
moos-essential:x64-windows=fail
moos-essential:x86-windows=fail
-moos-essential:x64-linux=ignore
+moos-essential:x64-linux=fail
mozjpeg:arm64-windows = skip
mozjpeg:arm-uwp = skip
mozjpeg:x64-linux = skip
@@ -1180,15 +1150,14 @@ nanorange:x64-windows=fail
nanorange:x64-windows-static=fail
nanorange:x86-windows=fail
nanovg:arm-uwp=fail
-nanovg:arm64-windows=ignore
+nanovg:arm64-windows=fail
nanovg:x64-uwp=fail
-nanovg:x64-linux=ignore
-nanovg:x64-windows=ignore
-nanovg:x64-windows-static=ignore
+nanovg:x64-linux=fail
+nanovg:x64-windows=fail
+nanovg:x64-windows-static=fail
nanovg:x86-windows=skip
nativefiledialog:arm-uwp=fail
nativefiledialog:x64-uwp=fail
-netcdf-cxx4:x64-linux=ignore
nethost:x64-uwp=fail
nethost:arm-uwp=fail
nettle:x64-windows-static=skip
@@ -1207,7 +1176,6 @@ nng:arm-uwp=fail
nng:x64-uwp=fail
nrf-ble-driver:arm-uwp=fail
nrf-ble-driver:x64-uwp=fail
-nrf-ble-driver:x64-linux=ignore
numactl:arm64-windows=fail
numactl:arm-uwp=fail
numactl:x64-osx=fail
@@ -1227,7 +1195,6 @@ octomap:x64-uwp=fail
ode:arm64-windows=fail
ode:arm-uwp=fail
ode:x64-uwp=fail
-ode:x64-linux=ignore
offscale-libetcd-cpp:arm64-windows=fail
offscale-libetcd-cpp:arm-uwp=fail
offscale-libetcd-cpp:x64-uwp=fail
@@ -1269,7 +1236,6 @@ opencensus-cpp:x86-windows=fail
opencensus-cpp:x64-uwp=fail
opencl:arm-uwp=fail
opencl:x64-uwp=fail
-opencolorio:x64-linux=ignore
opencsg:x64-uwp=fail
opencv2:arm64-windows = skip
opencv2:arm-uwp = skip
@@ -1294,9 +1260,8 @@ openexr:arm-uwp=fail
openexr:x64-uwp=fail
opengl:arm64-windows=fail
opengl:arm-uwp=fail
-openimageio:x64-linux=ignore
-openmama:x64-windows=ignore
-openmama:x86-windows=ignore
+openmama:x64-windows=fail
+openmama:x86-windows=fail
openmama:x64-linux=fail
openmama:x64-osx=fail
openmesh:arm64-windows=fail
@@ -1308,7 +1273,6 @@ openmpi:x64-uwp=fail
openmpi:x64-windows=fail
openmpi:x64-windows-static=fail
openmpi:x86-windows=fail
-openmvg:x64-linux=ignore
openmvs:x64-linux=fail
openni2:x64-uwp=fail
openni2:x64-windows-static=fail
@@ -1331,7 +1295,6 @@ openssl-windows:x64-osx=fail
openssl-windows:x64-uwp=fail
opentracing:arm-uwp=fail
opentracing:x64-uwp=fail
-openvdb:x64-linux=ignore
openvdb:x64-osx=fail
#openvdb:x64-windows-static=fail # https://github.com/microsoft/vcpkg/pull/10816#issuecomment-613784827
openvpn3:x64-osx=fail
@@ -1353,7 +1316,6 @@ optional-bare:x64-windows-static = skip
optional-bare:x86-windows = skip
opusfile:arm-uwp=fail
opusfile:x64-uwp=fail
-orc:x64-linux=ignore
orocos-kdl:arm-uwp=fail
orocos-kdl:x64-uwp=fail
osg:x86-windows=skip
@@ -1362,11 +1324,6 @@ osgearth:x64-osx=fail
osgearth:x64-linux=fail
osgearth:x64-windows-static=fail
osg-qt:x64-windows-static=fail
-otl:x64-windows=ignore
-otl:x64-windows-static=ignore
-otl:x64-uwp=ignore
-otl:x64-linux=ignore
-otl:x86-windows=ignore
paho-mqtt:arm-uwp=fail
paho-mqtt:x64-uwp=fail
pangolin:x64-linux=fail
@@ -1374,8 +1331,6 @@ pangolin:x64-osx=fail
pangolin:x64-uwp=fail
pangolin:x64-windows-static=fail
pangomm:x64-osx=fail
-pangomm:x64-windows=ignore
-pangomm:x86-windows=ignore
pangomm:arm64-windows=fail
parmetis:x64-linux=fail
parmetis:x64-osx=fail
@@ -1414,7 +1369,6 @@ pixel:x64-uwp=fail
pixel:x64-windows=fail
pixel:x64-windows-static=fail
pixel:x86-windows=fail
-pixel:x64-linux=ignore
platform-folders:arm-uwp=fail
platform-folders:x64-uwp=fail
plib:arm-uwp=fail
@@ -1434,7 +1388,6 @@ pmdk:x64-windows-static=fail
pmdk:x86-windows=fail
pngwriter:arm-uwp=fail
pngwriter:x64-uwp=fail
-pngwriter:x64-linux=ignore
polyhook2:arm64-windows=fail
polyhook2:arm-uwp=fail
polyhook2:x64-linux=fail
@@ -1452,15 +1405,11 @@ portmidi:arm-uwp=fail
portmidi:x64-linux=fail
portmidi:x64-osx=fail
portmidi:x64-uwp=fail
-ppconsul:x64-linux=ignore
pqp:arm-uwp=fail
pqp:x64-uwp=fail
proj4:arm64-windows=fail
proj4:arm-uwp=fail
proj4:x64-uwp=fail
-protobuf:x64-uwp=ignore
-protobuf:arm64-windows=ignore
-protobuf:arm-uwp=ignore
protobuf-c:x86-windows=fail
protobuf-c:x64-windows=fail
protobuf-c:x64-windows-static=fail
@@ -1488,9 +1437,8 @@ python3:x64-uwp=fail
qca:x64-linux=fail
qca:x64-osx=fail
qca:x64-windows-static=fail
-qhull:arm-uwp=ignore
-qhull:x64-windows-static=ignore
-qhull:x64-uwp=ignore
+qhull:x64-uwp=fail
+qhull:arm-uwp=fail
qpid-proton:arm-uwp=fail
qpid-proton:x64-uwp=fail
qpid-proton:x64-windows-static=fail
@@ -1525,13 +1473,13 @@ qt5-x11extras:x64-windows-static=fail
# Broken by VS2019 16.6 and throws a ton of dialogs attempting to build
# fixed by https://github.com/microsoft/vcpkg/pull/11596
qt5-translations:x64-windows-static=skip
-quickfast:x64-linux=ignore
-quickfix:x64-linux=ignore
-quickfix:x64-windows=ignore
-quickfix:x64-windows-static=ignore
-quickfix:x86-windows=ignore
-quickfix:x64-uwp=fail
quickfix:arm-uwp=fail
+quickfix:arm64-windows=fail
+quickfix:x64-linux=fail
+quickfix:x64-uwp=fail
+quickfix:x64-windows-static=fail
+quickfix:x64-windows=fail
+quickfix:x86-windows=fail
quill:arm64-windows=fail
quill:arm-uwp=fail
quill:x64-uwp=fail
@@ -1543,9 +1491,8 @@ quirc:x64-uwp = skip
quirc:x64-windows = skip
quirc:x64-windows-static = skip
quirc:x86-windows = skip
-qwt:x64-osx=ignore
+qwt:x64-osx=fail
rabit:x64-osx=fail
-rabit:x64-linux=ignore
ragel:arm-uwp=fail
ragel:x64-uwp=fail
range-v3-vs2015:arm64-windows = skip
@@ -1593,13 +1540,9 @@ rhash:arm-uwp=fail
rhash:x64-uwp=fail
rocksdb:arm-uwp=fail
rocksdb:x64-uwp=fail
-rocksdb:x64-linux=ignore
rpclib:arm64-windows=fail
rpclib:arm-uwp=fail
rpclib:x64-uwp=fail
-rpclib:x64-windows=ignore
-rpclib:x86-windows=ignore
-rpclib:x64-windows-static=ignore
rtlsdr:x64-uwp=fail
rtlsdr:arm64-windows=fail
rtlsdr:arm-uwp=fail
@@ -1636,7 +1579,6 @@ scylla-wrapper:x64-windows-static=fail
sdformat6:arm64-windows=fail
sdformat6:arm-uwp=fail
sdformat6:x64-uwp=fail
-sdformat6:x64-linux=ignore
sdformat9:x64-linux=fail
sdformat9:arm-uwp=fail
sdformat9:x64-uwp=fail
@@ -1654,7 +1596,6 @@ seal:arm-uwp=fail
seal:x64-uwp=fail
secp256k1:x64-linux=fail
secp256k1:x64-osx=fail
-selene:x64-linux=ignore
sentencepiece:arm64-windows=fail
sentencepiece:arm-uwp=fail
sentencepiece:x64-uwp=fail
@@ -1663,7 +1604,6 @@ sentencepiece:x86-windows=fail
septag-sx:arm64-windows=fail
septag-sx:arm-uwp=fail
septag-sx:x64-uwp=fail
-sfgui:x64-linux=ignore
sfml:arm64-windows=fail
shapelib:arm-uwp=fail
shapelib:x64-uwp=fail
@@ -1708,13 +1648,11 @@ soqt:arm64-windows=fail
soqt:arm-uwp=fail
soqt:x64-uwp=fail
soundtouch:arm-uwp=fail
-soundtouch:x64-linux=ignore
soundtouch:x64-uwp=fail
soundtouch:x64-windows-static=fail
spaceland:arm64-windows=fail
spaceland:arm-uwp=fail
spaceland:x64-uwp=fail
-spaceland:x64-linux=ignore
spdk:x64-linux=fail
spdk-dpdk:arm64-windows=fail
spdk-dpdk:arm-uwp=fail
@@ -1774,15 +1712,14 @@ superlu:x64-windows=skip
systemc:arm64-windows=fail
systemc:arm-uwp=fail
systemc:x64-uwp=fail
-taglib:x64-linux=ignore
tbb:arm64-windows=fail
tbb:arm-uwp=fail
tbb:x64-uwp=fail
-tcl:arm-uwp=ignore
-tcl:arm64-windows=ignore
-tcl:x64-uwp=ignore
-tcl:x64-linux=ignore
-tcl:x64-osx=ignore
+tcl:arm-uwp=fail
+tcl:arm64-windows=fail
+tcl:x64-uwp=fail
+tcl:x64-linux=fail
+tcl:x64-osx=fail
teemo:x64-uwp=fail
teemo:arm-uwp=fail
teemo:arm64-windows=fail
@@ -1795,9 +1732,9 @@ tensorflow-cc:x64-osx=skip
tensorflow-cc:x64-windows=fail
tensorflow-cc:x64-windows-static=fail
tensorflow-cc:x86-windows=fail
-tesseract:x64-windows=ignore
-tesseract:x64-windows-static=ignore
-tesseract:x86-windows=ignore
+tesseract:x64-windows=fail
+tesseract:x64-windows-static=fail
+tesseract:x86-windows=fail
tesseract:arm64-windows=fail
tfhe:x86-windows=fail
tfhe:x64-windows=fail
@@ -1821,7 +1758,6 @@ tinyexif:arm-uwp=fail
tinyexif:x64-uwp=fail
tinyfiledialogs:arm-uwp=fail
tinyfiledialogs:x64-uwp=fail
-tinynpy:x64-linux=ignore
tiny-process-library:arm-uwp=fail
tiny-process-library:x64-uwp=fail
tinyutf8:arm64-windows=fail
@@ -1909,15 +1845,13 @@ vxl:x64-windows = skip
vxl:x64-windows-static = skip
vxl:x86-windows = skip
wampcc:arm64-windows=fail
-wampcc:x64-linux=ignore
-wangle:x64-linux=ignore
wavpack:arm64-windows=fail
wavpack:x64-linux=fail
wavpack:x64-osx=fail
-wepoll:arm-uwp=ignore
-wepoll:x64-uwp=ignore
-wepoll:x64-linux=ignore
-wepoll:x64-osx=ignore
+wepoll:arm-uwp=fail
+wepoll:x64-uwp=fail
+wepoll:x64-linux=fail
+wepoll:x64-osx=fail
wildmidi:x64-osx=fail
wincrypt:x64-linux=fail
wincrypt:x64-osx=fail
@@ -1946,11 +1880,11 @@ wxchartdir:x64-osx=fail
wxwidgets:x64-linux=fail
x264:arm64-windows=fail
x264:arm-uwp=fail
-x264:x64-uwp=ignore
+x264:x64-uwp=fail
x264:x64-osx=fail
-x264:x86-windows=ignore
-x264:x64-windows=ignore
-x264:x64-windows-static=ignore
+x264:x86-windows=fail
+x264:x64-windows=fail
+x264:x64-windows-static=fail
x265:arm64-windows=fail
x265:arm-uwp=fail
x265:x64-uwp=fail
@@ -1961,7 +1895,6 @@ xbyak:arm-uwp=fail
xbyak:x64-uwp=fail
xerces-c:arm-uwp=fail
xerces-c:x64-uwp=fail
-xeus:x64-linux=ignore
xmlsec:arm-uwp=fail
xmlsec:x64-uwp=fail
# The xmsh upstream repository is gone, if we find no replacement before
@@ -1974,7 +1907,6 @@ xmsh:x64-uwp=skip
xmsh:x64-windows-static=skip
xmsh:x64-windows=skip
xmsh:x86-windows=skip
-xtensor-io:x64-uwp=ignore
x-plane:arm64-windows=fail
x-plane:arm-uwp=fail
x-plane:x64-linux=fail
diff --git a/toolsrc/include/vcpkg/base/files.h b/toolsrc/include/vcpkg/base/files.h
index 7676b49a0..68ef2dbcd 100644
--- a/toolsrc/include/vcpkg/base/files.h
+++ b/toolsrc/include/vcpkg/base/files.h
@@ -163,8 +163,10 @@ namespace vcpkg::Files
virtual bool is_empty(const fs::path& path) const = 0;
virtual bool create_directory(const fs::path& path, std::error_code& ec) = 0;
bool create_directory(const fs::path& path, ignore_errors_t);
+ bool create_directory(const fs::path& path, LineInfo li);
virtual bool create_directories(const fs::path& path, std::error_code& ec) = 0;
bool create_directories(const fs::path& path, ignore_errors_t);
+ bool create_directories(const fs::path& path, LineInfo);
virtual void copy(const fs::path& oldpath, const fs::path& newpath, fs::copy_options opts) = 0;
virtual bool copy_file(const fs::path& oldpath,
const fs::path& newpath,
diff --git a/toolsrc/include/vcpkg/binarycaching.h b/toolsrc/include/vcpkg/binarycaching.h
index c1db1f169..24c81b905 100644
--- a/toolsrc/include/vcpkg/binarycaching.h
+++ b/toolsrc/include/vcpkg/binarycaching.h
@@ -35,8 +35,6 @@ namespace vcpkg
virtual RestoreResult try_restore(const VcpkgPaths& paths, const Dependencies::InstallPlanAction& action) = 0;
/// Called upon a successful build of `action`
virtual void push_success(const VcpkgPaths& paths, const Dependencies::InstallPlanAction& action) = 0;
- /// Called upon a failure during the build of `action`
- virtual void push_failure(const VcpkgPaths& paths, const std::string& abi_tag, const PackageSpec& spec) = 0;
/// Requests the result of `try_restore()` without actually downloading the package. Used by CI to determine
/// missing packages.
virtual RestoreResult precheck(const VcpkgPaths& paths, const Dependencies::InstallPlanAction& action) = 0;
diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h
index 804cb6673..ea9f86fef 100644
--- a/toolsrc/include/vcpkg/build.h
+++ b/toolsrc/include/vcpkg/build.h
@@ -35,17 +35,40 @@ namespace vcpkg::System
namespace vcpkg::Build
{
+ enum class BuildResult
+ {
+ NULLVALUE = 0,
+ SUCCEEDED,
+ BUILD_FAILED,
+ POST_BUILD_CHECKS_FAILED,
+ FILE_CONFLICTS,
+ CASCADED_DUE_TO_MISSING_DEPENDENCIES,
+ EXCLUDED,
+ DOWNLOADED
+ };
+
+ struct IBuildLogsRecorder
+ {
+ virtual void record_build_result(const VcpkgPaths& paths,
+ const PackageSpec& spec,
+ BuildResult result) const = 0;
+ };
+
+ const IBuildLogsRecorder& null_build_logs_recorder() noexcept;
+
namespace Command
{
int perform_ex(const FullPackageSpec& full_spec,
const SourceControlFileLocation& scfl,
const PortFileProvider::PathsPortFileProvider& provider,
IBinaryProvider& binaryprovider,
+ const IBuildLogsRecorder& build_logs_recorder,
const VcpkgPaths& paths);
void perform_and_exit_ex(const FullPackageSpec& full_spec,
const SourceControlFileLocation& scfl,
const PortFileProvider::PathsPortFileProvider& provider,
IBinaryProvider& binaryprovider,
+ const IBuildLogsRecorder& build_logs_recorder,
const VcpkgPaths& paths);
int perform(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet);
@@ -100,13 +123,6 @@ namespace vcpkg::Build
ARIA2,
};
const std::string& to_string(DownloadTool tool);
-
- enum class FailOnTombstone
- {
- NO = 0,
- YES
- };
-
enum class PurgeDecompressFailure
{
NO = 0,
@@ -122,20 +138,18 @@ namespace vcpkg::Build
CleanPackages clean_packages;
CleanDownloads clean_downloads;
DownloadTool download_tool;
- FailOnTombstone fail_on_tombstone;
PurgeDecompressFailure purge_decompress_failure;
};
- enum class BuildResult
- {
- NULLVALUE = 0,
- SUCCEEDED,
- BUILD_FAILED,
- POST_BUILD_CHECKS_FAILED,
- FILE_CONFLICTS,
- CASCADED_DUE_TO_MISSING_DEPENDENCIES,
- EXCLUDED,
- DOWNLOADED
+ static constexpr BuildPackageOptions default_build_package_options{
+ Build::UseHeadVersion::NO,
+ Build::AllowDownloads::YES,
+ Build::OnlyDownloads::NO,
+ Build::CleanBuildtrees::YES,
+ Build::CleanPackages::YES,
+ Build::CleanDownloads::NO,
+ Build::DownloadTool::BUILT_IN,
+ Build::PurgeDecompressFailure::YES,
};
static constexpr std::array<BuildResult, 6> BUILD_RESULT_VALUES = {
@@ -194,6 +208,7 @@ namespace vcpkg::Build
ExtendedBuildResult build_package(const VcpkgPaths& paths,
const Dependencies::InstallPlanAction& config,
IBinaryProvider& binaries_provider,
+ const IBuildLogsRecorder& build_logs_recorder,
const StatusParagraphs& status_db);
enum class BuildPolicy
diff --git a/toolsrc/include/vcpkg/install.h b/toolsrc/include/vcpkg/install.h
index 9a438b039..2700ac3a8 100644
--- a/toolsrc/include/vcpkg/install.h
+++ b/toolsrc/include/vcpkg/install.h
@@ -86,6 +86,7 @@ namespace vcpkg::Install
const VcpkgPaths& paths,
StatusParagraphs& status_db,
IBinaryProvider& binaryprovider,
+ const Build::IBuildLogsRecorder& build_logs_recorder,
const CMakeVars::CMakeVarProvider& var_provider);
extern const CommandStructure COMMAND_STRUCTURE;
diff --git a/toolsrc/include/vcpkg/vcpkgpaths.h b/toolsrc/include/vcpkg/vcpkgpaths.h
index 08efc9541..296b6a314 100644
--- a/toolsrc/include/vcpkg/vcpkgpaths.h
+++ b/toolsrc/include/vcpkg/vcpkgpaths.h
@@ -75,6 +75,8 @@ namespace vcpkg
~VcpkgPaths();
fs::path package_dir(const PackageSpec& spec) const;
+ fs::path build_dir(const PackageSpec& spec) const;
+ fs::path build_dir(const std::string& package_name) const;
fs::path build_info_file_path(const PackageSpec& spec) const;
fs::path listfile_path(const BinaryParagraph& pgh) const;
diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp
index 2e39073ce..32a382154 100644
--- a/toolsrc/src/vcpkg/base/files.cpp
+++ b/toolsrc/src/vcpkg/base/files.cpp
@@ -204,11 +204,36 @@ namespace vcpkg::Files
return this->create_directory(path, ec);
}
+ bool Filesystem::create_directory(const fs::path& path, LineInfo li)
+ {
+ std::error_code ec;
+ bool result = this->create_directory(path, ec);
+ if (ec)
+ {
+ vcpkg::Checks::exit_with_message(li, "error creating directory %s", path.u8string(), ec.message());
+ }
+
+ return result;
+ }
+
bool Filesystem::create_directories(const fs::path& path, ignore_errors_t)
{
std::error_code ec;
return this->create_directories(path, ec);
}
+
+ bool Filesystem::create_directories(const fs::path& path, LineInfo li)
+ {
+ std::error_code ec;
+ bool result = this->create_directories(path, ec);
+ if (ec)
+ {
+ vcpkg::Checks::exit_with_message(li, "error creating directories %s", path.u8string(), ec.message());
+ }
+
+ return result;
+ }
+
void Filesystem::copy_file(const fs::path& oldpath, const fs::path& newpath, fs::copy_options opts, LineInfo li)
{
std::error_code ec;
diff --git a/toolsrc/src/vcpkg/binarycaching.cpp b/toolsrc/src/vcpkg/binarycaching.cpp
index 1c337aea5..21ef7094a 100644
--- a/toolsrc/src/vcpkg/binarycaching.cpp
+++ b/toolsrc/src/vcpkg/binarycaching.cpp
@@ -104,33 +104,10 @@ namespace
}
}
}
+
+ System::printf("Could not locate cached archive: %s\n", archive_path.u8string());
}
- for (auto&& archives_root_dir : m_read_dirs)
- {
- const std::string archive_name = abi_tag + ".zip";
- const fs::path archive_subpath = fs::u8path(abi_tag.substr(0, 2)) / fs::u8path(archive_name);
- const fs::path archive_tombstone_path = archives_root_dir / fs::u8path("fail") / archive_subpath;
- if (fs.exists(archive_tombstone_path))
- {
- if (action.build_options.fail_on_tombstone == Build::FailOnTombstone::YES)
- {
- System::print2("Found failure tombstone: ", archive_tombstone_path.u8string(), "\n");
- return RestoreResult::build_failed;
- }
- else
- {
- System::print2(System::Color::warning,
- "Found failure tombstone: ",
- archive_tombstone_path.u8string(),
- "\n");
- }
- }
- else
- {
- const fs::path archive_path = archives_root_dir / archive_subpath;
- System::printf("Could not locate cached archive: %s\n", archive_path.u8string());
- }
- }
+
return RestoreResult::missing;
}
void push_success(const VcpkgPaths& paths, const Dependencies::InstallPlanAction& action) override
@@ -167,46 +144,6 @@ namespace
}
if (m_write_dirs.size() > 1) fs.remove(tmp_archive_path, ignore_errors);
}
- void push_failure(const VcpkgPaths& paths, const std::string& abi_tag, const PackageSpec& spec) override
- {
- if (m_write_dirs.empty()) return;
- auto& fs = paths.get_filesystem();
- std::error_code ec;
- for (auto&& m_directory : m_write_dirs)
- {
- const fs::path& archives_root_dir = m_directory;
- const std::string archive_name = abi_tag + ".zip";
- const fs::path archive_subpath = fs::u8path(abi_tag.substr(0, 2)) / fs::u8path(archive_name);
- const fs::path archive_tombstone_path = archives_root_dir / fs::u8path("fail") / archive_subpath;
- if (!fs.exists(archive_tombstone_path))
- {
- // Build failed, store all failure logs in the tombstone.
- const auto spec_name_path = fs::u8path(spec.name());
- const auto tmp_log_path = paths.buildtrees / spec_name_path / fs::u8path("tmp_failure_logs");
- const auto tmp_log_path_destination = tmp_log_path / spec_name_path;
- const auto tmp_failure_zip = paths.buildtrees / spec_name_path / fs::u8path("failure_logs.zip");
- fs.create_directories(tmp_log_path_destination, ignore_errors);
-
- for (auto& log_file : fs::stdfs::directory_iterator(paths.buildtrees / spec.name()))
- {
- if (log_file.path().extension() == ".log")
- {
- fs.copy_file(log_file.path(),
- tmp_log_path_destination / log_file.path().filename(),
- fs::copy_options::none,
- ec);
- }
- }
-
- compress_directory(paths, tmp_log_path, tmp_failure_zip);
- fs.create_directories(archive_tombstone_path.parent_path(), ignore_errors);
- fs.rename_or_copy(tmp_failure_zip, archive_tombstone_path, ".tmp", ec);
-
- // clean up temporary directory
- fs.remove_all(tmp_log_path, VCPKG_LINE_INFO);
- }
- }
- }
RestoreResult precheck(const VcpkgPaths& paths, const Dependencies::InstallPlanAction& action) override
{
const auto& abi_tag = action.abi_info.value_or_exit(VCPKG_LINE_INFO).package_abi;
@@ -223,20 +160,6 @@ namespace
return RestoreResult::success;
}
}
- for (auto&& archives_root_dir : m_read_dirs)
- {
- const std::string archive_name = abi_tag + ".zip";
- const fs::path archive_subpath = fs::u8path(abi_tag.substr(0, 2)) / fs::u8path(archive_name);
- const fs::path archive_tombstone_path = archives_root_dir / fs::u8path("fail") / archive_subpath;
-
- if (fs.exists(archive_tombstone_path))
- {
- if (action.build_options.fail_on_tombstone == Build::FailOnTombstone::YES)
- {
- return RestoreResult::build_failed;
- }
- }
- }
return RestoreResult::missing;
}
@@ -525,7 +448,6 @@ namespace
paths.get_filesystem().remove(nupkg_path, ignore_errors);
}
}
- void push_failure(const VcpkgPaths&, const std::string&, const PackageSpec&) override {}
RestoreResult precheck(const VcpkgPaths&, const Dependencies::InstallPlanAction&) override
{
return RestoreResult::missing;
@@ -578,13 +500,6 @@ namespace
provider->push_success(paths, action);
}
}
- void push_failure(const VcpkgPaths& paths, const std::string& abi_tag, const PackageSpec& spec) override
- {
- for (auto&& provider : m_providers)
- {
- provider->push_failure(paths, abi_tag, spec);
- }
- }
RestoreResult precheck(const VcpkgPaths& paths, const Dependencies::InstallPlanAction& action) override
{
for (auto&& provider : m_providers)
@@ -613,7 +528,6 @@ namespace
return RestoreResult::missing;
}
void push_success(const VcpkgPaths&, const Dependencies::InstallPlanAction&) override {}
- void push_failure(const VcpkgPaths&, const std::string&, const PackageSpec&) override {}
RestoreResult precheck(const VcpkgPaths&, const Dependencies::InstallPlanAction&) override
{
return RestoreResult::missing;
diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp
index 7d2976165..d89bb5b74 100644
--- a/toolsrc/src/vcpkg/build.cpp
+++ b/toolsrc/src/vcpkg/build.cpp
@@ -32,6 +32,24 @@ using vcpkg::Parse::ParseControlErrorInfo;
using vcpkg::Parse::ParseExpected;
using vcpkg::PortFileProvider::PathsPortFileProvider;
+namespace
+{
+ using vcpkg::PackageSpec;
+ using vcpkg::VcpkgPaths;
+ using vcpkg::Build::IBuildLogsRecorder;
+ struct NullBuildLogsRecorder final : IBuildLogsRecorder
+ {
+ void record_build_result(const VcpkgPaths& paths, const PackageSpec& spec, BuildResult result) const override
+ {
+ (void)paths;
+ (void)spec;
+ (void)result;
+ }
+ };
+
+ static const NullBuildLogsRecorder null_build_logs_recorder_instance;
+}
+
namespace vcpkg::Build
{
using Dependencies::InstallPlanAction;
@@ -41,9 +59,11 @@ namespace vcpkg::Build
const SourceControlFileLocation& scfl,
const PathsPortFileProvider& provider,
IBinaryProvider& binaryprovider,
+ const IBuildLogsRecorder& build_logs_recorder,
const VcpkgPaths& paths)
{
- Checks::exit_with_code(VCPKG_LINE_INFO, perform_ex(full_spec, scfl, provider, binaryprovider, paths));
+ Checks::exit_with_code(VCPKG_LINE_INFO,
+ perform_ex(full_spec, scfl, provider, binaryprovider, build_logs_recorder, paths));
}
const CommandStructure COMMAND_STRUCTURE = {
@@ -63,6 +83,7 @@ namespace vcpkg::Build
const SourceControlFileLocation& scfl,
const PathsPortFileProvider& provider,
IBinaryProvider& binaryprovider,
+ const IBuildLogsRecorder& build_logs_recorder,
const VcpkgPaths& paths)
{
auto var_provider_storage = CMakeVars::make_triplet_cmake_var_provider(paths);
@@ -86,17 +107,6 @@ namespace vcpkg::Build
compute_all_abis(paths, action_plan, var_provider, status_db);
- const Build::BuildPackageOptions build_package_options{
- Build::UseHeadVersion::NO,
- Build::AllowDownloads::YES,
- Build::OnlyDownloads::NO,
- Build::CleanBuildtrees::NO,
- Build::CleanPackages::NO,
- Build::CleanDownloads::NO,
- Build::DownloadTool::BUILT_IN,
- Build::FailOnTombstone::NO,
- };
-
InstallPlanAction* action = nullptr;
for (auto& install_action : action_plan.already_installed)
{
@@ -115,10 +125,10 @@ namespace vcpkg::Build
Checks::check_exit(VCPKG_LINE_INFO, action != nullptr);
ASSUME(action != nullptr);
- action->build_options = build_package_options;
+ action->build_options = default_build_package_options;
const auto build_timer = Chrono::ElapsedTimer::create_started();
- const auto result = Build::build_package(paths, *action, binaryprovider, status_db);
+ const auto result = Build::build_package(paths, *action, binaryprovider, build_logs_recorder, status_db);
System::print2("Elapsed time for package ", spec, ": ", build_timer, '\n');
if (result.code == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES)
@@ -167,8 +177,12 @@ namespace vcpkg::Build
Checks::check_exit(VCPKG_LINE_INFO, scfl != nullptr, "Error: Couldn't find port '%s'", port_name);
ASSUME(scfl != nullptr);
- return perform_ex(
- spec, *scfl, provider, args.binary_caching_enabled() ? *binaryprovider : null_binary_provider(), paths);
+ return perform_ex(spec,
+ *scfl,
+ provider,
+ args.binary_caching_enabled() ? *binaryprovider : null_binary_provider(),
+ Build::null_build_logs_recorder(),
+ paths);
}
}
@@ -728,8 +742,7 @@ namespace vcpkg::Build
if (action.build_options.clean_buildtrees == CleanBuildtrees::YES)
{
auto& fs = paths.get_filesystem();
- const fs::path buildtrees_dir = paths.buildtrees / action.spec.name();
- auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir);
+ auto buildtree_files = fs.get_files_non_recursive(paths.build_dir(action.spec));
for (auto&& file : buildtree_files)
{
if (fs.is_directory(file)) // Will only keep the logs
@@ -771,7 +784,6 @@ namespace vcpkg::Build
{
auto& fs = paths.get_filesystem();
Triplet triplet = action.spec.triplet();
- const std::string& name = action.spec.name();
std::vector<AbiEntry> abi_tag_entries(dependency_abis.begin(), dependency_abis.end());
@@ -841,9 +853,9 @@ namespace vcpkg::Build
if (abi_tag_entries_missing.empty())
{
- std::error_code ec;
- fs.create_directories(paths.buildtrees / name, ec);
- const auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt");
+ auto current_build_tree = paths.build_dir(action.spec);
+ fs.create_directory(current_build_tree, VCPKG_LINE_INFO);
+ const auto abi_file_path = current_build_tree / (triplet.canonical_name() + ".vcpkg_abi_info.txt");
fs.write_contents(abi_file_path, full_abi_info, VCPKG_LINE_INFO);
return AbiTagAndFile{Hash::get_file_hash(VCPKG_LINE_INFO, fs, abi_file_path, Hash::Algorithm::Sha1),
@@ -919,6 +931,7 @@ namespace vcpkg::Build
ExtendedBuildResult build_package(const VcpkgPaths& paths,
const Dependencies::InstallPlanAction& action,
IBinaryProvider& binaries_provider,
+ const IBuildLogsRecorder& build_logs_recorder,
const StatusParagraphs& status_db)
{
auto& fs = paths.get_filesystem();
@@ -991,10 +1004,8 @@ namespace vcpkg::Build
{
binaries_provider.push_success(paths, action);
}
- else if ((result.code == BuildResult::BUILD_FAILED || result.code == BuildResult::POST_BUILD_CHECKS_FAILED))
- {
- binaries_provider.push_failure(paths, abi_info.package_abi, spec);
- }
+
+ build_logs_recorder.record_build_result(paths, spec, result.code);
return result;
}
@@ -1217,4 +1228,6 @@ namespace vcpkg::Build
: code(code), unmet_dependencies(std::move(unmet_deps))
{
}
+
+ const IBuildLogsRecorder& null_build_logs_recorder() noexcept { return null_build_logs_recorder_instance; }
}
diff --git a/toolsrc/src/vcpkg/commands.buildexternal.cpp b/toolsrc/src/vcpkg/commands.buildexternal.cpp
index 5609e28f8..5fc26b8ea 100644
--- a/toolsrc/src/vcpkg/commands.buildexternal.cpp
+++ b/toolsrc/src/vcpkg/commands.buildexternal.cpp
@@ -41,6 +41,7 @@ namespace vcpkg::Commands::BuildExternal
maybe_scfl.value_or_exit(VCPKG_LINE_INFO),
provider,
args.binary_caching_enabled() ? *binaryprovider : null_binary_provider(),
+ Build::null_build_logs_recorder(),
paths);
}
}
diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp
index df69d2e12..8453d7af6 100644
--- a/toolsrc/src/vcpkg/commands.ci.cpp
+++ b/toolsrc/src/vcpkg/commands.ci.cpp
@@ -20,6 +20,55 @@
using namespace vcpkg;
+namespace
+{
+ using namespace vcpkg::Build;
+
+ const fs::path dot_log = fs::u8path(".log");
+ const fs::path readme_dot_log = fs::u8path("readme.log");
+
+ class CiBuildLogsRecorder final : public IBuildLogsRecorder
+ {
+ fs::path base_path;
+
+ public:
+ CiBuildLogsRecorder(const fs::path& base_path_) : base_path(base_path_) {}
+
+ virtual void record_build_result(const VcpkgPaths& paths,
+ const PackageSpec& spec,
+ BuildResult result) const override
+ {
+ if (result == BuildResult::SUCCEEDED)
+ {
+ return;
+ }
+
+ auto& filesystem = paths.get_filesystem();
+ const auto source_path = paths.build_dir(spec);
+ auto children = filesystem.get_files_non_recursive(source_path);
+ Util::erase_remove_if(children, [](const fs::path& p) { return p.extension() != dot_log; });
+ const auto target_path = base_path / fs::u8path(spec.name());
+ (void)filesystem.create_directory(target_path, VCPKG_LINE_INFO);
+ if (children.empty())
+ {
+ std::string message =
+ "There are no build logs for " + spec.to_string() +
+ " build.\n"
+ "This is usually because the build failed early and outside of a task that is logged.\n"
+ "See the console output logs from vcpkg for more information on the failure.\n";
+ filesystem.write_contents(target_path / readme_dot_log, message, VCPKG_LINE_INFO);
+ }
+ else
+ {
+ for (const fs::path& p : children)
+ {
+ filesystem.copy_file(p, target_path / p.filename(), fs::copy_options::none, VCPKG_LINE_INFO);
+ }
+ }
+ }
+ };
+}
+
namespace vcpkg::Commands::CI
{
using Build::BuildResult;
@@ -34,13 +83,14 @@ namespace vcpkg::Commands::CI
static constexpr StringLiteral OPTION_DRY_RUN = "--dry-run";
static constexpr StringLiteral OPTION_EXCLUDE = "--exclude";
+ static constexpr StringLiteral OPTION_FAILURE_LOGS = "--failure-logs";
static constexpr StringLiteral OPTION_XUNIT = "--x-xunit";
static constexpr StringLiteral OPTION_RANDOMIZE = "--x-randomize";
- static constexpr std::array<CommandSetting, 2> CI_SETTINGS = {{
- {OPTION_EXCLUDE, "Comma separated list of ports to skip"},
- {OPTION_XUNIT, "File to output results in XUnit format (internal)"},
- }};
+ static constexpr std::array<CommandSetting, 3> CI_SETTINGS = {
+ {{OPTION_EXCLUDE, "Comma separated list of ports to skip"},
+ {OPTION_XUNIT, "File to output results in XUnit format (internal)"},
+ {OPTION_FAILURE_LOGS, "Directory to which failure logs will be copied"}}};
static constexpr std::array<CommandSwitch, 2> CI_SWITCHES = {{
{OPTION_DRY_RUN, "Print out plan without execution"},
@@ -245,17 +295,6 @@ namespace vcpkg::Commands::CI
std::set<PackageSpec> will_fail;
- const Build::BuildPackageOptions build_options = {
- Build::UseHeadVersion::NO,
- Build::AllowDownloads::YES,
- Build::OnlyDownloads::NO,
- Build::CleanBuildtrees::YES,
- Build::CleanPackages::YES,
- Build::CleanDownloads::NO,
- Build::DownloadTool::BUILT_IN,
- Build::FailOnTombstone::YES,
- };
-
std::vector<PackageSpec> packages_with_qualified_deps;
auto has_qualifier = [](Dependency const& dep) { return !dep.platform.is_empty(); };
for (auto&& spec : specs)
@@ -300,7 +339,7 @@ namespace vcpkg::Commands::CI
auto emp = ret->default_feature_provider.emplace(p->spec.name(), *scfl);
emp.first->second.source_control_file->core_paragraph->default_features = p->feature_list;
- p->build_options = build_options;
+ p->build_options = vcpkg::Build::default_build_package_options;
}
auto precheck_result = binaryprovider.precheck(paths, action);
@@ -361,11 +400,6 @@ namespace vcpkg::Commands::CI
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
{
- if (!args.binary_caching_enabled())
- {
- System::print2(System::Color::warning, "Warning: Running ci without binary caching!\n");
- }
-
std::unique_ptr<IBinaryProvider> binaryproviderStorage;
if (args.binary_caching_enabled())
{
@@ -376,10 +410,11 @@ namespace vcpkg::Commands::CI
IBinaryProvider& binaryprovider = binaryproviderStorage ? *binaryproviderStorage : null_binary_provider();
const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
+ auto& settings = options.settings;
std::set<std::string> exclusions_set;
- auto it_exclusions = options.settings.find(OPTION_EXCLUDE);
- if (it_exclusions != options.settings.end())
+ auto it_exclusions = settings.find(OPTION_EXCLUDE);
+ if (it_exclusions != settings.end())
{
auto exclusions = Strings::split(it_exclusions->second, ',');
exclusions_set.insert(exclusions.begin(), exclusions.end());
@@ -395,24 +430,28 @@ namespace vcpkg::Commands::CI
triplets.push_back(default_triplet);
}
+ auto& filesystem = paths.get_filesystem();
+ Optional<CiBuildLogsRecorder> build_logs_recorder_storage;
+ {
+ auto it_failure_logs = settings.find(OPTION_FAILURE_LOGS);
+ if (it_failure_logs != settings.end())
+ {
+ auto raw_path = fs::u8path(it_failure_logs->second);
+ System::printf("Creating failure logs output directory %s\n", it_failure_logs->second);
+ filesystem.create_directories(raw_path, VCPKG_LINE_INFO);
+ build_logs_recorder_storage = filesystem.canonical(VCPKG_LINE_INFO, raw_path);
+ }
+ }
+
+ const IBuildLogsRecorder& build_logs_recorder =
+ build_logs_recorder_storage ? *(build_logs_recorder_storage.get()) : null_build_logs_recorder();
+
StatusParagraphs status_db = database_load_check(paths);
PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
auto var_provider_storage = CMakeVars::make_triplet_cmake_var_provider(paths);
auto& var_provider = *var_provider_storage;
- const Build::BuildPackageOptions install_plan_options = {
- Build::UseHeadVersion::NO,
- Build::AllowDownloads::YES,
- Build::OnlyDownloads::NO,
- Build::CleanBuildtrees::YES,
- Build::CleanPackages::YES,
- Build::CleanDownloads::NO,
- Build::DownloadTool::BUILT_IN,
- Build::FailOnTombstone::YES,
- Build::PurgeDecompressFailure::YES,
- };
-
std::vector<std::map<PackageSpec, BuildResult>> all_known_results;
XunitTestResults xunitTestResults;
@@ -438,12 +477,8 @@ namespace vcpkg::Commands::CI
return FullPackageSpec{spec, std::move(default_features)};
});
- auto split_specs = find_unknown_ports_for_ci(paths,
- exclusions_set,
- provider,
- var_provider,
- all_default_full_specs,
- binaryprovider);
+ auto split_specs = find_unknown_ports_for_ci(
+ paths, exclusions_set, provider, var_provider, all_default_full_specs, binaryprovider);
PortFileProvider::MapPortFileProvider new_default_provider(split_specs->default_feature_provider);
Dependencies::CreateInstallPlanOptions serialize_options;
@@ -476,7 +511,7 @@ namespace vcpkg::Commands::CI
}
else
{
- action.build_options = install_plan_options;
+ action.build_options = vcpkg::Build::default_build_package_options;
}
}
@@ -487,8 +522,13 @@ namespace vcpkg::Commands::CI
else
{
auto collection_timer = Chrono::ElapsedTimer::create_started();
- auto summary = Install::perform(
- action_plan, Install::KeepGoing::YES, paths, status_db, binaryprovider, var_provider);
+ auto summary = Install::perform(action_plan,
+ Install::KeepGoing::YES,
+ paths,
+ status_db,
+ binaryprovider,
+ build_logs_recorder,
+ var_provider);
auto collection_time_elapsed = collection_timer.elapsed();
// Adding results for ports that were built or pulled from an archive
@@ -530,12 +570,10 @@ namespace vcpkg::Commands::CI
result.summary.print();
}
- auto& settings = options.settings;
auto it_xunit = settings.find(OPTION_XUNIT);
if (it_xunit != settings.end())
{
- paths.get_filesystem().write_contents(
- fs::u8path(it_xunit->second), xunitTestResults.build_xml(), VCPKG_LINE_INFO);
+ filesystem.write_contents(fs::u8path(it_xunit->second), xunitTestResults.build_xml(), VCPKG_LINE_INFO);
}
Checks::exit_success(VCPKG_LINE_INFO);
diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp
index e3c74d360..1f00a929e 100644
--- a/toolsrc/src/vcpkg/commands.edit.cpp
+++ b/toolsrc/src/vcpkg/commands.edit.cpp
@@ -115,7 +115,7 @@ namespace vcpkg::Commands::Edit
return Util::fmap(ports, [&](const std::string& port_name) -> std::string {
const auto portpath = paths.ports / port_name;
const auto portfile = portpath / "portfile.cmake";
- const auto buildtrees_current_dir = paths.buildtrees / port_name;
+ const auto buildtrees_current_dir = paths.build_dir(port_name);
const auto pattern = port_name + "_";
std::string package_paths;
@@ -138,8 +138,7 @@ namespace vcpkg::Commands::Edit
if (Util::Sets::contains(options.switches, OPTION_BUILDTREES))
{
return Util::fmap(ports, [&](const std::string& port_name) -> std::string {
- const auto buildtrees_current_dir = paths.buildtrees / port_name;
- return Strings::format(R"###("%s")###", buildtrees_current_dir.u8string());
+ return Strings::format(R"###("%s")###", paths.build_dir(port_name).u8string());
});
}
diff --git a/toolsrc/src/vcpkg/commands.setinstalled.cpp b/toolsrc/src/vcpkg/commands.setinstalled.cpp
index df191ee3e..d248a4b09 100644
--- a/toolsrc/src/vcpkg/commands.setinstalled.cpp
+++ b/toolsrc/src/vcpkg/commands.setinstalled.cpp
@@ -118,6 +118,7 @@ namespace vcpkg::Commands::SetInstalled
paths,
status_db,
args.binary_caching_enabled() ? binary_provider : null_binary_provider(),
+ Build::null_build_logs_recorder(),
cmake_vars);
System::print2("\nTotal elapsed time: ", summary.total_elapsed_time, "\n\n");
@@ -145,17 +146,6 @@ namespace vcpkg::Commands::SetInstalled
const bool dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN);
- const Build::BuildPackageOptions install_plan_options = {
- Build::UseHeadVersion::NO,
- Build::AllowDownloads::YES,
- Build::OnlyDownloads::NO,
- Build::CleanBuildtrees::YES,
- Build::CleanPackages::YES,
- Build::CleanDownloads::YES,
- Build::DownloadTool::BUILT_IN,
- Build::FailOnTombstone::NO,
- };
-
PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
auto cmake_vars = CMakeVars::make_triplet_cmake_var_provider(paths);
@@ -171,7 +161,7 @@ namespace vcpkg::Commands::SetInstalled
*binary_provider,
*cmake_vars,
specs,
- install_plan_options,
+ vcpkg::Build::default_build_package_options,
dry_run ? DryRun::Yes : DryRun::No,
pkgsconfig);
}
diff --git a/toolsrc/src/vcpkg/commands.upgrade.cpp b/toolsrc/src/vcpkg/commands.upgrade.cpp
index 89466ab60..32071259b 100644
--- a/toolsrc/src/vcpkg/commands.upgrade.cpp
+++ b/toolsrc/src/vcpkg/commands.upgrade.cpp
@@ -157,21 +157,10 @@ namespace vcpkg::Commands::Upgrade
Checks::check_exit(VCPKG_LINE_INFO, !action_plan.empty());
- const Build::BuildPackageOptions install_plan_options = {
- Build::UseHeadVersion::NO,
- Build::AllowDownloads::YES,
- Build::OnlyDownloads::NO,
- Build::CleanBuildtrees::NO,
- Build::CleanPackages::NO,
- Build::CleanDownloads::NO,
- Build::DownloadTool::BUILT_IN,
- Build::FailOnTombstone::NO,
- };
-
// Set build settings for all install actions
for (auto&& action : action_plan.install_actions)
{
- action.build_options = install_plan_options;
+ action.build_options = vcpkg::Build::default_build_package_options;
}
Dependencies::print_plan(action_plan, true, paths.ports);
@@ -192,6 +181,7 @@ namespace vcpkg::Commands::Upgrade
paths,
status_db,
args.binary_caching_enabled() ? *binaryprovider : null_binary_provider(),
+ Build::null_build_logs_recorder(),
var_provider);
System::print2("\nTotal elapsed time: ", summary.total_elapsed_time, "\n\n");
diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp
index 48e9747b3..3819584f9 100644
--- a/toolsrc/src/vcpkg/export.cpp
+++ b/toolsrc/src/vcpkg/export.cpp
@@ -76,17 +76,6 @@ namespace vcpkg::Export
{
static constexpr std::array<ExportPlanType, 2> ORDER = {ExportPlanType::ALREADY_BUILT,
ExportPlanType::NOT_BUILT};
- static constexpr Build::BuildPackageOptions BUILD_OPTIONS = {
- Build::UseHeadVersion::NO,
- Build::AllowDownloads::YES,
- Build::OnlyDownloads::NO,
- Build::CleanBuildtrees::NO,
- Build::CleanPackages::NO,
- Build::CleanDownloads::NO,
- Build::DownloadTool::BUILT_IN,
- Build::FailOnTombstone::NO,
- };
-
for (const ExportPlanType plan_type : ORDER)
{
const auto it = group_by_plan_type.find(plan_type);
@@ -98,7 +87,8 @@ namespace vcpkg::Export
std::vector<const ExportPlanAction*> cont = it->second;
std::sort(cont.begin(), cont.end(), &ExportPlanAction::compare_by_name);
const std::string as_string = Strings::join("\n", cont, [](const ExportPlanAction* p) {
- return Dependencies::to_output_string(p->request_type, p->spec.to_string(), BUILD_OPTIONS);
+ return Dependencies::to_output_string(
+ p->request_type, p->spec.to_string(), vcpkg::Build::default_build_package_options);
});
switch (plan_type)
diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp
index aa79bb1f2..842a7a7fa 100644
--- a/toolsrc/src/vcpkg/install.cpp
+++ b/toolsrc/src/vcpkg/install.cpp
@@ -308,7 +308,8 @@ namespace vcpkg::Install
static ExtendedBuildResult perform_install_plan_action(const VcpkgPaths& paths,
InstallPlanAction& action,
StatusParagraphs& status_db,
- IBinaryProvider& binaries_provider)
+ IBinaryProvider& binaries_provider,
+ const Build::IBuildLogsRecorder& build_logs_recorder)
{
const InstallPlanType& plan_type = action.plan_type;
const std::string display_name = action.spec.to_string();
@@ -328,19 +329,6 @@ namespace vcpkg::Install
return BuildResult::SUCCEEDED;
}
- auto aux_install = [&](const std::string& name, const BinaryControlFile& bcf) -> BuildResult {
- System::printf("Installing package %s...\n", name);
- const auto install_result = install_package(paths, bcf, &status_db);
- switch (install_result)
- {
- case InstallResult::SUCCESS:
- System::printf(System::Color::success, "Installing package %s... done\n", name);
- return BuildResult::SUCCEEDED;
- case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- };
-
if (plan_type == InstallPlanType::BUILD_AND_INSTALL)
{
if (use_head_version)
@@ -348,7 +336,7 @@ namespace vcpkg::Install
else
System::printf("Building package %s...\n", display_name_with_features);
- auto result = Build::build_package(paths, action, binaries_provider, status_db);
+ auto result = Build::build_package(paths, action, binaries_provider, build_logs_recorder, status_db);
if (BuildResult::DOWNLOADED == result.code)
{
@@ -367,7 +355,19 @@ namespace vcpkg::Install
auto bcf = std::make_unique<BinaryControlFile>(
Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO));
- auto code = aux_install(display_name_with_features, *bcf);
+ System::printf("Installing package %s...\n", display_name_with_features);
+ const auto install_result = install_package(paths, *bcf, &status_db);
+ BuildResult code;
+ switch (install_result)
+ {
+ case InstallResult::SUCCESS:
+ System::printf(
+ System::Color::success, "Installing package %s... done\n", display_name_with_features);
+ code = BuildResult::SUCCEEDED;
+ break;
+ case InstallResult::FILE_CONFLICTS: code = BuildResult::FILE_CONFLICTS; break;
+ default: Checks::unreachable(VCPKG_LINE_INFO);
+ }
if (action.build_options.clean_packages == Build::CleanPackages::YES)
{
@@ -429,44 +429,52 @@ namespace vcpkg::Install
}
}
+ struct TrackedPackageInstallGuard
+ {
+ SpecSummary* current_summary = nullptr;
+ Chrono::ElapsedTimer build_timer = Chrono::ElapsedTimer::create_started();
+
+ TrackedPackageInstallGuard(const size_t package_count, std::vector<SpecSummary>& results, const PackageSpec& spec)
+ {
+ results.emplace_back(spec, nullptr);
+ current_summary = &results.back();
+ System::printf("Starting package %zd/%zd: %s\n", results.size(), package_count, spec.to_string());
+ }
+
+ ~TrackedPackageInstallGuard()
+ {
+ current_summary->timing = build_timer.elapsed();
+ System::printf(
+ "Elapsed time for package %s: %s\n", current_summary->spec.to_string(), current_summary->timing);
+ }
+
+ TrackedPackageInstallGuard(const TrackedPackageInstallGuard&) = delete;
+ TrackedPackageInstallGuard& operator=(const TrackedPackageInstallGuard&) = delete;
+ };
+
InstallSummary perform(ActionPlan& action_plan,
const KeepGoing keep_going,
const VcpkgPaths& paths,
StatusParagraphs& status_db,
IBinaryProvider& binaryprovider,
+ const Build::IBuildLogsRecorder& build_logs_recorder,
const CMakeVars::CMakeVarProvider& var_provider)
{
std::vector<SpecSummary> results;
-
- const auto timer = Chrono::ElapsedTimer::create_started();
- size_t counter = 0;
const size_t package_count = action_plan.remove_actions.size() + action_plan.install_actions.size();
- auto with_tracking = [&](const PackageSpec& spec, auto f) {
- const auto build_timer = Chrono::ElapsedTimer::create_started();
- counter++;
-
- const std::string display_name = spec.to_string();
- System::printf("Starting package %zd/%zd: %s\n", counter, package_count, display_name);
-
- results.emplace_back(spec, nullptr);
-
- f();
-
- results.back().timing = build_timer.elapsed();
- System::printf("Elapsed time for package %s: %s\n", display_name, results.back().timing);
- };
-
+ const auto timer = Chrono::ElapsedTimer::create_started();
for (auto&& action : action_plan.remove_actions)
{
- with_tracking(action.spec,
- [&]() { Remove::perform_remove_plan_action(paths, action, Remove::Purge::YES, &status_db); });
+ TrackedPackageInstallGuard this_install(package_count, results, action.spec);
+ Remove::perform_remove_plan_action(paths, action, Remove::Purge::YES, &status_db);
}
for (auto&& action : action_plan.already_installed)
{
results.emplace_back(action.spec, &action);
- results.back().build_result = perform_install_plan_action(paths, action, status_db, binaryprovider);
+ results.back().build_result =
+ perform_install_plan_action(paths, action, status_db, binaryprovider, build_logs_recorder);
}
Build::compute_all_abis(paths, action_plan, var_provider, status_db);
@@ -475,19 +483,18 @@ namespace vcpkg::Install
for (auto&& action : action_plan.install_actions)
{
- with_tracking(action.spec, [&]() {
- auto result = perform_install_plan_action(paths, action, status_db, binaryprovider);
-
- if (result.code != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO)
- {
- System::print2(Build::create_user_troubleshooting_message(action.spec), '\n');
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
+ TrackedPackageInstallGuard this_install(package_count, results, action.spec);
+ auto result = perform_install_plan_action(paths, action, status_db, binaryprovider, build_logs_recorder);
+ if (result.code != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO)
+ {
+ System::print2(Build::create_user_troubleshooting_message(action.spec), '\n');
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
- results.back().action = &action;
- results.back().build_result = std::move(result);
- });
+ this_install.current_summary->action = &action;
+ this_install.current_summary->build_result = std::move(result);
}
+
return InstallSummary{std::move(results), timer.to_string()};
}
@@ -687,7 +694,6 @@ namespace vcpkg::Install
clean_after_build ? Build::CleanPackages::YES : Build::CleanPackages::NO,
clean_after_build ? Build::CleanDownloads::YES : Build::CleanDownloads::NO,
download_tool,
- Build::FailOnTombstone::NO,
};
PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
@@ -842,6 +848,7 @@ namespace vcpkg::Install
paths,
status_db,
args.binary_caching_enabled() && !only_downloads ? *binaryprovider : null_binary_provider(),
+ Build::null_build_logs_recorder(),
var_provider);
System::print2("\nTotal elapsed time: ", summary.total_elapsed_time, "\n\n");
diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp
index c6d5f04be..a50736e9b 100644
--- a/toolsrc/src/vcpkg/postbuildlint.cpp
+++ b/toolsrc/src/vcpkg/postbuildlint.cpp
@@ -318,7 +318,7 @@ namespace vcpkg::PostBuildLint
{
return LintStatus::SUCCESS;
}
- const fs::path current_buildtrees_dir = paths.buildtrees / spec.name();
+ const fs::path current_buildtrees_dir = paths.build_dir(spec);
const fs::path current_buildtrees_dir_src = current_buildtrees_dir / "src";
std::vector<fs::path> potential_copyright_files;
@@ -342,12 +342,13 @@ namespace vcpkg::PostBuildLint
System::printf(System::Color::warning,
"The software license must be available at ${CURRENT_PACKAGES_DIR}/share/%s/copyright\n",
spec.name());
- if (potential_copyright_files.size() ==
- 1) // if there is only one candidate, provide the cmake lines needed to place it in the proper location
+ if (potential_copyright_files.size() == 1)
{
+ // if there is only one candidate, provide the cmake lines needed to place it in the proper location
const fs::path found_file = potential_copyright_files[0];
- const fs::path relative_path = found_file.string().erase(
- 0, current_buildtrees_dir.string().size() + 1); // The +1 is needed to remove the "/"
+ auto found_relative_native = found_file.native();
+ found_relative_native.erase(current_buildtrees_dir.native().size() + 1); // The +1 is needed to remove the "/"
+ const fs::path relative_path = found_relative_native;
System::printf(
"\n configure_file(\"${CURRENT_BUILDTREES_DIR}/%s/%s\" \"${CURRENT_PACKAGES_DIR}/share/%s/copyright\" COPYONLY)\n",
relative_path.generic_string(),
diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp
index 3d5a3bd6f..30f7367bf 100644
--- a/toolsrc/src/vcpkg/vcpkgpaths.cpp
+++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp
@@ -229,7 +229,12 @@ If you wish to silence this error and use classic mode, you can:
m_pimpl->triplets_dirs.emplace_back(community_triplets);
}
- fs::path VcpkgPaths::package_dir(const PackageSpec& spec) const { return this->packages / spec.dir(); }
+ fs::path VcpkgPaths::package_dir(const PackageSpec& spec) const { return this->packages / fs::u8path(spec.dir()); }
+ fs::path VcpkgPaths::build_dir(const PackageSpec& spec) const { return this->buildtrees / fs::u8path(spec.name()); }
+ fs::path VcpkgPaths::build_dir(const std::string& package_name) const
+ {
+ return this->buildtrees / fs::u8path(package_name);
+ }
fs::path VcpkgPaths::build_info_file_path(const PackageSpec& spec) const
{
@@ -389,9 +394,7 @@ If you wish to silence this error and use classic mode, you can:
{
StringView flag;
bool enabled;
- } flags[] = {
- {VcpkgCmdArguments::MANIFEST_MODE_FEATURE, manifest_mode_enabled()}
- };
+ } flags[] = {{VcpkgCmdArguments::MANIFEST_MODE_FEATURE, manifest_mode_enabled()}};
for (const auto& flag : flags)
{