Files
windows-collect-dependencies/collect.ps1
T

170 lines
3.8 KiB
PowerShell

param(
[Parameter(Mandatory = $true)]
[string]$Executable,
[Parameter(Mandatory = $false)]
[string]$Output = "artifacts"
)
$ErrorActionPreference = "Stop"
if (-not (Test-Path $Executable)) {
throw "Executable does not exist: $Executable"
}
New-Item -ItemType Directory -Force -Path $Output | Out-Null
$vswherePath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
if (-not (Test-Path $vswherePath)) {
throw "Could not locate vswhere.exe. Verify that Visual Studio or Visual Studio Build Tools is installed."
}
$visualStudioPath = & $vswherePath `
-latest `
-products * `
-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
-property installationPath
if (-not $visualStudioPath) {
throw "Could not locate a Visual Studio installation with the MSVC C++ tools installed."
}
$toolsetVersionPath = Join-Path `
$visualStudioPath `
"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"
if (-not (Test-Path $toolsetVersionPath)) {
throw "Could not locate the MSVC toolset version file."
}
$toolsetVersion = (Get-Content $toolsetVersionPath -Raw).Trim()
$dumpbinPath = Join-Path `
$visualStudioPath `
"VC\Tools\MSVC\$toolsetVersion\bin\Hostx64\x64\dumpbin.exe"
if (-not (Test-Path $dumpbinPath)) {
throw "Could not locate dumpbin.exe at: $dumpbinPath"
}
Write-Host "Using dumpbin: $dumpbinPath"
$windowsDirectories = @(
$env:WINDIR,
(Join-Path $env:WINDIR "System32"),
(Join-Path $env:WINDIR "SysWOW64")
)
$windowsKitsDirectories = @(
"${env:ProgramFiles(x86)}\Windows Kits",
"$env:ProgramFiles\Windows Kits"
) | Where-Object {
$_ -and (Test-Path $_)
}
$processed = @{}
function Test-IsWindowsSystemDll {
param(
[string]$Name
)
if ($Name -like "api-ms-win-*.dll") {
return $true
}
foreach ($directory in $windowsDirectories) {
$path = Join-Path $directory $Name
if (Test-Path $path) {
return $true
}
}
foreach ($directory in $windowsKitsDirectories) {
$match = Get-ChildItem `
-Path $directory `
-Filter $Name `
-File `
-Recurse `
-ErrorAction SilentlyContinue |
Select-Object -First 1
if ($match) {
return $true
}
}
return $false
}
function Find-Dependency {
param(
[string]$Name,
[string]$BinaryDirectory
)
$localPath = Join-Path $BinaryDirectory $Name
if (Test-Path $localPath) {
return $localPath
}
$command = Get-Command $Name -ErrorAction SilentlyContinue
if ($command) {
return $command.Source
}
return $null
}
function Copy-Dependencies {
param(
[string]$Binary
)
$binaryDirectory = Split-Path -Parent $Binary
$dependencies = & $dumpbinPath /DEPENDENTS $Binary |
Select-String '^\s+.*\.dll$' |
ForEach-Object { $_.Line.Trim() } |
Sort-Object -Unique
foreach ($dll in $dependencies) {
$key = $dll.ToLowerInvariant()
if ($processed.ContainsKey($key)) {
continue
}
$processed[$key] = $true
if (Test-IsWindowsSystemDll $dll) {
Write-Host "Skipping Windows system dependency: $dll"
continue
}
$source = Find-Dependency `
-Name $dll `
-BinaryDirectory $binaryDirectory
if (-not $source) {
Write-Warning "Could not locate dependency: $dll"
continue
}
$destination = Join-Path $Output (Split-Path -Leaf $source)
if (-not (Test-Path $destination)) {
Write-Host "Copying dependency: $source"
Copy-Item $source $destination -Force
}
Copy-Dependencies -Binary $source
}
}
Copy-Dependencies -Binary $Executable