Skip to content

Commit 9b4fd54

Browse files
Ben HillisCopilot
andcommitted
setup-dev-env: prefer VS 2022, warn on VS 2026 fallback
Mirror CMakeLists.txt logic: query vswhere with [17.0,18.0) first for VS 2022, fall back to [18.0,19.0) for VS 2026 with a warning that clang-format output may differ from pipeline expectations. Component checks now run against the correct VS installation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a8ee043 commit 9b4fd54

File tree

1 file changed

+229
-0
lines changed

1 file changed

+229
-0
lines changed

tools/setup-dev-env.ps1

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
<#
2+
.SYNOPSIS
3+
Checks that all prerequisites for building WSL are installed.
4+
.DESCRIPTION
5+
Validates the development environment and reports missing tools
6+
with installation instructions. Run this before your first build.
7+
.EXAMPLE
8+
.\tools\setup-dev-env.ps1
9+
#>
10+
11+
Set-StrictMode -Version Latest
12+
$ErrorActionPreference = "Stop"
13+
14+
$script:Errors = 0
15+
$script:RepoRoot = (Resolve-Path "$PSScriptRoot\..").Path
16+
$script:VsConfigPath = Join-Path $script:RepoRoot ".vsconfig"
17+
$script:VsInstallFix = "Import .vsconfig via VS Installer -> More -> Import configuration, or: winget install Microsoft.VisualStudio.2022.Community --override ""--wait --quiet --config '$script:VsConfigPath'"""
18+
19+
function Check($Name, $Result, $Fix, [switch]$Optional)
20+
{
21+
if ($Result)
22+
{
23+
Write-Host " [OK] $Name" -ForegroundColor Green
24+
}
25+
elseif ($Optional)
26+
{
27+
Write-Host " [OPTIONAL] $Name" -ForegroundColor DarkYellow
28+
Write-Host " -> $Fix" -ForegroundColor Yellow
29+
}
30+
else
31+
{
32+
Write-Host " [MISSING] $Name" -ForegroundColor Red
33+
Write-Host " -> $Fix" -ForegroundColor Yellow
34+
$script:Errors++
35+
}
36+
}
37+
38+
Write-Host ""
39+
Write-Host "WSL Development Environment Check" -ForegroundColor Cyan
40+
Write-Host "==================================" -ForegroundColor Cyan
41+
Write-Host ""
42+
43+
# --- CMake ---
44+
Write-Host "Build Tools:" -ForegroundColor White
45+
$cmake = Get-Command "cmake" -ErrorAction SilentlyContinue
46+
$cmakeVersion = $null
47+
$cmakeOk = $false
48+
if ($cmake)
49+
{
50+
try
51+
{
52+
$cmakeVersion = [version]((cmake --version | Select-Object -First 1) -replace '[^0-9.]', '')
53+
$cmakeOk = $cmakeVersion -ge [version]"3.25"
54+
}
55+
catch
56+
{
57+
$cmakeVersion = $null
58+
$cmakeOk = $false
59+
}
60+
}
61+
Check "CMake >= 3.25$(if ($cmakeVersion) { " (found $cmakeVersion)" })" $cmakeOk "winget install Kitware.CMake"
62+
63+
# --- Visual Studio ---
64+
# Mirror CMakeLists.txt: prefer VS2022 [17.0,18.0) to keep clang-format
65+
# aligned with pipeline expectations. Fall back to VS2026 [18.0,19.0) with a warning.
66+
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
67+
$vsInstall = $null
68+
$vsVersion = $null
69+
$vsOk = $false
70+
$vsWarning = $null
71+
if (Test-Path $vswhere)
72+
{
73+
# Try VS2022 first
74+
$vsInstall = (& $vswhere -version "[17.0,18.0)" -products * -latest -property installationPath -prerelease 2>$null | Select-Object -First 1)
75+
$vsVersionText = (& $vswhere -version "[17.0,18.0)" -products * -latest -property installationVersion -prerelease 2>$null | Select-Object -First 1)
76+
77+
if (-not $vsInstall)
78+
{
79+
# Fall back to VS2026
80+
$vsInstall = (& $vswhere -version "[18.0,19.0)" -products * -latest -property installationPath -prerelease 2>$null | Select-Object -First 1)
81+
$vsVersionText = (& $vswhere -version "[18.0,19.0)" -products * -latest -property installationVersion -prerelease 2>$null | Select-Object -First 1)
82+
if ($vsInstall) { $vsWarning = "VS 2022 not found; using VS 2026. clang-format output may differ from pipeline expectations." }
83+
}
84+
85+
if ($vsInstall) { $vsInstall = $vsInstall.Trim() }
86+
if ($vsVersionText)
87+
{
88+
try
89+
{
90+
$vsVersion = [version]$vsVersionText.Trim()
91+
$vsOk = -not [string]::IsNullOrWhiteSpace($vsInstall)
92+
}
93+
catch {}
94+
}
95+
}
96+
Check "Visual Studio 2022+$(if ($vsVersion) { " (found $vsVersion)" })" $vsOk $script:VsInstallFix
97+
if ($vsWarning)
98+
{
99+
Write-Host " WARNING: $vsWarning" -ForegroundColor DarkYellow
100+
}
101+
102+
# --- VS Components (only check if VS 2022+ is found) ---
103+
if ($vsOk)
104+
{
105+
Write-Host ""
106+
Write-Host "Visual Studio Components:" -ForegroundColor White
107+
108+
# Check for specific required components via their markers
109+
$clangPath = Join-Path $vsInstall "VC\Tools\Llvm\*\bin\clang-format.exe"
110+
Check "C++ Clang Compiler for Windows" (Test-Path $clangPath) $script:VsInstallFix
111+
112+
$atlPath = Join-Path $vsInstall "VC\Tools\MSVC\*\atlmfc\include\atlbase.h"
113+
Check "C++ ATL for latest v143 tools" (Test-Path $atlPath) $script:VsInstallFix
114+
115+
$msbuild = Get-Command "msbuild" -ErrorAction SilentlyContinue
116+
if (-not $msbuild)
117+
{
118+
$msbuildPath = Join-Path $vsInstall "MSBuild\Current\Bin\MSBuild.exe"
119+
$msbuildAmd64 = Join-Path $vsInstall "MSBuild\Current\Bin\amd64\MSBuild.exe"
120+
$msbuild = (Test-Path $msbuildPath) -or (Test-Path $msbuildAmd64)
121+
}
122+
Check "MSBuild" ($null -ne $msbuild -and $msbuild) $script:VsInstallFix
123+
}
124+
125+
# --- Windows SDK ---
126+
Write-Host ""
127+
Write-Host "Windows SDK:" -ForegroundColor White
128+
$sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\10\Include\10.0.26100.0"
129+
Check "Windows SDK 26100" (Test-Path $sdkPath) $script:VsInstallFix
130+
131+
# --- NuGet Credential Provider (Azure DevOps feed) ---
132+
# nuget.exe resolves credential provider plugins using a priority chain:
133+
# 1. NUGET_NETFX_PLUGIN_PATHS (highest priority for standalone nuget.exe)
134+
# 2. NUGET_PLUGIN_PATHS (general override)
135+
# 3. %USERPROFILE%\.nuget\plugins\netfx\... (default)
136+
# If a higher-priority env var is set but points to a missing file, nuget.exe
137+
# fails even when the provider is installed at the default location.
138+
Write-Host ""
139+
Write-Host "NuGet:" -ForegroundColor White
140+
141+
$defaultNetfx = "${env:USERPROFILE}\.nuget\plugins\netfx\CredentialProvider.Microsoft\CredentialProvider.Microsoft.exe"
142+
143+
# Walk the priority chain to find the path nuget.exe will actually use.
144+
$effectivePath = $null
145+
$effectiveSource = $null
146+
foreach ($entry in @(
147+
@{ Var = "NUGET_NETFX_PLUGIN_PATHS"; Val = $env:NUGET_NETFX_PLUGIN_PATHS },
148+
@{ Var = "NUGET_PLUGIN_PATHS"; Val = $env:NUGET_PLUGIN_PATHS }
149+
))
150+
{
151+
if ($entry.Val)
152+
{
153+
$effectivePath = $entry.Val
154+
$effectiveSource = $entry.Var
155+
break
156+
}
157+
}
158+
if (-not $effectivePath)
159+
{
160+
$effectivePath = $defaultNetfx
161+
$effectiveSource = "default"
162+
}
163+
164+
$providerFound = Test-Path $effectivePath
165+
$label = "Azure Artifacts Credential Provider"
166+
if ($effectiveSource -ne "default")
167+
{
168+
$label += " (via $effectiveSource)"
169+
}
170+
171+
if ($providerFound)
172+
{
173+
Check $label $true ""
174+
}
175+
elseif ($effectiveSource -ne "default" -and (Test-Path $defaultNetfx))
176+
{
177+
# Provider is installed at the default location but an env var redirects
178+
# nuget.exe to a different path where it doesn't exist.
179+
$targetDir = Split-Path $effectivePath -Parent
180+
$sourceDir = Split-Path $defaultNetfx -Parent
181+
Check $label $false "New-Item -ItemType Directory -Force -Path '$targetDir' | Out-Null; Copy-Item '$sourceDir\*' '$targetDir' -Recurse -Force"
182+
}
183+
else
184+
{
185+
Check $label $false "See https://github.com/microsoft/artifacts-credprovider#installation"
186+
}
187+
188+
# --- Developer Mode / Symlinks ---
189+
Write-Host ""
190+
Write-Host "System Configuration:" -ForegroundColor White
191+
192+
$devMode = $false
193+
try
194+
{
195+
$devModeReg = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" -Name "AllowDevelopmentWithoutDevLicense" -ErrorAction SilentlyContinue
196+
$devMode = $devModeReg -and $devModeReg.AllowDevelopmentWithoutDevLicense -eq 1
197+
}
198+
catch {}
199+
200+
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
201+
Check "Developer Mode or Admin$(if ($devMode) { ' (Developer Mode)' } elseif ($isAdmin) { ' (Administrator)' })" ($devMode -or $isAdmin) "Settings -> System -> For developers -> Developer Mode"
202+
203+
# --- Optional tools ---
204+
Write-Host ""
205+
Write-Host "Optional Tools:" -ForegroundColor White
206+
207+
$windbg = Get-Command "WinDbgX.exe" -ErrorAction SilentlyContinue
208+
Check "WinDbg (for /attachdebugger)" ($null -ne $windbg) "winget install Microsoft.WinDbg" -Optional
209+
210+
$python = Get-Command "python3" -ErrorAction SilentlyContinue
211+
if (-not $python) { $python = Get-Command "python" -ErrorAction SilentlyContinue }
212+
Check "Python 3 (for validation scripts)" ($null -ne $python) "winget install Python.Python.3.13" -Optional
213+
214+
# --- Summary ---
215+
Write-Host ""
216+
if ($script:Errors -eq 0)
217+
{
218+
Write-Host "All prerequisites found. Ready to build!" -ForegroundColor Green
219+
Write-Host ""
220+
Write-Host " cmake ."
221+
Write-Host " cmake --build . -- -m"
222+
Write-Host ""
223+
}
224+
else
225+
{
226+
Write-Host "$($script:Errors) prerequisite(s) missing. Install them and re-run this script." -ForegroundColor Red
227+
Write-Host ""
228+
exit 1
229+
}

0 commit comments

Comments
 (0)