From e4a3ca8b3412581eaa9b6a7acb00d7d2b5a6b27a Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 May 2024 22:39:39 +0800 Subject: [PATCH 01/10] add icx for windows --- xmake/modules/detect/sdks/find_icxenv.lua | 106 +++++++++++++++++++++- xmake/toolchains/icx/check.lua | 44 ++++++++- xmake/toolchains/icx/load.lua | 73 ++++++++++++++- 3 files changed, 215 insertions(+), 8 deletions(-) diff --git a/xmake/modules/detect/sdks/find_icxenv.lua b/xmake/modules/detect/sdks/find_icxenv.lua index 55cd7d56e1..df0c50ddec 100644 --- a/xmake/modules/detect/sdks/find_icxenv.lua +++ b/xmake/modules/detect/sdks/find_icxenv.lua @@ -22,11 +22,113 @@ import("lib.detect.find_file") import("lib.detect.find_tool") --- find intel c/c++ envirnoment on windows +-- init icx variables +local icxvars = {"path", + "lib", + "libpath", + "include", + "DevEnvdir", + "VSInstallDir", + "VCInstallDir", + "WindowsSdkDir", + "WindowsLibPath", + "WindowsSDKVersion", + "WindowsSdkBinPath", + "UniversalCRTSdkDir", + "UCRTVersion"} + +-- load icxvars_bat environment variables +function _load_icxvars(icxvars_bat, arch, opt) + + -- make the genicxvars.bat + opt = opt or {} + local genicxvars_bat = os.tmpfile() .. "_genicxvars.bat" + local genicxvars_dat = os.tmpfile() .. "_genicxvars.txt" + local file = io.open(genicxvars_bat, "w") + file:print("@echo off") + file:print("call \"%s\" -arch %s > nul", icxvars_bat, arch) + for idx, var in ipairs(icxvars) do + file:print("echo " .. var .. " = %%" .. var .. "%% %s %s", idx == 1 and ">" or ">>", genicxvars_dat) + end + file:close() + + -- run genicxvars.bat + os.run(genicxvars_bat) + + -- load all envirnoment variables + local variables = {} + for _, line in ipairs((io.readfile(genicxvars_dat) or ""):split("\n")) do + 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 + end + end + if not variables.path then + return + end + + -- remove some empty entries + for _, name in ipairs(icxvars) do + if variables[name] and #variables[name]:trim() == 0 then + variables[name] = nil + end + end + + -- fix bin path for ia32 + if variables.path and arch == "ia32" then + variables.path = variables.path:gsub("windows\\bin\\intel64;", "windows\\bin\\intel64_ia32;") + 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 + +-- find intel llvm c/c++ envirnoment on windows function _find_intel_on_windows(opt) + + -- init options + opt = opt or {} + + -- find icxvars_bat.bat + local paths = {"$(env ICPP_COMPILER20)"} + local icxvars_bat = find_file("bin/icxvars.bat", paths) + -- look for setvars.bat which is new in 2021 + if not icxvars_bat then + -- find setvars.bat in intel oneapi toolkits rootdir + paths = {"$(env ONEAPI_ROOT)"} + icxvars_bat = find_file("setvars.bat", paths) + end + if not icxvars_bat then + -- find setvars.bat using ICPP_COMPILER.* + paths = { + "$(env ICPP_COMPILER21)", + "$(env ICPP_COMPILER22)", + "$(env ICPP_COMPILER23)" + } + icxvars_bat = find_file("../../../setvars.bat", paths) + end + if icxvars_bat then + + -- load icxvars_bat + local icxvars_x86 = _load_icxvars(icxvars_bat, "ia32", opt) + local icxvars_x64 = _load_icxvars(icxvars_bat, "intel64", opt) + + -- save results + return {icxvars_bat = icxvars_bat, icxvars = {x86 = icxvars_x86, x64 = icxvars_x64}} + end end --- find intel c/c++ envirnoment on linux +-- find intel llvm c/c++ envirnoment on linux function _find_intel_on_linux(opt) -- attempt to find the sdk directory diff --git a/xmake/toolchains/icx/check.lua b/xmake/toolchains/icx/check.lua index 4d627915bb..d22889f142 100644 --- a/xmake/toolchains/icx/check.lua +++ b/xmake/toolchains/icx/check.lua @@ -24,17 +24,44 @@ import("core.project.config") import("detect.sdks.find_icxenv") import("lib.detect.find_tool") --- main entry -function main(toolchain) +-- check intel on windows +function _check_intel_on_windows(toolchain) + + -- have been checked? + local varsall = toolchain:config("varsall") + if varsall then + return true + end + + -- find intel llvm c/c++ compiler environment + local icxenv = find_icxenv() + if icxenv and icxenv.icxvars then + local icxvarsall = icxenv.icxvars + local icxenv = icxvarsall[toolchain:arch()] + if icxenv and icxenv.PATH and icxenv.INCLUDE and icxenv.LIB then + local tool = find_tool("icx.exe", {force = true, envs = icxenv, version = true}) + if tool then + cprint("checking for Intel LLVM C/C++ Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) + toolchain:config_set("varsall", icxvarsall) + toolchain:configs_save() + return true + end + end + end +end + +-- check intel on linux +function _check_intel_on_linux(toolchain) local icxenv = toolchain:config("icxenv") if icxenv then return true end icxenv = find_icxenv() if icxenv then - local tool = find_tool("icx", {force = true, paths = icxenv.bindir}) + local ldname = is_host("macosx") and "DYLD_LIBRARY_PATH" or "LD_LIBRARY_PATH" + local tool = find_tool("icx", {force = true, envs = {[ldname] = icxenv.libdir}, paths = icxenv.bindir}) if tool then - cprint("checking for Intel LLVM C/C++ Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) + cprint("checking for Intel C/C++ Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) toolchain:config_set("icxenv", icxenv) toolchain:config_set("bindir", icxenv.bindir) toolchain:configs_save() @@ -44,3 +71,12 @@ function main(toolchain) end end +-- main entry +function main(toolchain) + if is_host("windows") then + return _check_intel_on_windows(toolchain) + else + return _check_intel_on_linux(toolchain) + end +end + diff --git a/xmake/toolchains/icx/load.lua b/xmake/toolchains/icx/load.lua index 4608c15ae8..ebe3e85545 100644 --- a/xmake/toolchains/icx/load.lua +++ b/xmake/toolchains/icx/load.lua @@ -22,8 +22,61 @@ import("core.base.option") import("core.project.config") --- main entry -function main(toolchain) +-- add the given icx environment +function _add_icxenv(toolchain, name) + + -- get icxvarsall + local icxvarsall = toolchain:config("varsall") + if not icxvarsall then + return + end + + -- get icx environment for the current arch + local arch = toolchain:arch() + local icxenv = icxvarsall[arch] or {} + + -- get the paths for the icx environment + local env = icxenv[name] + if env then + toolchain:add("runenvs", name:upper(), path.splitenv(env)) + end +end + +-- load intel on windows +function _load_intel_on_windows(toolchain) + + -- set toolset + if toolchain:is_plat("windows") then + toolchain:set("toolset", "cc", "icx.exe") + toolchain:set("toolset", "cxx", "icx.exe") + toolchain:set("toolset", "mrc", "rc.exe") + if toolchain:is_arch("x64") then + toolchain:set("toolset", "as", "ml64.exe") + else + toolchain:set("toolset", "as", "ml.exe") + end + toolchain:set("toolset", "ld", "link.exe") + toolchain:set("toolset", "sh", "link.exe") + toolchain:set("toolset", "ar", "link.exe") + else + toolchain:set("toolset", "cc", "icx") + toolchain:set("toolset", "cxx", "icpx", "icx") + toolchain:set("toolset", "ld", "icpx", "icx") + toolchain:set("toolset", "sh", "icpx", "icx") + toolchain:set("toolset", "ar", "ar") + toolchain:set("toolset", "strip", "strip") + toolchain:set("toolset", "as", "icx") + end + + -- add icx environments + _add_icxenv(toolchain, "PATH") + _add_icxenv(toolchain, "LIB") + _add_icxenv(toolchain, "INCLUDE") + _add_icxenv(toolchain, "LIBPATH") +end + +-- load intel on linux +function _load_intel_on_linux(toolchain) -- set toolset toolchain:set("toolset", "cc", "icx") @@ -47,5 +100,21 @@ function main(toolchain) toolchain:add("ldflags", march) toolchain:add("shflags", march) end + + -- get icx environments + local icxenv = toolchain:config("icxenv") + if icxenv then + local ldname = is_host("macosx") and "DYLD_LIBRARY_PATH" or "LD_LIBRARY_PATH" + toolchain:add("runenvs", ldname, icxenv.libdir) + end +end + +-- main entry +function main(toolchain) + if is_host("windows") then + return _load_intel_on_windows(toolchain) + else + return _load_intel_on_linux(toolchain) + end end From b3f983af7d3199a641c97b767a376042ff7e0a05 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 May 2024 22:52:53 +0800 Subject: [PATCH 02/10] improve to find ifort --- xmake/modules/detect/sdks/find_ifortenv.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xmake/modules/detect/sdks/find_ifortenv.lua b/xmake/modules/detect/sdks/find_ifortenv.lua index b0adceb06a..7c9665506e 100644 --- a/xmake/modules/detect/sdks/find_ifortenv.lua +++ b/xmake/modules/detect/sdks/find_ifortenv.lua @@ -116,6 +116,12 @@ function _find_intel_on_windows(opt) "$(env IFORT_COMPILER23)" } ifortvars_bat = find_file("../../../setvars.bat", paths) + if not ifortvars_bat then + paths = { + "$(env IFORT_COMPILER24)" + } + ifortvars_bat = find_file("../../setvars.bat", paths) + end end if ifortvars_bat then From c55ca98f52ea3dc5580506547aa0ceabf6c35ed7 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 May 2024 22:53:59 +0800 Subject: [PATCH 03/10] improve ifort rootdir --- xmake/modules/detect/sdks/find_ifortenv.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xmake/modules/detect/sdks/find_ifortenv.lua b/xmake/modules/detect/sdks/find_ifortenv.lua index 7c9665506e..2a6f937d4c 100644 --- a/xmake/modules/detect/sdks/find_ifortenv.lua +++ b/xmake/modules/detect/sdks/find_ifortenv.lua @@ -53,7 +53,11 @@ function _load_ifortvars(ifortvars_bat, arch, opt) file:close() -- run genifortvars.bat - os.run(genifortvars_bat) + local oneapi_rootdir = os.getenv("ONEAPI_ROOT") + if not oneapi_rootdir then + oneapi_rootdir = path.directory(ifortvars_bat) + end + os.runv(genifortvars_bat, {envs = {ONEAPI_ROOT = oneapi_rootdir}}) -- load all envirnoment variables local variables = {} From 537c5aacf5d0306a3ca786932737991c29e8ecc5 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 May 2024 22:55:48 +0800 Subject: [PATCH 04/10] revert ifort --- xmake/modules/detect/sdks/find_ifortenv.lua | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/xmake/modules/detect/sdks/find_ifortenv.lua b/xmake/modules/detect/sdks/find_ifortenv.lua index 2a6f937d4c..7c9665506e 100644 --- a/xmake/modules/detect/sdks/find_ifortenv.lua +++ b/xmake/modules/detect/sdks/find_ifortenv.lua @@ -53,11 +53,7 @@ function _load_ifortvars(ifortvars_bat, arch, opt) file:close() -- run genifortvars.bat - local oneapi_rootdir = os.getenv("ONEAPI_ROOT") - if not oneapi_rootdir then - oneapi_rootdir = path.directory(ifortvars_bat) - end - os.runv(genifortvars_bat, {envs = {ONEAPI_ROOT = oneapi_rootdir}}) + os.run(genifortvars_bat) -- load all envirnoment variables local variables = {} From be0da314e2a706fff2d10ef68588275d2a90e638 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 May 2024 22:57:20 +0800 Subject: [PATCH 05/10] check vs for ifort/icx --- xmake/toolchains/icx/check.lua | 85 +++++++++++++++++++++++++++++++- xmake/toolchains/icx/load.lua | 37 ++++++++++++++ xmake/toolchains/ifort/check.lua | 84 ++++++++++++++++++++++++++++++- xmake/toolchains/ifort/load.lua | 37 ++++++++++++++ 4 files changed, 241 insertions(+), 2 deletions(-) diff --git a/xmake/toolchains/icx/check.lua b/xmake/toolchains/icx/check.lua index d22889f142..d2d7b2df94 100644 --- a/xmake/toolchains/icx/check.lua +++ b/xmake/toolchains/icx/check.lua @@ -22,8 +22,91 @@ import("core.base.option") import("core.project.config") import("detect.sdks.find_icxenv") +import("detect.sdks.find_vstudio") import("lib.detect.find_tool") +-- attempt to check vs environment +function _check_vsenv(toolchain) + + -- has been checked? + local vs = toolchain:config("vs") or config.get("vs") + if vs then + vs = tostring(vs) + end + local vcvars = toolchain:config("vcvars") + if vs and vcvars then + return vs + end + + -- find vstudio + local vs_toolset = toolchain:config("vs_toolset") or config.get("vs_toolset") + local vs_sdkver = toolchain:config("vs_sdkver") or config.get("vs_sdkver") + local vstudio = find_vstudio({vcvars_ver = vs_toolset, sdkver = vs_sdkver}) + if vstudio then + + -- make order vsver + local vsvers = {} + for vsver, _ in pairs(vstudio) do + if not vs or vs ~= vsver then + table.insert(vsvers, vsver) + end + end + table.sort(vsvers, function (a, b) return tonumber(a) > tonumber(b) end) + if vs then + table.insert(vsvers, 1, vs) + end + + -- get vcvarsall + for _, vsver in ipairs(vsvers) do + local vcvarsall = (vstudio[vsver] or {}).vcvarsall or {} + 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 program + local paths + local pathenv = os.getenv("PATH") + if pathenv then + paths = path.splitenv(pathenv) + end + local tool = find_tool("cl.exe", {version = true, force = true, paths = paths, envs = vcvars}) + if tool then + program = tool.program + end + if program then + return vsver, tool + end + end + end + end +end + +-- check the visual studio +function _check_vstudio(toolchain) + local vs, cl = _check_vsenv(toolchain) + if vs then + if toolchain:is_global() then + config.set("vs", vs, {force = true, readonly = true}) + end + toolchain:config_set("vs", vs) + toolchain:configs_save() + cprint("checking for Microsoft Visual Studio (%s) version ... ${color.success}%s", toolchain:arch(), vs) + if cl and cl.version then + cprint("checking for LLVM Clang C/C++ Compiler (%s) version ... ${color.success}%s", toolchain:arch(), cl.version) + end + else + cprint("checking for Microsoft Visual Studio (%s) version ... ${color.nothing}${text.nothing}", toolchain:arch()) + end + return vs +end + + -- check intel on windows function _check_intel_on_windows(toolchain) @@ -44,7 +127,7 @@ function _check_intel_on_windows(toolchain) cprint("checking for Intel LLVM C/C++ Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) toolchain:config_set("varsall", icxvarsall) toolchain:configs_save() - return true + return _check_vstudio(toolchain) end end end diff --git a/xmake/toolchains/icx/load.lua b/xmake/toolchains/icx/load.lua index ebe3e85545..74f021c074 100644 --- a/xmake/toolchains/icx/load.lua +++ b/xmake/toolchains/icx/load.lua @@ -21,6 +21,31 @@ -- imports import("core.base.option") import("core.project.config") +import("detect.sdks.find_vstudio") + +-- add the given vs environment +function _add_vsenv(toolchain, name, curenvs) + + -- get vcvars + local vcvars = toolchain:config("vcvars") + if not vcvars then + return + end + + -- get the paths for the vs environment + local new = vcvars[name] + if new then + -- fix case naming conflict for cmake/msbuild between the new msvc envs and current environment, if we are running xmake in vs prompt. + -- @see https://github.com/xmake-io/xmake/issues/4751 + for k, c in pairs(curenvs) do + if name:lower() == k:lower() and name ~= k then + name = k + break + end + end + toolchain:add("runenvs", name, table.unwrap(path.splitenv(new))) + end +end -- add the given icx environment function _add_icxenv(toolchain, name) @@ -73,6 +98,18 @@ function _load_intel_on_windows(toolchain) _add_icxenv(toolchain, "LIB") _add_icxenv(toolchain, "INCLUDE") _add_icxenv(toolchain, "LIBPATH") + + -- add vs environments + local expect_vars = {"PATH", "LIB", "INCLUDE", "LIBPATH"} + local curenvs = os.getenvs() + for _, name in ipairs(expect_vars) do + _add_vsenv(toolchain, name, curenvs) + end + for _, name in ipairs(find_vstudio.get_vcvars()) do + if not table.contains(expect_vars, name:upper()) then + _add_vsenv(toolchain, name, curenvs) + end + end end -- load intel on linux diff --git a/xmake/toolchains/ifort/check.lua b/xmake/toolchains/ifort/check.lua index 285f5c86c5..8ba2a3881b 100644 --- a/xmake/toolchains/ifort/check.lua +++ b/xmake/toolchains/ifort/check.lua @@ -22,8 +22,90 @@ import("core.base.option") import("core.project.config") import("detect.sdks.find_ifortenv") +import("detect.sdks.find_vstudio") import("lib.detect.find_tool") +-- attempt to check vs environment +function _check_vsenv(toolchain) + + -- has been checked? + local vs = toolchain:config("vs") or config.get("vs") + if vs then + vs = tostring(vs) + end + local vcvars = toolchain:config("vcvars") + if vs and vcvars then + return vs + end + + -- find vstudio + local vs_toolset = toolchain:config("vs_toolset") or config.get("vs_toolset") + local vs_sdkver = toolchain:config("vs_sdkver") or config.get("vs_sdkver") + local vstudio = find_vstudio({vcvars_ver = vs_toolset, sdkver = vs_sdkver}) + if vstudio then + + -- make order vsver + local vsvers = {} + for vsver, _ in pairs(vstudio) do + if not vs or vs ~= vsver then + table.insert(vsvers, vsver) + end + end + table.sort(vsvers, function (a, b) return tonumber(a) > tonumber(b) end) + if vs then + table.insert(vsvers, 1, vs) + end + + -- get vcvarsall + for _, vsver in ipairs(vsvers) do + local vcvarsall = (vstudio[vsver] or {}).vcvarsall or {} + 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 program + local paths + local pathenv = os.getenv("PATH") + if pathenv then + paths = path.splitenv(pathenv) + end + local tool = find_tool("cl.exe", {version = true, force = true, paths = paths, envs = vcvars}) + if tool then + program = tool.program + end + if program then + return vsver, tool + end + end + end + end +end + +-- check the visual studio +function _check_vstudio(toolchain) + local vs, cl = _check_vsenv(toolchain) + if vs then + if toolchain:is_global() then + config.set("vs", vs, {force = true, readonly = true}) + end + toolchain:config_set("vs", vs) + toolchain:configs_save() + cprint("checking for Microsoft Visual Studio (%s) version ... ${color.success}%s", toolchain:arch(), vs) + if cl and cl.version then + cprint("checking for LLVM Clang C/C++ Compiler (%s) version ... ${color.success}%s", toolchain:arch(), cl.version) + end + else + cprint("checking for Microsoft Visual Studio (%s) version ... ${color.nothing}${text.nothing}", toolchain:arch()) + end + return vs +end + -- check intel on windows function _check_intel_on_windows(toolchain) @@ -44,7 +126,7 @@ function _check_intel_on_windows(toolchain) cprint("checking for Intel Fortran Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) toolchain:config_set("varsall", ifortvarsall) toolchain:configs_save() - return true + return _check_vstudio(toolchain) end end end diff --git a/xmake/toolchains/ifort/load.lua b/xmake/toolchains/ifort/load.lua index 2cb212a579..d0333ea771 100644 --- a/xmake/toolchains/ifort/load.lua +++ b/xmake/toolchains/ifort/load.lua @@ -21,6 +21,31 @@ -- imports import("core.base.option") import("core.project.config") +import("detect.sdks.find_vstudio") + +-- add the given vs environment +function _add_vsenv(toolchain, name, curenvs) + + -- get vcvars + local vcvars = toolchain:config("vcvars") + if not vcvars then + return + end + + -- get the paths for the vs environment + local new = vcvars[name] + if new then + -- fix case naming conflict for cmake/msbuild between the new msvc envs and current environment, if we are running xmake in vs prompt. + -- @see https://github.com/xmake-io/xmake/issues/4751 + for k, c in pairs(curenvs) do + if name:lower() == k:lower() and name ~= k then + name = k + break + end + end + toolchain:add("runenvs", name, table.unwrap(path.splitenv(new))) + end +end -- add the given ifort environment function _add_ifortenv(toolchain, name) @@ -62,6 +87,18 @@ function _load_intel_on_windows(toolchain) _add_ifortenv(toolchain, "LIB") _add_ifortenv(toolchain, "INCLUDE") _add_ifortenv(toolchain, "LIBPATH") + + -- add vs environments + local expect_vars = {"PATH", "LIB", "INCLUDE", "LIBPATH"} + local curenvs = os.getenvs() + for _, name in ipairs(expect_vars) do + _add_vsenv(toolchain, name, curenvs) + end + for _, name in ipairs(find_vstudio.get_vcvars()) do + if not table.contains(expect_vars, name:upper()) then + _add_vsenv(toolchain, name, curenvs) + end + end end -- load intel on linux From dc2e263f79ecd7c71662cae167767594a5420689 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 May 2024 22:59:35 +0800 Subject: [PATCH 06/10] fix icx/ifort envs --- xmake/toolchains/icx/load.lua | 27 +++++++++++++++------------ xmake/toolchains/ifort/load.lua | 27 +++++++++++++++------------ 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/xmake/toolchains/icx/load.lua b/xmake/toolchains/icx/load.lua index 74f021c074..f20ca31def 100644 --- a/xmake/toolchains/icx/load.lua +++ b/xmake/toolchains/icx/load.lua @@ -43,12 +43,12 @@ function _add_vsenv(toolchain, name, curenvs) break end end - toolchain:add("runenvs", name, table.unwrap(path.splitenv(new))) + toolchain:add("runenvs", name, table.unpack(path.splitenv(new))) end end -- add the given icx environment -function _add_icxenv(toolchain, name) +function _add_icxenv(toolchain, name, curenvs) -- get icxvarsall local icxvarsall = toolchain:config("varsall") @@ -61,9 +61,17 @@ function _add_icxenv(toolchain, name) local icxenv = icxvarsall[arch] or {} -- get the paths for the icx environment - local env = icxenv[name] - if env then - toolchain:add("runenvs", name:upper(), path.splitenv(env)) + local new = icxvarsall[name] + if new then + -- fix case naming conflict for cmake/msbuild between the new msvc envs and current environment, if we are running xmake in vs prompt. + -- @see https://github.com/xmake-io/xmake/issues/4751 + for k, c in pairs(curenvs) do + if name:lower() == k:lower() and name ~= k then + name = k + break + end + end + toolchain:add("runenvs", name, table.unpack(path.splitenv(new))) end end @@ -93,17 +101,12 @@ function _load_intel_on_windows(toolchain) toolchain:set("toolset", "as", "icx") end - -- add icx environments - _add_icxenv(toolchain, "PATH") - _add_icxenv(toolchain, "LIB") - _add_icxenv(toolchain, "INCLUDE") - _add_icxenv(toolchain, "LIBPATH") - - -- add vs environments + -- add vs/icx environments local expect_vars = {"PATH", "LIB", "INCLUDE", "LIBPATH"} local curenvs = os.getenvs() for _, name in ipairs(expect_vars) do _add_vsenv(toolchain, name, curenvs) + _add_icxenv(toolchain, name, curenvs) end for _, name in ipairs(find_vstudio.get_vcvars()) do if not table.contains(expect_vars, name:upper()) then diff --git a/xmake/toolchains/ifort/load.lua b/xmake/toolchains/ifort/load.lua index d0333ea771..8eb6164751 100644 --- a/xmake/toolchains/ifort/load.lua +++ b/xmake/toolchains/ifort/load.lua @@ -43,12 +43,12 @@ function _add_vsenv(toolchain, name, curenvs) break end end - toolchain:add("runenvs", name, table.unwrap(path.splitenv(new))) + toolchain:add("runenvs", name, table.unpack(path.splitenv(new))) end end -- add the given ifort environment -function _add_ifortenv(toolchain, name) +function _add_ifortenv(toolchain, name, curenvs) -- get ifortvarsall local ifortvarsall = toolchain:config("varsall") @@ -61,9 +61,17 @@ function _add_ifortenv(toolchain, name) local ifortenv = ifortvarsall[arch] or {} -- get the paths for the ifort environment - local env = ifortenv[name] - if env then - toolchain:add("runenvs", name:upper(), path.splitenv(env)) + local new = ifortvarsall[name] + if new then + -- fix case naming conflict for cmake/msbuild between the new msvc envs and current environment, if we are running xmake in vs prompt. + -- @see https://github.com/xmake-io/xmake/issues/4751 + for k, c in pairs(curenvs) do + if name:lower() == k:lower() and name ~= k then + name = k + break + end + end + toolchain:add("runenvs", name, table.unpack(path.splitenv(new))) end end @@ -82,17 +90,12 @@ function _load_intel_on_windows(toolchain) toolchain:set("toolset", "fcsh", "ifort.exe") toolchain:set("toolset", "ar", "link.exe") - -- add ifort environments - _add_ifortenv(toolchain, "PATH") - _add_ifortenv(toolchain, "LIB") - _add_ifortenv(toolchain, "INCLUDE") - _add_ifortenv(toolchain, "LIBPATH") - - -- add vs environments + -- add ifort and vs environments local expect_vars = {"PATH", "LIB", "INCLUDE", "LIBPATH"} local curenvs = os.getenvs() for _, name in ipairs(expect_vars) do _add_vsenv(toolchain, name, curenvs) + _add_ifortenv(toolchain, name, curenvs) end for _, name in ipairs(find_vstudio.get_vcvars()) do if not table.contains(expect_vars, name:upper()) then From be0dfd9660593047612afbad24a1c637c5883655 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 May 2024 23:00:06 +0800 Subject: [PATCH 07/10] fix ifort env --- xmake/toolchains/icx/load.lua | 2 +- xmake/toolchains/ifort/load.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/toolchains/icx/load.lua b/xmake/toolchains/icx/load.lua index f20ca31def..0e7d2a685c 100644 --- a/xmake/toolchains/icx/load.lua +++ b/xmake/toolchains/icx/load.lua @@ -61,7 +61,7 @@ function _add_icxenv(toolchain, name, curenvs) local icxenv = icxvarsall[arch] or {} -- get the paths for the icx environment - local new = icxvarsall[name] + local new = icxenv[name] if new then -- fix case naming conflict for cmake/msbuild between the new msvc envs and current environment, if we are running xmake in vs prompt. -- @see https://github.com/xmake-io/xmake/issues/4751 diff --git a/xmake/toolchains/ifort/load.lua b/xmake/toolchains/ifort/load.lua index 8eb6164751..2dadba2407 100644 --- a/xmake/toolchains/ifort/load.lua +++ b/xmake/toolchains/ifort/load.lua @@ -61,7 +61,7 @@ function _add_ifortenv(toolchain, name, curenvs) local ifortenv = ifortvarsall[arch] or {} -- get the paths for the ifort environment - local new = ifortvarsall[name] + local new = ifortenv[name] if new then -- fix case naming conflict for cmake/msbuild between the new msvc envs and current environment, if we are running xmake in vs prompt. -- @see https://github.com/xmake-io/xmake/issues/4751 From 476153ac1e36d99285fb16cd75eae2ce88932fff Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 May 2024 23:01:03 +0800 Subject: [PATCH 08/10] improve icl envs --- xmake/toolchains/icc/check.lua | 84 +++++++++++++++++++++++++++++++++- xmake/toolchains/icc/load.lua | 58 +++++++++++++++++++---- xmake/toolchains/icx/check.lua | 1 - 3 files changed, 132 insertions(+), 11 deletions(-) diff --git a/xmake/toolchains/icc/check.lua b/xmake/toolchains/icc/check.lua index 9dde538f08..9ca496a633 100644 --- a/xmake/toolchains/icc/check.lua +++ b/xmake/toolchains/icc/check.lua @@ -22,8 +22,90 @@ import("core.base.option") import("core.project.config") import("detect.sdks.find_iccenv") +import("detect.sdks.find_vstudio") import("lib.detect.find_tool") +-- attempt to check vs environment +function _check_vsenv(toolchain) + + -- has been checked? + local vs = toolchain:config("vs") or config.get("vs") + if vs then + vs = tostring(vs) + end + local vcvars = toolchain:config("vcvars") + if vs and vcvars then + return vs + end + + -- find vstudio + local vs_toolset = toolchain:config("vs_toolset") or config.get("vs_toolset") + local vs_sdkver = toolchain:config("vs_sdkver") or config.get("vs_sdkver") + local vstudio = find_vstudio({vcvars_ver = vs_toolset, sdkver = vs_sdkver}) + if vstudio then + + -- make order vsver + local vsvers = {} + for vsver, _ in pairs(vstudio) do + if not vs or vs ~= vsver then + table.insert(vsvers, vsver) + end + end + table.sort(vsvers, function (a, b) return tonumber(a) > tonumber(b) end) + if vs then + table.insert(vsvers, 1, vs) + end + + -- get vcvarsall + for _, vsver in ipairs(vsvers) do + local vcvarsall = (vstudio[vsver] or {}).vcvarsall or {} + 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 program + local paths + local pathenv = os.getenv("PATH") + if pathenv then + paths = path.splitenv(pathenv) + end + local tool = find_tool("cl.exe", {version = true, force = true, paths = paths, envs = vcvars}) + if tool then + program = tool.program + end + if program then + return vsver, tool + end + end + end + end +end + +-- check the visual studio +function _check_vstudio(toolchain) + local vs, cl = _check_vsenv(toolchain) + if vs then + if toolchain:is_global() then + config.set("vs", vs, {force = true, readonly = true}) + end + toolchain:config_set("vs", vs) + toolchain:configs_save() + cprint("checking for Microsoft Visual Studio (%s) version ... ${color.success}%s", toolchain:arch(), vs) + if cl and cl.version then + cprint("checking for LLVM Clang C/C++ Compiler (%s) version ... ${color.success}%s", toolchain:arch(), cl.version) + end + else + cprint("checking for Microsoft Visual Studio (%s) version ... ${color.nothing}${text.nothing}", toolchain:arch()) + end + return vs +end + -- check intel on windows function _check_intel_on_windows(toolchain) @@ -44,7 +126,7 @@ function _check_intel_on_windows(toolchain) cprint("checking for Intel C/C++ Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) toolchain:config_set("varsall", iclvarsall) toolchain:configs_save() - return true + return _check_vstudio(toolchain) end end end diff --git a/xmake/toolchains/icc/load.lua b/xmake/toolchains/icc/load.lua index e1ceba2604..21cb0170b0 100644 --- a/xmake/toolchains/icc/load.lua +++ b/xmake/toolchains/icc/load.lua @@ -21,9 +21,34 @@ -- imports import("core.base.option") import("core.project.config") +import("detect.sdks.find_vstudio") + +-- add the given vs environment +function _add_vsenv(toolchain, name, curenvs) + + -- get vcvars + local vcvars = toolchain:config("vcvars") + if not vcvars then + return + end + + -- get the paths for the vs environment + local new = vcvars[name] + if new then + -- fix case naming conflict for cmake/msbuild between the new msvc envs and current environment, if we are running xmake in vs prompt. + -- @see https://github.com/xmake-io/xmake/issues/4751 + for k, c in pairs(curenvs) do + if name:lower() == k:lower() and name ~= k then + name = k + break + end + end + toolchain:add("runenvs", name, table.unpack(path.splitenv(new))) + end +end -- add the given icl environment -function _add_iclenv(toolchain, name) +function _add_iclenv(toolchain, name, curenvs) -- get iclvarsall local iclvarsall = toolchain:config("varsall") @@ -36,9 +61,17 @@ function _add_iclenv(toolchain, name) local iclenv = iclvarsall[arch] or {} -- get the paths for the icl environment - local env = iclenv[name] - if env then - toolchain:add("runenvs", name:upper(), path.splitenv(env)) + local new = iclenv[name] + if new then + -- fix case naming conflict for cmake/msbuild between the new msvc envs and current environment, if we are running xmake in vs prompt. + -- @see https://github.com/xmake-io/xmake/issues/4751 + for k, c in pairs(curenvs) do + if name:lower() == k:lower() and name ~= k then + name = k + break + end + end + toolchain:add("runenvs", name, table.unpack(path.splitenv(new))) end end @@ -68,11 +101,18 @@ function _load_intel_on_windows(toolchain) toolchain:set("toolset", "as", "icc") end - -- add icl environments - _add_iclenv(toolchain, "PATH") - _add_iclenv(toolchain, "LIB") - _add_iclenv(toolchain, "INCLUDE") - _add_iclenv(toolchain, "LIBPATH") + -- add vs/icl environments + local expect_vars = {"PATH", "LIB", "INCLUDE", "LIBPATH"} + local curenvs = os.getenvs() + for _, name in ipairs(expect_vars) do + _add_vsenv(toolchain, name, curenvs) + _add_iclenv(toolchain, name, curenvs) + end + for _, name in ipairs(find_vstudio.get_vcvars()) do + if not table.contains(expect_vars, name:upper()) then + _add_vsenv(toolchain, name, curenvs) + end + end end -- load intel on linux diff --git a/xmake/toolchains/icx/check.lua b/xmake/toolchains/icx/check.lua index d2d7b2df94..c65e3ff817 100644 --- a/xmake/toolchains/icx/check.lua +++ b/xmake/toolchains/icx/check.lua @@ -106,7 +106,6 @@ function _check_vstudio(toolchain) return vs end - -- check intel on windows function _check_intel_on_windows(toolchain) From 31dae5851e114d2e183b6957e062f14831a73a82 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 May 2024 23:01:26 +0800 Subject: [PATCH 09/10] improve to find iccenv --- xmake/modules/detect/sdks/find_iccenv.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xmake/modules/detect/sdks/find_iccenv.lua b/xmake/modules/detect/sdks/find_iccenv.lua index 68428f6fbb..29a7bbb569 100644 --- a/xmake/modules/detect/sdks/find_iccenv.lua +++ b/xmake/modules/detect/sdks/find_iccenv.lua @@ -116,6 +116,12 @@ function _find_intel_on_windows(opt) "$(env ICPP_COMPILER23)" } iclvars_bat = find_file("../../../setvars.bat", paths) + if not iclvars_bat then + paths = { + "$(env ICPP_COMPILER24)" + } + iclvars_bat = find_file("../../setvars.bat", paths) + end end if iclvars_bat then From 2322a631b30ca69cd719e0acb1ba4ec735a26b81 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 May 2024 23:05:18 +0800 Subject: [PATCH 10/10] improve to find icx --- xmake/modules/detect/sdks/find_icxenv.lua | 29 +++++++---------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/xmake/modules/detect/sdks/find_icxenv.lua b/xmake/modules/detect/sdks/find_icxenv.lua index df0c50ddec..4e22934150 100644 --- a/xmake/modules/detect/sdks/find_icxenv.lua +++ b/xmake/modules/detect/sdks/find_icxenv.lua @@ -95,35 +95,22 @@ end -- find intel llvm c/c++ envirnoment on windows function _find_intel_on_windows(opt) - - -- init options opt = opt or {} -- find icxvars_bat.bat - local paths = {"$(env ICPP_COMPILER20)"} - local icxvars_bat = find_file("bin/icxvars.bat", paths) - -- look for setvars.bat which is new in 2021 - if not icxvars_bat then - -- find setvars.bat in intel oneapi toolkits rootdir - paths = {"$(env ONEAPI_ROOT)"} - icxvars_bat = find_file("setvars.bat", paths) - end + local paths = {"$(env ONEAPI_ROOT)"} + local icxvars_bat = find_file("setvars.bat", paths) if not icxvars_bat then - -- find setvars.bat using ICPP_COMPILER.* - paths = { - "$(env ICPP_COMPILER21)", - "$(env ICPP_COMPILER22)", - "$(env ICPP_COMPILER23)" - } - icxvars_bat = find_file("../../../setvars.bat", paths) + paths = {} + local keys = winos.registry_keys("HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Intel\\DPCPPSuites\\**\\DPC++") + for _, key in ipairs(keys) do + table.insert(paths, format("$(reg %s;ProductDir)", key)) + end + icxvars_bat = find_file("../../setvars.bat", paths) end if icxvars_bat then - - -- load icxvars_bat local icxvars_x86 = _load_icxvars(icxvars_bat, "ia32", opt) local icxvars_x64 = _load_icxvars(icxvars_bat, "intel64", opt) - - -- save results return {icxvars_bat = icxvars_bat, icxvars = {x86 = icxvars_x86, x64 = icxvars_x64}} end end