diff options
| author | 5an7y <[email protected]> | 2026-06-23 10:38:40 -0700 |
|---|---|---|
| committer | 5an7y <[email protected]> | 2026-06-23 10:38:40 -0700 |
| commit | ceceab78412feefd2f343a0e3bc07f1262665b62 (patch) | |
| tree | 046ae1a9f147f5be0fec14f8cd7b9c97a8791296 | |
| parent | be91bbd2dc4478a57a4007fc32fe320da79f85e1 (diff) | |
Auto-discover _NT_TARGET_VERSION; remove the TargetVersion axis
- Remove the -TargetVersion parameter and all its plumbing from Build-Samples.ps1 (restoring
the original hard-coded -p:TargetVersion=Windows10), and drop the TargetVersions column from
exclusions.csv and Import-SampleExclusions. Only _NT_TARGET_VERSION remains exposed.
- Add Get-NtTargetVersions.ps1, which auto-discovers the valid _NT_TARGET_VERSION values (and
their NTDDI codes) by parsing the active WDK's DriverGeneral.xml rule. Build-Samples.ps1 uses
it to validate -NtTargetVersion, default to the latest, and map to the msbuild code, so a new
WDK version needs no script change (accepts '10.0.<build>' or the short '<build>' tag).
- CI: ci.yml and ci-pr.yml gain a 'discover' job that emits the newest-N versions as JSON; the
build matrix consumes it via fromJSON, so there is no hand-maintained version list anywhere.
Build-ChangedSamples.ps1 treats Get-NtTargetVersions.ps1 as a full-build trigger.
- Docs updated accordingly.
Co-authored-by: Copilot <[email protected]>
| -rw-r--r-- | .github/scripts/Build-ChangedSamples.ps1 | 2 | ||||
| -rw-r--r-- | .github/workflows/ci-pr.yml | 33 | ||||
| -rw-r--r-- | .github/workflows/ci.yml | 33 | ||||
| -rw-r--r-- | Build-Samples.ps1 | 112 | ||||
| -rw-r--r-- | Building-Locally.md | 55 | ||||
| -rw-r--r-- | Get-NtTargetVersions.ps1 | 100 | ||||
| -rw-r--r-- | exclusions.csv | 40 |
7 files changed, 235 insertions, 140 deletions
diff --git a/.github/scripts/Build-ChangedSamples.ps1 b/.github/scripts/Build-ChangedSamples.ps1 index 3e91eb88..f03f93f3 100644 --- a/.github/scripts/Build-ChangedSamples.ps1 +++ b/.github/scripts/Build-ChangedSamples.ps1 @@ -22,7 +22,7 @@ foreach ($file in $ChangedFiles) { $filename = Split-Path $file -Leaf # Files that can affect how every sample is built should trigger a full build - if ($filename -eq "Build-Samples.ps1" -or $filename -eq "exclusions.csv" -or $filename -eq "Directory.Build.props" -or $filename -eq "packages.config") { + if ($filename -eq "Build-Samples.ps1" -or $filename -eq "Get-NtTargetVersions.ps1" -or $filename -eq "exclusions.csv" -or $filename -eq "Directory.Build.props" -or $filename -eq "packages.config") { $buildAll = $true } if ($dir -like "$root\.github\scripts" -or $dir -like "$root\.github\scripts\*") { diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml index 7983c8dd..8119c94c 100644 --- a/.github/workflows/ci-pr.yml +++ b/.github/workflows/ci-pr.yml @@ -8,20 +8,39 @@ on: - '**.md' - 'LICENSE' jobs: + # Auto-discover the available _NT_TARGET_VERSION values from the active WDK so the build + # matrix never needs a hand-maintained version list. Change -Newest to build more/fewer. + discover: + name: discover _NT_TARGET_VERSIONs + runs-on: windows-2025-vs2026 + outputs: + versions: ${{ steps.nt.outputs.versions }} + steps: + - name: Check out repository code + uses: actions/checkout@v4 + + - name: Install Nuget Packages + run: nuget restore .\packages.config -PackagesDirectory .\packages\ + + - name: Discover the newest _NT_TARGET_VERSION values + id: nt + shell: pwsh + run: | + $json = .\Get-NtTargetVersions.ps1 -Newest 4 -AsMatrixJson + "versions=$json" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 + Write-Host "Discovered _NT_TARGET_VERSION matrix: $json" + build: name: build ${{ matrix.nt.tag }} ${{ matrix.configuration }} ${{ matrix.platform }} + needs: discover strategy: fail-fast: false matrix: configuration: [Debug, Release] platform: [x64, arm64] - # _NT_TARGET_VERSION = the WDK library version drivers link against (newest first). - # Each { version, tag } runs as its own parallel job; trim this list to reduce CI load. - nt: - - { version: '10.0.28000', tag: '28000' } - - { version: '10.0.26100', tag: '26100' } - - { version: '10.0.22621', tag: '22621' } - - { version: '10.0.22000', tag: '22000' } + # _NT_TARGET_VERSION values are auto-discovered by the 'discover' job from the active + # WDK, so there is no version list to maintain here. + nt: ${{ fromJSON(needs.discover.outputs.versions) }} runs-on: windows-2025-vs2026 steps: - name: Check out repository code diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 022ae4f6..de856d55 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,20 +11,39 @@ on: # Runs every Saturday at 00:00 PST (08:00 UTC) - cron: '0 8 * * 6' jobs: + # Auto-discover the available _NT_TARGET_VERSION values from the active WDK so the build + # matrix never needs a hand-maintained version list. Change -Newest to build more/fewer. + discover: + name: discover _NT_TARGET_VERSIONs + runs-on: windows-2025-vs2026 + outputs: + versions: ${{ steps.nt.outputs.versions }} + steps: + - name: Check out repository code + uses: actions/checkout@v4 + + - name: Install Nuget Packages + run: nuget restore .\packages.config -PackagesDirectory .\packages\ + + - name: Discover the newest _NT_TARGET_VERSION values + id: nt + shell: pwsh + run: | + $json = .\Get-NtTargetVersions.ps1 -Newest 4 -AsMatrixJson + "versions=$json" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 + Write-Host "Discovered _NT_TARGET_VERSION matrix: $json" + build: name: build ${{ matrix.nt.tag }} ${{ matrix.configuration }} ${{ matrix.platform }} + needs: discover strategy: fail-fast: false matrix: configuration: [Debug, Release] platform: [x64, arm64] - # _NT_TARGET_VERSION = the WDK library version drivers link against (newest first). - # Each { version, tag } runs as its own parallel job; trim this list to reduce CI load. - nt: - - { version: '10.0.28000', tag: '28000' } - - { version: '10.0.26100', tag: '26100' } - - { version: '10.0.22621', tag: '22621' } - - { version: '10.0.22000', tag: '22000' } + # _NT_TARGET_VERSION values are auto-discovered by the 'discover' job from the active + # WDK, so there is no version list to maintain here. + nt: ${{ fromJSON(needs.discover.outputs.versions) }} runs-on: windows-2025-vs2026 steps: - name: Check out repository code diff --git a/Build-Samples.ps1 b/Build-Samples.ps1 index c58164b2..861ec39a 100644 --- a/Build-Samples.ps1 +++ b/Build-Samples.ps1 @@ -27,21 +27,13 @@ .PARAMETER Platforms Build platforms (e.g. 'x64','arm64'). Defaults to $env:WDS_Platform or ('x64','arm64'). -.PARAMETER TargetVersion - Target OS version the drivers are built for (the msbuild 'TargetVersion' property). - Valid values are defined by the WDK DriverGeneral.xml rule and are listed newest-first: - Windows10 - Windows 10 or higher (default, latest) - WindowsV6.3 - Windows 8.1 - Windows8 - Windows 8 - Windows7 - Windows 7 - Defaults to $env:WDS_TargetVersion, or 'Windows10' (the latest) when unset. - .PARAMETER NtTargetVersion The _NT_TARGET_VERSION value - the WDK library version the driver links against - ("OS version of libraries"), which is independent of the Target OS Version. Accepts the - Windows build-number form (e.g. '10.0.28000'); valid values come from the WDK - DriverGeneral.xml rule and are listed newest-first. Defaults to $env:WDS_NtTargetVersion, - or '10.0.28000' (the latest) when unset. + ("OS version of libraries"). Accepts the Windows build-number form '10.0.<build>' or the + short '<build>' tag (e.g. '10.0.28000' or '28000'). The valid values are auto-discovered + from the active WDK's DriverGeneral.xml rule (see Get-NtTargetVersions.ps1), so a new WDK + version is picked up with no script change. Defaults to $env:WDS_NtTargetVersion, or the + latest discovered version when unset. .PARAMETER LogFilesDirectory Directory for build log files. Defaults to _logs in the current directory. @@ -87,9 +79,9 @@ Forces WDK mode regardless of environment variables. .EXAMPLE - .\Build-Samples -TargetVersion Windows7 + .\Build-Samples -NtTargetVersion 10.0.22000 - Builds all samples targeting Windows 7 instead of the default (latest) Windows10. + Builds all samples linking against the 10.0.22000 library set instead of the latest. #> #Requires -Version 7.0 @@ -99,13 +91,9 @@ param( [string[]]$Samples, [string[]]$Configurations = @(if ([string]::IsNullOrEmpty($env:WDS_Configuration)) { ('Debug', 'Release') } else { $env:WDS_Configuration }), [string[]]$Platforms = @(if ([string]::IsNullOrEmpty($env:WDS_Platform)) { ('x64', 'arm64') } else { $env:WDS_Platform }), - # Valid TargetVersion values come from the WDK DriverGeneral.xml rule (newest first). - [ValidateSet('Windows10', 'WindowsV6.3', 'Windows8', 'Windows7')] - [string]$TargetVersion = $(if ([string]::IsNullOrEmpty($env:WDS_TargetVersion)) { 'Windows10' } else { $env:WDS_TargetVersion }), - # _NT_TARGET_VERSION = the WDK library version the driver links against (newest first; - # values come from the WDK DriverGeneral.xml rule). Default is the latest. - [ValidateSet('10.0.28000', '10.0.26100', '10.0.22621', '10.0.22000', '10.0.20348', '10.0.19041', '10.0.18362', '10.0.17763', '10.0.17134', '10.0.16299', '10.0.15063', '10.0.14393', '10.0.10586', '10.0.10240')] - [string]$NtTargetVersion = $(if ([string]::IsNullOrEmpty($env:WDS_NtTargetVersion)) { '10.0.28000' } else { $env:WDS_NtTargetVersion }), + # _NT_TARGET_VERSION = the WDK library version the driver links against. Valid values are + # auto-discovered from the WDK (Get-NtTargetVersions.ps1); empty = the latest discovered. + [string]$NtTargetVersion = $env:WDS_NtTargetVersion, [string]$LogFilesDirectory = (Join-Path (Get-Location) "_logs"), [string]$ReportFileName = $(if ([string]::IsNullOrEmpty($env:WDS_ReportFileName)) { "_overview" } else { $env:WDS_ReportFileName }), [string]$InfOptions, @@ -131,24 +119,18 @@ function Import-SampleExclusions { - Reason: human-readable explanation A row is only returned when ALL of the following match the current build: - - its [MinBuild, MaxBuild] range includes the given build number, + - its [MinBuild, MaxBuild] range includes the given build number, and - its [MinNtTargetVersion, MaxNtTargetVersion] range includes the current - _NT_TARGET_VERSION build number (e.g. 22000 parsed from '10.0.22000'), and - - its TargetVersions list matches the given TargetVersion. TargetVersions is - blank/'*' for all versions, or a ';'-separated list of -like patterns - (e.g. 'Windows8', 'Windows7;Windows8', 'Windows*'). - Rows outside any range, or whose TargetVersions does not match, are skipped. - MinBuild/MaxBuild and MinNtTargetVersion/MaxNtTargetVersion are blank = unbounded. + _NT_TARGET_VERSION build number (e.g. 22000 parsed from '10.0.22000'). + Rows outside either range are skipped; blank range bounds mean unbounded. .NOTES - CSV format: Path,Configurations,TargetVersions,MinBuild,MaxBuild,MinNtTargetVersion,MaxNtTargetVersion,Reason - Example row: network\wlan\wdi,*,,,27100,,,"failure introduced in VS17.14" - Target-specific: somepath,*|ARM64,Windows8,,,,,"ARM not supported when targeting Windows 8" - NT-version-specific: somepath,*,,,,,22621,"needs an API newer than the 10.0.22621 library" + CSV format: Path,Configurations,MinBuild,MaxBuild,MinNtTargetVersion,MaxNtTargetVersion,Reason + Example row: network\wlan\wdi,*,26100,,,,"failure introduced in VS17.14" + NT-version-specific: somepath,*,,,,22621,"needs an API newer than the 10.0.22621 library" #> param( [string]$CsvPath, [int]$BuildNumber, - [string]$TargetVersion = 'Windows10', [string]$NtTargetVersion = '10.0.28000' ) @@ -165,22 +147,15 @@ function Import-SampleExclusions { Import-Csv $CsvPath | ForEach-Object { $pattern = $_.Path.Trim('\').Replace('\', '.').ToLower() $configs = if ([string]::IsNullOrWhiteSpace($_.Configurations)) { '*' } else { $_.Configurations } - # TargetVersions column is optional; blank or missing means "all target versions". - $targets = if ([string]::IsNullOrWhiteSpace($_.TargetVersions)) { '*' } else { $_.TargetVersions } $minBuild = if ([string]::IsNullOrWhiteSpace($_.MinBuild)) { 0 } else { [int]$_.MinBuild } $maxBuild = if ([string]::IsNullOrWhiteSpace($_.MaxBuild)) { 99999 } else { [int]$_.MaxBuild } # Min/MaxNtTargetVersion columns are optional; blank or missing means "all NT versions". $minNt = if ([string]::IsNullOrWhiteSpace($_.MinNtTargetVersion)) { 0 } else { [int]$_.MinNtTargetVersion } $maxNt = if ([string]::IsNullOrWhiteSpace($_.MaxNtTargetVersion)) { 9999999 } else { [int]$_.MaxNtTargetVersion } - # TargetVersion and _NT_TARGET_VERSION are constant for the whole run, so (like the - # build number) filter these rows out here at load time. - $targetMatches = $targets.Split(';') | Where-Object { $TargetVersion -like $_.Trim() } - - if (-not $targetMatches) { - Write-Verbose "Exclusion skipped: '$pattern' - target '$TargetVersion' not in '$targets'" - } - elseif ($ntBuild -lt $minNt -or $ntBuild -gt $maxNt) { + # _NT_TARGET_VERSION is constant for the whole run, so (like the build number) filter + # these rows out here at load time. + if ($ntBuild -lt $minNt -or $ntBuild -gt $maxNt) { Write-Verbose "Exclusion skipped: '$pattern' - _NT_TARGET_VERSION $ntBuild outside [$minNt, $maxNt]" } elseif ($minBuild -le $BuildNumber -and $BuildNumber -le $maxBuild) { @@ -189,7 +164,7 @@ function Import-SampleExclusions { Configurations = $configs Reason = $_.Reason }) - Write-Verbose "Exclusion applied: '$pattern' configs='$configs' targets='$targets' ntRange=[$minNt,$maxNt] reason='$($_.Reason)'" + Write-Verbose "Exclusion applied: '$pattern' configs='$configs' ntRange=[$minNt,$maxNt] reason='$($_.Reason)'" } else { Write-Verbose "Exclusion skipped: '$pattern' - build $BuildNumber outside [$minBuild, $maxBuild]" @@ -230,7 +205,6 @@ function Build-SingleSample { [string]$SampleName, [string]$Configuration = 'Debug', [string]$Platform = 'x64', - [string]$TargetVersion = 'Windows10', [string]$NtTargetVersionCode = '0xA000012', [string]$InfVerif_AdditionalOptions = '/samples', [string]$LogFilesDirectory = (Get-Location), @@ -308,7 +282,7 @@ function Build-SingleSample { -clp:Verbosity=m -t:rebuild ` -property:Configuration=$Configuration ` -property:Platform=$Platform ` - -p:TargetVersion=$TargetVersion ` + -p:TargetVersion=Windows10 ` -p:_NT_TARGET_VERSION=$NtTargetVersionCode ` -p:InfVerif_AdditionalOptions="$InfVerif_AdditionalOptions" ` -warnaserror ` @@ -454,26 +428,36 @@ else { } # ============================================================================= -# Step 5b - Resolve _NT_TARGET_VERSION code +# Step 5b - Resolve _NT_TARGET_VERSION # ============================================================================= # -# _NT_TARGET_VERSION selects the WDK library version the driver links against -# (independent of the Target OS Version). The MSBuild property takes the NTDDI hex -# code, so map the friendly build number to it. Codes come from WDK DriverGeneral.xml. -$ntTargetVersionCodes = [ordered]@{ - '10.0.28000' = '0xA000012'; '10.0.26100' = '0xA000010'; '10.0.22621' = '0xA00000C' - '10.0.22000' = '0xA00000B'; '10.0.20348' = '0xA00000A'; '10.0.19041' = '0xA000008' - '10.0.18362' = '0xA000007'; '10.0.17763' = '0xA000006'; '10.0.17134' = '0xA000005' - '10.0.16299' = '0xA000004'; '10.0.15063' = '0xA000003'; '10.0.14393' = '0xA000002' - '10.0.10586' = '0xA000001'; '10.0.10240' = '0x0A00' +# _NT_TARGET_VERSION selects the WDK library version the driver links against. The valid +# values (and their NTDDI codes) are auto-discovered from the active WDK by +# Get-NtTargetVersions.ps1, so nothing here needs updating when a new WDK version ships. +# msbuild takes the NTDDI code. +$ntVersions = & (Join-Path $PSScriptRoot 'Get-NtTargetVersions.ps1') +if (-not $ntVersions) { + Write-Error "Could not discover any _NT_TARGET_VERSION values from the active WDK." + exit 1 +} +if ([string]::IsNullOrWhiteSpace($NtTargetVersion) -or $NtTargetVersion -eq 'latest') { + $ntSelected = $ntVersions[0] # newest +} +else { + $ntSelected = $ntVersions | Where-Object { $_.Version -eq $NtTargetVersion -or $_.Tag -eq $NtTargetVersion } | Select-Object -First 1 + if (-not $ntSelected) { + Write-Error "Invalid -NtTargetVersion '$NtTargetVersion'. Valid values: $(($ntVersions.Version) -join ', ')" + exit 1 + } } -$ntTargetVersionCode = $ntTargetVersionCodes[$NtTargetVersion] +$NtTargetVersion = $ntSelected.Version +$ntTargetVersionCode = $ntSelected.Code # ============================================================================= # Step 6 - Load Exclusions # ============================================================================= -$exclusions = Import-SampleExclusions -CsvPath (Join-Path $root 'exclusions.csv') -BuildNumber $buildNumber -TargetVersion $TargetVersion -NtTargetVersion $NtTargetVersion +$exclusions = Import-SampleExclusions -CsvPath (Join-Path $root 'exclusions.csv') -BuildNumber $buildNumber -NtTargetVersion $NtTargetVersion # ============================================================================= # Step 7 - Print Build Plan @@ -494,7 +478,6 @@ Write-Output "" Write-Output " Samples: $($sampleSet.Count) ($skippedCount skipped)" Write-Output " Configurations: $($Configurations -join ', ')" Write-Output " Platforms: $($Platforms -join ', ')" -Write-Output " Target Version: $TargetVersion" Write-Output " NT Target Ver: $NtTargetVersion ($ntTargetVersionCode)" Write-Output " Combinations: $combinationsTotal" Write-Output " Exclusions: $($exclusions.Count)" @@ -542,7 +525,6 @@ $sampleSet.GetEnumerator() | ForEach-Object -ThrottleLimit $ThrottleLimit -Paral $configs = $using:Configurations $platforms = $using:Platforms $infOpts = $using:infVerifOptions - $targetVer = $using:TargetVersion $ntCode = $using:ntTargetVersionCode $isVerbose = $using:verbose $state = $using:buildState @@ -594,8 +576,7 @@ $sampleSet.GetEnumerator() | ForEach-Object -ThrottleLimit $ThrottleLimit -Paral $buildResult = Build-SingleSample ` -Directory $directory -SampleName $sampleName ` -LogFilesDirectory $logDir -Configuration $configuration ` - -Platform $platform -TargetVersion $targetVer ` - -NtTargetVersionCode $ntCode ` + -Platform $platform -NtTargetVersionCode $ntCode ` -InfVerif_AdditionalOptions $infOpts ` -Verbose:$isVerbose @@ -714,7 +695,6 @@ Write-Output "" Write-Output " Samples: $($sampleSet.Count)" Write-Output " Configurations: $($Configurations -join ', ')" Write-Output " Platforms: $($Platforms -join ', ')" -Write-Output " Target Version: $TargetVersion" Write-Output " NT Target Ver: $NtTargetVersion ($ntTargetVersionCode)" Write-Output " Combinations: $combinationsTotal" Write-Output "" @@ -735,7 +715,7 @@ Write-Output "------------------------------------------------------------------ $sortedResults = $buildState.Results | Sort-Object { $_.Sample } $sortedResults | ConvertTo-Csv | Out-File $reportCsvPath -$sortedResults | ConvertTo-Html -Title "WDK Sample Build Overview - TargetVersion $TargetVersion, _NT_TARGET_VERSION $NtTargetVersion" | Out-File $reportHtmlPath +$sortedResults | ConvertTo-Html -Title "WDK Sample Build Overview - _NT_TARGET_VERSION $NtTargetVersion" | Out-File $reportHtmlPath # Only open the HTML report interactively (not in CI/automation) if (-not $env:BUILD_BUILDID -and [Environment]::UserInteractive) { @@ -755,7 +735,7 @@ if ($env:GITHUB_STEP_SUMMARY) { $md = [System.Text.StringBuilder]::new() [void]$md.AppendLine("## $icon ``$cfgLabel`` · _NT_TARGET_VERSION ``$NtTargetVersion``") [void]$md.AppendLine() - [void]$md.AppendLine("Environment **$($buildEnv.Name)** · WDK build **$buildNumber** · TargetVersion **$TargetVersion** · **$($sampleSet.Count)** samples · $($elapsed.Minutes)m $($elapsed.Seconds)s") + [void]$md.AppendLine("Environment **$($buildEnv.Name)** · WDK build **$buildNumber** · **$($sampleSet.Count)** samples · $($elapsed.Minutes)m $($elapsed.Seconds)s") [void]$md.AppendLine() [void]$md.AppendLine("| :white_check_mark: Succeeded | :x: Failed | :warning: Sporadic | :heavy_minus_sign: Excluded | :grey_question: Unsupported |") [void]$md.AppendLine("|---:|---:|---:|---:|---:|") diff --git a/Building-Locally.md b/Building-Locally.md index 8c11d012..ebddbfba 100644 --- a/Building-Locally.md +++ b/Building-Locally.md @@ -121,36 +121,20 @@ Get-Help .\Build-Samples.ps1 -Detailed # Build a specific sample for Debug|x64 only: .\Build-Samples.ps1 -Samples 'tools.sdv.samples.sampledriver' -Configurations 'Debug' -Platforms 'x64' -# Build every sample targeting an older OS version (default is the latest, Windows10): -.\Build-Samples.ps1 -TargetVersion Windows7 - # Build every sample linking against an older WDK library set (default is the latest): .\Build-Samples.ps1 -NtTargetVersion 10.0.22000 ``` -The `-TargetVersion` values come from the WDK `DriverGeneral.xml` rule and are listed -newest-first. The default is the latest, `Windows10`: - -| Value | Target OS | -| ------------- | ---------------------- | -| `Windows10` | Windows 10 or higher (default) | -| `WindowsV6.3` | Windows 8.1 | -| `Windows8` | Windows 8 | -| `Windows7` | Windows 7 | - -`-TargetVersion` (Target OS Version) selects the driver's *platform model* and is gated to -Windows 10+ for Universal / Windows Driver samples. To instead vary the **library version the -driver links against** - the WDK's `_NT_TARGET_VERSION` ("OS version of libraries") - while -keeping the platform on Windows 10, use `-NtTargetVersion`. It accepts a Windows build number; -values come from the WDK `DriverGeneral.xml` rule (newest-first), default latest `10.0.28000`: +`-NtTargetVersion` selects the WDK **`_NT_TARGET_VERSION`** — the OS version of the libraries +the driver links against. It accepts the Windows build number (`10.0.<build>`) or the short +`<build>` tag (e.g. `10.0.22000` or `22000`); when omitted it uses the latest. The valid +values are **auto-discovered from the active WDK** — `Get-NtTargetVersions.ps1` parses the +WDK's `DriverGeneral.xml` rule — so a new WDK version is picked up automatically with no edits. +List what's available with: -| `-NtTargetVersion` | Links against | -| ------------------ | ----------------- | -| `10.0.28000` | latest (default) | -| `10.0.26100` | 24H2 | -| `10.0.22621` | 22H2 | -| `10.0.22000` | 21H2 | -| ... | down to `10.0.10240` | +```powershell +.\Get-NtTargetVersions.ps1 +``` --- @@ -159,36 +143,29 @@ values come from the WDK `DriverGeneral.xml` rule (newest-first), default latest Samples that are known not to build for a given environment are listed in `exclusions.csv` at the repo root. Each row excludes a path (with wildcards) for specific configuration/platform combinations, an optional WDK build-number range, and an optional -set of target versions: +`_NT_TARGET_VERSION` range: ``` -Path,Configurations,TargetVersions,MinBuild,MaxBuild,MinNtTargetVersion,MaxNtTargetVersion,Reason +Path,Configurations,MinBuild,MaxBuild,MinNtTargetVersion,MaxNtTargetVersion,Reason ``` | Column | Meaning | | ---------------- | ---------------------------------------------------------------------------------------- | | `Path` | Sample path (backslashes); supports `*`/`?` wildcards. | | `Configurations` | `;`-separated `Config\|Platform` patterns, or `*` for all (e.g. `*\|ARM64`, `Debug\|x64`). | -| `TargetVersions` | `;`-separated `-like` patterns matched against `-TargetVersion`; blank or `*` = all (e.g. `Windows8`, `Windows7;Windows8`, `Windows*`). | | `MinBuild`/`MaxBuild` | Inclusive WDK build-number range; blank = unbounded. | | `MinNtTargetVersion`/`MaxNtTargetVersion` | Inclusive `-NtTargetVersion` build-number range (e.g. `22621` matches `10.0.22621`); blank = unbounded. Use this for samples that fail only when linking against older libraries. | | `Reason` | Human-readable explanation (keep this column last; quote it if it contains commas). | A row is applied only when every populated condition matches the current run (path, -configuration/platform, WDK build-number range, NT target-version range, and target version -are AND-ed together). Leave a column blank to ignore that dimension (the default for most rows). - -For example, to exclude all ARM platforms only when building for Windows 8: - -``` -somepath,*|ARM64,Windows8,,,,,"ARM not supported when targeting Windows 8" -``` +configuration/platform, WDK build-number range, and NT target-version range are AND-ed +together). Leave a column blank to ignore that dimension (the default for most rows). -Or to exclude a sample (Debug builds only) when linking against the `10.0.22621` library set -or older, because it uses a newer API: +For example, to exclude a sample (Debug builds only) when linking against the `10.0.22621` +library set or older, because it uses a newer API: ``` -somepath,Debug|*,,,,,22621,uses an API newer than the 10.0.22621 library +somepath,Debug|*,,,,22621,uses an API newer than the 10.0.22621 library ``` --- diff --git a/Get-NtTargetVersions.ps1 b/Get-NtTargetVersions.ps1 new file mode 100644 index 00000000..68088277 --- /dev/null +++ b/Get-NtTargetVersions.ps1 @@ -0,0 +1,100 @@ +<# +.SYNOPSIS + Auto-discovers the valid _NT_TARGET_VERSION values from the active WDK. + +.DESCRIPTION + The _NT_TARGET_VERSION property (the OS version of the libraries a driver links against) + is an enumeration defined by the WDK in its 'DriverGeneral.xml' rule file. This script + locates that rule file (from the restored NuGet packages, or the installed WDK) and parses + the enumeration so that nothing in the build needs a hard-coded version list: when a new + WDK adds a new _NT_TARGET_VERSION it is picked up automatically. + + Returns one object per Windows 10/11 entry, newest-first: + Version e.g. 10.0.28000 (use with -NtTargetVersion) + Tag e.g. 28000 (short, filename/CI-friendly) + Code e.g. 0xA000012 (the NTDDI value passed to msbuild) + Build e.g. 28000 (numeric, for sorting/ranges) + +.PARAMETER XmlPath + Optional explicit path to a DriverGeneral.xml. When omitted the newest available rule file + is auto-located. + +.PARAMETER Newest + Return only the newest N versions (0 = all). Useful for bounding the CI build matrix. + +.PARAMETER AsMatrixJson + Emit a compact JSON array of { version, tag } objects for a GitHub Actions matrix + (consumed via fromJSON). Implies a single-line output. + +.EXAMPLE + .\Get-NtTargetVersions.ps1 # all discovered versions (objects) + +.EXAMPLE + .\Get-NtTargetVersions.ps1 -Newest 4 -AsMatrixJson +#> +[CmdletBinding()] +param( + [string]$XmlPath, + [int]$Newest = 0, + [switch]$AsMatrixJson +) + +function Find-DriverGeneralXml { + # Prefer the restored NuGet WDK package (matches what the build actually uses), then the + # installed WDK. Within each source, pick the highest build version. + $candidates = @() + $candidates += Get-ChildItem -Path (Join-Path $PSScriptRoot 'packages') -Recurse -Filter 'DriverGeneral.xml' -ErrorAction SilentlyContinue + foreach ($kitsRoot in @("${env:ProgramFiles(x86)}\Windows Kits\10\build", "${env:ProgramFiles}\Windows Kits\10\build")) { + if ($kitsRoot -and (Test-Path $kitsRoot)) { + $candidates += Get-ChildItem -Path $kitsRoot -Recurse -Filter 'DriverGeneral.xml' -ErrorAction SilentlyContinue + } + } + # EWDK / arbitrary build environments expose the build tree via these variables. + foreach ($envRoot in @($env:WDKContentRoot, $env:WindowsSdkDir)) { + if ($envRoot -and (Test-Path $envRoot)) { + $buildDir = Join-Path $envRoot 'build' + if (Test-Path $buildDir) { + $candidates += Get-ChildItem -Path $buildDir -Recurse -Filter 'DriverGeneral.xml' -ErrorAction SilentlyContinue + } + } + } + if (-not $candidates) { return $null } + # Order by the build version embedded in the path (e.g. ...\10.0.28000.0\...), highest first. + return ($candidates | Sort-Object { + if ($_.FullName -match '10\.0\.(\d+)\.\d') { [int]$Matches[1] } else { 0 } + } -Descending | Select-Object -First 1).FullName +} + +if (-not $XmlPath) { $XmlPath = Find-DriverGeneralXml } +if (-not $XmlPath -or -not (Test-Path $XmlPath)) { + throw "Could not locate DriverGeneral.xml. Restore the WDK NuGet packages or install the WDK, or pass -XmlPath." +} + +[xml]$xml = Get-Content -Path $XmlPath -Raw +$enum = $xml.ProjectSchemaDefinitions.Rule.EnumProperty | Where-Object { $_.Name -eq '_NT_TARGET_VERSION' } +if (-not $enum) { throw "No _NT_TARGET_VERSION enumeration found in '$XmlPath'." } + +$versions = + $enum.EnumValue | + ForEach-Object { + # DisplayName is e.g. "Windows 10.0.28000"; Name is the NTDDI code e.g. "0xA000012". + if ("$($_.DisplayName)" -match 'Windows\s+(?<v>10\.0\.(?<b>\d+))\s*$') { + [pscustomobject]@{ + Version = $Matches.v + Tag = $Matches.b + Code = $_.Name + Build = [int]$Matches.b + } + } + } | + Sort-Object Build -Descending + +if ($Newest -gt 0) { $versions = $versions | Select-Object -First $Newest } + +if ($AsMatrixJson) { + # Compact, single-line JSON for a GitHub Actions matrix: [{ "version": "...", "tag": "..." }, ...] + $matrix = @($versions | ForEach-Object { [ordered]@{ version = $_.Version; tag = $_.Tag } }) + return ($matrix | ConvertTo-Json -Compress -Depth 3) +} + +return $versions diff --git a/exclusions.csv b/exclusions.csv index 566c685d..0cae0380 100644 --- a/exclusions.csv +++ b/exclusions.csv @@ -1,20 +1,20 @@ -Path,Configurations,TargetVersions,MinBuild,MaxBuild,MinNtTargetVersion,MaxNtTargetVersion,Reason -audio\acx\samples\audiocodec\driver,*,,,22621,,,Only NI: error C1083: Cannot open include file: 'acx.h': No such file or directory -general\dchu\osrfx2_dchu_extension_loose,*|x64,,,22621,,,Only NI: Only x64: Fails to build -general\dchu\osrfx2_dchu_extension_tight,*|x64,,,22621,,,Only NI: Only x64: Fails to build -network\trans\WFPSampler,Debug|ARM64,,,22621,,,Only NI: Only ARM: Fails to build on EWDK 22621 with VS 17.1.5 - CallingConvention=StdCall not supported -prm,*,,,22621,,,Only NI: Not supported on NI. -powerlimit\plclient,*,,,22621,,,Only NI: Not supported on NI. -powerlimit\plpolicy,*,,,22621,,,Only NI: Not supported on NI. -general\pcidrv,*,,26100,,,,"failure introduced in VS17.14, suppressed until fix" -serial\serial,*,,26100,,,,"failure introduced in VS17.14, suppressed until fix" -network\wlan\wdi,*,,26100,,,,"failure introduced in VS17.14, suppressed until fix" -tools\kasan\samples\kasandemo-wdm,*|x64,,26100,,,,"failure introduced in VS17.14, suppressed until fix" -audio\sysvad,*,,,,,22000,_NT_TARGET_VERSION: KSJACK_DESCRIPTION3 undeclared; audio jack descriptor v3 was added in 22H2 (10.0.22621) -network\netadaptercx\netvadapter,*,,,,,22621,_NT_TARGET_VERSION: requests an NDIS/DDI version newer than the linked library (C1189 wrong NDIS or DDI version) -network\wlan\wificx,*,,,,,22621,_NT_TARGET_VERSION: requests an NDIS/DDI version newer than the linked library (C1189 wrong NDIS or DDI version) -powerlimit\plclient,*,,,,,22621,_NT_TARGET_VERSION: POWER_LIMIT_ATTRIBUTES not declared in the older library (C2061) -powerlimit\plpolicy,*,,,,,22621,_NT_TARGET_VERSION: POWER_LIMIT_ATTRIBUTES not declared in the older library (C2061) -storage\class\classpnp,Debug|*,,,,,22621,_NT_TARGET_VERSION: STOR_ADDRESS_TYPE_NVME undeclared in the older library (C2065); Debug only -storage\miniports\storahci,Debug|*,,,,,22621,_NT_TARGET_VERSION: STOR_ADDRESS_TYPE_NVME undeclared in the older library (C2065); Debug only -storage\msdsm,Debug|x64,,,,,22621,_NT_TARGET_VERSION: STOR_ADDRESS_TYPE_NVME undeclared in the older library (C2065); Debug|x64 only +Path,Configurations,MinBuild,MaxBuild,MinNtTargetVersion,MaxNtTargetVersion,Reason +audio\acx\samples\audiocodec\driver,*,,22621,,,Only NI: error C1083: Cannot open include file: 'acx.h': No such file or directory +general\dchu\osrfx2_dchu_extension_loose,*|x64,,22621,,,Only NI: Only x64: Fails to build +general\dchu\osrfx2_dchu_extension_tight,*|x64,,22621,,,Only NI: Only x64: Fails to build +network\trans\WFPSampler,Debug|ARM64,,22621,,,Only NI: Only ARM: Fails to build on EWDK 22621 with VS 17.1.5 - CallingConvention=StdCall not supported +prm,*,,22621,,,Only NI: Not supported on NI. +powerlimit\plclient,*,,22621,,,Only NI: Not supported on NI. +powerlimit\plpolicy,*,,22621,,,Only NI: Not supported on NI. +general\pcidrv,*,26100,,,,"failure introduced in VS17.14, suppressed until fix" +serial\serial,*,26100,,,,"failure introduced in VS17.14, suppressed until fix" +network\wlan\wdi,*,26100,,,,"failure introduced in VS17.14, suppressed until fix" +tools\kasan\samples\kasandemo-wdm,*|x64,26100,,,,"failure introduced in VS17.14, suppressed until fix" +audio\sysvad,*,,,,22000,_NT_TARGET_VERSION: KSJACK_DESCRIPTION3 undeclared; audio jack descriptor v3 was added in 22H2 (10.0.22621) +network\netadaptercx\netvadapter,*,,,,22621,_NT_TARGET_VERSION: requests an NDIS/DDI version newer than the linked library (C1189 wrong NDIS or DDI version) +network\wlan\wificx,*,,,,22621,_NT_TARGET_VERSION: requests an NDIS/DDI version newer than the linked library (C1189 wrong NDIS or DDI version) +powerlimit\plclient,*,,,,22621,_NT_TARGET_VERSION: POWER_LIMIT_ATTRIBUTES not declared in the older library (C2061) +powerlimit\plpolicy,*,,,,22621,_NT_TARGET_VERSION: POWER_LIMIT_ATTRIBUTES not declared in the older library (C2061) +storage\class\classpnp,Debug|*,,,,22621,_NT_TARGET_VERSION: STOR_ADDRESS_TYPE_NVME undeclared in the older library (C2065); Debug only +storage\miniports\storahci,Debug|*,,,,22621,_NT_TARGET_VERSION: STOR_ADDRESS_TYPE_NVME undeclared in the older library (C2065); Debug only +storage\msdsm,Debug|x64,,,,22621,_NT_TARGET_VERSION: STOR_ADDRESS_TYPE_NVME undeclared in the older library (C2065); Debug|x64 only |
