Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Support custom vc build tools #5823

Merged
merged 13 commits into from
Nov 20, 2024
56 changes: 56 additions & 0 deletions xmake/modules/detect/sdks/find_vstudio.lua
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,62 @@ function get_vcvars()
return realvcvars
end

function load_custom_vcenv(opt)
opt = opt or {}

if opt.bat and os.isfile(opt.bat) then
star-hengxing marked this conversation as resolved.
Show resolved Hide resolved
local file = io.readfile(opt.bat)
if file then
local variables = {}
for line in file:gmatch("[^\r\n]+") do
star-hengxing marked this conversation as resolved.
Show resolved Hide resolved
local key, value = line:match("set%s+(.-)=(.*)")
star-hengxing marked this conversation as resolved.
Show resolved Hide resolved
if key and value then
value = value:gsub("%%%{(.-)%}", variables)
if value == "%~dp0" then
value = path.directory(opt.bat) .. "\\"
else
for match in value:gmatch("%%(.-)%%") do
value = value:gsub("%%" .. match .. "%%", variables[match] or "")
end
end
variables[key] = value
end
end

for _, name in ipairs(vcvars) do
if variables[name] and #variables[name]:trim() == 0 then
variables[name] = nil
end
end

local vcvarsall = {}
if not variables["VCToolsVersion"] then
variables.VCToolsVersion = path.filename(variables["VCToolsInstallDir"])
end
vcvarsall[variables["VSCMD_ARG_TGT_ARCH"]] = variables
return vcvarsall
end
end

-- TODO: custom search
local vs_build_tools = opt.vs_build_tools
if vs_build_tools then
local VCToolsInstallDir
local VCToolsInstallDirs = os.dirs(path.join(vs_build_tools, "VC/Tools/MSVC/*"))
for _, ver in ipairs(VCToolsInstallDirs) do
if ver == opt.vs_toolset then
VCToolsInstallDir = ver
end
end

if not VCToolsInstallDir and #VCToolsInstallDirs ~= 0 then
VCToolsInstallDir = VCToolsInstallDirs[1]
end

local WindowsSDKDir = path.join(vs_build_tools, "Windows Kits/10")
star-hengxing marked this conversation as resolved.
Show resolved Hide resolved
end
end

-- load vcvarsall environment variables
function _load_vcvarsall(vcvarsall, vsver, arch, opt)
opt = opt or {}
Expand Down
2 changes: 2 additions & 0 deletions xmake/platforms/windows/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ platform("windows")
, " e.g. --vs_sdkver=10.0.15063.0" }
, {nil, "vs_runtime", "kv", nil, "The Runtime library of Visual Studio (deprecated, please use --runtimes)"
, values = {"MT", "MTd", "MD", "MDd"} }
, {nil, "vc_bat", "kv", nil, "The BuildTools bat file"
, " e.g. --vc_bat=C:/BuildTools/devcmd.bat" }
star-hengxing marked this conversation as resolved.
Show resolved Hide resolved
, {category = "Cuda SDK Configuration" }
, {nil, "cuda", "kv", "auto", "The Cuda SDK Directory" }
, {category = "Qt SDK Configuration" }
Expand Down
19 changes: 10 additions & 9 deletions xmake/plugins/project/clang/compile_commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,27 +60,28 @@ function _get_windows_sdk_arguments(target)
local args = {}
local msvc = target:toolchain("msvc")
if msvc then
local includedirs = {}
local envs = msvc:runenvs()
local WindowsSdkDir = envs.WindowsSdkDir
local WindowsSDKVersion = envs.WindowsSDKVersion
local VCToolsInstallDir = envs.VCToolsInstallDir
if WindowsSdkDir and WindowsSDKVersion then
local includedirs = os.dirs(path.join(WindowsSdkDir, "Include", envs.WindowsSDKVersion, "*"))
table.join2(includedirs, os.dirs(path.join(WindowsSdkDir, "Include", envs.WindowsSDKVersion, "*")))
for _, tool in ipairs({"atlmfc", "diasdk"}) do
local tool_dir = path.join(WindowsSdkDir, tool, "include")
if os.isdir(tool_dir) then
table.insert(includedirs, tool_dir)
end
end
end

if VCToolsInstallDir then
table.insert(includedirs, path.join(VCToolsInstallDir, "include"))
end
local VCToolsInstallDir = envs.VCToolsInstallDir
if VCToolsInstallDir then
table.insert(includedirs, path.join(VCToolsInstallDir, "include"))
end

for _, dir in ipairs(includedirs) do
table.insert(args, "-imsvc")
table.insert(args, dir)
end
for _, dir in ipairs(includedirs) do
table.insert(args, "-imsvc")
table.insert(args, dir)
end
end
return args
Expand Down
29 changes: 28 additions & 1 deletion xmake/toolchains/msvc/check.lua
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,28 @@ function _check_vstudio(toolchain)
return vs
end

-- check the visual studio
function _check_vc_build_tools(toolchain, bat)
local opt = {}
opt.bat = bat
local vcvarsall = find_vstudio.load_custom_vcenv(opt)
local vcvars = vcvarsall[toolchain:arch()]
if vcvars and vcvars.PATH and vcvars.INCLUDE and vcvars.LIB then
-- save vcvars
toolchain:config_set("vcvars", vcvars)
toolchain:config_set("vcarchs", table.orderkeys(vcvarsall))
toolchain:config_set("vs_toolset", vcvars.VCToolsVersion)
toolchain:config_set("vs_sdkver", vcvars.WindowsSDKVersion)

-- check compiler
local cl = find_tool("cl.exe", {version = true, force = true, envs = vcvars})
if cl and cl.version then
cprint("checking for Microsoft C/C++ Compiler (%s) version ... ${color.success}%s", toolchain:arch(), cl.version)
end
return vcvars
end
end

-- main entry
function main(toolchain)

Expand All @@ -113,7 +135,12 @@ function main(toolchain)
local cxx = path.basename(config.get("cxx") or "cl"):lower()
local mrc = path.basename(config.get("mrc") or "rc"):lower()
if cc == "cl" or cxx == "cl" or mrc == "rc" then
return _check_vstudio(toolchain)
local vc_bat = option.get("vc_bat")
if vc_bat then
return _check_vc_build_tools(toolchain, vc_bat)
else
return _check_vstudio(toolchain)
end
end
end

Loading