diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index caa155e..52883cc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -379,7 +379,8 @@ jobs: uses: `${repo}@${branch}`, with: { 'swift-version': 'latest', - 'check-latest': '${{ needs.ci.outputs.check_latest }}' + 'check-latest': '${{ needs.ci.outputs.check_latest }}', + 'visual-studio-components': 'Microsoft.VisualStudio.Component.Windows11SDK.22621' } } ] diff --git a/__tests__/installer/windows.test.ts b/__tests__/installer/windows.test.ts index 8ac0c13..087aab2 100644 --- a/__tests__/installer/windows.test.ts +++ b/__tests__/installer/windows.test.ts @@ -28,7 +28,11 @@ describe('windows toolchain installation verification', () => { catalog: {productDisplayVersion: '17'}, properties: { setupEngineFilePath: path.join('C:', 'Visual Studio', 'setup.exe') - } + }, + components: [ + 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + 'Microsoft.VisualStudio.Component.Windows11SDK.22621' + ] }) const vsEnvs = [ `UniversalCRTSdkDir=${path.join('C:', 'Windows Kits')}`, @@ -46,16 +50,19 @@ describe('windows toolchain installation verification', () => { }) it('tests adding additional components', async () => { + jest.spyOn(os, 'release').mockReturnValue('10.0.17063') jest .spyOn(core, 'getInput') .mockReturnValue( 'Microsoft.VisualStudio.Component.VC.ATL;Microsoft.VisualStudio.Component.VC.CMake.Project;Microsoft.VisualStudio.Component.Windows10SDK' ) const installer = new WindowsToolchainInstaller(toolchain) - expect(installer['vsRequirement'].components.slice(2)).toStrictEqual([ + expect(installer['vsRequirement'].components).toStrictEqual([ + 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', 'Microsoft.VisualStudio.Component.VC.ATL', 'Microsoft.VisualStudio.Component.VC.CMake.Project', - 'Microsoft.VisualStudio.Component.Windows10SDK' + 'Microsoft.VisualStudio.Component.Windows10SDK', + 'Microsoft.VisualStudio.Component.Windows10SDK.17763' ]) }) @@ -77,6 +84,18 @@ describe('windows toolchain installation verification', () => { ]) }) + it('tests setting up on Windows 11 with custom SDK', async () => { + jest.spyOn(os, 'release').mockReturnValue('10.0.26100') + jest + .spyOn(core, 'getInput') + .mockReturnValue('Microsoft.VisualStudio.Component.Windows11SDK.22621') + const installer = new WindowsToolchainInstaller(toolchain) + expect(installer['vsRequirement'].components).toStrictEqual([ + 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + 'Microsoft.VisualStudio.Component.Windows11SDK.22621' + ]) + }) + it('tests download without caching', async () => { const installer = new WindowsToolchainInstaller(toolchain) expect(installer['version']).toStrictEqual(parseSemVer('5.8')) @@ -181,7 +200,7 @@ describe('windows toolchain installation verification', () => { .mockResolvedValue() await installer['add']('') expect(setupSpy).toHaveBeenCalled() - expect(updateSpy).toHaveBeenCalledWith('root', true) + expect(updateSpy).toHaveBeenCalledWith('root') }) it('tests unpack for failed path matching without additional module setup', async () => { @@ -231,7 +250,7 @@ describe('windows toolchain installation verification', () => { .mockResolvedValue() await installer['add']('') expect(setupSpy).toHaveBeenCalled() - expect(updateSpy).toHaveBeenCalledWith('root', false) + expect(updateSpy).toHaveBeenCalledWith('root') }) it('tests add to PATH', async () => { diff --git a/__tests__/utils/visual_studio/setup.test.ts b/__tests__/utils/visual_studio/setup.test.ts index 555fbdd..fb1783b 100644 --- a/__tests__/utils/visual_studio/setup.test.ts +++ b/__tests__/utils/visual_studio/setup.test.ts @@ -1,5 +1,6 @@ import * as path from 'path' import {promises as fs} from 'fs' +import os from 'os' import * as exec from '@actions/exec' import {VisualStudio} from '../../../src/utils/visual_studio' @@ -11,7 +12,11 @@ describe('visual studio setup validation', () => { catalog: {productDisplayVersion: '17'}, properties: { setupEngineFilePath: path.join('C:', 'Visual Studio', 'setup.exe') - } + }, + components: [ + 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + 'Microsoft.VisualStudio.Component.Windows11SDK.22621' + ] }) beforeEach(() => { @@ -33,7 +38,7 @@ describe('visual studio setup validation', () => { stderr: '' }) await expect( - VisualStudio.setup({version: '16', components: ['Component']}) + VisualStudio.setup({version: '16', components: visualStudio.components}) ).rejects.toMatchObject( new Error( `Unable to find any Visual Studio installation for version: 16.` @@ -51,7 +56,35 @@ describe('visual studio setup validation', () => { stderr: '' }) await expect( - VisualStudio.setup({version: '16', components: ['Component']}) + VisualStudio.setup({version: '16', components: visualStudio.components}) ).resolves.toMatchObject(visualStudio) }) + + it('tests visual studio environment setup', async () => { + jest.spyOn(os, 'arch').mockReturnValue('x64') + const execSpy = jest.spyOn(exec, 'getExecOutput').mockResolvedValue({ + exitCode: 0, + stdout: '', + stderr: '' + }) + await visualStudio.env() + const arg = execSpy.mock.calls.at(0) + expect(arg).toBeTruthy() + expect(arg?.[0]).toBe('cmd') + expect(arg?.[1]).toStrictEqual([ + '/k', + path.join( + visualStudio.installationPath, + 'Common7', + 'Tools', + 'VsDevCmd.bat' + ), + '-arch=x64', + '-winsdk=10.0.22621.0', + '&&', + 'set', + '&&', + 'exit' + ]) + }) }) diff --git a/dist/index.js b/dist/index.js index 0fb934a..e393be3 100644 --- a/dist/index.js +++ b/dist/index.js @@ -512,14 +512,20 @@ class WindowsToolchainInstaller extends verify_1.VerifyingToolchainInstaller { get vsRequirement() { const componentsStr = core.getInput('visual-studio-components'); const providedComponents = componentsStr ? componentsStr.split(';') : []; + const winsdkComponent = providedComponents.find(component => { + return ((utils_1.VISUAL_STUDIO_WINSDK_COMPONENT_REGEX.exec(component)?.length ?? 0) > 1); + }); + const vsComponents = [ + 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + ...providedComponents + ]; + if (!winsdkComponent) { + vsComponents.push(this.winsdk); + } return { version: '16', swift: this.version, - components: [ - 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', - this.winsdk, - ...providedComponents - ] + components: vsComponents }; } async download() { @@ -574,7 +580,7 @@ class WindowsToolchainInstaller extends verify_1.VerifyingToolchainInstaller { return; } const visualStudio = await utils_1.VisualStudio.setup(this.vsRequirement); - await visualStudio.update(sdkroot, !this.version || semver.lt(this.version, '6.0.0')); + await visualStudio.update(sdkroot); const swiftFlags = [ '-sdk', sdkroot, @@ -2106,32 +2112,48 @@ var __importStar = (this && this.__importStar) || (function () { }; })(); Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.VisualStudio = void 0; +exports.VisualStudio = exports.VISUAL_STUDIO_WINSDK_COMPONENT_REGEX = void 0; const os = __importStar(__nccwpck_require__(857)); const path = __importStar(__nccwpck_require__(6928)); const exec_1 = __nccwpck_require__(5236); +exports.VISUAL_STUDIO_WINSDK_COMPONENT_REGEX = /Microsoft\.VisualStudio\.Component\.Windows[0-9]+SDK\.([0-9]+)/; class VisualStudio { installationPath; installationVersion; catalog; properties; - constructor(installationPath, installationVersion, catalog, properties) { + components; + constructor(installationPath, installationVersion, catalog, properties, components) { this.installationPath = installationPath; this.installationVersion = installationVersion; this.catalog = catalog; this.properties = properties; + this.components = components; } // eslint-disable-next-line @typescript-eslint/no-explicit-any static createFromJSON(json) { - return new VisualStudio(json.installationPath, json.installationVersion, json.catalog, json.properties); + return new VisualStudio(json.installationPath, json.installationVersion, json.catalog, json.properties, json.components); } async env() { /// https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-170 const nativeToolsScriptx86 = path.join(this.installationPath, 'Common7', 'Tools', 'VsDevCmd.bat'); + const args = []; + const sdkComponentMatch = this.components + .map(component => { + return exports.VISUAL_STUDIO_WINSDK_COMPONENT_REGEX.exec(component); + }) + .filter(match => { + return match && match.length > 1; + }) + .at(0); + if (sdkComponentMatch) { + args.push(`-winsdk=10.0.${sdkComponentMatch[1]}.0`); + } const { stdout } = await (0, exec_1.getExecOutput)('cmd', [ '/k', nativeToolsScriptx86, `-arch=${os.arch()}`, + ...args, '&&', 'set', '&&', @@ -2242,7 +2264,10 @@ base_1.VisualStudio.setup = async function (requirement) { '-version', requirement.version ]); - const vs = base_1.VisualStudio.createFromJSON(JSON.parse(stdout)[0]); + const vs = base_1.VisualStudio.createFromJSON({ + ...JSON.parse(stdout)[0], + components: requirement.components + }); if (!vs.installationPath) { throw new Error(`Unable to find any Visual Studio installation for version: ${requirement.version}.`); } @@ -2319,7 +2344,7 @@ const fs_1 = __nccwpck_require__(9896); const core = __importStar(__nccwpck_require__(7484)); const base_1 = __nccwpck_require__(3093); /// Update swift version based additional support files setup -base_1.VisualStudio.prototype.update = async function (sdkroot, copyModules) { +base_1.VisualStudio.prototype.update = async function (sdkroot) { const vsEnv = await this.env(); for (const property in vsEnv) { if (vsEnv[property] === process.env[property]) { @@ -2327,9 +2352,6 @@ base_1.VisualStudio.prototype.update = async function (sdkroot, copyModules) { } core.exportVariable(property, vsEnv[property]); } - if (!copyModules) { - return; - } const universalCRTSdkDir = vsEnv.UniversalCRTSdkDir; const uCRTVersion = vsEnv.UCRTVersion; const vCToolsInstallDir = vsEnv.VCToolsInstallDir; diff --git a/src/installer/windows/index.ts b/src/installer/windows/index.ts index 8b2a204..6413acf 100644 --- a/src/installer/windows/index.ts +++ b/src/installer/windows/index.ts @@ -5,7 +5,7 @@ import * as core from '@actions/core' import * as semver from 'semver' import {VerifyingToolchainInstaller} from '../verify' import {WindowsToolchainSnapshot} from '../../snapshot' -import {VisualStudio} from '../../utils' +import {VisualStudio, VISUAL_STUDIO_WINSDK_COMPONENT_REGEX} from '../../utils' import {Installation, CustomInstallation} from './installation' export class WindowsToolchainInstaller extends VerifyingToolchainInstaller { @@ -22,14 +22,23 @@ export class WindowsToolchainInstaller extends VerifyingToolchainInstaller { + return ( + (VISUAL_STUDIO_WINSDK_COMPONENT_REGEX.exec(component)?.length ?? 0) > 1 + ) + }) + + const vsComponents = [ + 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + ...providedComponents + ] + if (!winsdkComponent) { + vsComponents.push(this.winsdk) + } return { version: '16', swift: this.version, - components: [ - 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', - this.winsdk, - ...providedComponents - ] + components: vsComponents } } @@ -89,10 +98,7 @@ export class WindowsToolchainInstaller extends VerifyingToolchainInstaller { + return VISUAL_STUDIO_WINSDK_COMPONENT_REGEX.exec(component) + }) + .filter(match => { + return match && match.length > 1 + }) + .at(0) + if (sdkComponentMatch) { + args.push(`-winsdk=10.0.${sdkComponentMatch[1]}.0`) + } + const {stdout} = await getExecOutput( 'cmd', [ '/k', nativeToolsScriptx86, `-arch=${os.arch()}`, + ...args, '&&', 'set', '&&', diff --git a/src/utils/visual_studio/setup.ts b/src/utils/visual_studio/setup.ts index 2aefab7..24c3250 100644 --- a/src/utils/visual_studio/setup.ts +++ b/src/utils/visual_studio/setup.ts @@ -35,7 +35,10 @@ VisualStudio.setup = async function (requirement: VisualStudioRequirement) { '-version', requirement.version ]) - const vs = VisualStudio.createFromJSON(JSON.parse(stdout)[0]) + const vs = VisualStudio.createFromJSON({ + ...JSON.parse(stdout)[0], + components: requirement.components + }) if (!vs.installationPath) { throw new Error( `Unable to find any Visual Studio installation for version: ${requirement.version}.` diff --git a/src/utils/visual_studio/update.ts b/src/utils/visual_studio/update.ts index 847ef0b..a501063 100644 --- a/src/utils/visual_studio/update.ts +++ b/src/utils/visual_studio/update.ts @@ -6,15 +6,12 @@ import {VisualStudio} from './base' declare module './base' { // eslint-disable-next-line no-shadow export interface VisualStudio { - update(sdkroot: string, copyModules: boolean): Promise + update(sdkroot: string): Promise } } /// Update swift version based additional support files setup -VisualStudio.prototype.update = async function ( - sdkroot: string, - copyModules: boolean -) { +VisualStudio.prototype.update = async function (sdkroot: string) { const vsEnv = await this.env() for (const property in vsEnv) { if (vsEnv[property] === process.env[property]) { @@ -22,10 +19,6 @@ VisualStudio.prototype.update = async function ( } core.exportVariable(property, vsEnv[property]) } - - if (!copyModules) { - return - } const universalCRTSdkDir = vsEnv.UniversalCRTSdkDir const uCRTVersion = vsEnv.UCRTVersion const vCToolsInstallDir = vsEnv.VCToolsInstallDir