diff options
| author | ruki <[email protected]> | 2025-10-17 09:42:46 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-10-17 09:42:46 +0800 |
| commit | 3dabadefbaa64a385158305108a7802a6ad0a911 (patch) | |
| tree | b61c120b0ee976bcafe2e1ac6b1e6ffc61c4f458 | |
| parent | 4253fdd36cf2b4de908466b24da608a865fe9400 (diff) | |
| parent | 61dda4e81f4c4328f49eaa439dd6fca4f94954a3 (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.lua | 2 | ||||
| -rw-r--r-- | xmake/core/platform/platform.lua | 2 | ||||
| -rw-r--r-- | xmake/core/project/project.lua | 7 | ||||
| -rw-r--r-- | xmake/core/tool/toolchain.lua | 110 | ||||
| -rw-r--r-- | xmake/modules/detect/sdks/find_ndk.lua | 16 | ||||
| -rw-r--r-- | xmake/toolchains/mingw/xmake.lua | 40 | ||||
| -rw-r--r-- | xmake/toolchains/ndk/check.lua | 1 | ||||
| -rw-r--r-- | xmake/toolchains/ndk/load.lua | 23 |
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"} |
