Skip to content

Commit 376f89c

Browse files
authored
fix: used installed Windows SDKs instead of hardcoded version (#417)
1 parent f779706 commit 376f89c

File tree

8 files changed

+194
-35
lines changed

8 files changed

+194
-35
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ jobs:
381381
with: {
382382
'swift-version': 'latest',
383383
'check-latest': '${{ needs.ci.outputs.check_latest }}',
384-
'visual-studio-components': 'Microsoft.VisualStudio.Component.Windows11SDK.22000'
384+
'visual-studio-components': '${{ matrix.os }}'.includes('arm') ? 'Microsoft.VisualStudio.Component.Windows11SDK.22000' : ''
385385
}
386386
}
387387
]

__tests__/installer/windows.test.ts

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as path from 'path'
2-
import {promises as fs} from 'fs'
2+
import {Dirent, promises as fs} from 'fs'
33
import * as core from '@actions/core'
44
import * as exec from '@actions/exec'
55
import * as cache from '@actions/cache'
@@ -57,7 +57,9 @@ describe('windows toolchain installation verification', () => {
5757
'Microsoft.VisualStudio.Component.VC.ATL;Microsoft.VisualStudio.Component.VC.CMake.Project;Microsoft.VisualStudio.Component.Windows10SDK'
5858
)
5959
const installer = new WindowsToolchainInstaller(toolchain)
60-
expect(installer['vsRequirement']('x86_64').components).toStrictEqual([
60+
expect(
61+
(await installer['vsRequirement']('x86_64')).components
62+
).toStrictEqual([
6163
'Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
6264
'Microsoft.VisualStudio.Component.VC.ATL',
6365
'Microsoft.VisualStudio.Component.VC.CMake.Project',
@@ -69,7 +71,9 @@ describe('windows toolchain installation verification', () => {
6971
it('tests setting up on Windows 10', async () => {
7072
jest.spyOn(os, 'release').mockReturnValue('10.0.17063')
7173
const installer = new WindowsToolchainInstaller(toolchain)
72-
expect(installer['vsRequirement']('x86_64').components).toStrictEqual([
74+
expect(
75+
(await installer['vsRequirement']('x86_64')).components
76+
).toStrictEqual([
7377
'Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
7478
'Microsoft.VisualStudio.Component.Windows10SDK.17763'
7579
])
@@ -78,7 +82,9 @@ describe('windows toolchain installation verification', () => {
7882
it('tests setting up on ARM64 Windows 10', async () => {
7983
jest.spyOn(os, 'release').mockReturnValue('10.0.17063')
8084
const installer = new WindowsToolchainInstaller(toolchain)
81-
expect(installer['vsRequirement']('arm64').components).toStrictEqual([
85+
expect(
86+
(await installer['vsRequirement']('arm64')).components
87+
).toStrictEqual([
8288
'Microsoft.VisualStudio.Component.VC.Tools.ARM64',
8389
'Microsoft.VisualStudio.Component.Windows10SDK.17763'
8490
])
@@ -87,7 +93,9 @@ describe('windows toolchain installation verification', () => {
8793
it('tests setting up on Windows 11', async () => {
8894
jest.spyOn(os, 'release').mockReturnValue('10.0.22621')
8995
const installer = new WindowsToolchainInstaller(toolchain)
90-
expect(installer['vsRequirement']('x86_64').components).toStrictEqual([
96+
expect(
97+
(await installer['vsRequirement']('x86_64')).components
98+
).toStrictEqual([
9199
'Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
92100
'Microsoft.VisualStudio.Component.Windows11SDK.22621'
93101
])
@@ -99,7 +107,9 @@ describe('windows toolchain installation verification', () => {
99107
.spyOn(core, 'getInput')
100108
.mockReturnValue('Microsoft.VisualStudio.Component.Windows11SDK.22621')
101109
const installer = new WindowsToolchainInstaller(toolchain)
102-
expect(installer['vsRequirement']('x86_64').components).toStrictEqual([
110+
expect(
111+
(await installer['vsRequirement']('x86_64')).components
112+
).toStrictEqual([
103113
'Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
104114
'Microsoft.VisualStudio.Component.Windows11SDK.22621'
105115
])
@@ -118,12 +128,45 @@ describe('windows toolchain installation verification', () => {
118128
preventCaching: false
119129
}
120130
const installer = new WindowsToolchainInstaller(toolchain)
121-
expect(installer['vsRequirement']('arm64').components).toStrictEqual([
131+
expect(
132+
(await installer['vsRequirement']('arm64')).components
133+
).toStrictEqual([
122134
'Microsoft.VisualStudio.Component.VC.Tools.ARM64',
123135
'Microsoft.VisualStudio.Component.Windows11SDK.22000'
124136
])
125137
})
126138

139+
it('tests setting up on Windows 10 with Windows 11 SDK with unavailable recommended SDK', async () => {
140+
jest.spyOn(os, 'release').mockReturnValue('10.0.17063')
141+
jest.spyOn(fs, 'readdir').mockResolvedValue([
142+
{
143+
name: 'wdf',
144+
isDirectory: () => true
145+
} as unknown as Dirent,
146+
{
147+
name: '10.0.22621.0',
148+
isDirectory: () => true
149+
} as unknown as Dirent
150+
])
151+
const toolchain = {
152+
name: 'Windows 10 Swift Development Snapshot',
153+
date: new Date('2025-04-03 10:10:00-06:00'),
154+
download: 'swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a-windows10.exe',
155+
dir: 'swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a',
156+
platform: 'windows10',
157+
branch: 'development',
158+
windows: true,
159+
preventCaching: false
160+
}
161+
const installer = new WindowsToolchainInstaller(toolchain)
162+
expect(
163+
(await installer['vsRequirement']('arm64')).components
164+
).toStrictEqual([
165+
'Microsoft.VisualStudio.Component.VC.Tools.ARM64',
166+
'Microsoft.VisualStudio.Component.Windows11SDK.22621'
167+
])
168+
})
169+
127170
it('tests download without caching', async () => {
128171
const installer = new WindowsToolchainInstaller(toolchain)
129172
expect(installer['version']).toStrictEqual(parseSemVer('5.8'))

dist/index.js

Lines changed: 91 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"ci"
2828
],
2929
"scripts": {
30-
"prepare": "npm run build && node -e \"require('./.github/utils/update_metadata').fetch()\"",
30+
"prepare": "node -e \"require('./.github/utils/update_metadata').fetch()\" && npm run build",
3131
"build": "tsc",
3232
"format": "prettier --write \"**/*.ts\"",
3333
"lint": "depcheck --ignores ts-node,ts-jest,globals,@eslint/js,@eslint/eslintrc && eslint src/**/*.ts && prettier --check \"**/*.ts\"",

src/installer/windows/index.ts

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,46 @@ import * as semver from 'semver'
66
import {VerifyingToolchainInstaller} from '../verify'
77
import {WindowsToolchainSnapshot} from '../../snapshot'
88
import {VisualStudio, VISUAL_STUDIO_WINSDK_COMPONENT_REGEX} from '../../utils'
9+
import {program86} from '../../utils/windows'
910
import {Installation, CustomInstallation} from './installation'
1011

1112
export class WindowsToolchainInstaller extends VerifyingToolchainInstaller<WindowsToolchainSnapshot> {
12-
private get winsdk() {
13+
private async winsdk() {
1314
const win11Semver = '10.0.22000'
1415
const recommended = semver.gte(this.version ?? '6.2.0', '6.2.0')
1516
? win11Semver
1617
: '10.0.17763'
1718
const current = os.release()
18-
const version = semver.gte(current, recommended) ? current : recommended
19+
let version = semver.gte(current, recommended) ? current : recommended
20+
const insatlled = await this.insatlledSdks()
21+
if (insatlled.length && !insatlled.includes(version)) {
22+
version = insatlled[0]
23+
}
24+
1925
const major = semver.lt(version, win11Semver) ? semver.major(version) : 11
2026
const minor = semver.patch(version)
2127
return `Microsoft.VisualStudio.Component.Windows${major}SDK.${minor}`
2228
}
2329

24-
private vsRequirement(arch: string) {
30+
private async insatlledSdks() {
31+
const sdksPath = path.join(program86(), 'Windows Kits', '10', 'Include')
32+
try {
33+
const dirs = await fs.readdir(sdksPath, {withFileTypes: true})
34+
return dirs
35+
.filter(dirent => dirent.isDirectory())
36+
.map(dirent => {
37+
const parts = dirent.name.split('.')
38+
return parts.length >= 3 ? parts.slice(0, 3).join('.') : dirent.name
39+
})
40+
.filter(version => semver.valid(version))
41+
.sort(semver.rcompare)
42+
} catch (error) {
43+
core.warning(`Unable to get installed SDKs due to: "${error}"`)
44+
return []
45+
}
46+
}
47+
48+
private async vsRequirement(arch: string) {
2549
const componentsStr = core.getInput('visual-studio-components')
2650
const providedComponents = componentsStr ? componentsStr.split(';') : []
2751
const winsdkComponent = providedComponents.find(component => {
@@ -47,7 +71,7 @@ export class WindowsToolchainInstaller extends VerifyingToolchainInstaller<Windo
4771
...providedComponents
4872
]
4973
if (!winsdkComponent) {
50-
vsComponents.push(this.winsdk)
74+
vsComponents.push(await this.winsdk())
5175
}
5276
return {
5377
version: '16',
@@ -61,7 +85,7 @@ export class WindowsToolchainInstaller extends VerifyingToolchainInstaller<Windo
6185
`Using VS requirement ${JSON.stringify(this.vsRequirement(arch))}`
6286
)
6387
const [, toolchain] = await Promise.all([
64-
VisualStudio.setup(this.vsRequirement(arch)),
88+
VisualStudio.setup(await this.vsRequirement(arch)),
6589
super.download(arch)
6690
])
6791
const exeFile = `${toolchain}.exe`
@@ -114,7 +138,9 @@ export class WindowsToolchainInstaller extends VerifyingToolchainInstaller<Windo
114138
return
115139
}
116140

117-
const visualStudio = await VisualStudio.setup(this.vsRequirement(arch))
141+
const visualStudio = await VisualStudio.setup(
142+
await this.vsRequirement(arch)
143+
)
118144
await visualStudio.update(sdkroot)
119145
const swiftFlags = [
120146
'-sdk',

0 commit comments

Comments
 (0)