You've already forked setup-msbuild
mirror of
https://github.com/microsoft/setup-msbuild.git
synced 2026-09-25 11:17:01 +07:00
Default to auto-detected 64-bit MSBuild on 64-bit hosts (breaking change, v4)
Fixes #88 - msbuild-architecture no longer hardcodes a default of "x86". When the input is left unspecified, the action now auto-detects: it prefers x64 when running on a 64-bit machine and the resolved VS/MSBuild install is 17.0+ (VS 2022+), and falls back to x86 otherwise. An explicit msbuild-architecture value is always respected. - Extracted resolveMSBuildArchitecture()/parseMajorVersion() as pure, exported helpers and added jest tests covering the resolution matrix. - Bumped package.json version to 4.0.0 (breaking change/new major version). - Updated action.yml input description and README (usage examples now reference @v4, new "Breaking Changes in v4" section, and the architecture-selection docs rewritten to describe auto-detection). - Rebuilt dist/index.js via ncc. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -5,11 +5,25 @@ This action will help discover where the `MSBuild` tool is and automatically add
|
||||
> [!IMPORTANT]
|
||||
> Please note this tool does NOT add other Visual Studio tools (like VSTest, cl, cmake, or others) to `PATH`
|
||||
|
||||
## Breaking Changes in v4
|
||||
|
||||
Starting with `v4`, the default value of `msbuild-architecture` is no longer always `x86`. When
|
||||
`msbuild-architecture` is not explicitly specified, the action now **auto-detects** the best
|
||||
architecture:
|
||||
|
||||
- `x64` when running on a 64-bit machine **and** the resolved Visual Studio/MSBuild install is
|
||||
version 17.0 or later (Visual Studio 2022+, which ships a native 64-bit MSBuild).
|
||||
- `x86` otherwise (older Visual Studio versions, or 32-bit hosts), matching the previous behavior.
|
||||
|
||||
If you explicitly set `msbuild-architecture` (e.g. `x86`, `x64`, or `arm64`), that value is always
|
||||
respected and this auto-detection does not apply. If your workflow depends on always getting the
|
||||
32-bit MSBuild by default, set `msbuild-architecture: x86` explicitly.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```yml
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
uses: microsoft/setup-msbuild@v4
|
||||
|
||||
- name: Build app for release
|
||||
run: msbuild src\YourProjectFile.csproj -t:rebuild -verbosity:diag -property:Configuration=Release
|
||||
@@ -29,7 +43,7 @@ You may have a situation where your Actions runner has multiple versions of Visu
|
||||
|
||||
```yml
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
uses: microsoft/setup-msbuild@v4
|
||||
with:
|
||||
vs-version: '[16.4,16.5)'
|
||||
```
|
||||
@@ -42,18 +56,22 @@ If you need your Actions runner to target a pre-release version of Visual Studio
|
||||
|
||||
```yml
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
uses: microsoft/setup-msbuild@v4
|
||||
with:
|
||||
vs-prerelease: true
|
||||
```
|
||||
|
||||
### Specifying MSBuild architecture (optional)
|
||||
|
||||
By default the action will use the x86 architecture for MSBuild, but it is possible to target the x64 versions instead. Simply add the `msbuild-architecture` input. Valid input values are `x86` (default), `x64`, and `arm64`. Note that the success of these will rely on the runner OS.
|
||||
By default (as of `v4`), the action auto-detects the preferred MSBuild architecture: it uses `x64`
|
||||
when running on a 64-bit machine with Visual Studio/MSBuild 17.0 or later installed, and falls back
|
||||
to `x86` otherwise. You can override this by explicitly setting the `msbuild-architecture` input.
|
||||
Valid input values are `x86`, `x64`, and `arm64`. Note that the success of these will rely on the
|
||||
runner OS.
|
||||
|
||||
```yml
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
uses: microsoft/setup-msbuild@v4
|
||||
with:
|
||||
msbuild-architecture: x64
|
||||
```
|
||||
@@ -64,7 +82,7 @@ This makes use of the vswhere tool which is a tool delivered by Microsoft to hel
|
||||
|
||||
```yml
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
uses: microsoft/setup-msbuild@v4
|
||||
with:
|
||||
vswhere-path: 'C:\path\to\your\tools\'
|
||||
```
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import {
|
||||
MIN_VS_VERSION_FOR_X64,
|
||||
parseMajorVersion,
|
||||
resolveMSBuildArchitecture
|
||||
} from '../src/main'
|
||||
|
||||
describe('parseMajorVersion', () => {
|
||||
it('parses a standard installationVersion string', () => {
|
||||
expect(parseMajorVersion('17.9.34728.123')).toBe(17)
|
||||
})
|
||||
|
||||
it('parses a single-segment version', () => {
|
||||
expect(parseMajorVersion('16')).toBe(16)
|
||||
})
|
||||
|
||||
it('trims whitespace before parsing', () => {
|
||||
expect(parseMajorVersion(' 17.0.0.0 ')).toBe(17)
|
||||
})
|
||||
|
||||
it('returns undefined for an empty string', () => {
|
||||
expect(parseMajorVersion('')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('returns undefined for a non-numeric string', () => {
|
||||
expect(parseMajorVersion('not-a-version')).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('resolveMSBuildArchitecture', () => {
|
||||
it('always respects an explicit architecture, regardless of OS/version', () => {
|
||||
expect(resolveMSBuildArchitecture('x86', true, 17)).toBe('x86')
|
||||
expect(resolveMSBuildArchitecture('x64', false, 15)).toBe('x64')
|
||||
expect(resolveMSBuildArchitecture('arm64', true, 17)).toBe('arm64')
|
||||
})
|
||||
|
||||
it('defaults to x64 on a 64-bit host with VS/MSBuild 17+', () => {
|
||||
expect(resolveMSBuildArchitecture('', true, MIN_VS_VERSION_FOR_X64)).toBe(
|
||||
'x64'
|
||||
)
|
||||
expect(resolveMSBuildArchitecture('', true, 18)).toBe('x64')
|
||||
})
|
||||
|
||||
it('defaults to x86 on a 64-bit host with VS/MSBuild older than 17', () => {
|
||||
expect(resolveMSBuildArchitecture('', true, 16)).toBe('x86')
|
||||
})
|
||||
|
||||
it('defaults to x86 on a non-64-bit host even with VS/MSBuild 17+', () => {
|
||||
expect(resolveMSBuildArchitecture('', false, 17)).toBe('x86')
|
||||
})
|
||||
|
||||
it('defaults to x86 when the VS/MSBuild version could not be determined', () => {
|
||||
expect(resolveMSBuildArchitecture('', true, undefined)).toBe('x86')
|
||||
})
|
||||
})
|
||||
+1
-2
@@ -15,9 +15,8 @@ inputs:
|
||||
description: "Enable searching for pre-release versions of Visual Studio/MSBuild"
|
||||
required: false
|
||||
msbuild-architecture:
|
||||
description: 'The preferred processor architecture of MSBuild. Can be either "x86", "x64", or "arm64". "x64" is only available from Visual Studio version 17.0 and later.'
|
||||
description: 'The preferred processor architecture of MSBuild. Can be either "x86", "x64", or "arm64". "x64" is only available from Visual Studio version 17.0 and later. If left unspecified, the action auto-detects the best option: "x64" on 64-bit machines when a Visual Studio/MSBuild 17.0+ install is found, otherwise "x86".'
|
||||
required: false
|
||||
default: "x86"
|
||||
outputs:
|
||||
msbuildPath:
|
||||
description: "The resulting location of msbuild for your inputs"
|
||||
|
||||
Vendored
+54
-1
@@ -26,13 +26,45 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
const core = __importStar(__nccwpck_require__(484));
|
||||
const exec = __importStar(__nccwpck_require__(236));
|
||||
const fs = __importStar(__nccwpck_require__(896));
|
||||
const os = __importStar(__nccwpck_require__(857));
|
||||
const path = __importStar(__nccwpck_require__(928));
|
||||
const io = __importStar(__nccwpck_require__(994));
|
||||
const IS_WINDOWS = process.platform === 'win32';
|
||||
const VS_VERSION = core.getInput('vs-version') || 'latest';
|
||||
const VSWHERE_PATH = core.getInput('vswhere-path');
|
||||
const ALLOW_PRERELEASE = core.getInput('vs-prerelease') || 'false';
|
||||
let MSBUILD_ARCH = core.getInput('msbuild-architecture') || 'x86';
|
||||
const MSBUILD_ARCH_INPUT = core.getInput('msbuild-architecture');
|
||||
let MSBUILD_ARCH = MSBUILD_ARCH_INPUT;
|
||||
// The minimum Visual Studio/MSBuild major version that ships a native x64 MSBuild.exe
|
||||
exports.MIN_VS_VERSION_FOR_X64 = 17;
|
||||
// Determines the effective MSBuild architecture to use.
|
||||
// If the user explicitly specified `msbuild-architecture`, that choice is always respected.
|
||||
// Otherwise (breaking change as of v4), the action auto-detects and prefers x64 when
|
||||
// running on a 64-bit OS and the resolved VS/MSBuild installation is version 17.0 or later.
|
||||
// If the VS version can't be determined, or the host isn't 64-bit, it falls back to x86.
|
||||
function resolveMSBuildArchitecture(explicitArch, isWindows64Bit, vsMajorVersion) {
|
||||
if (explicitArch) {
|
||||
return explicitArch;
|
||||
}
|
||||
if (isWindows64Bit &&
|
||||
vsMajorVersion !== undefined &&
|
||||
vsMajorVersion >= exports.MIN_VS_VERSION_FOR_X64) {
|
||||
return 'x64';
|
||||
}
|
||||
return 'x86';
|
||||
}
|
||||
exports.resolveMSBuildArchitecture = resolveMSBuildArchitecture;
|
||||
// Parses the major version number out of a vswhere `installationVersion` string
|
||||
// such as "17.9.34728.123". Returns undefined if it cannot be parsed.
|
||||
function parseMajorVersion(installationVersion) {
|
||||
const match = installationVersion.trim().match(/^(\d+)/);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
const major = parseInt(match[1], 10);
|
||||
return isNaN(major) ? undefined : major;
|
||||
}
|
||||
exports.parseMajorVersion = parseMajorVersion;
|
||||
// if a specific version of VS is requested
|
||||
let VSWHERE_EXEC = '-products * -requires Microsoft.Component.MSBuild -property installationPath -latest ';
|
||||
if (ALLOW_PRERELEASE === 'true') {
|
||||
@@ -75,6 +107,27 @@ function run() {
|
||||
return;
|
||||
}
|
||||
core.debug(`Full tool exe: ${vswhereToolExe}`);
|
||||
// if the user did not explicitly specify an architecture, auto-detect the
|
||||
// preferred architecture based on the host OS and the resolved VS/MSBuild version
|
||||
if (!MSBUILD_ARCH_INPUT) {
|
||||
let vsMajorVersion;
|
||||
const versionOptions = {};
|
||||
versionOptions.listeners = {
|
||||
stdout: (data) => {
|
||||
const installationVersion = data.toString().trim();
|
||||
core.debug(`Found installation version: ${installationVersion}`);
|
||||
const parsed = parseMajorVersion(installationVersion);
|
||||
if (parsed !== undefined) {
|
||||
vsMajorVersion = parsed;
|
||||
}
|
||||
}
|
||||
};
|
||||
const versionExec = VSWHERE_EXEC.replace('-property installationPath', '-property installationVersion');
|
||||
yield exec.exec(`"${vswhereToolExe}" ${versionExec}`, [], versionOptions);
|
||||
const isWindows64Bit = os.arch() === 'x64' || os.arch() === 'arm64';
|
||||
MSBUILD_ARCH = resolveMSBuildArchitecture(MSBUILD_ARCH_INPUT, isWindows64Bit, vsMajorVersion);
|
||||
core.info(`Auto-detected msbuild-architecture: ${MSBUILD_ARCH} (os.arch=${os.arch()}, vsMajorVersion=${vsMajorVersion})`);
|
||||
}
|
||||
let foundToolPath = '';
|
||||
const options = {};
|
||||
options.listeners = {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "setup-msbuild",
|
||||
"version": "3.0.0",
|
||||
"version": "4.0.0",
|
||||
"private": true,
|
||||
"description": "Helps set up specific MSBuild tool into PATH for later usage.",
|
||||
"main": "lib/main.js",
|
||||
|
||||
+79
-2
@@ -1,6 +1,7 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as exec from '@actions/exec'
|
||||
import * as fs from 'fs'
|
||||
import * as os from 'os'
|
||||
import * as path from 'path'
|
||||
import * as io from '@actions/io'
|
||||
import {ExecOptions} from '@actions/exec/lib/interfaces'
|
||||
@@ -9,10 +10,53 @@ const IS_WINDOWS = process.platform === 'win32'
|
||||
const VS_VERSION = core.getInput('vs-version') || 'latest'
|
||||
const VSWHERE_PATH = core.getInput('vswhere-path')
|
||||
const ALLOW_PRERELEASE = core.getInput('vs-prerelease') || 'false'
|
||||
let MSBUILD_ARCH = core.getInput('msbuild-architecture') || 'x86'
|
||||
const MSBUILD_ARCH_INPUT = core.getInput('msbuild-architecture')
|
||||
let MSBUILD_ARCH = MSBUILD_ARCH_INPUT
|
||||
|
||||
// The minimum Visual Studio/MSBuild major version that ships a native x64 MSBuild.exe
|
||||
export const MIN_VS_VERSION_FOR_X64 = 17
|
||||
|
||||
// Determines the effective MSBuild architecture to use.
|
||||
// If the user explicitly specified `msbuild-architecture`, that choice is always respected.
|
||||
// Otherwise (breaking change as of v4), the action auto-detects and prefers x64 when
|
||||
// running on a 64-bit OS and the resolved VS/MSBuild installation is version 17.0 or later.
|
||||
// If the VS version can't be determined, or the host isn't 64-bit, it falls back to x86.
|
||||
export function resolveMSBuildArchitecture(
|
||||
explicitArch: string,
|
||||
isWindows64Bit: boolean,
|
||||
vsMajorVersion: number | undefined
|
||||
): string {
|
||||
if (explicitArch) {
|
||||
return explicitArch
|
||||
}
|
||||
|
||||
if (
|
||||
isWindows64Bit &&
|
||||
vsMajorVersion !== undefined &&
|
||||
vsMajorVersion >= MIN_VS_VERSION_FOR_X64
|
||||
) {
|
||||
return 'x64'
|
||||
}
|
||||
|
||||
return 'x86'
|
||||
}
|
||||
|
||||
// Parses the major version number out of a vswhere `installationVersion` string
|
||||
// such as "17.9.34728.123". Returns undefined if it cannot be parsed.
|
||||
export function parseMajorVersion(
|
||||
installationVersion: string
|
||||
): number | undefined {
|
||||
const match = installationVersion.trim().match(/^(\d+)/)
|
||||
if (!match) {
|
||||
return undefined
|
||||
}
|
||||
const major = parseInt(match[1], 10)
|
||||
return isNaN(major) ? undefined : major
|
||||
}
|
||||
|
||||
// if a specific version of VS is requested
|
||||
let VSWHERE_EXEC = '-products * -requires Microsoft.Component.MSBuild -property installationPath -latest '
|
||||
let VSWHERE_EXEC =
|
||||
'-products * -requires Microsoft.Component.MSBuild -property installationPath -latest '
|
||||
if (ALLOW_PRERELEASE === 'true') {
|
||||
VSWHERE_EXEC += ' -prerelease '
|
||||
}
|
||||
@@ -64,6 +108,39 @@ async function run(): Promise<void> {
|
||||
|
||||
core.debug(`Full tool exe: ${vswhereToolExe}`)
|
||||
|
||||
// if the user did not explicitly specify an architecture, auto-detect the
|
||||
// preferred architecture based on the host OS and the resolved VS/MSBuild version
|
||||
if (!MSBUILD_ARCH_INPUT) {
|
||||
let vsMajorVersion: number | undefined
|
||||
const versionOptions: ExecOptions = {}
|
||||
versionOptions.listeners = {
|
||||
stdout: (data: Buffer) => {
|
||||
const installationVersion = data.toString().trim()
|
||||
core.debug(`Found installation version: ${installationVersion}`)
|
||||
const parsed = parseMajorVersion(installationVersion)
|
||||
if (parsed !== undefined) {
|
||||
vsMajorVersion = parsed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const versionExec = VSWHERE_EXEC.replace(
|
||||
'-property installationPath',
|
||||
'-property installationVersion'
|
||||
)
|
||||
await exec.exec(`"${vswhereToolExe}" ${versionExec}`, [], versionOptions)
|
||||
|
||||
const isWindows64Bit = os.arch() === 'x64' || os.arch() === 'arm64'
|
||||
MSBUILD_ARCH = resolveMSBuildArchitecture(
|
||||
MSBUILD_ARCH_INPUT,
|
||||
isWindows64Bit,
|
||||
vsMajorVersion
|
||||
)
|
||||
core.info(
|
||||
`Auto-detected msbuild-architecture: ${MSBUILD_ARCH} (os.arch=${os.arch()}, vsMajorVersion=${vsMajorVersion})`
|
||||
)
|
||||
}
|
||||
|
||||
let foundToolPath = ''
|
||||
const options: ExecOptions = {}
|
||||
options.listeners = {
|
||||
|
||||
Reference in New Issue
Block a user