summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2026-02-04 11:16:33 +0800
committerGitHub <[email protected]>2026-02-04 11:16:33 +0800
commit8f34a923760d6af7225df86683fa591bbac667e8 (patch)
tree2575132b179615d8c71548fb50f547aa344f8331
parent1bcce9d85f07cae1f7ac9f3a3099047539d26c84 (diff)
parenteea6cdd0be89085cf72b8277ea9dba31af07ad3b (diff)
Merge pull request #7290 from xmake-io/vs
improve vcvars
-rw-r--r--xmake/modules/detect/sdks/find_vstudio.lua145
1 files changed, 82 insertions, 63 deletions
diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua
index 22f5dea6b..8a805aae6 100644
--- a/xmake/modules/detect/sdks/find_vstudio.lua
+++ b/xmake/modules/detect/sdks/find_vstudio.lua
@@ -28,35 +28,8 @@ import("lib.detect.find_tool")
import("lib.detect.find_directory")
import("core.cache.global_detectcache")
--- init vc variables
-local vcvars = {"path",
- "lib",
- "libpath",
- "include",
- "DevEnvdir",
- "VSInstallDir",
- "VCInstallDir",
- "WindowsSdkDir",
- "WindowsLibPath",
- "WindowsSDKVersion",
- "WindowsSdkBinPath",
- "WindowsSdkVerBinPath",
- "ExtensionSdkDir",
- "UniversalCRTSdkDir",
- "UCRTVersion",
- "VCToolsVersion",
- "VCIDEInstallDir",
- "VCToolsInstallDir",
- "VCToolsRedistDir",
- "VisualStudioVersion",
- "VSCMD_VER",
- "VSCMD_ARG_app_plat",
- "VSCMD_ARG_HOST_ARCH",
- "VSCMD_ARG_TGT_ARCH"}
-
-- init vsvers
-local vsvers =
-{
+local vsvers = {
["18.0"] = "2026"
, ["17.0"] = "2022"
, ["16.0"] = "2019"
@@ -75,8 +48,7 @@ local vsvers =
}
-- init vsenvs
-local vsenvs =
-{
+local vsenvs = {
["18.0"] = "VS180COMNTOOLS"
, ["17.0"] = "VS170COMNTOOLS"
, ["16.0"] = "VS160COMNTOOLS"
@@ -99,6 +71,32 @@ local _env_orgs = {}
-- get all known Visual Studio environment variables
function get_vcvars()
+ local vcvars = {
+ "PATH",
+ "LIB",
+ "LIBPATH",
+ "INCLUDE",
+ "DevEnvdir",
+ "VSInstallDir",
+ "VCInstallDir",
+ "WindowsSdkDir",
+ "WindowsLibPath",
+ "WindowsSDKVersion",
+ "WindowsSdkBinPath",
+ "WindowsSdkVerBinPath",
+ "ExtensionSdkDir",
+ "UniversalCRTSdkDir",
+ "UCRTVersion",
+ "VCToolsVersion",
+ "VCIDEInstallDir",
+ "VCToolsInstallDir",
+ "VCToolsRedistDir",
+ "VisualStudioVersion",
+ "VSCMD_VER",
+ "VSCMD_ARG_app_plat",
+ "VSCMD_ARG_HOST_ARCH",
+ "VSCMD_ARG_TGT_ARCH"}
+
local realvcvars = vcvars
for _, v in pairs(vsenvs) do
table.insert(realvcvars, v)
@@ -310,39 +308,36 @@ function _load_vcvarsall_impl(vcvarsall, vsver, arch, opt)
local p = line:find('=', 1, true)
if p then
local name = line:sub(1, p - 1):trim()
- local value = line:sub(p + 1):trim()
- variables[name] = value
+ if #name > 0 then
+ local value = line:sub(p + 1):trim()
+ if #value > 0 then
+ variables[name] = value
+ end
+ end
end
end
-- check if the environment variables are truncated
_check_vcvarsall_env(variables)
- if not variables.path then
+ if not variables.PATH then
return
end
- -- remove some empty entries
- for _, name in ipairs(vcvars) do
- if variables[name] and #variables[name]:trim() == 0 then
- variables[name] = nil
- end
- end
-
-- fix WindowsSDKVersion
- local WindowsSDKVersion = variables["WindowsSDKVersion"]
+ local WindowsSDKVersion = variables.WindowsSDKVersion
if WindowsSDKVersion then
WindowsSDKVersion = WindowsSDKVersion:gsub("\\", ""):trim()
if WindowsSDKVersion ~= "" then
- variables["WindowsSDKVersion"] = WindowsSDKVersion
+ variables.WindowsSDKVersion = WindowsSDKVersion
end
else
-- sometimes the variable `WindowsSDKVersion` is not available
-- then parse it from `WindowsSdkBinPath`, such as: `C:\\Program Files (x86)\\Windows Kits\\8.1\\bin`
- local WindowsSdkBinPath = variables["WindowsSdkBinPath"]
+ local WindowsSdkBinPath = variables.WindowsSdkBinPath
if WindowsSdkBinPath then
WindowsSDKVersion = string.match(WindowsSdkBinPath, "\\(%d+%.%d+)\\bin$")
if WindowsSDKVersion then
- variables["WindowsSDKVersion"] = WindowsSDKVersion
+ variables.WindowsSDKVersion = WindowsSDKVersion
end
end
end
@@ -351,31 +346,21 @@ function _load_vcvarsall_impl(vcvarsall, vsver, arch, opt)
--
-- @note vcvarsall.bat maybe detect error if install WDK and SDK at same time (multi-sdk version exists in include directory).
--
- local UCRTVersion = variables["UCRTVersion"]
+ local UCRTVersion = variables.UCRTVersion
if UCRTVersion and WindowsSDKVersion and UCRTVersion ~= WindowsSDKVersion and WindowsSDKVersion ~= "" then
- local lib = variables["lib"]
+ local lib = variables.LIB
if lib then
lib = lib:gsub(UCRTVersion, WindowsSDKVersion)
- variables["lib"] = lib
+ variables.LIB = lib
end
- local include = variables["include"]
+ local include = variables.INCLUDE
if include then
include = include:gsub(UCRTVersion, WindowsSDKVersion)
- variables["include"] = include
+ variables.INCLUDE = include
end
UCRTVersion = WindowsSDKVersion
- variables["UCRTVersion"] = UCRTVersion
+ variables.UCRTVersion = UCRTVersion
end
-
- -- convert path/lib/include to PATH/LIB/INCLUDE
- variables.PATH = variables.path
- variables.LIB = variables.lib
- variables.LIBPATH = variables.libpath
- variables.INCLUDE = variables.include
- variables.path = nil
- variables.lib = nil
- variables.include = nil
- variables.libpath = nil
return variables
end
@@ -406,7 +391,7 @@ function _check_vcvarsall_env(vars)
end
value_org = _env_orgs[name]
end
- local value_new = vars[name] or vars[name:lower()]
+ local value_new = vars[name]
if value_org and value_new and #value_org > 0 then
local values_new = hashset.from(path.splitenv(value_new))
for _, p in ipairs(value_org) do
@@ -562,7 +547,7 @@ function _find_vstudio(opt)
if vsenvs[version] then
table.insert(paths, format("$(env %s)\\..\\..\\VC", vsenvs[version]))
end
-
+
if vswhere_VCAuxiliaryBuildDir then
for _, vc_path in ipairs(vswhere_VCAuxiliaryBuildDir) do
if os.isdir(vc_path) then
@@ -695,6 +680,33 @@ function _get_last_mtime(vstudio)
return mtime
end
+function _show_vstudio_diagnosis_result(vstudio)
+ local found = {}
+ for vsver, msvc in pairs(vstudio) do
+ if type(msvc) == "table" and msvc.version then
+ local toolset
+ local vcvarsall = msvc.vcvarsall
+ if type(vcvarsall) == "table" then
+ for _, envs in pairs(vcvarsall) do
+ if type(envs) == "table" and envs.VCToolsVersion then
+ toolset = _strip_toolset_ver(envs.VCToolsVersion)
+ break
+ end
+ end
+ end
+ if toolset then
+ table.insert(found, tostring(vsver) .. "(" .. tostring(msvc.version) .. ", toolset:" .. tostring(toolset) .. ")")
+ else
+ table.insert(found, tostring(vsver) .. "(" .. tostring(msvc.version) .. ")")
+ end
+ else
+ table.insert(found, tostring(vsver))
+ end
+ end
+ table.sort(found, function (a, b) return a > b end)
+ cprint("${dim}detecting vstudio environment ... ${color.success}%s", table.concat(found, ", "))
+end
+
-- find vstudio environment
--
-- @param opt the options, e.g. {toolset = 14.0, sdkver = "10.0.15063.0"}
@@ -729,6 +741,7 @@ function main(opt)
end
-- find and cache result
+ cprint("${color.warning}Detecting Visual Studio environment (cached); run `xmake global --clean` first if vs updated.")
vstudio = _find_vstudio(opt)
if vstudio then
local mtime = _get_last_mtime(vstudio)
@@ -736,6 +749,12 @@ function main(opt)
global_detectcache:set2(key, "mtime", mtime)
global_detectcache:save()
end
+ if option.get("diagnosis") then
+ if vstudio and not table.empty(vstudio) then
+ _show_vstudio_diagnosis_result(vstudio)
+ else
+ cprint("${dim}detecting vstudio environment ...${color.failure}${text.failure}")
+ end
+ end
return vstudio
end
-