Skip to content

Commit

Permalink
Merge pull request #5643 from xmake-io/toolchain
Browse files Browse the repository at this point in the history
improve host toolchain #5639
  • Loading branch information
waruqi committed Sep 25, 2024
2 parents dc097d1 + 3f025d4 commit 2a4c217
Show file tree
Hide file tree
Showing 16 changed files with 224 additions and 133 deletions.
6 changes: 6 additions & 0 deletions xmake/actions/config/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ task("config")
, " - xmake f --toolchain=[cross|llvm|sdcc ..] --sdk=/xxx"
, " - run `xmake show -l toolchains` to get all toolchains"
, values = _toolchain_values},
{nil, "toolchain_host", "kv", nil, "Set host toolchain name, it's only for building packages on host machine."
, "e.g. "
, " - xmake f --toolchain_host=clang"
, " - xmake f --toolchain_host=[cross|llvm|sdcc ..] --sdk=/xxx"
, " - run `xmake show -l toolchains` to get all toolchains"
, values = _toolchain_values},
{nil, "runtimes", "kv", nil, "Set the compiler runtime library."
, "e.g. "
, " - xmake f --runtimes=MTd"
Expand Down
45 changes: 29 additions & 16 deletions xmake/core/package/package.lua
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,7 @@ function _instance:plat()
if self._PLAT then
return self._PLAT
end
-- @note we uses os.host() instead of them for the binary package
if self:is_binary() then
if self:is_host() then
return os.subhost()
end
local requireinfo = self:requireinfo()
Expand All @@ -182,8 +181,7 @@ function _instance:arch()
if self._ARCH then
return self._ARCH
end
-- @note we uses os.arch() instead of them for the binary package
if self:is_binary() then
if self:is_host() then
return os.subarch()
end
return self:targetarch()
Expand Down Expand Up @@ -668,6 +666,31 @@ function _instance:is_local()
return self._IS_LOCAL or self:is_source_embed() or self:is_binary_embed() or self:is_thirdparty()
end

-- is debug package? (deprecated)
function _instance:debug()
return self:is_debug()
end

-- is host package?
--
-- @note It is different from not is_cross() in that users do not use host packages directly,
-- they are usually used to build library packages.
function _instance:is_host()
local requireinfo = self:requireinfo()
if requireinfo and requireinfo.host then
return true
end
return self:is_binary()
end

-- is cross-compilation?
function _instance:is_cross()
if self:is_host() then
return false
end
return is_cross(self:plat(), self:arch())
end

-- mark it as local package
function _instance:_mark_as_local(is_local)
if self:is_local() ~= is_local then
Expand Down Expand Up @@ -699,16 +722,6 @@ function _instance:use_external_includes()
return external
end

-- is debug package? (deprecated)
function _instance:debug()
return self:is_debug()
end

-- is cross-compilation?
function _instance:is_cross()
return is_cross(self:plat(), self:arch())
end

-- get the filelock of the whole package directory
function _instance:filelock()
local filelock = self._FILELOCK
Expand Down Expand Up @@ -1267,7 +1280,7 @@ function _instance:tool(toolkind)
local cachekey = "package_" .. tostring(self)
return toolchain.tool(self:toolchains(), toolkind, {cachekey = cachekey, plat = self:plat(), arch = self:arch()})
else
return platform.tool(toolkind, self:plat(), self:arch())
return platform.tool(toolkind, self:plat(), self:arch(), {host = self:is_host()})
end
end

Expand All @@ -1277,7 +1290,7 @@ function _instance:toolconfig(name)
local cachekey = "package_" .. tostring(self)
return toolchain.toolconfig(self:toolchains(), name, {cachekey = cachekey, plat = self:plat(), arch = self:arch()})
else
return platform.toolconfig(name, self:plat(), self:arch())
return platform.toolconfig(name, self:plat(), self:arch(), {host = self:is_host()})
end
end

Expand Down
53 changes: 34 additions & 19 deletions xmake/core/platform/platform.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,22 @@ local os = require("base/os")
local path = require("base/path")
local utils = require("base/utils")
local table = require("base/table")
local global = require("base/global")
local interpreter = require("base/interpreter")
local toolchain = require("tool/toolchain")
local memcache = require("cache/memcache")
local sandbox = require("sandbox/sandbox")
local config = require("project/config")
local global = require("base/global")
local scheduler = require("sandbox/modules/import/core/base/scheduler")

-- new an instance
function _instance.new(name, arch, info)
function _instance.new(name, info, opt)
opt = opt or{}
local instance = table.inherit(_instance)
instance._NAME = name
instance._ARCH = arch
instance._INFO = info
instance._ARCH = opt.arch
instance._IS_HOST = opt.host or false
return instance
end

Expand All @@ -54,6 +56,11 @@ function _instance:_memcache()
return cache
end

-- the toolchains cache key for names
function _instance:_toolchains_key()
return "__toolchains_" .. self:name() .. "_" .. self:arch() .. (self:is_host() and "_host" or "")
end

-- get platform name
function _instance:name()
return self._NAME
Expand All @@ -74,6 +81,11 @@ function _instance:arch_set(arch)
end
end

-- is host platform, it will use the host toolchain
function _instance:is_host()
return self._IS_HOST
end

-- set the value to the platform configuration
function _instance:set(name, ...)
self._INFO:apival_set(name, ...)
Expand Down Expand Up @@ -157,11 +169,11 @@ function _instance:toolchains(opt)
local names = nil
toolchains = {}
if not (opt and opt.all) then
names = config.get("__toolchains_" .. self:name() .. "_" .. self:arch())
names = config.get(self:_toolchains_key())
end
if not names then
-- get the given toolchain
local toolchain_given = config.get("toolchain")
local toolchain_given = config.get(self:is_host() and "toolchain_host" or "toolchain")
if toolchain_given then
local toolchain_inst, errors = toolchain.load(toolchain_given, {
plat = self:name(), arch = self:arch()})
Expand Down Expand Up @@ -192,7 +204,10 @@ function _instance:toolchains(opt)
if not toolchain_inst then
os.raise(errors)
end
table.insert(toolchains, toolchain_inst)
-- ignore cross toolchains for the host platform:w
if (self:is_host() and not toolchain_inst:is_cross()) or not self:is_host() then
table.insert(toolchains, toolchain_inst)
end
end
end
self:_memcache():set("toolchains", toolchains)
Expand Down Expand Up @@ -276,7 +291,7 @@ function _instance:check()
end

-- save valid toolchains
config.set("__toolchains_" .. self:name() .. "_" .. self:arch(), toolchains_valid)
config.set(self:_toolchains_key(), toolchains_valid)
self:_memcache():set("checked", true)
scheduler.co_unlock(lockname)
return true
Expand Down Expand Up @@ -407,14 +422,16 @@ function platform.add_directories(...)
end

-- load the given platform
function platform.load(plat, arch)

-- get platform name
function platform.load(plat, arch, opt)
opt = opt or {}
plat = plat or config.get("plat") or os.host()
arch = arch or config.get("arch") or os.arch()

-- get cache key
local cachekey = plat .. "_" .. arch
if opt.host then
cachekey = cachekey .. "_host"
end

-- get it directly from cache dirst
platform._PLATFORMS = platform._PLATFORMS or {}
Expand All @@ -425,8 +442,6 @@ function platform.load(plat, arch)
-- find the platform script path
local scriptpath = nil
for _, dir in ipairs(platform.directories()) do

-- find this directory
scriptpath = path.join(dir, plat, "xmake.lua")
if os.isfile(scriptpath) then
break
Expand Down Expand Up @@ -469,14 +484,14 @@ function platform.load(plat, arch)
end

-- save instance to the cache
local instance = _instance.new(plat, arch, result)
local instance = _instance.new(plat, result, {arch = arch, host = opt.host})
platform._PLATFORMS[cachekey] = instance
return instance
end

-- get the given platform configuration
function platform.get(name, plat, arch)
local instance, errors = platform.load(plat, arch)
function platform.get(name, plat, arch, opt)
local instance, errors = platform.load(plat, arch, opt)
if instance then
return instance:get(name)
else
Expand All @@ -488,8 +503,8 @@ end
--
-- e.g. cc, cxx, mm, mxx, as, ar, ld, sh, ..
--
function platform.tool(toolkind, plat, arch)
local instance, errors = platform.load(plat, arch)
function platform.tool(toolkind, plat, arch, opt)
local instance, errors = platform.load(plat, arch, opt)
if instance then
return instance:tool(toolkind)
else
Expand All @@ -498,8 +513,8 @@ function platform.tool(toolkind, plat, arch)
end

-- get the given tool configuration
function platform.toolconfig(name, plat, arch)
local instance, errors = platform.load(plat, arch)
function platform.toolconfig(name, plat, arch, opt)
local instance, errors = platform.load(plat, arch, opt)
if instance then
return instance:toolconfig(name)
else
Expand Down
16 changes: 8 additions & 8 deletions xmake/core/sandbox/modules/import/core/platform/platform.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ local platform = require("platform/platform")
local raise = require("sandbox/modules/raise")

-- load the current platform
function sandbox_core_platform.load(plat, arch)
local instance, errors = platform.load(plat, arch)
function sandbox_core_platform.load(plat, arch, opt)
local instance, errors = platform.load(plat, arch, opt)
if not instance then
raise(errors)
end
Expand Down Expand Up @@ -55,21 +55,21 @@ function sandbox_core_platform.archs(plat, arch)
end

-- get the current platform configuration
function sandbox_core_platform.get(name, plat, arch)
return platform.get(name, plat, arch)
function sandbox_core_platform.get(name, plat, arch, opt)
return platform.get(name, plat, arch, opt)
end

-- get the platform tool from the kind
--
-- e.g. cc, cxx, mm, mxx, as, ar, ld, sh, ..
--
function sandbox_core_platform.tool(toolkind, plat, arch)
return platform.tool(toolkind, plat, arch)
function sandbox_core_platform.tool(toolkind, plat, arch, opt)
return platform.tool(toolkind, plat, arch, opt)
end

-- get the current platform tool configuration
function sandbox_core_platform.toolconfig(name, plat, arch)
return platform.toolconfig(name, plat, arch)
function sandbox_core_platform.toolconfig(name, plat, arch, opt)
return platform.toolconfig(name, plat, arch, opt)
end

-- return module
Expand Down
12 changes: 11 additions & 1 deletion xmake/core/tool/compiler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,18 @@ function compiler._load_tool(sourcekind, target)
program, toolname, toolchain_info = target:tool(sourcekind)
end

-- is host?
local is_host
if target and target.is_host then
is_host = target:is_host()
end

-- load the compiler tool from the source kind
local result, errors = tool.load(sourcekind, {program = program, toolname = toolname, toolchain_info = toolchain_info})
local result, errors = tool.load(sourcekind, {
host = is_host,
program = program,
toolname = toolname,
toolchain_info = toolchain_info})
if not result then
return nil, errors
end
Expand Down
12 changes: 11 additions & 1 deletion xmake/core/tool/linker.lua
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,18 @@ function linker._load_tool(targetkind, sourcekinds, target)
program, toolname, toolchain_info = target:tool(_linkerinfo.linkerkind)
end

-- is host?
local is_host
if target and target.is_host then
is_host = target:is_host()
end

-- load the linker tool from the linker kind (with cache)
linkertool, errors = tool.load(_linkerinfo.linkerkind, {program = program, toolname = toolname, toolchain_info = toolchain_info})
linkertool, errors = tool.load(_linkerinfo.linkerkind, {
host = is_host,
program = program,
toolname = toolname,
toolchain_info = toolchain_info})
if linkertool then
linkerinfo = _linkerinfo
linkerinfo.program = program
Expand Down
6 changes: 2 additions & 4 deletions xmake/core/tool/tool.lua
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,6 @@ end
-- @param opt.toolchain_info the toolchain info (optional)
--
function tool.load(kind, opt)

-- get tool information
opt = opt or {}
local program = opt.program
local toolname = opt.toolname
Expand All @@ -249,7 +247,7 @@ function tool.load(kind, opt)
local arch = toolchain_info.arch or config.get("arch") or os.arch()

-- init cachekey
local cachekey = kind .. (program or "") .. plat .. arch
local cachekey = kind .. (program or "") .. plat .. arch .. (opt.host and "host" or "")

-- get it directly from cache dirst
tool._TOOLS = tool._TOOLS or {}
Expand All @@ -273,7 +271,7 @@ function tool.load(kind, opt)

-- get the tool program and name
if not program then
program, toolname, toolchain_info = platform.tool(kind, plat, arch)
program, toolname, toolchain_info = platform.tool(kind, plat, arch, {host = opt.host})
if toolchain_info then
assert(toolchain_info.plat == plat)
assert(toolchain_info.arch == arch)
Expand Down
2 changes: 1 addition & 1 deletion xmake/core/tool/toolchain.lua
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ end
function _instance:is_cross()
if self:kind() == "cross" then
return true
elseif self:kind() == "standalone" and (self:cross() or self:sdkdir()) then
elseif self:kind() == "standalone" and (self:cross() or self:config("sdkdir") or self:info():get("sdkdir")) then
return true
end
end
Expand Down
13 changes: 11 additions & 2 deletions xmake/modules/private/action/require/impl/install_packages.lua
Original file line number Diff line number Diff line change
Expand Up @@ -738,9 +738,18 @@ function _install_packages(requires, opt)

-- exists unsupported packages?
if #packages_unsupported > 0 then
cprint("${bright color.warning}note: ${clear}the following packages are unsupported on $(plat)/$(arch):")
local packages_unsupported_maps = {}
for _, instance in ipairs(packages_unsupported) do
print(" -> %s %s", instance:displayname(), instance:version_str() or "")
local key = instance:plat() .. "/" .. instance:arch()
packages_unsupported_maps[key] = packages_unsupported_maps[key] or {}
table.insert(packages_unsupported_maps[key], instance)
end
for key, instances in pairs(packages_unsupported_maps) do
cprint("${bright color.warning}note: ${clear}the following packages are unsupported on %s:", key)
for _, instance in ipairs(instances) do
cprint(" ${yellow}->${clear} %s %s ${dim}%s",
instance:displayname(), instance:version_str() or "", package.get_configs_str(instance))
end
end
has_errors = true
end
Expand Down
Loading

0 comments on commit 2a4c217

Please sign in to comment.