mirror of
https://github.com/microsoft/vcpkg.git
synced 2024-12-27 18:31:15 +08:00
[vcpkg] Significantly reduce usage of powershell. Reduce console font switching bug
This commit is contained in:
parent
52f01eefa6
commit
1b0682a39e
@ -1,8 +1,3 @@
|
|||||||
function vcpkgHasModule([Parameter(Mandatory=$true)][string]$moduleName)
|
|
||||||
{
|
|
||||||
return [bool](Get-Module -ListAvailable -Name $moduleName)
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgHasProperty([Parameter(Mandatory=$true)][AllowNull()]$object, [Parameter(Mandatory=$true)]$propertyName)
|
function vcpkgHasProperty([Parameter(Mandatory=$true)][AllowNull()]$object, [Parameter(Mandatory=$true)]$propertyName)
|
||||||
{
|
{
|
||||||
if ($object -eq $null)
|
if ($object -eq $null)
|
||||||
@ -10,320 +5,21 @@ function vcpkgHasProperty([Parameter(Mandatory=$true)][AllowNull()]$object, [Par
|
|||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
return [bool]($object.psobject.Properties | where { $_.Name -eq "$propertyName"})
|
return [bool]($object.psobject.Properties | Where-Object { $_.Name -eq "$propertyName"})
|
||||||
}
|
}
|
||||||
|
|
||||||
function vcpkgCreateDirectoryIfNotExists([Parameter(Mandatory=$true)][string]$dirPath)
|
function getProgramFiles32bit()
|
||||||
{
|
{
|
||||||
if (!(Test-Path $dirPath))
|
$out = ${env:PROGRAMFILES(X86)}
|
||||||
|
if ($out -eq $null)
|
||||||
{
|
{
|
||||||
New-Item -ItemType Directory -Path $dirPath | Out-Null
|
$out = ${env:PROGRAMFILES}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgCreateParentDirectoryIfNotExists([Parameter(Mandatory=$true)][string]$path)
|
|
||||||
{
|
|
||||||
$parentDir = split-path -parent $path
|
|
||||||
if ([string]::IsNullOrEmpty($parentDir))
|
|
||||||
{
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(Test-Path $parentDir))
|
if ($out -eq $null)
|
||||||
{
|
{
|
||||||
New-Item -ItemType Directory -Path $parentDir | Out-Null
|
throw "Could not find [Program Files 32-bit]"
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgIsDirectory([Parameter(Mandatory=$true)][string]$path)
|
|
||||||
{
|
|
||||||
return (Get-Item $path) -is [System.IO.DirectoryInfo]
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgRemoveItem([Parameter(Mandatory=$true)][string]$path)
|
|
||||||
{
|
|
||||||
if ([string]::IsNullOrEmpty($path))
|
|
||||||
{
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-Path $path)
|
return $out
|
||||||
{
|
}
|
||||||
# Remove-Item -Recurse occasionally fails. This is a workaround
|
|
||||||
if (vcpkgIsDirectory $path)
|
|
||||||
{
|
|
||||||
& cmd.exe /c rd /s /q $path
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Remove-Item $path -Force
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgHasCommand([Parameter(Mandatory=$true)][string]$commandName)
|
|
||||||
{
|
|
||||||
return [bool](Get-Command -Name $commandName -ErrorAction SilentlyContinue)
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgHasCommandParameter([Parameter(Mandatory=$true)][string]$commandName, [Parameter(Mandatory=$true)][string]$parameterName)
|
|
||||||
{
|
|
||||||
return (Get-Command $commandName).Parameters.Keys -contains $parameterName
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgGetCredentials()
|
|
||||||
{
|
|
||||||
if (vcpkgHasCommandParameter -commandName 'Get-Credential' -parameterName 'Message')
|
|
||||||
{
|
|
||||||
return Get-Credential -Message "Enter credentials for Proxy Authentication"
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Write-Host "Enter credentials for Proxy Authentication"
|
|
||||||
return Get-Credential
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgGetSHA512([Parameter(Mandatory=$true)][string]$filePath)
|
|
||||||
{
|
|
||||||
if (vcpkgHasCommand -commandName 'Microsoft.PowerShell.Utility\Get-FileHash')
|
|
||||||
{
|
|
||||||
Write-Verbose("Hashing with Microsoft.PowerShell.Utility\Get-FileHash")
|
|
||||||
$hashresult = Microsoft.PowerShell.Utility\Get-FileHash -Path $filePath -Algorithm SHA512 -ErrorVariable hashError
|
|
||||||
if ($hashError)
|
|
||||||
{
|
|
||||||
Start-Sleep 3
|
|
||||||
$hashresult = Microsoft.PowerShell.Utility\Get-FileHash -Path $filePath -Algorithm SHA512 -ErrorVariable Stop
|
|
||||||
}
|
|
||||||
$hash = $hashresult.Hash
|
|
||||||
}
|
|
||||||
elseif(vcpkgHasCommand -commandName 'Pscx\Get-Hash')
|
|
||||||
{
|
|
||||||
Write-Verbose("Hashing with Pscx\Get-Hash")
|
|
||||||
$hash = (Pscx\Get-Hash -Path $filePath -Algorithm SHA512).HashString
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Write-Verbose("Hashing with .NET")
|
|
||||||
$hashAlgorithm = [Security.Cryptography.HashAlgorithm]::Create("SHA512")
|
|
||||||
$fileAsByteArray = [io.File]::ReadAllBytes($filePath)
|
|
||||||
$hashByteArray = $hashAlgorithm.ComputeHash($fileAsByteArray)
|
|
||||||
$hash = -Join ($hashByteArray | ForEach-Object {"{0:x2}" -f $_})
|
|
||||||
}
|
|
||||||
|
|
||||||
return $hash.ToLower()
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgCheckEqualFileHash( [Parameter(Mandatory=$true)][string]$url,
|
|
||||||
[Parameter(Mandatory=$true)][string]$filePath,
|
|
||||||
[Parameter(Mandatory=$true)][string]$expectedHash)
|
|
||||||
{
|
|
||||||
$actualHash = vcpkgGetSHA512 $filePath
|
|
||||||
if ($expectedHash -ne $actualHash)
|
|
||||||
{
|
|
||||||
Write-Host ("`nFile does not have expected hash:`n" +
|
|
||||||
" url: [ $url ]`n" +
|
|
||||||
" File path: [ $filePath ]`n" +
|
|
||||||
" Expected hash: [ $expectedHash ]`n" +
|
|
||||||
" Actual hash: [ $actualHash ]`n")
|
|
||||||
throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgDownloadFile( [Parameter(Mandatory=$true)][string]$url,
|
|
||||||
[Parameter(Mandatory=$true)][string]$downloadPath,
|
|
||||||
[Parameter(Mandatory=$true)][string]$sha512)
|
|
||||||
{
|
|
||||||
if ($url -match "github")
|
|
||||||
{
|
|
||||||
if ([System.Enum]::IsDefined([Net.SecurityProtocolType], "Tls12"))
|
|
||||||
{
|
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Write-Warning "Github has dropped support for TLS versions prior to 1.2, which is not available on your system"
|
|
||||||
Write-Warning "Please manually download $url to $downloadPath"
|
|
||||||
Write-Warning "To solve this issue for future downloads, you can also install Windows Management Framework 5.1+"
|
|
||||||
throw "Download failed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vcpkgCreateParentDirectoryIfNotExists $downloadPath
|
|
||||||
|
|
||||||
$downloadPartPath = "$downloadPath.part"
|
|
||||||
vcpkgRemoveItem $downloadPartPath
|
|
||||||
|
|
||||||
$wc = New-Object System.Net.WebClient
|
|
||||||
if (!$wc.Proxy.IsBypassed($url))
|
|
||||||
{
|
|
||||||
$wc.Proxy.Credentials = vcpkgGetCredentials
|
|
||||||
}
|
|
||||||
|
|
||||||
$wc.DownloadFile($url, $downloadPartPath)
|
|
||||||
vcpkgCheckEqualFileHash -url $url -filePath $downloadPartPath -expectedHash $sha512
|
|
||||||
Move-Item -Path $downloadPartPath -Destination $downloadPath
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgDownloadFileWithAria2( [Parameter(Mandatory=$true)][string]$aria2exe,
|
|
||||||
[Parameter(Mandatory=$true)][string]$url,
|
|
||||||
[Parameter(Mandatory=$true)][string]$downloadPath,
|
|
||||||
[Parameter(Mandatory=$true)][string]$sha512)
|
|
||||||
{
|
|
||||||
vcpkgCreateParentDirectoryIfNotExists $downloadPath
|
|
||||||
$downloadPartPath = "$downloadPath.part"
|
|
||||||
vcpkgRemoveItem $downloadPartPath
|
|
||||||
|
|
||||||
$parentDir = split-path -parent $downloadPath
|
|
||||||
$filename = split-path -leaf $downloadPath
|
|
||||||
|
|
||||||
if ((Test-Path $url) -or ($url.StartsWith("file://"))) # if is local file
|
|
||||||
{
|
|
||||||
vcpkgDownloadFile $url $downloadPath $sha512
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
$ec = vcpkgInvokeCommand "$aria2exe" "--dir=`"$parentDir`" --out=`"$filename.part`" $url"
|
|
||||||
if ($ec -ne 0)
|
|
||||||
{
|
|
||||||
Write-Host "Could not download $url"
|
|
||||||
throw
|
|
||||||
}
|
|
||||||
|
|
||||||
vcpkgCheckEqualFileHash -url $url -filePath $downloadPartPath -expectedHash $sha512
|
|
||||||
Move-Item -Path $downloadPartPath -Destination $downloadPath
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgExtractFileWith7z([Parameter(Mandatory=$true)][string]$sevenZipExe,
|
|
||||||
[Parameter(Mandatory=$true)][string]$archivePath,
|
|
||||||
[Parameter(Mandatory=$true)][string]$destinationDir)
|
|
||||||
{
|
|
||||||
vcpkgRemoveItem $destinationDir
|
|
||||||
$destinationPartial = "$destinationDir.partial"
|
|
||||||
vcpkgRemoveItem $destinationPartial
|
|
||||||
vcpkgCreateDirectoryIfNotExists $destinationPartial
|
|
||||||
$ec = vcpkgInvokeCommand "$sevenZipExe" "x `"$archivePath`" -o`"$destinationPartial`" -y"
|
|
||||||
if ($ec -ne 0)
|
|
||||||
{
|
|
||||||
Write-Host "Could not extract $archivePath"
|
|
||||||
throw
|
|
||||||
}
|
|
||||||
Rename-Item -Path "$destinationPartial" -NewName $destinationDir -ErrorVariable renameResult
|
|
||||||
if ($renameResult)
|
|
||||||
{
|
|
||||||
Start-Sleep 3
|
|
||||||
Rename-Item -Path "$destinationPartial" -NewName $destinationDir -ErrorAction Stop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgExtractZipFile( [Parameter(Mandatory=$true)][string]$archivePath,
|
|
||||||
[Parameter(Mandatory=$true)][string]$destinationDir)
|
|
||||||
{
|
|
||||||
vcpkgRemoveItem $destinationDir
|
|
||||||
$destinationPartial = "$destinationDir.partial"
|
|
||||||
vcpkgRemoveItem $destinationPartial
|
|
||||||
vcpkgCreateDirectoryIfNotExists $destinationPartial
|
|
||||||
|
|
||||||
|
|
||||||
if (vcpkgHasCommand -commandName 'Microsoft.PowerShell.Archive\Expand-Archive')
|
|
||||||
{
|
|
||||||
Write-Verbose("Extracting with Microsoft.PowerShell.Archive\Expand-Archive")
|
|
||||||
Microsoft.PowerShell.Archive\Expand-Archive -path $archivePath -destinationpath $destinationPartial
|
|
||||||
}
|
|
||||||
elseif (vcpkgHasCommand -commandName 'Pscx\Expand-Archive')
|
|
||||||
{
|
|
||||||
Write-Verbose("Extracting with Pscx\Expand-Archive")
|
|
||||||
Pscx\Expand-Archive -path $archivePath -OutputPath $destinationPartial
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Write-Verbose("Extracting via shell")
|
|
||||||
$shell = new-object -com shell.application
|
|
||||||
$zip = $shell.NameSpace($(Get-Item $archivePath).fullname)
|
|
||||||
foreach($item in $zip.items())
|
|
||||||
{
|
|
||||||
# Piping to Out-Null is used to block until finished
|
|
||||||
$shell.Namespace($destinationPartial).copyhere($item) | Out-Null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rename-Item -Path "$destinationPartial" -NewName $destinationDir
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgInvokeCommand()
|
|
||||||
{
|
|
||||||
param ( [Parameter(Mandatory=$true)][string]$executable,
|
|
||||||
[string]$arguments = "")
|
|
||||||
|
|
||||||
Write-Verbose "Executing: ${executable} ${arguments}"
|
|
||||||
$process = Start-Process -FilePath "`"$executable`"" -ArgumentList $arguments -PassThru -NoNewWindow
|
|
||||||
Wait-Process -InputObject $process
|
|
||||||
$ec = $process.ExitCode
|
|
||||||
Write-Verbose "Execution terminated with exit code $ec."
|
|
||||||
return $ec
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgInvokeCommandClean()
|
|
||||||
{
|
|
||||||
param ( [Parameter(Mandatory=$true)][string]$executable,
|
|
||||||
[string]$arguments = "")
|
|
||||||
|
|
||||||
Write-Verbose "Clean-Executing: ${executable} ${arguments}"
|
|
||||||
$scriptsDir = split-path -parent $script:MyInvocation.MyCommand.Definition
|
|
||||||
$cleanEnvScript = "$scriptsDir\VcpkgPowershellUtils-ClearEnvironment.ps1"
|
|
||||||
$tripleQuotes = "`"`"`""
|
|
||||||
$argumentsWithEscapedQuotes = $arguments -replace "`"", $tripleQuotes
|
|
||||||
$command = ". $tripleQuotes$cleanEnvScript$tripleQuotes; & $tripleQuotes$executable$tripleQuotes $argumentsWithEscapedQuotes"
|
|
||||||
$arg = "-NoProfile", "-ExecutionPolicy Bypass", "-command $command"
|
|
||||||
|
|
||||||
$process = Start-Process -FilePath powershell.exe -ArgumentList $arg -PassThru -NoNewWindow
|
|
||||||
Wait-Process -InputObject $process
|
|
||||||
$ec = $process.ExitCode
|
|
||||||
Write-Verbose "Execution terminated with exit code $ec."
|
|
||||||
return $ec
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgFormatElapsedTime([TimeSpan]$ts)
|
|
||||||
{
|
|
||||||
if ($ts.TotalHours -ge 1)
|
|
||||||
{
|
|
||||||
return [string]::Format( "{0:N2} h", $ts.TotalHours);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ts.TotalMinutes -ge 1)
|
|
||||||
{
|
|
||||||
return [string]::Format( "{0:N2} min", $ts.TotalMinutes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ts.TotalSeconds -ge 1)
|
|
||||||
{
|
|
||||||
return [string]::Format( "{0:N2} s", $ts.TotalSeconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ts.TotalMilliseconds -ge 1)
|
|
||||||
{
|
|
||||||
return [string]::Format( "{0:N2} ms", $ts.TotalMilliseconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw $ts
|
|
||||||
}
|
|
||||||
|
|
||||||
function vcpkgFindFileRecursivelyUp()
|
|
||||||
{
|
|
||||||
param(
|
|
||||||
[ValidateNotNullOrEmpty()]
|
|
||||||
[Parameter(Mandatory=$true)][string]$startingDir,
|
|
||||||
[ValidateNotNullOrEmpty()]
|
|
||||||
[Parameter(Mandatory=$true)][string]$filename
|
|
||||||
)
|
|
||||||
|
|
||||||
$currentDir = $startingDir
|
|
||||||
|
|
||||||
while (!($currentDir -eq "") -and !(Test-Path "$currentDir\$filename"))
|
|
||||||
{
|
|
||||||
Write-Verbose "Examining $currentDir for $filename"
|
|
||||||
$currentDir = Split-path $currentDir -Parent
|
|
||||||
}
|
|
||||||
Write-Verbose "Examining $currentDir for $filename - Found"
|
|
||||||
return $currentDir
|
|
||||||
}
|
|
@ -18,10 +18,10 @@ $scriptsDir = split-path -parent $script:MyInvocation.MyCommand.Definition
|
|||||||
|
|
||||||
$profileEntry = "Import-Module '$scriptsDir\posh-vcpkg'"
|
$profileEntry = "Import-Module '$scriptsDir\posh-vcpkg'"
|
||||||
$profilePath = $PROFILE # Implicit powershell variable
|
$profilePath = $PROFILE # Implicit powershell variable
|
||||||
if (!(Test-Path $profilePath))
|
$profileDir = Split-Path $profilePath -Parent
|
||||||
|
if (!(Test-Path $profileDir))
|
||||||
{
|
{
|
||||||
$profileDir = Split-Path $profilePath -Parent
|
New-Item -ItemType Directory -Path $profileDir | Out-Null
|
||||||
vcpkgCreateDirectoryIfNotExists $profileDir
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "`nAdding the following line to ${profilePath}:"
|
Write-Host "`nAdding the following line to ${profilePath}:"
|
||||||
@ -38,6 +38,7 @@ if ($existingImports.Count -gt 0)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Modifying the profile will invalidate any signatures.
|
||||||
# Posh-git does the following check, so we should too.
|
# Posh-git does the following check, so we should too.
|
||||||
# https://github.com/dahlbyk/posh-git/blob/master/src/Utils.ps1
|
# https://github.com/dahlbyk/posh-git/blob/master/src/Utils.ps1
|
||||||
# If the profile script exists and is signed, then we should not modify it
|
# If the profile script exists and is signed, then we should not modify it
|
||||||
|
@ -5,35 +5,18 @@ param(
|
|||||||
)
|
)
|
||||||
Set-StrictMode -Version Latest
|
Set-StrictMode -Version Latest
|
||||||
$scriptsDir = split-path -parent $script:MyInvocation.MyCommand.Definition
|
$scriptsDir = split-path -parent $script:MyInvocation.MyCommand.Definition
|
||||||
. "$scriptsDir\VcpkgPowershellUtils.ps1"
|
|
||||||
$vcpkgRootDir = vcpkgFindFileRecursivelyUp $scriptsDir .vcpkg-root
|
|
||||||
Write-Verbose("vcpkg Path " + $vcpkgRootDir)
|
|
||||||
|
|
||||||
$gitHash = "unknownhash"
|
$vcpkgRootDir = $scriptsDir
|
||||||
$oldpath = $env:path
|
$withVSPath = $withVSPath -replace "\\$" # Remove potential trailing backslash
|
||||||
try
|
|
||||||
|
while (!($vcpkgRootDir -eq "") -and !(Test-Path "$vcpkgRootDir\.vcpkg-root"))
|
||||||
{
|
{
|
||||||
[xml]$asXml = Get-Content "$scriptsDir\vcpkgTools.xml"
|
Write-Verbose "Examining $vcpkgRootDir for .vcpkg-root"
|
||||||
$toolData = $asXml.SelectSingleNode("//tools/tool[@name=`"git`"]")
|
$vcpkgRootDir = Split-path $vcpkgRootDir -Parent
|
||||||
$gitFromDownload = "$vcpkgRootDir\downloads\$($toolData.exeRelativePath)"
|
|
||||||
$gitDir = split-path -parent $gitFromDownload
|
|
||||||
|
|
||||||
$env:path += ";$gitDir"
|
|
||||||
if (Get-Command "git" -ErrorAction SilentlyContinue)
|
|
||||||
{
|
|
||||||
$gitHash = git log HEAD -n 1 --format="%cd-%H" --date=short
|
|
||||||
if ($LASTEXITCODE -ne 0)
|
|
||||||
{
|
|
||||||
$gitHash = "unknownhash"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally
|
Write-Verbose "Examining $vcpkgRootDir for .vcpkg-root - Found"
|
||||||
{
|
|
||||||
$env:path = $oldpath
|
|
||||||
}
|
|
||||||
Write-Verbose("Git repo version string is " + $gitHash)
|
|
||||||
|
|
||||||
|
$gitHash = "nohash"
|
||||||
$vcpkgSourcesPath = "$vcpkgRootDir\toolsrc"
|
$vcpkgSourcesPath = "$vcpkgRootDir\toolsrc"
|
||||||
|
|
||||||
if (!(Test-Path $vcpkgSourcesPath))
|
if (!(Test-Path $vcpkgSourcesPath))
|
||||||
@ -42,7 +25,58 @@ if (!(Test-Path $vcpkgSourcesPath))
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$msbuildExeWithPlatformToolset = & $scriptsDir\findAnyMSBuildWithCppPlatformToolset.ps1 $withVSPath
|
function findAnyMSBuildWithCppPlatformToolset([string]$withVSPath)
|
||||||
|
{
|
||||||
|
$VisualStudioInstances = & $scriptsDir\getVisualStudioInstances.ps1
|
||||||
|
if ($VisualStudioInstances -eq $null)
|
||||||
|
{
|
||||||
|
throw "Could not find Visual Studio. VS2015 or VS2017 (with C++) needs to be installed."
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose "VS Candidates:`n`r$([system.String]::Join([Environment]::NewLine, $VisualStudioInstances))"
|
||||||
|
foreach ($instanceCandidateWithEOL in $VisualStudioInstances)
|
||||||
|
{
|
||||||
|
$instanceCandidate = $instanceCandidateWithEOL -replace "<sol>::" -replace "::<eol>"
|
||||||
|
Write-Verbose "Inspecting: $instanceCandidate"
|
||||||
|
$split = $instanceCandidate -split "::"
|
||||||
|
# $preferenceWeight = $split[0]
|
||||||
|
# $releaseType = $split[1]
|
||||||
|
$version = $split[2]
|
||||||
|
$path = $split[3]
|
||||||
|
|
||||||
|
if ($withVSPath -ne "" -and $withVSPath -ne $path)
|
||||||
|
{
|
||||||
|
Write-Verbose "Skipping: $instanceCandidate"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$majorVersion = $version.Substring(0,2);
|
||||||
|
if ($majorVersion -eq "15")
|
||||||
|
{
|
||||||
|
$VCFolder= "$path\VC\Tools\MSVC\"
|
||||||
|
if (Test-Path $VCFolder)
|
||||||
|
{
|
||||||
|
Write-Verbose "Picking: $instanceCandidate"
|
||||||
|
return "$path\MSBuild\15.0\Bin\MSBuild.exe", "v141"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($majorVersion -eq "14")
|
||||||
|
{
|
||||||
|
$clExe= "$path\VC\bin\cl.exe"
|
||||||
|
if (Test-Path $clExe)
|
||||||
|
{
|
||||||
|
Write-Verbose "Picking: $instanceCandidate"
|
||||||
|
$programFilesPath = getProgramFiles32bit
|
||||||
|
return "$programFilesPath\MSBuild\14.0\Bin\MSBuild.exe", "v140"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw "Could not find MSBuild version with C++ support. VS2015 or VS2017 (with C++) needs to be installed."
|
||||||
|
}
|
||||||
|
|
||||||
|
$msbuildExeWithPlatformToolset = findAnyMSBuildWithCppPlatformToolset $withVSPath
|
||||||
$msbuildExe = $msbuildExeWithPlatformToolset[0]
|
$msbuildExe = $msbuildExeWithPlatformToolset[0]
|
||||||
$platformToolset = $msbuildExeWithPlatformToolset[1]
|
$platformToolset = $msbuildExeWithPlatformToolset[1]
|
||||||
$windowsSDK = & $scriptsDir\getWindowsSDK.ps1
|
$windowsSDK = & $scriptsDir\getWindowsSDK.ps1
|
||||||
@ -54,10 +88,33 @@ $arguments = (
|
|||||||
"/p:Platform=x86",
|
"/p:Platform=x86",
|
||||||
"/p:PlatformToolset=$platformToolset",
|
"/p:PlatformToolset=$platformToolset",
|
||||||
"/p:TargetPlatformVersion=$windowsSDK",
|
"/p:TargetPlatformVersion=$windowsSDK",
|
||||||
|
"/verbosity:minimal",
|
||||||
"/m",
|
"/m",
|
||||||
|
"/nologo",
|
||||||
"`"$vcpkgSourcesPath\dirs.proj`"") -join " "
|
"`"$vcpkgSourcesPath\dirs.proj`"") -join " "
|
||||||
|
|
||||||
|
function vcpkgInvokeCommandClean()
|
||||||
|
{
|
||||||
|
param ( [Parameter(Mandatory=$true)][string]$executable,
|
||||||
|
[string]$arguments = "")
|
||||||
|
|
||||||
|
Write-Verbose "Clean-Executing: ${executable} ${arguments}"
|
||||||
|
$scriptsDir = split-path -parent $script:MyInvocation.MyCommand.Definition
|
||||||
|
$cleanEnvScript = "$scriptsDir\VcpkgPowershellUtils-ClearEnvironment.ps1"
|
||||||
|
$tripleQuotes = "`"`"`""
|
||||||
|
$argumentsWithEscapedQuotes = $arguments -replace "`"", $tripleQuotes
|
||||||
|
$command = ". $tripleQuotes$cleanEnvScript$tripleQuotes; & $tripleQuotes$executable$tripleQuotes $argumentsWithEscapedQuotes"
|
||||||
|
$arg = "-NoProfile", "-ExecutionPolicy Bypass", "-command $command"
|
||||||
|
|
||||||
|
$process = Start-Process -FilePath powershell.exe -ArgumentList $arg -PassThru -NoNewWindow
|
||||||
|
Wait-Process -InputObject $process
|
||||||
|
$ec = $process.ExitCode
|
||||||
|
Write-Verbose "Execution terminated with exit code $ec."
|
||||||
|
return $ec
|
||||||
|
}
|
||||||
|
|
||||||
# vcpkgInvokeCommandClean cmd "/c echo %PATH%"
|
# vcpkgInvokeCommandClean cmd "/c echo %PATH%"
|
||||||
|
Write-Host "`nBuilding vcpkg.exe ...`n"
|
||||||
$ec = vcpkgInvokeCommandClean $msbuildExe $arguments
|
$ec = vcpkgInvokeCommandClean $msbuildExe $arguments
|
||||||
|
|
||||||
if ($ec -ne 0)
|
if ($ec -ne 0)
|
||||||
@ -65,6 +122,7 @@ if ($ec -ne 0)
|
|||||||
Write-Error "Building vcpkg.exe failed. Please ensure you have installed Visual Studio with the Desktop C++ workload and the Windows SDK for Desktop C++."
|
Write-Error "Building vcpkg.exe failed. Please ensure you have installed Visual Studio with the Desktop C++ workload and the Windows SDK for Desktop C++."
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Write-Host "`nBuilding vcpkg.exe... done.`n"
|
||||||
|
|
||||||
Write-Verbose("Placing vcpkg.exe in the correct location")
|
Write-Verbose("Placing vcpkg.exe in the correct location")
|
||||||
|
|
||||||
|
@ -1,109 +0,0 @@
|
|||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory=$true)][string]$tool
|
|
||||||
)
|
|
||||||
|
|
||||||
Set-StrictMode -Version Latest
|
|
||||||
|
|
||||||
$scriptsDir = split-path -parent $script:MyInvocation.MyCommand.Definition
|
|
||||||
. "$scriptsDir\VcpkgPowershellUtils.ps1"
|
|
||||||
|
|
||||||
Write-Verbose "Fetching tool: $tool"
|
|
||||||
$vcpkgRootDir = vcpkgFindFileRecursivelyUp $scriptsDir .vcpkg-root
|
|
||||||
|
|
||||||
$downloadsDir = "$vcpkgRootDir\downloads"
|
|
||||||
vcpkgCreateDirectoryIfNotExists $downloadsDir
|
|
||||||
$downloadsDir = Resolve-Path $downloadsDir
|
|
||||||
|
|
||||||
function fetchToolInternal([Parameter(Mandatory=$true)][string]$tool)
|
|
||||||
{
|
|
||||||
$tool = $tool.toLower()
|
|
||||||
|
|
||||||
[xml]$asXml = Get-Content "$scriptsDir\vcpkgTools.xml"
|
|
||||||
$toolData = $asXml.SelectSingleNode("//tools/tool[@name=`"$tool`"]") # Case-sensitive!
|
|
||||||
|
|
||||||
if ($toolData -eq $null)
|
|
||||||
{
|
|
||||||
throw "Unknown tool $tool"
|
|
||||||
}
|
|
||||||
|
|
||||||
$toolPath="$downloadsDir\tools\$tool-$($toolData.version)-windows"
|
|
||||||
$exePath = "$toolPath\$($toolData.exeRelativePath)"
|
|
||||||
|
|
||||||
if (Test-Path $exePath)
|
|
||||||
{
|
|
||||||
return $exePath
|
|
||||||
}
|
|
||||||
|
|
||||||
$isArchive = vcpkgHasProperty -object $toolData -propertyName "archiveName"
|
|
||||||
if ($isArchive)
|
|
||||||
{
|
|
||||||
$downloadPath = "$downloadsDir\$($toolData.archiveName)"
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$downloadPath = "$toolPath\$($toolData.exeRelativePath)"
|
|
||||||
}
|
|
||||||
|
|
||||||
[String]$url = $toolData.url
|
|
||||||
if (!(Test-Path $downloadPath))
|
|
||||||
{
|
|
||||||
Write-Host "Downloading $tool..."
|
|
||||||
|
|
||||||
# Download aria2 with .NET. aria2 will be used to download everything else.
|
|
||||||
if ($tool -eq "aria2")
|
|
||||||
{
|
|
||||||
vcpkgDownloadFile $url $downloadPath $toolData.sha512
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$aria2exe = fetchToolInternal "aria2"
|
|
||||||
vcpkgDownloadFileWithAria2 $aria2exe $url $downloadPath $toolData.sha512
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Downloading $tool... done."
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vcpkgCheckEqualFileHash -url $url -filePath $downloadPath -expectedHash $toolData.sha512
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($isArchive)
|
|
||||||
{
|
|
||||||
Write-Host "Extracting $tool..."
|
|
||||||
# Extract 7zip920 with shell because we need it to extract 7zip
|
|
||||||
# Extract aria2 with shell because we need it to download 7zip
|
|
||||||
if ($tool -eq "7zip920" -or $tool -eq "aria2")
|
|
||||||
{
|
|
||||||
vcpkgExtractZipFile -ArchivePath $downloadPath -DestinationDir $toolPath
|
|
||||||
}
|
|
||||||
elseif ($tool -eq "7zip")
|
|
||||||
{
|
|
||||||
$sevenZip920 = fetchToolInternal "7zip920"
|
|
||||||
$ec = vcpkgInvokeCommand "$sevenZip920" "x `"$downloadPath`" -o`"$toolPath`" -y"
|
|
||||||
if ($ec -ne 0)
|
|
||||||
{
|
|
||||||
Write-Host "Could not extract $downloadPath"
|
|
||||||
throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$sevenZipExe = fetchToolInternal "7zip"
|
|
||||||
vcpkgExtractFileWith7z -sevenZipExe "$sevenZipExe" -ArchivePath $downloadPath -DestinationDir $toolPath
|
|
||||||
}
|
|
||||||
Write-Host "Extracting $tool... done."
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-not (Test-Path $exePath))
|
|
||||||
{
|
|
||||||
Write-Error "Could not detect or download $tool"
|
|
||||||
throw
|
|
||||||
}
|
|
||||||
|
|
||||||
return $exePath
|
|
||||||
}
|
|
||||||
|
|
||||||
$path = fetchToolInternal $tool
|
|
||||||
Write-Verbose "Fetching tool: $tool. Done."
|
|
||||||
return "<sol>::$path::<eol>"
|
|
@ -1,58 +0,0 @@
|
|||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory=$False)]
|
|
||||||
[string]$withVSPath = ""
|
|
||||||
)
|
|
||||||
|
|
||||||
Set-StrictMode -Version Latest
|
|
||||||
$scriptsDir = split-path -parent $script:MyInvocation.MyCommand.Definition
|
|
||||||
|
|
||||||
$withVSPath = $withVSPath -replace "\\$" # Remove potential trailing backslash
|
|
||||||
|
|
||||||
$VisualStudioInstallationInstances = & $scriptsDir\findVisualStudioInstallationInstances.ps1
|
|
||||||
if ($VisualStudioInstallationInstances -eq $null)
|
|
||||||
{
|
|
||||||
throw "Could not find Visual Studio. VS2015 or VS2017 (with C++) needs to be installed."
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Verbose "VS Candidates:`n`r$([system.String]::Join([Environment]::NewLine, $VisualStudioInstallationInstances))"
|
|
||||||
foreach ($instanceCandidateWithEOL in $VisualStudioInstallationInstances)
|
|
||||||
{
|
|
||||||
$instanceCandidate = $instanceCandidateWithEOL -replace "<sol>::" -replace "::<eol>"
|
|
||||||
Write-Verbose "Inspecting: $instanceCandidate"
|
|
||||||
$split = $instanceCandidate -split "::"
|
|
||||||
# $preferenceWeight = $split[0]
|
|
||||||
# $releaseType = $split[1]
|
|
||||||
$version = $split[2]
|
|
||||||
$path = $split[3]
|
|
||||||
|
|
||||||
if ($withVSPath -ne "" -and $withVSPath -ne $path)
|
|
||||||
{
|
|
||||||
Write-Verbose "Skipping: $instanceCandidate"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
$majorVersion = $version.Substring(0,2);
|
|
||||||
if ($majorVersion -eq "15")
|
|
||||||
{
|
|
||||||
$VCFolder= "$path\VC\Tools\MSVC\"
|
|
||||||
if (Test-Path $VCFolder)
|
|
||||||
{
|
|
||||||
Write-Verbose "Picking: $instanceCandidate"
|
|
||||||
return "$path\MSBuild\15.0\Bin\MSBuild.exe", "v141"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($majorVersion -eq "14")
|
|
||||||
{
|
|
||||||
$clExe= "$path\VC\bin\cl.exe"
|
|
||||||
if (Test-Path $clExe)
|
|
||||||
{
|
|
||||||
Write-Verbose "Picking: $instanceCandidate"
|
|
||||||
$programFilesPath = & $scriptsDir\getProgramFiles32bit.ps1
|
|
||||||
return "$programFilesPath\MSBuild\14.0\Bin\MSBuild.exe", "v140"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw "Could not find MSBuild version with C++ support. VS2015 or VS2017 (with C++) needs to be installed."
|
|
@ -1,61 +0,0 @@
|
|||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
|
|
||||||
)
|
|
||||||
Set-StrictMode -Version Latest
|
|
||||||
$scriptsDir = split-path -parent $script:MyInvocation.MyCommand.Definition
|
|
||||||
. "$scriptsDir\VcpkgPowershellUtils.ps1"
|
|
||||||
|
|
||||||
$vswhereExe = (& $scriptsDir\fetchTool.ps1 "vswhere") -replace "<sol>::" -replace "::<eol>"
|
|
||||||
|
|
||||||
$output = & $vswhereExe -prerelease -legacy -products * -format xml
|
|
||||||
[xml]$asXml = $output
|
|
||||||
|
|
||||||
$results = New-Object System.Collections.ArrayList
|
|
||||||
foreach ($instance in $asXml.instances.instance)
|
|
||||||
{
|
|
||||||
$installationPath = $instance.InstallationPath -replace "\\$" # Remove potential trailing backslash
|
|
||||||
$installationVersion = $instance.InstallationVersion
|
|
||||||
|
|
||||||
$isPrerelease = -7
|
|
||||||
if (vcpkgHasProperty -object $instance -propertyName "isPrerelease")
|
|
||||||
{
|
|
||||||
$isPrerelease = $instance.isPrerelease
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($isPrerelease -eq 0)
|
|
||||||
{
|
|
||||||
$releaseType = "PreferenceWeight3::StableRelease"
|
|
||||||
}
|
|
||||||
elseif ($isPrerelease -eq 1)
|
|
||||||
{
|
|
||||||
$releaseType = "PreferenceWeight2::PreRelease"
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$releaseType = "PreferenceWeight1::Legacy"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Placed like that for easy sorting according to preference
|
|
||||||
$results.Add("<sol>::${releaseType}::${installationVersion}::${installationPath}::<eol>") > $null
|
|
||||||
}
|
|
||||||
|
|
||||||
# If nothing is found, attempt to find VS2015 Build Tools (not detected by vswhere.exe)
|
|
||||||
if ($results.Count -eq 0)
|
|
||||||
{
|
|
||||||
$programFiles = & $scriptsDir\getProgramFiles32bit.ps1
|
|
||||||
$installationPath = "$programFiles\Microsoft Visual Studio 14.0"
|
|
||||||
$clExe = "$installationPath\VC\bin\cl.exe"
|
|
||||||
$vcvarsallbat = "$installationPath\VC\vcvarsall.bat"
|
|
||||||
|
|
||||||
if ((Test-Path $clExe) -And (Test-Path $vcvarsallbat))
|
|
||||||
{
|
|
||||||
return "<sol>::PreferenceWeight1::Legacy::14.0::$installationPath::<eol>"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$results.Sort()
|
|
||||||
$results.Reverse()
|
|
||||||
|
|
||||||
return $results
|
|
@ -1,17 +0,0 @@
|
|||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
$out = ${env:PROGRAMFILES(X86)}
|
|
||||||
if ($out -eq $null)
|
|
||||||
{
|
|
||||||
$out = ${env:PROGRAMFILES}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($out -eq $null)
|
|
||||||
{
|
|
||||||
throw "Could not find [Program Files 32-bit]"
|
|
||||||
}
|
|
||||||
|
|
||||||
return $out
|
|
@ -1,17 +0,0 @@
|
|||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
$out = ${env:ProgramW6432}
|
|
||||||
if ($out -eq $null)
|
|
||||||
{
|
|
||||||
$out = ${env:PROGRAMFILES}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($out -eq $null)
|
|
||||||
{
|
|
||||||
throw "Could not find [Program Files Platform Bitness]"
|
|
||||||
}
|
|
||||||
|
|
||||||
return $out
|
|
74
scripts/getVisualStudioInstances.ps1
Normal file
74
scripts/getVisualStudioInstances.ps1
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
|
||||||
|
)
|
||||||
|
Set-StrictMode -Version Latest
|
||||||
|
$scriptsDir = split-path -parent $script:MyInvocation.MyCommand.Definition
|
||||||
|
. "$scriptsDir\VcpkgPowershellUtils.ps1"
|
||||||
|
|
||||||
|
$programFiles = getProgramFiles32bit
|
||||||
|
|
||||||
|
$results = New-Object System.Collections.ArrayList
|
||||||
|
|
||||||
|
$vswhereExe = "$programFiles\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||||
|
|
||||||
|
if (Test-Path $vswhereExe)
|
||||||
|
{
|
||||||
|
$output = & $vswhereExe -prerelease -legacy -products * -format xml
|
||||||
|
[xml]$asXml = $output
|
||||||
|
|
||||||
|
foreach ($instance in $asXml.instances.instance)
|
||||||
|
{
|
||||||
|
$installationPath = $instance.InstallationPath -replace "\\$" # Remove potential trailing backslash
|
||||||
|
$installationVersion = $instance.InstallationVersion
|
||||||
|
|
||||||
|
$isPrerelease = -7
|
||||||
|
if (vcpkgHasProperty -object $instance -propertyName "isPrerelease")
|
||||||
|
{
|
||||||
|
$isPrerelease = $instance.isPrerelease
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($isPrerelease -eq 0)
|
||||||
|
{
|
||||||
|
$releaseType = "PreferenceWeight3::StableRelease"
|
||||||
|
}
|
||||||
|
elseif ($isPrerelease -eq 1)
|
||||||
|
{
|
||||||
|
$releaseType = "PreferenceWeight2::PreRelease"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$releaseType = "PreferenceWeight1::Legacy"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Placed like that for easy sorting according to preference
|
||||||
|
$results.Add("<sol>::${releaseType}::${installationVersion}::${installationPath}::<eol>") > $null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Write-Verbose "Could not locate vswhere at $vswhereExe"
|
||||||
|
}
|
||||||
|
|
||||||
|
$installationPath = Split-Path -Parent $(Split-Path -Parent "$env:vs140comntools")
|
||||||
|
$clExe = "$installationPath\VC\bin\cl.exe"
|
||||||
|
$vcvarsallbat = "$installationPath\VC\vcvarsall.bat"
|
||||||
|
|
||||||
|
if ((Test-Path $clExe) -And (Test-Path $vcvarsallbat))
|
||||||
|
{
|
||||||
|
$results.Add("<sol>::PreferenceWeight1::Legacy::14.0::$installationPath::<eol>") > $null
|
||||||
|
}
|
||||||
|
|
||||||
|
$installationPath = "$programFiles\Microsoft Visual Studio 14.0"
|
||||||
|
$clExe = "$installationPath\VC\bin\cl.exe"
|
||||||
|
$vcvarsallbat = "$installationPath\VC\vcvarsall.bat"
|
||||||
|
|
||||||
|
if ((Test-Path $clExe) -And (Test-Path $vcvarsallbat))
|
||||||
|
{
|
||||||
|
$results.Add("<sol>::PreferenceWeight1::Legacy::14.0::$installationPath::<eol>") > $null
|
||||||
|
}
|
||||||
|
|
||||||
|
$results.Sort()
|
||||||
|
$results.Reverse()
|
||||||
|
|
||||||
|
return $results
|
@ -61,17 +61,10 @@
|
|||||||
</tool>
|
</tool>
|
||||||
<tool name="7zip" os="windows">
|
<tool name="7zip" os="windows">
|
||||||
<version>18.01.0</version>
|
<version>18.01.0</version>
|
||||||
<exeRelativePath>7za.exe</exeRelativePath>
|
<exeRelativePath>7-Zip.CommandLine.18.1.0\tools\7za.exe</exeRelativePath>
|
||||||
<url>https://www.7-zip.org/a/7z1801-extra.7z</url>
|
<url>https://www.nuget.org/api/v2/package/7-Zip.CommandLine/18.1.0</url>
|
||||||
<sha512>9133fc551d76515e37fdd4dd8c1e28d464aea493548246b44565a42bba46715764f41f9cfa14d470d298c3a6e9829d200f8be5168cb67cf8f23d8042fca833bc</sha512>
|
<sha512>8c75314102e68d2b2347d592f8e3eb05812e1ebb525decbac472231633753f1d4ca31c8e6881a36144a8da26b2571305b3ae3f4e2b85fc4a290aeda63d1a13b8</sha512>
|
||||||
<archiveName>7z1801-extra.7z</archiveName>
|
<archiveName>7-zip.commandline.18.1.0.nupkg</archiveName>
|
||||||
</tool>
|
|
||||||
<tool name="7zip920" os="windows">
|
|
||||||
<version>9.20.0</version>
|
|
||||||
<exeRelativePath>7za.exe</exeRelativePath>
|
|
||||||
<url>https://www.7-zip.org/a/7za920.zip</url>
|
|
||||||
<sha512>84e830c91a0e8ae499cc4814080da6569d8a6acbddc585c8b62abc86c809793aeb669b0a741063a379fd281ade85f120bc27efeb67d63bf961be893eec8bc3b3</sha512>
|
|
||||||
<archiveName>7za920.zip</archiveName>
|
|
||||||
</tool>
|
</tool>
|
||||||
<tool name="aria2" os="windows">
|
<tool name="aria2" os="windows">
|
||||||
<version>18.01.0</version>
|
<version>18.01.0</version>
|
||||||
|
@ -47,6 +47,7 @@ namespace vcpkg::System
|
|||||||
|
|
||||||
ExitCodeAndOutput cmd_execute_and_capture_output(const CStringView cmd_line);
|
ExitCodeAndOutput cmd_execute_and_capture_output(const CStringView cmd_line);
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
void powershell_execute(const std::string& title,
|
void powershell_execute(const std::string& title,
|
||||||
const fs::path& script_path,
|
const fs::path& script_path,
|
||||||
const std::vector<PowershellParameter>& parameters = {});
|
const std::vector<PowershellParameter>& parameters = {});
|
||||||
@ -54,6 +55,7 @@ namespace vcpkg::System
|
|||||||
std::string powershell_execute_and_capture_output(const std::string& title,
|
std::string powershell_execute_and_capture_output(const std::string& title,
|
||||||
const fs::path& script_path,
|
const fs::path& script_path,
|
||||||
const std::vector<PowershellParameter>& parameters = {});
|
const std::vector<PowershellParameter>& parameters = {});
|
||||||
|
#endif
|
||||||
|
|
||||||
enum class Color
|
enum class Color
|
||||||
{
|
{
|
||||||
|
@ -132,14 +132,14 @@ namespace vcpkg::Commands
|
|||||||
namespace Hash
|
namespace Hash
|
||||||
{
|
{
|
||||||
std::string get_string_hash(const std::string& s, const std::string& hash_type);
|
std::string get_string_hash(const std::string& s, const std::string& hash_type);
|
||||||
std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type);
|
std::string get_file_hash(const Files::Filesystem& fs, const fs::path& path, const std::string& hash_type);
|
||||||
|
|
||||||
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths);
|
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Fetch
|
namespace Fetch
|
||||||
{
|
{
|
||||||
std::vector<Toolset> find_toolset_instances(const VcpkgPaths& paths);
|
std::vector<Toolset> find_toolset_instances_prefered_first(const VcpkgPaths& paths);
|
||||||
fs::path get_tool_path(const VcpkgPaths& paths, const std::string& tool);
|
fs::path get_tool_path(const VcpkgPaths& paths, const std::string& tool);
|
||||||
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths);
|
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths);
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,7 @@ namespace vcpkg
|
|||||||
fs::path triplets;
|
fs::path triplets;
|
||||||
fs::path scripts;
|
fs::path scripts;
|
||||||
|
|
||||||
|
fs::path tools;
|
||||||
fs::path buildsystems;
|
fs::path buildsystems;
|
||||||
fs::path buildsystems_msbuild_targets;
|
fs::path buildsystems_msbuild_targets;
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ namespace vcpkg::Checks
|
|||||||
|
|
||||||
const auto elapsed_us = GlobalState::timer.lock()->microseconds();
|
const auto elapsed_us = GlobalState::timer.lock()->microseconds();
|
||||||
|
|
||||||
|
Debug::println("Exiting after %d us", static_cast<int>(elapsed_us));
|
||||||
|
|
||||||
auto metrics = Metrics::g_metrics.lock();
|
auto metrics = Metrics::g_metrics.lock();
|
||||||
metrics->track_metric("elapsed_us", elapsed_us);
|
metrics->track_metric("elapsed_us", elapsed_us);
|
||||||
GlobalState::debugging = false;
|
GlobalState::debugging = false;
|
||||||
|
@ -155,6 +155,7 @@ namespace vcpkg::System
|
|||||||
|
|
||||||
int cmd_execute_clean(const CStringView cmd_line, const std::unordered_map<std::string, std::string>& extra_env)
|
int cmd_execute_clean(const CStringView cmd_line, const std::unordered_map<std::string, std::string>& extra_env)
|
||||||
{
|
{
|
||||||
|
auto timer = Chrono::ElapsedTimer::create_started();
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
static const std::string SYSTEM_ROOT = get_environment_variable("SystemRoot").value_or_exit(VCPKG_LINE_INFO);
|
static const std::string SYSTEM_ROOT = get_environment_variable("SystemRoot").value_or_exit(VCPKG_LINE_INFO);
|
||||||
static const std::string SYSTEM_32 = SYSTEM_ROOT + R"(\system32)";
|
static const std::string SYSTEM_32 = SYSTEM_ROOT + R"(\system32)";
|
||||||
@ -271,7 +272,7 @@ namespace vcpkg::System
|
|||||||
DWORD exit_code = 0;
|
DWORD exit_code = 0;
|
||||||
GetExitCodeProcess(process_info.hProcess, &exit_code);
|
GetExitCodeProcess(process_info.hProcess, &exit_code);
|
||||||
|
|
||||||
Debug::println("CreateProcessW() returned %lu", exit_code);
|
Debug::println("CreateProcessW() returned %lu after %d us", exit_code, static_cast<int>(timer.microseconds()));
|
||||||
return static_cast<int>(exit_code);
|
return static_cast<int>(exit_code);
|
||||||
#else
|
#else
|
||||||
Debug::println("system(%s)", cmd_line.c_str());
|
Debug::println("system(%s)", cmd_line.c_str());
|
||||||
@ -369,13 +370,20 @@ namespace vcpkg::System
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
void powershell_execute(const std::string& title,
|
void powershell_execute(const std::string& title,
|
||||||
const fs::path& script_path,
|
const fs::path& script_path,
|
||||||
const std::vector<PowershellParameter>& parameters)
|
const std::vector<PowershellParameter>& parameters)
|
||||||
{
|
{
|
||||||
|
SetConsoleCP(437);
|
||||||
|
SetConsoleOutputCP(437);
|
||||||
|
|
||||||
const std::string cmd = make_powershell_cmd(script_path, parameters);
|
const std::string cmd = make_powershell_cmd(script_path, parameters);
|
||||||
const int rc = System::cmd_execute(cmd);
|
const int rc = System::cmd_execute(cmd);
|
||||||
|
|
||||||
|
SetConsoleCP(CP_UTF8);
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
System::println(Color::error,
|
System::println(Color::error,
|
||||||
@ -394,14 +402,22 @@ namespace vcpkg::System
|
|||||||
Checks::exit_with_code(VCPKG_LINE_INFO, rc);
|
Checks::exit_with_code(VCPKG_LINE_INFO, rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
std::string powershell_execute_and_capture_output(const std::string& title,
|
std::string powershell_execute_and_capture_output(const std::string& title,
|
||||||
const fs::path& script_path,
|
const fs::path& script_path,
|
||||||
const std::vector<PowershellParameter>& parameters)
|
const std::vector<PowershellParameter>& parameters)
|
||||||
{
|
{
|
||||||
|
SetConsoleCP(437);
|
||||||
|
SetConsoleOutputCP(437);
|
||||||
|
|
||||||
const std::string cmd = make_powershell_cmd(script_path, parameters);
|
const std::string cmd = make_powershell_cmd(script_path, parameters);
|
||||||
auto rc = System::cmd_execute_and_capture_output(cmd);
|
auto rc = System::cmd_execute_and_capture_output(cmd);
|
||||||
|
|
||||||
|
SetConsoleCP(CP_UTF8);
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
|
||||||
if (rc.exit_code)
|
if (rc.exit_code)
|
||||||
{
|
{
|
||||||
System::println(Color::error,
|
System::println(Color::error,
|
||||||
@ -433,6 +449,7 @@ namespace vcpkg::System
|
|||||||
|
|
||||||
return rc.output;
|
return rc.output;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void println() { putchar('\n'); }
|
void println() { putchar('\n'); }
|
||||||
|
|
||||||
|
@ -461,9 +461,9 @@ namespace vcpkg::Build
|
|||||||
abi_tag_entries.insert(abi_tag_entries.end(), dependency_abis.begin(), dependency_abis.end());
|
abi_tag_entries.insert(abi_tag_entries.end(), dependency_abis.begin(), dependency_abis.end());
|
||||||
|
|
||||||
abi_tag_entries.emplace_back(
|
abi_tag_entries.emplace_back(
|
||||||
AbiEntry{"portfile", Commands::Hash::get_file_hash(paths, config.port_dir / "portfile.cmake", "SHA1")});
|
AbiEntry{"portfile", Commands::Hash::get_file_hash(fs, config.port_dir / "portfile.cmake", "SHA1")});
|
||||||
abi_tag_entries.emplace_back(
|
abi_tag_entries.emplace_back(
|
||||||
AbiEntry{"control", Commands::Hash::get_file_hash(paths, config.port_dir / "CONTROL", "SHA1")});
|
AbiEntry{"control", Commands::Hash::get_file_hash(fs, config.port_dir / "CONTROL", "SHA1")});
|
||||||
|
|
||||||
abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag});
|
abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag});
|
||||||
|
|
||||||
@ -498,7 +498,7 @@ namespace vcpkg::Build
|
|||||||
const auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt");
|
const auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt");
|
||||||
fs.write_contents(abi_file_path, full_abi_info);
|
fs.write_contents(abi_file_path, full_abi_info);
|
||||||
|
|
||||||
return AbiTagAndFile{Commands::Hash::get_file_hash(paths, abi_file_path, "SHA1"), abi_file_path};
|
return AbiTagAndFile{Commands::Hash::get_file_hash(fs, abi_file_path, "SHA1"), abi_file_path};
|
||||||
}
|
}
|
||||||
|
|
||||||
System::println(
|
System::println(
|
||||||
@ -783,14 +783,12 @@ namespace vcpkg::Build
|
|||||||
{
|
{
|
||||||
return it_hash->second;
|
return it_hash->second;
|
||||||
}
|
}
|
||||||
auto hash = Commands::Hash::get_file_hash(paths, triplet_file_path, "SHA1");
|
auto hash = Commands::Hash::get_file_hash(paths.get_filesystem(), triplet_file_path, "SHA1");
|
||||||
s_hash_cache.emplace(triplet_file_path, hash);
|
s_hash_cache.emplace(triplet_file_path, hash);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return std::string();
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
}();
|
}();
|
||||||
|
|
||||||
const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path,
|
const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path,
|
||||||
|
@ -43,7 +43,7 @@ namespace vcpkg::Commands
|
|||||||
{"portsdiff", &PortsDiff::perform_and_exit},
|
{"portsdiff", &PortsDiff::perform_and_exit},
|
||||||
{"autocomplete", &Autocomplete::perform_and_exit},
|
{"autocomplete", &Autocomplete::perform_and_exit},
|
||||||
{"hash", &Hash::perform_and_exit},
|
{"hash", &Hash::perform_and_exit},
|
||||||
// {"fetch", &Fetch::perform_and_exit},
|
{"fetch", &Fetch::perform_and_exit},
|
||||||
};
|
};
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
#include <vcpkg/base/checks.h>
|
#include <vcpkg/base/checks.h>
|
||||||
|
#include <vcpkg/base/sortedvector.h>
|
||||||
#include <vcpkg/base/strings.h>
|
#include <vcpkg/base/strings.h>
|
||||||
#include <vcpkg/base/system.h>
|
#include <vcpkg/base/system.h>
|
||||||
#include <vcpkg/base/util.h>
|
#include <vcpkg/base/util.h>
|
||||||
@ -19,6 +20,7 @@ namespace vcpkg::Commands::Fetch
|
|||||||
fs::path exe_path;
|
fs::path exe_path;
|
||||||
std::string url;
|
std::string url;
|
||||||
fs::path download_path;
|
fs::path download_path;
|
||||||
|
bool is_archive;
|
||||||
fs::path tool_dir_path;
|
fs::path tool_dir_path;
|
||||||
std::string sha512;
|
std::string sha512;
|
||||||
};
|
};
|
||||||
@ -41,20 +43,85 @@ namespace vcpkg::Commands::Fetch
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Optional<std::string> extract_string_between_delimiters(const std::string& input,
|
struct VcpkgStringRange
|
||||||
const std::string& left_delim,
|
|
||||||
const std::string& right_delim,
|
|
||||||
const size_t& starting_offset = 0)
|
|
||||||
{
|
{
|
||||||
const size_t from = input.find(left_delim, starting_offset);
|
VcpkgStringRange() = default;
|
||||||
if (from == std::string::npos) return nullopt;
|
|
||||||
|
|
||||||
const size_t substring_start = from + left_delim.length();
|
// Implicit by design
|
||||||
|
VcpkgStringRange(const std::string& s) : begin(s.cbegin()), end(s.cend()) {}
|
||||||
|
|
||||||
const size_t to = input.find(right_delim, substring_start);
|
VcpkgStringRange(const std::string::const_iterator begin, const std::string::const_iterator end)
|
||||||
if (from == std::string::npos) return nullopt;
|
: begin(begin), end(end)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
return input.substr(substring_start, to - substring_start);
|
std::string::const_iterator begin;
|
||||||
|
std::string::const_iterator end;
|
||||||
|
|
||||||
|
std::string to_string() const { return std::string(this->begin, this->end); }
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::vector<VcpkgStringRange> find_all_enclosed(const VcpkgStringRange& input,
|
||||||
|
const std::string& left_delim,
|
||||||
|
const std::string& right_delim)
|
||||||
|
{
|
||||||
|
std::string::const_iterator it_left = input.begin;
|
||||||
|
std::string::const_iterator it_right = input.begin;
|
||||||
|
|
||||||
|
std::vector<VcpkgStringRange> output;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
it_left = std::search(it_right, input.end, left_delim.cbegin(), left_delim.cend());
|
||||||
|
if (it_left == input.end) break;
|
||||||
|
|
||||||
|
it_left += left_delim.length();
|
||||||
|
|
||||||
|
it_right = std::search(it_left, input.end, right_delim.cbegin(), right_delim.cend());
|
||||||
|
if (it_right == input.end) break;
|
||||||
|
|
||||||
|
output.emplace_back(it_left, it_right);
|
||||||
|
|
||||||
|
++it_right;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VcpkgStringRange find_exactly_one_enclosed(const VcpkgStringRange& input,
|
||||||
|
const std::string& left_tag,
|
||||||
|
const std::string& right_tag)
|
||||||
|
{
|
||||||
|
std::vector<VcpkgStringRange> result = find_all_enclosed(input, left_tag, right_tag);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
result.size() == 1,
|
||||||
|
"Found %d sets of %s.*%s but expected exactly 1, in block:\n%s",
|
||||||
|
result.size(),
|
||||||
|
left_tag,
|
||||||
|
right_tag,
|
||||||
|
input);
|
||||||
|
return std::move(result.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
static Optional<VcpkgStringRange> find_at_most_one_enclosed(const VcpkgStringRange& input,
|
||||||
|
const std::string& left_tag,
|
||||||
|
const std::string& right_tag)
|
||||||
|
{
|
||||||
|
std::vector<VcpkgStringRange> result = find_all_enclosed(input, left_tag, right_tag);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
result.size() <= 1,
|
||||||
|
"Found %d sets of %s.*%s but expected at most 1, in block:\n%s",
|
||||||
|
result.size(),
|
||||||
|
left_tag,
|
||||||
|
right_tag,
|
||||||
|
input);
|
||||||
|
|
||||||
|
if (result.empty())
|
||||||
|
{
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool)
|
static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool)
|
||||||
@ -72,21 +139,6 @@ namespace vcpkg::Commands::Fetch
|
|||||||
#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__)
|
#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__)
|
||||||
static const std::string XML_VERSION = "2";
|
static const std::string XML_VERSION = "2";
|
||||||
static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml";
|
static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml";
|
||||||
|
|
||||||
const auto get_string_inside_tags =
|
|
||||||
[](const std::string& input, const std::string& left_delim, const std::string& right_delim) -> std::string {
|
|
||||||
Optional<std::string> result = extract_string_between_delimiters(input, left_delim, right_delim);
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO,
|
|
||||||
result.has_value(),
|
|
||||||
"Could not find tag <%s>.*<%s> in %s",
|
|
||||||
left_delim,
|
|
||||||
right_delim,
|
|
||||||
XML_PATH.generic_string());
|
|
||||||
|
|
||||||
auto r = *result.get();
|
|
||||||
return Strings::trim(std::move(r));
|
|
||||||
};
|
|
||||||
|
|
||||||
static const std::regex XML_VERSION_REGEX{R"###(<tools[\s]+version="([^"]+)">)###"};
|
static const std::regex XML_VERSION_REGEX{R"###(<tools[\s]+version="([^"]+)">)###"};
|
||||||
static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO);
|
static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO);
|
||||||
std::smatch match_xml_version;
|
std::smatch match_xml_version;
|
||||||
@ -112,14 +164,14 @@ namespace vcpkg::Commands::Fetch
|
|||||||
tool,
|
tool,
|
||||||
XML_PATH.generic_string());
|
XML_PATH.generic_string());
|
||||||
|
|
||||||
const std::string tool_data = get_string_inside_tags(XML, match_tool_entry[0], R"(</tool>)");
|
const std::string tool_data = find_exactly_one_enclosed(XML, match_tool_entry[0], "</tool>").to_string();
|
||||||
|
const std::string version_as_string =
|
||||||
const std::string version_as_string = get_string_inside_tags(tool_data, "<version>", R"(</version>)");
|
find_exactly_one_enclosed(tool_data, "<version>", "</version>").to_string();
|
||||||
const std::string exe_relative_path =
|
const std::string exe_relative_path =
|
||||||
get_string_inside_tags(tool_data, "<exeRelativePath>", R"(</exeRelativePath>)");
|
find_exactly_one_enclosed(tool_data, "<exeRelativePath>", "</exeRelativePath>").to_string();
|
||||||
const std::string url = get_string_inside_tags(tool_data, "<url>", R"(</url>)");
|
const std::string url = find_exactly_one_enclosed(tool_data, "<url>", "</url>").to_string();
|
||||||
const std::string sha512 = get_string_inside_tags(tool_data, "<sha512>", R"(</sha512>)");
|
const std::string sha512 = find_exactly_one_enclosed(tool_data, "<sha512>", "</sha512>").to_string();
|
||||||
auto archive_name = extract_string_between_delimiters(tool_data, "<archiveName>", R"(</archiveName>)");
|
auto archive_name = find_at_most_one_enclosed(tool_data, "<archiveName>", "</archiveName>");
|
||||||
|
|
||||||
const Optional<std::array<int, 3>> version = parse_version_string(version_as_string);
|
const Optional<std::array<int, 3>> version = parse_version_string(version_as_string);
|
||||||
Checks::check_exit(VCPKG_LINE_INFO,
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
@ -129,13 +181,14 @@ namespace vcpkg::Commands::Fetch
|
|||||||
version_as_string);
|
version_as_string);
|
||||||
|
|
||||||
const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, version_as_string, OS_STRING);
|
const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, version_as_string, OS_STRING);
|
||||||
const fs::path tool_dir_path = paths.downloads / "tools" / tool_dir_name;
|
const fs::path tool_dir_path = paths.tools / tool_dir_name;
|
||||||
const fs::path exe_path = tool_dir_path / exe_relative_path;
|
const fs::path exe_path = tool_dir_path / exe_relative_path;
|
||||||
|
|
||||||
return ToolData{*version.get(),
|
return ToolData{*version.get(),
|
||||||
exe_path,
|
exe_path,
|
||||||
url,
|
url,
|
||||||
paths.downloads / archive_name.value_or(exe_relative_path),
|
paths.downloads / archive_name.value_or(exe_relative_path).to_string(),
|
||||||
|
archive_name.has_value(),
|
||||||
tool_dir_path,
|
tool_dir_path,
|
||||||
sha512};
|
sha512};
|
||||||
#endif
|
#endif
|
||||||
@ -163,51 +216,87 @@ namespace vcpkg::Commands::Fetch
|
|||||||
actual_version[2] >= expected_version[2]));
|
actual_version[2] >= expected_version[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Optional<fs::path> find_if_has_equal_or_greater_version(const std::vector<fs::path>& candidate_paths,
|
static Optional<fs::path> find_if_has_equal_or_greater_version(Files::Filesystem& fs,
|
||||||
|
const std::vector<fs::path>& candidate_paths,
|
||||||
const std::string& version_check_arguments,
|
const std::string& version_check_arguments,
|
||||||
const std::array<int, 3>& expected_version)
|
const std::array<int, 3>& expected_version)
|
||||||
{
|
{
|
||||||
auto it = Util::find_if(candidate_paths, [&](const fs::path& p) {
|
const auto it = Util::find_if(candidate_paths, [&](const fs::path& p) {
|
||||||
|
if (!fs.exists(p)) return false;
|
||||||
const std::string cmd = Strings::format(R"("%s" %s)", p.u8string(), version_check_arguments);
|
const std::string cmd = Strings::format(R"("%s" %s)", p.u8string(), version_check_arguments);
|
||||||
return exists_and_has_equal_or_greater_version(cmd, expected_version);
|
return exists_and_has_equal_or_greater_version(cmd, expected_version);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (it != candidate_paths.cend())
|
if (it != candidate_paths.cend())
|
||||||
{
|
{
|
||||||
return std::move(*it);
|
return *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> keep_data_lines(const std::string& data_blob)
|
|
||||||
{
|
|
||||||
static const std::regex DATA_LINE_REGEX(R"(<sol>::(.+?)(?=::<eol>))");
|
|
||||||
|
|
||||||
std::vector<std::string> data_lines;
|
|
||||||
|
|
||||||
const std::sregex_iterator it(data_blob.cbegin(), data_blob.cend(), DATA_LINE_REGEX);
|
|
||||||
const std::sregex_iterator end;
|
|
||||||
for (std::sregex_iterator i = it; i != end; ++i)
|
|
||||||
{
|
|
||||||
const std::smatch match = *i;
|
|
||||||
data_lines.push_back(match[1].str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return data_lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
static void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path)
|
static void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path)
|
||||||
{
|
{
|
||||||
Files::Filesystem& fs = paths.get_filesystem();
|
Files::Filesystem& fs = paths.get_filesystem();
|
||||||
const fs::path to_path_partial = to_path.u8string() + ".partial";
|
const fs::path to_path_partial = to_path.u8string() + ".partial";
|
||||||
|
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
|
fs.remove_all(to_path, ec);
|
||||||
fs.remove_all(to_path_partial, ec);
|
fs.remove_all(to_path_partial, ec);
|
||||||
fs.create_directories(to_path_partial, ec);
|
fs.create_directories(to_path_partial, ec);
|
||||||
|
|
||||||
const auto ext = archive.extension();
|
const auto ext = archive.extension();
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (ext == ".nupkg")
|
||||||
|
{
|
||||||
|
static bool recursion_limiter_sevenzip_old = false;
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip_old);
|
||||||
|
recursion_limiter_sevenzip_old = true;
|
||||||
|
const auto nuget_exe = get_tool_path(paths, Tools::NUGET);
|
||||||
|
|
||||||
|
const std::string stem = archive.stem().u8string();
|
||||||
|
// assuming format of [name].[version in the form d.d.d]
|
||||||
|
// This assumption may not always hold
|
||||||
|
std::smatch match;
|
||||||
|
const bool has_match = std::regex_match(stem, match, std::regex{R"###(^(.+)\.(\d+\.\d+\.\d+)$)###"});
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
has_match,
|
||||||
|
"Could not deduce nuget id and version from filename: %s",
|
||||||
|
archive.u8string());
|
||||||
|
|
||||||
|
const std::string nugetid = match[1];
|
||||||
|
const std::string version = match[2];
|
||||||
|
|
||||||
|
const auto code_and_output = System::cmd_execute_and_capture_output(Strings::format(
|
||||||
|
R"("%s" install %s -Version %s -OutputDirectory "%s" -Source "%s" -nocache -DirectDownload -NonInteractive -ForceEnglishOutput -PackageSaveMode nuspec)",
|
||||||
|
nuget_exe.u8string(),
|
||||||
|
nugetid,
|
||||||
|
version,
|
||||||
|
to_path_partial.u8string(),
|
||||||
|
paths.downloads.u8string()));
|
||||||
|
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
code_and_output.exit_code == 0,
|
||||||
|
"Failed to extract '%s' with message:\n%s",
|
||||||
|
archive.u8string(),
|
||||||
|
code_and_output.output);
|
||||||
|
recursion_limiter_sevenzip_old = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static bool recursion_limiter_sevenzip = false;
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip);
|
||||||
|
recursion_limiter_sevenzip = true;
|
||||||
|
const auto seven_zip = get_tool_path(paths, Tools::SEVEN_ZIP);
|
||||||
|
const auto code_and_output = System::cmd_execute_and_capture_output(Strings::format(
|
||||||
|
R"("%s" x "%s" -o"%s" -y)", seven_zip.u8string(), archive.u8string(), to_path_partial.u8string()));
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
code_and_output.exit_code == 0,
|
||||||
|
"7zip failed while extracting '%s' with message:\n%s",
|
||||||
|
archive.u8string(),
|
||||||
|
code_and_output.output);
|
||||||
|
recursion_limiter_sevenzip = false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (ext == ".gz" && ext.extension() != ".tar")
|
if (ext == ".gz" && ext.extension() != ".tar")
|
||||||
{
|
{
|
||||||
const auto code = System::cmd_execute(
|
const auto code = System::cmd_execute(
|
||||||
@ -224,16 +313,23 @@ namespace vcpkg::Commands::Fetch
|
|||||||
{
|
{
|
||||||
Checks::exit_with_message(VCPKG_LINE_INFO, "Unexpected archive extension: %s", ext.u8string());
|
Checks::exit_with_message(VCPKG_LINE_INFO, "Unexpected archive extension: %s", ext.u8string());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fs.rename(to_path_partial, to_path);
|
fs.rename(to_path_partial, to_path, ec);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
!ec,
|
||||||
|
"Failed to do post-extract rename-in-place.\nfs.rename(%s, %s, %s)",
|
||||||
|
to_path_partial.u8string(),
|
||||||
|
to_path.u8string(),
|
||||||
|
ec.message());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verify_hash(const VcpkgPaths& paths,
|
static void verify_hash(const Files::Filesystem& fs,
|
||||||
const std::string& url,
|
const std::string& url,
|
||||||
const fs::path& path,
|
const fs::path& path,
|
||||||
const std::string& sha512)
|
const std::string& sha512)
|
||||||
{
|
{
|
||||||
const std::string actual_hash = Hash::get_file_hash(paths, path, "SHA512");
|
const std::string actual_hash = Hash::get_file_hash(fs, path, "SHA512");
|
||||||
Checks::check_exit(VCPKG_LINE_INFO,
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
sha512 == actual_hash,
|
sha512 == actual_hash,
|
||||||
"File does not have the expected hash:\n"
|
"File does not have the expected hash:\n"
|
||||||
@ -247,24 +343,119 @@ namespace vcpkg::Commands::Fetch
|
|||||||
actual_hash);
|
actual_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void download_file(const VcpkgPaths& paths,
|
#if defined(_WIN32)
|
||||||
|
static void winhttp_download_file(Files::Filesystem& fs,
|
||||||
|
CStringView target_file_path,
|
||||||
|
CStringView hostname,
|
||||||
|
CStringView url_path)
|
||||||
|
{
|
||||||
|
// Make sure the directories are present, otherwise fopen_s fails
|
||||||
|
const auto dir = fs::path(target_file_path.c_str()).parent_path();
|
||||||
|
std::error_code ec;
|
||||||
|
fs.create_directories(dir, ec);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not create directories %s", dir.u8string());
|
||||||
|
|
||||||
|
FILE* f = nullptr;
|
||||||
|
const errno_t err = fopen_s(&f, target_file_path.c_str(), "wb");
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
!err,
|
||||||
|
"Could not download https://%s%s. Failed to open file %s. Error code was %s",
|
||||||
|
hostname,
|
||||||
|
url_path,
|
||||||
|
target_file_path,
|
||||||
|
std::to_string(err));
|
||||||
|
|
||||||
|
auto hSession = WinHttpOpen(
|
||||||
|
L"vcpkg/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, hSession, "WinHttpOpen() failed: %d", GetLastError());
|
||||||
|
|
||||||
|
// Use Windows 10 defaults on Windows 7
|
||||||
|
DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
|
||||||
|
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2);
|
||||||
|
WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols));
|
||||||
|
|
||||||
|
// Specify an HTTP server.
|
||||||
|
auto hConnect = WinHttpConnect(hSession, Strings::to_utf16(hostname).c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, hConnect, "WinHttpConnect() failed: %d", GetLastError());
|
||||||
|
|
||||||
|
// Create an HTTP request handle.
|
||||||
|
auto hRequest = WinHttpOpenRequest(hConnect,
|
||||||
|
L"GET",
|
||||||
|
Strings::to_utf16(url_path).c_str(),
|
||||||
|
nullptr,
|
||||||
|
WINHTTP_NO_REFERER,
|
||||||
|
WINHTTP_DEFAULT_ACCEPT_TYPES,
|
||||||
|
WINHTTP_FLAG_SECURE);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, hRequest, "WinHttpOpenRequest() failed: %d", GetLastError());
|
||||||
|
|
||||||
|
// Send a request.
|
||||||
|
auto bResults =
|
||||||
|
WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpSendRequest() failed: %d", GetLastError());
|
||||||
|
|
||||||
|
// End the request.
|
||||||
|
bResults = WinHttpReceiveResponse(hRequest, NULL);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReceiveResponse() failed: %d", GetLastError());
|
||||||
|
|
||||||
|
std::vector<char> buf;
|
||||||
|
|
||||||
|
size_t total_downloaded_size = 0;
|
||||||
|
DWORD dwSize = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DWORD downloaded_size = 0;
|
||||||
|
bResults = WinHttpQueryDataAvailable(hRequest, &dwSize);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpQueryDataAvailable() failed: %d", GetLastError());
|
||||||
|
|
||||||
|
if (buf.size() < dwSize) buf.resize(dwSize * 2);
|
||||||
|
|
||||||
|
bResults = WinHttpReadData(hRequest, (LPVOID)buf.data(), dwSize, &downloaded_size);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReadData() failed: %d", GetLastError());
|
||||||
|
fwrite(buf.data(), 1, downloaded_size, f);
|
||||||
|
|
||||||
|
total_downloaded_size += downloaded_size;
|
||||||
|
} while (dwSize > 0);
|
||||||
|
|
||||||
|
WinHttpCloseHandle(hSession);
|
||||||
|
WinHttpCloseHandle(hConnect);
|
||||||
|
WinHttpCloseHandle(hRequest);
|
||||||
|
fflush(f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void download_file(Files::Filesystem& fs,
|
||||||
const std::string& url,
|
const std::string& url,
|
||||||
const fs::path& download_path,
|
const fs::path& download_path,
|
||||||
const std::string& sha512)
|
const std::string& sha512)
|
||||||
{
|
{
|
||||||
Files::Filesystem& fs = paths.get_filesystem();
|
|
||||||
const std::string download_path_part = download_path.u8string() + ".part";
|
const std::string download_path_part = download_path.u8string() + ".part";
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
|
fs.remove(download_path, ec);
|
||||||
fs.remove(download_path_part, ec);
|
fs.remove(download_path_part, ec);
|
||||||
|
#if defined(_WIN32)
|
||||||
|
auto url_no_proto = url.substr(8); // drop https://
|
||||||
|
auto path_begin = Util::find(url_no_proto, '/');
|
||||||
|
std::string hostname(url_no_proto.begin(), path_begin);
|
||||||
|
std::string path(path_begin, url_no_proto.end());
|
||||||
|
|
||||||
|
winhttp_download_file(fs, download_path_part.c_str(), hostname, path);
|
||||||
|
#else
|
||||||
const auto code = System::cmd_execute(
|
const auto code = System::cmd_execute(
|
||||||
Strings::format(R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part));
|
Strings::format(R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part));
|
||||||
Checks::check_exit(VCPKG_LINE_INFO, code == 0, "Could not download %s", url);
|
Checks::check_exit(VCPKG_LINE_INFO, code == 0, "Could not download %s", url);
|
||||||
|
#endif
|
||||||
|
|
||||||
verify_hash(paths, url, download_path_part, sha512);
|
verify_hash(fs, url, download_path_part, sha512);
|
||||||
fs.rename(download_path_part, download_path);
|
fs.rename(download_path_part, download_path, ec);
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
!ec,
|
||||||
|
"Failed to do post-download rename-in-place.\nfs.rename(%s, %s, %s)",
|
||||||
|
download_path_part,
|
||||||
|
download_path.u8string(),
|
||||||
|
ec.message());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data)
|
static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data)
|
||||||
{
|
{
|
||||||
const std::array<int, 3>& version = tool_data.version;
|
const std::array<int, 3>& version = tool_data.version;
|
||||||
@ -280,50 +471,37 @@ namespace vcpkg::Commands::Fetch
|
|||||||
version_as_string,
|
version_as_string,
|
||||||
tool_name,
|
tool_name,
|
||||||
version_as_string);
|
version_as_string);
|
||||||
#if defined(_WIN32)
|
auto& fs = paths.get_filesystem();
|
||||||
const fs::path script = paths.scripts / "fetchtool.ps1";
|
|
||||||
const std::string title = Strings::format(
|
|
||||||
"Fetching %s version %s (No sufficient installed version was found)", tool_name, version_as_string);
|
|
||||||
const System::PowershellParameter tool_param("tool", tool_name);
|
|
||||||
const std::string output = System::powershell_execute_and_capture_output(title, script, {tool_param});
|
|
||||||
|
|
||||||
const std::vector<std::string> tool_path = keep_data_lines(output);
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO, tool_path.size() == 1, "Expected tool path, but got %s", output);
|
|
||||||
|
|
||||||
const fs::path actual_downloaded_path = Strings::trim(std::string{tool_path.at(0)});
|
|
||||||
const fs::path& expected_downloaded_path = tool_data.exe_path;
|
|
||||||
std::error_code ec;
|
|
||||||
const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec);
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO,
|
|
||||||
eq && !ec,
|
|
||||||
"Expected tool downloaded path to be %s, but was %s",
|
|
||||||
expected_downloaded_path.u8string(),
|
|
||||||
actual_downloaded_path.u8string());
|
|
||||||
return actual_downloaded_path;
|
|
||||||
#else
|
|
||||||
const auto& fs = paths.get_filesystem();
|
|
||||||
if (!fs.exists(tool_data.download_path))
|
if (!fs.exists(tool_data.download_path))
|
||||||
{
|
{
|
||||||
System::println("Downloading %s...", tool_name);
|
System::println("Downloading %s...", tool_name);
|
||||||
download_file(paths, tool_data.url, tool_data.download_path, tool_data.sha512);
|
download_file(fs, tool_data.url, tool_data.download_path, tool_data.sha512);
|
||||||
System::println("Downloading %s... done.", tool_name);
|
System::println("Downloading %s... done.", tool_name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
verify_hash(paths, tool_data.url, tool_data.download_path, tool_data.sha512);
|
verify_hash(fs, tool_data.url, tool_data.download_path, tool_data.sha512);
|
||||||
}
|
}
|
||||||
|
|
||||||
System::println("Extracting %s...", tool_name);
|
if (tool_data.is_archive)
|
||||||
extract_archive(paths, tool_data.download_path, tool_data.tool_dir_path);
|
{
|
||||||
System::println("Extracting %s... done.", tool_name);
|
System::println("Extracting %s...", tool_name);
|
||||||
|
extract_archive(paths, tool_data.download_path, tool_data.tool_dir_path);
|
||||||
|
System::println("Extracting %s... done.", tool_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::error_code ec;
|
||||||
|
fs.create_directories(tool_data.exe_path.parent_path(), ec);
|
||||||
|
fs.rename(tool_data.download_path, tool_data.exe_path, ec);
|
||||||
|
}
|
||||||
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO,
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
fs.exists(tool_data.exe_path),
|
fs.exists(tool_data.exe_path),
|
||||||
"Expected %s to exist after extracting",
|
"Expected %s to exist after fetching",
|
||||||
tool_data.exe_path);
|
tool_data.exe_path.u8string());
|
||||||
|
|
||||||
return tool_data.exe_path;
|
return tool_data.exe_path;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static fs::path get_cmake_path(const VcpkgPaths& paths)
|
static fs::path get_cmake_path(const VcpkgPaths& paths)
|
||||||
@ -345,8 +523,8 @@ namespace vcpkg::Commands::Fetch
|
|||||||
const auto& program_files_32_bit = System::get_program_files_32_bit();
|
const auto& program_files_32_bit = System::get_program_files_32_bit();
|
||||||
if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe");
|
if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe");
|
||||||
|
|
||||||
const Optional<fs::path> path =
|
const Optional<fs::path> path = find_if_has_equal_or_greater_version(
|
||||||
find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
|
paths.get_filesystem(), candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
|
||||||
if (const auto p = path.get())
|
if (const auto p = path.get())
|
||||||
{
|
{
|
||||||
return *p;
|
return *p;
|
||||||
@ -378,7 +556,8 @@ namespace vcpkg::Commands::Fetch
|
|||||||
const std::vector<fs::path> from_path = Files::find_from_PATH("ninja");
|
const std::vector<fs::path> from_path = Files::find_from_PATH("ninja");
|
||||||
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
|
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
|
||||||
|
|
||||||
auto path = find_if_has_equal_or_greater_version(candidate_paths, "--version", TOOL_DATA.version);
|
auto path = find_if_has_equal_or_greater_version(
|
||||||
|
paths.get_filesystem(), candidate_paths, "--version", TOOL_DATA.version);
|
||||||
if (const auto p = path.get())
|
if (const auto p = path.get())
|
||||||
{
|
{
|
||||||
return *p;
|
return *p;
|
||||||
@ -396,7 +575,8 @@ namespace vcpkg::Commands::Fetch
|
|||||||
const std::vector<fs::path> from_path = Files::find_from_PATH("nuget");
|
const std::vector<fs::path> from_path = Files::find_from_PATH("nuget");
|
||||||
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
|
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
|
||||||
|
|
||||||
auto path = find_if_has_equal_or_greater_version(candidate_paths, "", TOOL_DATA.version);
|
auto path =
|
||||||
|
find_if_has_equal_or_greater_version(paths.get_filesystem(), candidate_paths, "", TOOL_DATA.version);
|
||||||
if (const auto p = path.get())
|
if (const auto p = path.get())
|
||||||
{
|
{
|
||||||
return *p;
|
return *p;
|
||||||
@ -422,8 +602,8 @@ namespace vcpkg::Commands::Fetch
|
|||||||
const auto& program_files_32_bit = System::get_program_files_32_bit();
|
const auto& program_files_32_bit = System::get_program_files_32_bit();
|
||||||
if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe");
|
if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe");
|
||||||
|
|
||||||
const Optional<fs::path> path =
|
const Optional<fs::path> path = find_if_has_equal_or_greater_version(
|
||||||
find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
|
paths.get_filesystem(), candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
|
||||||
if (const auto p = path.get())
|
if (const auto p = path.get())
|
||||||
{
|
{
|
||||||
return *p;
|
return *p;
|
||||||
@ -448,8 +628,8 @@ namespace vcpkg::Commands::Fetch
|
|||||||
// candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" /
|
// candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" /
|
||||||
// "QtIFW-3.1.0" / "bin" / "installerbase.exe");
|
// "QtIFW-3.1.0" / "bin" / "installerbase.exe");
|
||||||
|
|
||||||
const Optional<fs::path> path =
|
const Optional<fs::path> path = find_if_has_equal_or_greater_version(
|
||||||
find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
|
paths.get_filesystem(), candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
|
||||||
if (const auto p = path.get())
|
if (const auto p = path.get())
|
||||||
{
|
{
|
||||||
return *p;
|
return *p;
|
||||||
@ -460,48 +640,114 @@ namespace vcpkg::Commands::Fetch
|
|||||||
|
|
||||||
struct VisualStudioInstance
|
struct VisualStudioInstance
|
||||||
{
|
{
|
||||||
|
enum class ReleaseType
|
||||||
|
{
|
||||||
|
STABLE,
|
||||||
|
PRERELEASE,
|
||||||
|
LEGACY
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool prefered_first_comparator(const VisualStudioInstance& left, const VisualStudioInstance& right)
|
||||||
|
{
|
||||||
|
const auto get_preference_weight = [](const ReleaseType& type) -> int {
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ReleaseType::STABLE: return 3;
|
||||||
|
case ReleaseType::PRERELEASE: return 2;
|
||||||
|
case ReleaseType::LEGACY: return 1;
|
||||||
|
default: Checks::unreachable(VCPKG_LINE_INFO);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (left.release_type != right.release_type)
|
||||||
|
{
|
||||||
|
return get_preference_weight(left.release_type) > get_preference_weight(right.release_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return left.version > right.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
VisualStudioInstance(fs::path&& root_path, std::string&& version, const ReleaseType& release_type)
|
||||||
|
: root_path(std::move(root_path)), version(std::move(version)), release_type(release_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
fs::path root_path;
|
fs::path root_path;
|
||||||
std::string version;
|
std::string version;
|
||||||
std::string release_type;
|
ReleaseType release_type;
|
||||||
std::string preference_weight; // Mostly unused, just for verification that order is as intended
|
|
||||||
|
|
||||||
std::string major_version() const { return version.substr(0, 2); }
|
std::string major_version() const { return version.substr(0, 2); }
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<VisualStudioInstance> get_visual_studio_instances(const VcpkgPaths& paths)
|
static std::vector<VisualStudioInstance> get_visual_studio_instances(const VcpkgPaths& paths)
|
||||||
{
|
{
|
||||||
const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1";
|
const auto& fs = paths.get_filesystem();
|
||||||
const std::string output =
|
|
||||||
System::powershell_execute_and_capture_output("Detecting Visual Studio instances", script);
|
const auto& program_files_32_bit = System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO);
|
||||||
|
const fs::path vswhere_exe = program_files_32_bit / "Microsoft Visual Studio" / "Installer" / "vswhere.exe";
|
||||||
|
Checks::check_exit(
|
||||||
|
VCPKG_LINE_INFO, fs.exists(vswhere_exe), "Could not locate vswhere at %s", vswhere_exe.u8string());
|
||||||
|
|
||||||
|
const auto code_and_output = System::cmd_execute_and_capture_output(
|
||||||
|
Strings::format(R"("%s" -prerelease -legacy -products * -format xml)", vswhere_exe.u8string()));
|
||||||
|
|
||||||
const std::vector<std::string> instances_as_strings = keep_data_lines(output);
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO,
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
!instances_as_strings.empty(),
|
code_and_output.exit_code == 0,
|
||||||
"Could not detect any Visual Studio instances.\n"
|
"Running vswhere.exe failed with message:\n%s",
|
||||||
"Powershell script:\n"
|
code_and_output.output);
|
||||||
" %s\n"
|
|
||||||
"returned:\n"
|
const auto& xml_as_string = code_and_output.output;
|
||||||
"%s",
|
|
||||||
script.generic_string(),
|
const auto instance_entries = find_all_enclosed(xml_as_string, "<instance>", "</instance>");
|
||||||
output);
|
|
||||||
|
|
||||||
std::vector<VisualStudioInstance> instances;
|
std::vector<VisualStudioInstance> instances;
|
||||||
for (const std::string& instance_as_string : instances_as_strings)
|
for (const VcpkgStringRange& instance : instance_entries)
|
||||||
{
|
{
|
||||||
const std::vector<std::string> split = Strings::split(instance_as_string, "::");
|
auto maybe_is_prerelease = find_at_most_one_enclosed(instance, "<isPrerelease>", "</isPrerelease>");
|
||||||
Checks::check_exit(VCPKG_LINE_INFO,
|
|
||||||
split.size() == 4,
|
VisualStudioInstance::ReleaseType release_type = VisualStudioInstance::ReleaseType::LEGACY;
|
||||||
"Invalid Visual Studio instance format.\n"
|
if (auto p = maybe_is_prerelease.get())
|
||||||
"Expected: PreferenceWeight::ReleaseType::Version::PathToVisualStudio\n"
|
{
|
||||||
"Actual : %s\n",
|
auto s = p->to_string();
|
||||||
instance_as_string);
|
if (s == "0")
|
||||||
instances.push_back({split.at(3), split.at(2), split.at(1), split.at(0)});
|
release_type = VisualStudioInstance::ReleaseType::STABLE;
|
||||||
|
else if (s == "1")
|
||||||
|
release_type = VisualStudioInstance::ReleaseType::PRERELEASE;
|
||||||
|
else
|
||||||
|
Checks::unreachable(VCPKG_LINE_INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
instances.emplace_back(
|
||||||
|
find_exactly_one_enclosed(instance, "<installationPath>", "</installationPath>").to_string(),
|
||||||
|
find_exactly_one_enclosed(instance, "<installationVersion>", "</installationVersion>").to_string(),
|
||||||
|
release_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto append_if_has_cl = [&](fs::path&& path_root) {
|
||||||
|
const auto cl_exe = path_root / "VC" / "bin" / "cl.exe";
|
||||||
|
const auto vcvarsall_bat = path_root / "VC" / "vcvarsall.bat";
|
||||||
|
|
||||||
|
if (fs.exists(cl_exe) && fs.exists(vcvarsall_bat))
|
||||||
|
instances.emplace_back(std::move(path_root), "14.0", VisualStudioInstance::ReleaseType::LEGACY);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto maybe_vs140comntools = System::get_environment_variable("vs140comntools");
|
||||||
|
if (const auto path_as_string = maybe_vs140comntools.get())
|
||||||
|
{
|
||||||
|
// We want lexically_normal(), but it is not available
|
||||||
|
// Correct root path might be 2 or 3 levels up, depending on if the path has trailing backslash. Try both.
|
||||||
|
auto common7_tools = fs::path{*path_as_string};
|
||||||
|
append_if_has_cl(fs::path{*path_as_string}.parent_path().parent_path());
|
||||||
|
append_if_has_cl(fs::path{*path_as_string}.parent_path().parent_path().parent_path());
|
||||||
|
}
|
||||||
|
|
||||||
|
append_if_has_cl(program_files_32_bit / "Microsoft Visual Studio 14.0");
|
||||||
|
|
||||||
return instances;
|
return instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Toolset> find_toolset_instances(const VcpkgPaths& paths)
|
#if defined(_WIN32)
|
||||||
|
std::vector<Toolset> find_toolset_instances_prefered_first(const VcpkgPaths& paths)
|
||||||
{
|
{
|
||||||
using CPU = System::CPUArchitecture;
|
using CPU = System::CPUArchitecture;
|
||||||
|
|
||||||
@ -513,12 +759,14 @@ namespace vcpkg::Commands::Fetch
|
|||||||
std::vector<Toolset> found_toolsets;
|
std::vector<Toolset> found_toolsets;
|
||||||
std::vector<Toolset> excluded_toolsets;
|
std::vector<Toolset> excluded_toolsets;
|
||||||
|
|
||||||
const std::vector<VisualStudioInstance> vs_instances = get_visual_studio_instances(paths);
|
const SortedVector<VisualStudioInstance> sorted{get_visual_studio_instances(paths),
|
||||||
const bool v140_is_available = Util::find_if(vs_instances, [&](const VisualStudioInstance& vs_instance) {
|
VisualStudioInstance::prefered_first_comparator};
|
||||||
return vs_instance.major_version() == "14";
|
|
||||||
}) != vs_instances.cend();
|
|
||||||
|
|
||||||
for (const VisualStudioInstance& vs_instance : vs_instances)
|
const bool v140_is_available = Util::find_if(sorted, [&](const VisualStudioInstance& vs_instance) {
|
||||||
|
return vs_instance.major_version() == "14";
|
||||||
|
}) != sorted.end();
|
||||||
|
|
||||||
|
for (const VisualStudioInstance& vs_instance : sorted)
|
||||||
{
|
{
|
||||||
const std::string major_version = vs_instance.major_version();
|
const std::string major_version = vs_instance.major_version();
|
||||||
if (major_version == "15")
|
if (major_version == "15")
|
||||||
@ -672,6 +920,7 @@ namespace vcpkg::Commands::Fetch
|
|||||||
|
|
||||||
return found_toolsets;
|
return found_toolsets;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fs::path get_tool_path(const VcpkgPaths& paths, const std::string& tool)
|
fs::path get_tool_path(const VcpkgPaths& paths, const std::string& tool)
|
||||||
{
|
{
|
||||||
|
@ -154,10 +154,9 @@ namespace vcpkg::Commands::Hash
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type)
|
std::string get_file_hash(const Files::Filesystem& fs, const fs::path& path, const std::string& hash_type)
|
||||||
{
|
{
|
||||||
Checks::check_exit(
|
Checks::check_exit(VCPKG_LINE_INFO, fs.exists(path), "File %s does not exist", path.u8string());
|
||||||
VCPKG_LINE_INFO, paths.get_filesystem().exists(path), "File %s does not exist", path.u8string());
|
|
||||||
return BCryptHasher{hash_type}.hash_file(path);
|
return BCryptHasher{hash_type}.hash_file(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +238,7 @@ namespace vcpkg::Commands::Hash
|
|||||||
|
|
||||||
const fs::path file_to_hash = args.command_arguments[0];
|
const fs::path file_to_hash = args.command_arguments[0];
|
||||||
const std::string algorithm = args.command_arguments.size() == 2 ? args.command_arguments[1] : "SHA512";
|
const std::string algorithm = args.command_arguments.size() == 2 ? args.command_arguments[1] : "SHA512";
|
||||||
const std::string hash = get_file_hash(paths, file_to_hash, algorithm);
|
const std::string hash = get_file_hash(paths.get_filesystem(), file_to_hash, algorithm);
|
||||||
System::println(hash);
|
System::println(hash);
|
||||||
Checks::exit_success(VCPKG_LINE_INFO);
|
Checks::exit_success(VCPKG_LINE_INFO);
|
||||||
}
|
}
|
||||||
|
@ -227,8 +227,6 @@ namespace vcpkg::Export
|
|||||||
{fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"},
|
{fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"},
|
||||||
{fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"},
|
{fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"},
|
||||||
{fs::path{"scripts"} / "getWindowsSDK.ps1"},
|
{fs::path{"scripts"} / "getWindowsSDK.ps1"},
|
||||||
{fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"},
|
|
||||||
{fs::path{"scripts"} / "getProgramFiles32bit.ps1"},
|
|
||||||
{fs::path{"scripts"} / "VcpkgPowershellUtils.ps1"},
|
{fs::path{"scripts"} / "VcpkgPowershellUtils.ps1"},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ namespace vcpkg
|
|||||||
paths.triplets = paths.root / "triplets";
|
paths.triplets = paths.root / "triplets";
|
||||||
paths.scripts = paths.root / "scripts";
|
paths.scripts = paths.root / "scripts";
|
||||||
|
|
||||||
|
paths.tools = paths.downloads / "tools";
|
||||||
paths.buildsystems = paths.scripts / "buildsystems";
|
paths.buildsystems = paths.scripts / "buildsystems";
|
||||||
paths.buildsystems_msbuild_targets = paths.buildsystems / "msbuild" / "vcpkg.targets";
|
paths.buildsystems_msbuild_targets = paths.buildsystems / "msbuild" / "vcpkg.targets";
|
||||||
|
|
||||||
@ -113,9 +114,11 @@ namespace vcpkg
|
|||||||
return external_toolset;
|
return external_toolset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invariant: toolsets are non-empty and sorted with newest at back()
|
#if !defined(_WIN32)
|
||||||
|
Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot build windows triplets from non-windows.");
|
||||||
|
#else
|
||||||
const std::vector<Toolset>& vs_toolsets =
|
const std::vector<Toolset>& vs_toolsets =
|
||||||
this->toolsets.get_lazy([this]() { return Commands::Fetch::find_toolset_instances(*this); });
|
this->toolsets.get_lazy([this]() { return Commands::Fetch::find_toolset_instances_prefered_first(*this); });
|
||||||
|
|
||||||
std::vector<const Toolset*> candidates = Util::element_pointers(vs_toolsets);
|
std::vector<const Toolset*> candidates = Util::element_pointers(vs_toolsets);
|
||||||
const auto tsv = prebuildinfo.platform_toolset.get();
|
const auto tsv = prebuildinfo.platform_toolset.get();
|
||||||
@ -159,6 +162,8 @@ namespace vcpkg
|
|||||||
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO, !candidates.empty(), "No suitable Visual Studio instances were found");
|
Checks::check_exit(VCPKG_LINE_INFO, !candidates.empty(), "No suitable Visual Studio instances were found");
|
||||||
return *candidates.front();
|
return *candidates.front();
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); }
|
Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); }
|
||||||
|
@ -15,11 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{F589
|
|||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
..\scripts\bootstrap.ps1 = ..\scripts\bootstrap.ps1
|
..\scripts\bootstrap.ps1 = ..\scripts\bootstrap.ps1
|
||||||
..\scripts\fetchDependency.ps1 = ..\scripts\fetchDependency.ps1
|
..\scripts\fetchDependency.ps1 = ..\scripts\fetchDependency.ps1
|
||||||
..\scripts\findAnyMSBuildWithCppPlatformToolset.ps1 = ..\scripts\findAnyMSBuildWithCppPlatformToolset.ps1
|
..\scripts\getVisualStudioInstances.ps1 = ..\scripts\getVisualStudioInstances.ps1
|
||||||
..\scripts\findVisualStudioInstallationInstances.ps1 = ..\scripts\findVisualStudioInstallationInstances.ps1
|
|
||||||
..\scripts\get_triplet_environment.cmake = ..\scripts\get_triplet_environment.cmake
|
..\scripts\get_triplet_environment.cmake = ..\scripts\get_triplet_environment.cmake
|
||||||
..\scripts\getProgramFiles32bit.ps1 = ..\scripts\getProgramFiles32bit.ps1
|
|
||||||
..\scripts\getProgramFilesPlatformBitness.ps1 = ..\scripts\getProgramFilesPlatformBitness.ps1
|
|
||||||
..\scripts\getWindowsSDK.ps1 = ..\scripts\getWindowsSDK.ps1
|
..\scripts\getWindowsSDK.ps1 = ..\scripts\getWindowsSDK.ps1
|
||||||
..\scripts\internalCI.ps1 = ..\scripts\internalCI.ps1
|
..\scripts\internalCI.ps1 = ..\scripts\internalCI.ps1
|
||||||
..\scripts\ports.cmake = ..\scripts\ports.cmake
|
..\scripts\ports.cmake = ..\scripts\ports.cmake
|
||||||
|
Loading…
x
Reference in New Issue
Block a user