From 2e2bdd3d9459b4ae2e18ea3bde19b7376e8816b0 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Mon, 6 Oct 2025 06:04:40 -0400 Subject: [PATCH] GP-6005: Manually sorting detected Visual Studio installations by version --- GPL/vsconfig.gradle | 179 ++++++++++++++++++++++++-------------------- 1 file changed, 99 insertions(+), 80 deletions(-) diff --git a/GPL/vsconfig.gradle b/GPL/vsconfig.gradle index 9821653a43..5e0d35c4ae 100644 --- a/GPL/vsconfig.gradle +++ b/GPL/vsconfig.gradle @@ -9,87 +9,106 @@ * and SDKs are installed. ****************************************************************************/ -if (!hasProperty("VISUAL_STUDIO_INSTALL_DIR")) { - configureVisualStudio() -} +if (!hasProperty("VISUAL_STUDIO_INSTALL_DIR") && isCurrentWindows()) { -def configureVisualStudio() { - - if (isCurrentWindows()) { - - // Initialize variables - rootProject.ext.VISUAL_STUDIO_INSTALL_DIR = "" - rootProject.ext.VISUAL_STUDIO_TOOLS_VERSION_DEFAULT = "" - rootProject.ext.VISUAL_STUDIO_SDK_DIR_DEFAULT = "" - rootProject.ext.VISUAL_STUDIO_SDK_VERSION_DEFAULT = "" - rootProject.ext.VISUAL_STUDIO_SDK_VERSION_OVERRIDE = "" - rootProject.ext.VISUAL_STUDIO_VCVARS_CMD = "" - - // Use vswhere.exe to search for latest Visual Studio installation - println "Searching for latest Visual Studio and required components..." - def programFiles = System.getenv()["ProgramFiles(x86)"] ?: "C:\\Program Files (x86)" - def vswherePath = findProperty("vswherePath") ?: "${programFiles}\\Microsoft Visual Studio\\Installer\\vswhere.exe" - if (!file(vswherePath).exists()) { - println " -> Visual Studio vswhere.exe not found at \"${vswherePath}\"" - println " -> To manually specify the location of vswhere.exe, add \"-PvswherePath=\" to the Gradle command line arguments" - return - } - def vswhereProcess = "\"${vswherePath}\" -products * -sort -prerelease -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -format json -utf8".execute() - def vswhereOutput = vswhereProcess.text.trim() - def vswhereExit = vswhereProcess.exitValue() - if (vswhereExit != 0) { - if (vswhereExit == 87) { // ERROR_INVALID_PARAMATER - println " -> Visual Studio vswhere.exe was passed an unsupported argument!" - } - else { - println " -> Visual Studio vswhere.exe returned an error code (${vswhereExit})!" - } - println " -> Please confirm ${vswherePath} is version 2.5 or later." - println " -> Please check README.md or GettingStarted.md to verify you are using a supported version of Visual Studio." - return - } - def vswhereJson = new groovy.json.JsonSlurper().parseText(vswhereOutput); - def usePrerelease = project.hasProperty("vswherePrerelease") - def i = -1 - println " -> Searching for Visual Studio installations..." - vswhereJson.eachWithIndex { item, index -> - def isPrerelease = item.get("isPrerelease") - def name = item.get("displayName") + (isPrerelease ? " Prerelease" : "") - if (i == -1) { - if (usePrerelease || !isPrerelease) { - i = index - } - } - println " ${index + 1}: ${name}" + - (i == index ? " (selected)" : "") + - (isPrerelease && !usePrerelease ? " (enable with -PvswherePrerelease)" : "") - } - if (i == -1) { - println " -> Visual Studio not found!" - return - } - - def vsInstallDir = vswhereJson[i].installationPath - println " -> Installation Directory: ${vsInstallDir}" + // Initialize variables + rootProject.ext.VISUAL_STUDIO_INSTALL_DIR = "" + rootProject.ext.VISUAL_STUDIO_TOOLS_VERSION_DEFAULT = "" + rootProject.ext.VISUAL_STUDIO_SDK_DIR_DEFAULT = "" + rootProject.ext.VISUAL_STUDIO_SDK_VERSION_DEFAULT = "" + rootProject.ext.VISUAL_STUDIO_SDK_VERSION_OVERRIDE = "" + rootProject.ext.VISUAL_STUDIO_VCVARS_CMD = "" - // Use vcvarsall.bat to determine the latest Visual Studio's default SDK and tool versions - def vcvarsPath = "${vsInstallDir}\\VC\\Auxiliary\\Build\\vcvarsall.bat" - def vcvarsCmd = "\"${vcvarsPath}\" x86_amd64" - def vcvarsEnvCmd = "cmd /v:ON /c ${vcvarsCmd} > nul && cmd /c echo" - def sdkDir = "${vcvarsEnvCmd} !WindowsSdkDir!".execute().text.trim() - println " -> SDK Directory (default): ${sdkDir}" - def sdkVersion = "${vcvarsEnvCmd} !WindowsSDKVersion!".execute().text.trim().replace('\\', '') - println " -> SDK Version (default): ${sdkVersion}" - - // Check Gradle properties for override values - def windowsTargetPlatformVersion = findProperty("WindowsTargetPlatformVersion") - println " -> SDK Version (override): " + (windowsTargetPlatformVersion ?: "N/A") - - // Save Visual Studio information so other projects can access it - rootProject.ext.VISUAL_STUDIO_INSTALL_DIR = vsInstallDir - rootProject.ext.VISUAL_STUDIO_SDK_DIR_DEFAULT = sdkDir - rootProject.ext.VISUAL_STUDIO_SDK_VERSION_DEFAULT = sdkVersion - rootProject.ext.VISUAL_STUDIO_SDK_VERSION_OVERRIDE = windowsTargetPlatformVersion - rootProject.ext.VISUAL_STUDIO_VCVARS_CMD = vcvarsCmd + // Use vswhere.exe to search for latest Visual Studio installation + println "Searching for latest Visual Studio and required components..." + def programFiles = System.getenv()["ProgramFiles(x86)"] ?: "C:\\Program Files (x86)" + def vswherePath = findProperty("vswherePath") ?: "${programFiles}\\Microsoft Visual Studio\\Installer\\vswhere.exe" + if (!file(vswherePath).exists()) { + println " -> Visual Studio vswhere.exe not found at \"${vswherePath}\"" + println " -> To manually specify the location of vswhere.exe, add \"-PvswherePath=\" to the Gradle command line arguments" + return } + def vswhereProcess = "\"${vswherePath}\" -products * -prerelease -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -format json -utf8".execute() + def vswhereOutput = vswhereProcess.text.trim() + def vswhereExit = vswhereProcess.exitValue() + if (vswhereExit != 0) { + if (vswhereExit == 87) { // ERROR_INVALID_PARAMATER + println " -> Visual Studio vswhere.exe was passed an unsupported argument!" + } + else { + println " -> Visual Studio vswhere.exe returned an error code (${vswhereExit})!" + } + println " -> Please confirm ${vswherePath} is version 2.5 or later." + println " -> Please check README.md or GettingStarted.md to verify you are using a supported version of Visual Studio." + return + } + def vswhereJson = new groovy.json.JsonSlurper().parseText(vswhereOutput); + + // Our minimum supported version of vswhere does not support the -sort arg, so we must + // manually sort. The -sort arg was introduced in vswhere 2.6.7. + sortVisualStudioVersions(vswhereJson) + + def usePrerelease = project.hasProperty("vswherePrerelease") + def i = -1 + println " -> Searching for Visual Studio installations..." + vswhereJson.eachWithIndex { item, index -> + def isPrerelease = item.get("isPrerelease") + if (i == -1 && (usePrerelease || !isPrerelease)) { + i = index + } + println " ${index + 1}: ${item.displayName}" + + (i == index ? " (selected)" : "") + + (isPrerelease && !usePrerelease ? " (enable with -PvswherePrerelease)" : "") + println " - Installation Version: ${item.installationVersion}" + + (item.containsKey("unsupportedVersion") ? " (failed to sort)" : "") + println " - Installation Date: ${item.installDate}" + println " - Installation Path: ${item.installationPath}" + if (isPrerelease) { + println " - Prerelease" + } + } + if (i == -1) { + println " -> Visual Studio not found!" + return + } + + def vsInstallDir = vswhereJson[i].installationPath + println " -> Installation Directory: ${vsInstallDir}" + + // Use vcvarsall.bat to determine the latest Visual Studio's default SDK and tool versions + def vcvarsPath = "${vsInstallDir}\\VC\\Auxiliary\\Build\\vcvarsall.bat" + def vcvarsCmd = "\"${vcvarsPath}\" x86_amd64" + def vcvarsEnvCmd = "cmd /v:ON /c ${vcvarsCmd} > nul && cmd /c echo" + def sdkDir = "${vcvarsEnvCmd} !WindowsSdkDir!".execute().text.trim() + println " -> SDK Directory (default): ${sdkDir}" + def sdkVersion = "${vcvarsEnvCmd} !WindowsSDKVersion!".execute().text.trim().replace('\\', '') + println " -> SDK Version (default): ${sdkVersion}" + + // Check Gradle properties for override values + def windowsTargetPlatformVersion = findProperty("WindowsTargetPlatformVersion") + println " -> SDK Version (override): " + (windowsTargetPlatformVersion ?: "N/A") + + // Save Visual Studio information so other projects can access it + rootProject.ext.VISUAL_STUDIO_INSTALL_DIR = vsInstallDir + rootProject.ext.VISUAL_STUDIO_SDK_DIR_DEFAULT = sdkDir + rootProject.ext.VISUAL_STUDIO_SDK_VERSION_DEFAULT = sdkVersion + rootProject.ext.VISUAL_STUDIO_SDK_VERSION_OVERRIDE = windowsTargetPlatformVersion + rootProject.ext.VISUAL_STUDIO_VCVARS_CMD = vcvarsCmd +} + +def sortVisualStudioVersions(vswhereJson) { + + // Try to parse each version using Java's own version parser, marking the entries that failed + // (none should fail) + vswhereJson.each { + try { + Runtime.Version.parse(it.installationVersion) + } + catch (Exception e) { + it.put("unsupportedVersion", "true") + } + } + + vswhereJson.sort { a, b -> b.instanceId <=> a.instanceId } // secondary sort + vswhereJson.sort { a, b -> Runtime.Version.parse(b.installationVersion) <=> Runtime.Version.parse(a.installationVersion) } // primary sort }