summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2025-10-17 09:42:46 +0800
committerGitHub <[email protected]>2025-10-17 09:42:46 +0800
commit3dabadefbaa64a385158305108a7802a6ad0a911 (patch)
treeb61c120b0ee976bcafe2e1ac6b1e6ffc61c4f458
parent4253fdd36cf2b4de908466b24da608a865fe9400 (diff)
parent61dda4e81f4c4328f49eaa439dd6fca4f94954a3 (diff)
Merge pull request #6924 from xmake-io/toolchain
Improve toolchain configs, add_toolchains("name[configs]")
-rw-r--r--tests/projects/package/toolchain_llvm_mingw/xmake.lua2
-rw-r--r--xmake/core/platform/platform.lua2
-rw-r--r--xmake/core/project/project.lua7
-rw-r--r--xmake/core/tool/toolchain.lua110
-rw-r--r--xmake/modules/detect/sdks/find_ndk.lua16
-rw-r--r--xmake/toolchains/mingw/xmake.lua40
-rw-r--r--xmake/toolchains/ndk/check.lua1
-rw-r--r--xmake/toolchains/ndk/load.lua23
8 files changed, 143 insertions, 58 deletions
diff --git a/tests/projects/package/toolchain_llvm_mingw/xmake.lua b/tests/projects/package/toolchain_llvm_mingw/xmake.lua
index da5c71225..57016326e 100644
--- a/tests/projects/package/toolchain_llvm_mingw/xmake.lua
+++ b/tests/projects/package/toolchain_llvm_mingw/xmake.lua
@@ -4,4 +4,4 @@ add_requires("llvm-mingw")
target("test")
set_kind("binary")
add_files("src/*.c")
- set_toolchains("mingw@llvm-mingw")
+ set_toolchains("mingw[clang]@llvm-mingw")
diff --git a/xmake/core/platform/platform.lua b/xmake/core/platform/platform.lua
index a06a45414..61fee4ec3 100644
--- a/xmake/core/platform/platform.lua
+++ b/xmake/core/platform/platform.lua
@@ -281,7 +281,7 @@ function _instance:check()
standalone = true
end
idx = idx + 1
- table.insert(toolchains_valid, toolchain:name())
+ table.insert(toolchains_valid, toolchain:fullname())
end
end
if #toolchains == 0 then
diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua
index 5af05c21f..8b94cbff7 100644
--- a/xmake/core/project/project.lua
+++ b/xmake/core/project/project.lua
@@ -1207,9 +1207,14 @@ end
-- get the given toolchain
function project.toolchain(name, opt)
opt = opt or {}
- local toolchain_name = toolchain.parsename(name) -- we need to ignore `@packagename`
+ local parseinfo = toolchain.parsename(name) -- we need to ignore `@packagename`
+ local toolchain_name = parseinfo.name
local info = project._toolchains()[toolchain_name]
if info == nil and opt.namespace then
+ local requirestr = parseinfo.requirestr
+ if requirestr then
+ toolchain_name = toolchain_name .. "[" .. requirestr .. "]"
+ end
info = project._toolchains()[opt.namespace .. "::" .. toolchain_name]
end
if info then
diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua
index 188bbdbdf..57b2f5073 100644
--- a/xmake/core/tool/toolchain.lua
+++ b/xmake/core/tool/toolchain.lua
@@ -40,8 +40,11 @@ local sandbox = require("sandbox/sandbox")
local sandbox_module = require("sandbox/modules/import/core/sandbox/module")
-- new an instance
-function _instance.new(name, info, cachekey, is_builtin, configs)
- local instance = table.inherit(_instance)
+function _instance.new(name, info, opt)
+ opt = opt or {}
+ local cachekey = opt.cachekey
+ local configs = opt.configs
+ local instance = table.inherit(_instance)
local parts = name:split("::", {plain = true})
instance._NAME = parts[#parts]
table.remove(parts)
@@ -49,7 +52,8 @@ function _instance.new(name, info, cachekey, is_builtin, configs)
instance._NAMESPACE = table.concat(parts, "::")
end
instance._INFO = info
- instance._IS_BUILTIN = is_builtin
+ instance._REQUIRESTR = opt.requirestr
+ instance._IS_BUILTIN = opt.is_builtin
instance._CACHE = toolchain._localcache()
instance._CACHEKEY = cachekey
local toolchain_configs = instance._CACHE:get(cachekey)
@@ -86,7 +90,12 @@ end
-- get the full name
function _instance:fullname()
local namespace = self:namespace()
- return namespace and namespace .. "::" .. self:name() or self:name()
+ local name = self:name()
+ local requirestr = self._REQUIRESTR
+ if requirestr then
+ name = name .. "[" .. requirestr .. "]"
+ end
+ return namespace and namespace .. "::" .. name or name
end
-- get toolchain platform
@@ -592,11 +601,19 @@ function toolchain._cachekey(name, opt)
return cachekey
end
--- parse toolchain and package name
+-- parse toolchain, configs and package name
+--
+-- formats:
+--
+-- 1. only toolchain name
+-- e.g. clang, gcc
--
--- format: toolchain@package
+-- 2. toolchain@package
-- e.g. "clang@llvm-10", "@muslcc", zig
--
+-- 3. toolchain[configs]@package
+-- e.g. "mingw[clang]@llvm-mingw", "msvc[vs=2025,..]"
+--
function toolchain.parsename(name)
local splitinfo = name:split('@', {plain = true, strict = true})
local toolchain_name = splitinfo[1]
@@ -607,7 +624,34 @@ function toolchain.parsename(name)
if packages == "" then
packages = nil
end
- return toolchain_name or packages, packages
+ local requireconfs, requirestr
+ if toolchain_name then
+ local toolchain_name_raw, configs_str = toolchain_name:match("(.-)%[(.*)%]")
+ if toolchain_name_raw and configs_str then
+ configs_str = configs_str:gsub("%[(.*)%]", function (w)
+ return w:replace(",", ":")
+ end)
+ requirestr = configs_str
+ toolchain_name = toolchain_name_raw
+ local splitinfo = configs_str:split(",", {plain = true})
+ for _, v in ipairs(splitinfo) do
+ local parts = v:split("=", {plain = true})
+ local k = parts[1]
+ v = parts[2]
+ requireconfs = requireconfs or {}
+ if v then
+ if v:find(":", 1 ,true) then
+ requireconfs[k] = v:split(":", {plain = true})
+ else
+ requireconfs[k] = option.boolean(v)
+ end
+ else
+ requireconfs[k] = true
+ end
+ end
+ end
+ end
+ return {name = toolchain_name or packages, packages = packages, requireconfs = requireconfs, requirestr = requirestr}
end
-- get toolchain apis
@@ -663,18 +707,22 @@ end
-- load toolchain
function toolchain.load(name, opt)
-
- -- get toolchain name and packages
opt = opt or {}
- local packages
- name, packages = toolchain.parsename(name)
- opt.packages = opt.packages or packages
+
+ -- parse toolchain name
+ local parseinfo = toolchain.parsename(name)
+ name = parseinfo.name
+
+ -- init configs
+ local configs = parseinfo.requireconfs or {}
+ table.join2(configs, opt)
+ configs.packages = opt.packages or parseinfo.packages
+ configs.plat = opt.plat or config.get("plat") or os.host()
+ configs.arch = opt.arch or config.get("arch") or os.arch()
-- get cache
- opt.plat = opt.plat or config.get("plat") or os.host()
- opt.arch = opt.arch or config.get("arch") or os.arch()
local cache = toolchain._memcache()
- local cachekey = toolchain._cachekey(name, opt)
+ local cachekey = toolchain._cachekey(name, configs)
-- get it directly from cache dirst
local instance = cache:get(cachekey)
@@ -709,32 +757,37 @@ function toolchain.load(name, opt)
return nil, errors
end
- -- check the toolchain name
- local result = results[name]
- if not result then
+ -- get toolchain info
+ local info = results[name]
+ if not info then
return nil, string.format("the toolchain %s not found!", name)
end
-- save instance to the cache
- instance = _instance.new(name, result, cachekey, true, opt)
+ instance = _instance.new(name, info, {cachekey = cachekey,
+ is_builtin = true, configs = configs, requirestr = parseinfo.requirestr})
cache:set(cachekey, instance)
return instance
end
-- load toolchain from the give toolchain info
function toolchain.load_withinfo(name, info, opt)
-
- -- get toolchain name and packages
opt = opt or {}
- local packages
- name, packages = toolchain.parsename(name)
- opt.packages = opt.packages or packages
+
+ -- parse toolchain name
+ local parseinfo = toolchain.parsename(name)
+ name = parseinfo.name
+
+ -- init configs
+ local configs = parseinfo.requireconfs or {}
+ table.join2(configs, opt)
+ configs.packages = opt.packages or parseinfo.packages
+ configs.plat = opt.plat or config.get("plat") or os.host()
+ configs.arch = opt.arch or config.get("arch") or os.arch()
-- get cache key
- opt.plat = opt.plat or config.get("plat") or os.host()
- opt.arch = opt.arch or config.get("arch") or os.arch()
local cache = toolchain._memcache()
- local cachekey = toolchain._cachekey(name, opt)
+ local cachekey = toolchain._cachekey(name, configs)
-- get it directly from cache dirst
local instance = cache:get(cachekey)
@@ -743,7 +796,8 @@ function toolchain.load_withinfo(name, info, opt)
end
-- save instance to the cache
- instance = _instance.new(name, info, cachekey, false, opt)
+ instance = _instance.new(name, info, {cachekey = cachekey,
+ is_builtin = false, configs = configs, requirestr = parseinfo.requirestr})
cache:set(cachekey, instance)
return instance
end
diff --git a/xmake/modules/detect/sdks/find_ndk.lua b/xmake/modules/detect/sdks/find_ndk.lua
index 0ac0a4f83..43d822845 100644
--- a/xmake/modules/detect/sdks/find_ndk.lua
+++ b/xmake/modules/detect/sdks/find_ndk.lua
@@ -158,7 +158,13 @@ function _find_ndk_sysroot(sdkdir)
end
-- find the ndk toolchain
-function _find_ndk(sdkdir, arch, ndk_sdkver, ndk_toolchains_ver)
+function _find_ndk(opt)
+ opt = opt or {}
+ local arch = opt.arch
+ local sdkdir = opt.sdkdir
+ local ndk_sdkver = opt.ndk_sdkver
+ local ndk_toolchains_ver = opt.ndk_toolchains_ver
+ local compiler = opt.compiler
-- find ndk root directory
sdkdir = _find_ndkdir(sdkdir)
@@ -204,7 +210,7 @@ function _find_ndk(sdkdir, arch, ndk_sdkver, ndk_toolchains_ver)
local llvm_toolchain
local prebuilt = (is_host("macosx") and "darwin" or os.host()) .. "-x86_64"
local bindir = find_directory("bin", path.join(sdkdir, "toolchains", "llvm", "prebuilt", prebuilt)) -- larger than ndk r16
- if bindir then
+ if bindir and compiler ~= "gcc" then
llvm_toolchain = path.directory(bindir)
else
bindir = find_directory("bin", path.join(sdkdir, "toolchains", gcc_toolchain_subdir, "prebuilt", "*"))
@@ -285,7 +291,11 @@ function main(sdkdir, opt)
local arch = opt.arch or config.get("arch") or "armeabi-v7a"
-- find ndk
- local ndk = _find_ndk(sdkdir or config.get("ndk") or global.get("ndk"), arch, opt.sdkver or config.get("ndk_sdkver"), opt.toolchains_ver or config.get("ndk_toolchains_ver"))
+ local ndk = _find_ndk({sdkdir = sdkdir or config.get("ndk") or global.get("ndk"),
+ arch = arch,
+ ndk_sdkver = opt.sdkver or config.get("ndk_sdkver"),
+ ndk_toolchains_ver = opt.toolchains_ver or config.get("ndk_toolchains_ver"),
+ compiler = opt.compiler})
if ndk and ndk.sdkdir then
config.set("ndk", ndk.sdkdir, {force = true, readonly = true})
config.set("ndkver", ndk.ndkver, {force = true, readonly = true})
diff --git a/xmake/toolchains/mingw/xmake.lua b/xmake/toolchains/mingw/xmake.lua
index 13690b14f..5c63cb734 100644
--- a/xmake/toolchains/mingw/xmake.lua
+++ b/xmake/toolchains/mingw/xmake.lua
@@ -26,7 +26,9 @@ toolchain("mingw")
on_check("check")
on_load(function (toolchain)
- import("core.project.config")
+
+ -- use clang for llvm-mingw?
+ local use_clang = toolchain:config("clang")
-- get cross
local cross
@@ -49,34 +51,38 @@ toolchain("mingw")
end
-- set toolset
+ local cc = use_clang and "clang" or "gcc"
+ local cxx = use_clang and "clang++" or "g++"
+ local ar = use_clang and "llvm-ar" or "ar"
+ local ranlib = use_clang and "llvm-ranlib" or "ranlib"
if is_host("windows") and bindir then
-- @note we uses bin/ar.exe instead of bin/cross-gcc-ar.exe, @see https://github.com/xmake-io/xmake/issues/807#issuecomment-635779210
- toolchain:add("toolset", "ar", path.join(bindir, "ar"))
+ toolchain:add("toolset", "ar", path.join(bindir, ar))
toolchain:add("toolset", "strip", path.join(bindir, "strip"))
- toolchain:add("toolset", "ranlib", path.join(bindir, "ranlib"))
+ toolchain:add("toolset", "ranlib", path.join(bindir, ranlib))
toolchain:add("toolset", "objcopy", path.join(bindir, "objcopy"))
end
- toolchain:add("toolset", "cc", cross .. "gcc")
- toolchain:add("toolset", "cxx", cross .. "g++", cross .. "gcc")
- toolchain:add("toolset", "cpp", cross .. "gcc -E")
- toolchain:add("toolset", "as", cross .. "gcc")
- toolchain:add("toolset", "ld", cross .. "g++", cross .. "gcc")
- toolchain:add("toolset", "sh", cross .. "g++", cross .. "gcc")
- toolchain:add("toolset", "ar", cross .. "ar")
+ toolchain:add("toolset", "cc", cross .. cc)
+ toolchain:add("toolset", "cxx", cross .. cxx, cross .. cc)
+ toolchain:add("toolset", "cpp", cross .. cc .. " -E")
+ toolchain:add("toolset", "as", cross .. cc)
+ toolchain:add("toolset", "ld", cross .. cxx, cross .. cc)
+ toolchain:add("toolset", "sh", cross .. cxx, cross .. cc)
+ toolchain:add("toolset", "ar", cross .. ar)
toolchain:add("toolset", "strip", cross .. "strip")
- toolchain:add("toolset", "ranlib", cross .. "ranlib")
+ toolchain:add("toolset", "ranlib", cross .. ranlib)
toolchain:add("toolset", "objcopy", cross .. "objcopy")
toolchain:add("toolset", "mrc", cross .. "windres")
toolchain:add("toolset", "dlltool", cross .. "dlltool")
if is_host("windows") and bindir then
-- we use bin/gcc.exe if cross not found
-- @see https://github.com/xmake-io/xmake/issues/977#issuecomment-704863677
- toolchain:add("toolset", "cc", path.join(bindir, "gcc"))
- toolchain:add("toolset", "cxx", path.join(bindir, "g++"), path.join(bindir, "gcc"))
- toolchain:add("toolset", "cpp", path.join(bindir, "gcc -E"))
- toolchain:add("toolset", "as", path.join(bindir, "gcc"))
- toolchain:add("toolset", "ld", path.join(bindir, "g++"), path.join(bindir, "gcc"))
- toolchain:add("toolset", "sh", path.join(bindir, "g++"), path.join(bindir, "gcc"))
+ toolchain:add("toolset", "cc", path.join(bindir, cc))
+ toolchain:add("toolset", "cxx", path.join(bindir, cxx), path.join(bindir, cc))
+ toolchain:add("toolset", "cpp", path.join(bindir, cc .. " -E"))
+ toolchain:add("toolset", "as", path.join(bindir, cc))
+ toolchain:add("toolset", "ld", path.join(bindir, cxx), path.join(bindir, cc))
+ toolchain:add("toolset", "sh", path.join(bindir, cxx), path.join(bindir, cc))
toolchain:add("toolset", "mrc", path.join(bindir, "windres"))
toolchain:add("toolset", "dlltool", path.join(bindir, "dlltool"))
end
diff --git a/xmake/toolchains/ndk/check.lua b/xmake/toolchains/ndk/check.lua
index 2845623c1..dc929085e 100644
--- a/xmake/toolchains/ndk/check.lua
+++ b/xmake/toolchains/ndk/check.lua
@@ -43,6 +43,7 @@ function _check_ndk(toolchain)
ndk = find_ndk(toolchain:config("ndk") or config.get("ndk"), {force = true, verbose = true,
plat = toolchain:plat(),
arch = toolchain:arch(),
+ compiler = toolchain:config("gcc") and "gcc" or "clang",
sdkver = toolchain:config("sdkver")})
end
if ndk then
diff --git a/xmake/toolchains/ndk/load.lua b/xmake/toolchains/ndk/load.lua
index 5a3c0ed4d..cee7f8c3e 100644
--- a/xmake/toolchains/ndk/load.lua
+++ b/xmake/toolchains/ndk/load.lua
@@ -85,16 +85,25 @@ function main(toolchain)
local ndk_sdkver = toolchain:config("ndk_sdkver")
-- set toolset
- toolchain:set("toolset", "cc", "clang", cross .. "gcc")
- toolchain:set("toolset", "cxx", "clang++", cross .. "g++")
- toolchain:set("toolset", "cpp", "clang -E", cross .. "gcc -E")
- toolchain:set("toolset", "as", "clang", cross .. "gcc")
- toolchain:set("toolset", "ld", "clang++", "clang", cross .. "g++", cross .. "gcc")
- toolchain:set("toolset", "sh", "clang++", "clang", cross .. "g++", cross .. "gcc")
+ local use_gcc = toolchain:config("gcc")
+ if use_gcc then
+ toolchain:set("toolset", "cc", cross .. "gcc")
+ toolchain:set("toolset", "cxx", cross .. "g++")
+ toolchain:set("toolset", "cpp", cross .. "gcc -E")
+ toolchain:set("toolset", "as", cross .. "gcc")
+ toolchain:set("toolset", "ld", cross .. "g++", cross .. "gcc")
+ toolchain:set("toolset", "sh", cross .. "g++", cross .. "gcc")
+ else
+ toolchain:set("toolset", "cc", "clang", cross .. "gcc")
+ toolchain:set("toolset", "cxx", "clang++", cross .. "g++")
+ toolchain:set("toolset", "cpp", "clang -E", cross .. "gcc -E")
+ toolchain:set("toolset", "as", "clang", cross .. "gcc")
+ toolchain:set("toolset", "ld", "clang++", "clang", cross .. "g++", cross .. "gcc")
+ toolchain:set("toolset", "sh", "clang++", "clang", cross .. "g++", cross .. "gcc")
+ end
toolchain:set("toolset", "ar", gcc_toolchain_bin and path.join(gcc_toolchain_bin, cross .. "ar") or (cross .. "ar"), "llvm-ar")
toolchain:set("toolset", "ranlib", gcc_toolchain_bin and path.join(gcc_toolchain_bin, cross .. "ranlib") or (cross .. "ranlib"))
toolchain:set("toolset", "strip", gcc_toolchain_bin and path.join(gcc_toolchain_bin, cross .. "strip") or (cross .. "strip"), "llvm-strip")
-
-- gnustl and stlport have been removed in ndk r18 (deprecated in ndk r17)
-- https://github.com/android/ndk/wiki/Changelog-r18
local old_runtimes = {"gnustl_static", "gnustl_shared", "stlport_static", "stlport_shared"}