Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions Build/Agent/FwBuildEnvironment.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,70 @@
# VS Environment Functions
# =============================================================================

function Get-PreferredVcToolBinPath {
<#
.SYNOPSIS
Returns the preferred HostX64\x64 MSVC tool bin directory.
#>
if (-not $env:VCINSTALLDIR) {
return $null
}

$toolsRoot = Join-Path $env:VCINSTALLDIR 'Tools\MSVC'
if (-not (Test-Path $toolsRoot)) {
return $null
}

$versionSort = {
$parsedVersion = [version]'0.0'
$isVersion = [version]::TryParse($_.Name, [ref]$parsedVersion)
if ($isVersion) {
return $parsedVersion
}

return [version]'0.0'
}

$sortProperties = @(
@{ Expression = {
$parsedVersion = [version]'0.0'
[version]::TryParse($_.Name, [ref]$parsedVersion)
}; Descending = $true }
@{ Expression = $versionSort; Descending = $true }
@{ Expression = { $_.Name }; Descending = $true }
)

$preferred = Get-ChildItem -Path $toolsRoot -Directory -ErrorAction SilentlyContinue |
Sort-Object -Property $sortProperties |
ForEach-Object { Join-Path $_.FullName 'bin\HostX64\x64' } |
Where-Object { Test-Path $_ } |
Select-Object -First 1

return $preferred
}

function Ensure-PreferredVcToolPath {
<#
.SYNOPSIS
Moves the preferred HostX64\x64 MSVC bin directory to the front of PATH.
#>
$preferred = Get-PreferredVcToolBinPath
if (-not $preferred) {
return
}

$pathEntries = @()
if (-not [string]::IsNullOrWhiteSpace($env:PATH)) {
$pathEntries = $env:PATH -split ';' | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
}

$filteredEntries = $pathEntries | Where-Object {
-not [string]::Equals($_.TrimEnd('\'), $preferred.TrimEnd('\'), [System.StringComparison]::OrdinalIgnoreCase)
}

$env:PATH = (@($preferred) + $filteredEntries) -join ';'
}

function Initialize-VsDevEnvironment {
<#
.SYNOPSIS
Expand All @@ -27,6 +91,7 @@ function Initialize-VsDevEnvironment {
}

if ($env:VCINSTALLDIR) {
Ensure-PreferredVcToolPath
Write-Host '[OK] Visual Studio environment already initialized' -ForegroundColor Green
return
}
Expand Down Expand Up @@ -87,6 +152,8 @@ function Initialize-VsDevEnvironment {
throw 'Visual Studio C++ environment not configured'
}

Ensure-PreferredVcToolPath

Write-Host '[OK] Visual Studio environment initialized successfully' -ForegroundColor Green
Write-Host " VCINSTALLDIR: $env:VCINSTALLDIR" -ForegroundColor Gray
}
Expand Down
10 changes: 8 additions & 2 deletions Build/Agent/Verify-FwDependencies.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
.DESCRIPTION
Checks for required tools and SDKs needed to build FieldWorks.
Can be run locally for testing or called from GitHub Actions workflows.
By default, the script writes host output only and does not emit result objects.
Use -PassThru when a caller needs structured results returned on the pipeline.

Expected dependencies (typically pre-installed on windows-latest):
- Visual Studio 2022 with Desktop & C++ workloads
Expand All @@ -24,7 +26,8 @@
If specified, prints the full per-dependency section headers and success details instead of the compact summary-only output.

.PARAMETER PassThru
If specified, returns the dependency result objects for scripting callers instead of writing them implicitly.
If specified, returns the dependency result objects for scripting callers.
Without -PassThru, the script is quiet-by-default and writes host output only.

.EXAMPLE
# Quick check
Expand All @@ -45,6 +48,9 @@
.EXAMPLE
# Capture structured results for automation
$results = .\Build\Agent\Verify-FwDependencies.ps1 -IncludeOptional -PassThru

.NOTES
Behavioral change: this script no longer emits dependency result objects unless -PassThru is specified.
#>

[CmdletBinding()]
Expand Down Expand Up @@ -217,7 +223,7 @@ $results += Test-Dependency -Name "WiX Toolset (v6 via NuGet)" -Required "Option
throw "Installer project not found: $wixProj"
}

[xml]$wixProjXml = Get-Content -LiteralPath $wixProj
[xml]$wixProjXml = Get-Content -LiteralPath $wixProj -Raw
$projectNode = $wixProjXml.Project
$hasWixSdk = $false

Expand Down
72 changes: 71 additions & 1 deletion Build/Src/FwBuildTasks/Make.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,62 @@ protected override string ToolName
}
}

private static string FindVisualStudioToolPath(string vcInstallDir, string toolName)
{
if (String.IsNullOrEmpty(vcInstallDir) || !Directory.Exists(vcInstallDir))
return null;

string toolsRoot = Path.Combine(vcInstallDir, "Tools", "MSVC");
if (!Directory.Exists(toolsRoot))
return null;

string[] versionDirs = Directory.GetDirectories(toolsRoot);
Array.Sort(versionDirs, CompareVersionDirectories);

foreach (string versionDir in versionDirs)
{
string[] candidateDirs =
{
Path.Combine(versionDir, "bin", "Hostx64", "x64"),
Path.Combine(versionDir, "bin", "Hostx64", "x86"),
Path.Combine(versionDir, "bin", "Hostx86", "x86"),
Path.Combine(versionDir, "bin", "Hostx86", "x64")
};

foreach (string candidateDir in candidateDirs)
{
if (File.Exists(Path.Combine(candidateDir, toolName)))
return candidateDir;
}
}

return null;
}

private static int CompareVersionDirectories(string left, string right)
{
string leftName = Path.GetFileName(left);
string rightName = Path.GetFileName(right);

Version leftVersion;
Version rightVersion;
bool leftIsVersion = Version.TryParse(leftName, out leftVersion);
bool rightIsVersion = Version.TryParse(rightName, out rightVersion);

if (leftIsVersion && rightIsVersion)
{
int versionComparison = rightVersion.CompareTo(leftVersion);
if (versionComparison != 0)
return versionComparison;
}
else if (leftIsVersion != rightIsVersion)
{
return rightIsVersion.CompareTo(leftIsVersion);
}

return StringComparer.OrdinalIgnoreCase.Compare(rightName, leftName);
}

private void CheckToolPath()
{
string path = Environment.GetEnvironmentVariable("PATH");
Expand Down Expand Up @@ -140,7 +196,21 @@ private void CheckToolPath()
// Fall Back to the install directory (if VCINSTALLDIR is set)
if (!String.IsNullOrEmpty(vcInstallDir))
{
ToolPath = Path.Combine(vcInstallDir, "bin");
string visualStudioToolPath = FindVisualStudioToolPath(vcInstallDir, ToolName);
if (!String.IsNullOrEmpty(visualStudioToolPath))
{
ToolPath = visualStudioToolPath;
return;
}

string legacyToolPath = Path.Combine(vcInstallDir, "bin");
if (File.Exists(Path.Combine(legacyToolPath, ToolName)))
{
ToolPath = legacyToolPath;
return;
}

ToolPath = String.Empty;
}
else
{
Expand Down
Loading