diff options
| author | ruki <[email protected]> | 2020-06-23 22:37:44 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-06-23 22:37:44 +0800 |
| commit | c18d15eb89116a0f3ce96bd56f3ccf861849f6ec (patch) | |
| tree | 52b63db3274349f9a41872414208c7c30058cfd7 /xmake/core/tool | |
| parent | 53df324acd9c7432336a5894ceef578daa1ce38d (diff) | |
| parent | 18bded45c229f5580c13fc8b4afc5edb6f18819a (diff) | |
Merge pull request #857 from xmake-io/toolchain
Improve toolchain to support host and cross toolchains at same time
Diffstat (limited to 'xmake/core/tool')
| -rw-r--r-- | xmake/core/tool/builder.lua | 10 | ||||
| -rw-r--r-- | xmake/core/tool/compiler.lua | 8 | ||||
| -rw-r--r-- | xmake/core/tool/linker.lua | 6 | ||||
| -rw-r--r-- | xmake/core/tool/tool.lua | 82 | ||||
| -rw-r--r-- | xmake/core/tool/toolchain.lua | 104 |
5 files changed, 156 insertions, 54 deletions
diff --git a/xmake/core/tool/builder.lua b/xmake/core/tool/builder.lua index 03a9f34ed..d8a01ba2a 100644 --- a/xmake/core/tool/builder.lua +++ b/xmake/core/tool/builder.lua @@ -383,6 +383,16 @@ function builder:program() return self:_tool():program() end +-- get toolchain of this tool +function builder:toolchain() + return self:_tool():toolchain() +end + +-- get the run environments +function builder:runenvs() + return self:_tool():runenvs() +end + -- get properties of the tool function builder:get(name) return self:_tool():get(name) diff --git a/xmake/core/tool/compiler.lua b/xmake/core/tool/compiler.lua index e56f2d300..c47ffb9e1 100644 --- a/xmake/core/tool/compiler.lua +++ b/xmake/core/tool/compiler.lua @@ -78,13 +78,13 @@ end function compiler._load_tool(sourcekind, target) -- get program from target - local program, toolname + local program, toolname, toolchain_info if target and target:type() == "target" then - program, toolname = target:tool(sourcekind) + program, toolname, toolchain_info = target:tool(sourcekind) end -- load the compiler tool from the source kind - local result, errors = tool.load(sourcekind, program, toolname) + local result, errors = tool.load(sourcekind, {program = program, toolname = toolname, toolchain_info = toolchain_info}) if not result then return nil, errors end @@ -236,7 +236,7 @@ function compiler:compile(sourcefiles, objectfile, opt) end -- compile it - return sandbox.load(self:_tool().compile, self:_tool(), sourcefiles, objectfile, opt.dependinfo, compflags) + return sandbox.load(self:_tool().compile, self:_tool(), sourcefiles, objectfile, opt.dependinfo, compflags, opt) end -- get the compile arguments list diff --git a/xmake/core/tool/linker.lua b/xmake/core/tool/linker.lua index baafde7ae..06ae051cb 100644 --- a/xmake/core/tool/linker.lua +++ b/xmake/core/tool/linker.lua @@ -85,13 +85,13 @@ function linker._load_tool(targetkind, sourcekinds, target) for _, _linkerinfo in ipairs(linkerinfos) do -- get program from target - local program, toolname + local program, toolname, toolchain_info if target and target:type() == "target" then - program, toolname = target:tool(_linkerinfo.linkerkind) + program, toolname, toolchain_info = target:tool(_linkerinfo.linkerkind) end -- load the linker tool from the linker kind (with cache) - linkertool, errors = tool.load(_linkerinfo.linkerkind, program, toolname) + linkertool, errors = tool.load(_linkerinfo.linkerkind, {program = program, toolname = toolname, toolchain_info = toolchain_info}) if linkertool then linkerinfo = _linkerinfo linkerinfo.program = program diff --git a/xmake/core/tool/tool.lua b/xmake/core/tool/tool.lua index 9e6dec6d4..b8eb29ddd 100644 --- a/xmake/core/tool/tool.lua +++ b/xmake/core/tool/tool.lua @@ -30,16 +30,17 @@ local table = require("base/table") local string = require("base/string") local config = require("project/config") local sandbox = require("sandbox/sandbox") +local toolchain = require("tool/toolchain") local platform = require("platform/platform") local import = require("sandbox/modules/import") -- new an instance -function _instance.new(kind, name, program) +function _instance.new(kind, name, program, plat, arch, toolchain_inst) -- import "core.tools.xxx" local toolclass = nil if os.isfile(path.join(os.programdir(), "modules", "core", "tools", name .. ".lua")) then - toolclass = import("core.tools." .. name) + toolclass = import("core.tools." .. name, {nocache = true}) -- @note we need create a tool instance with unique toolclass context (_g) end -- not found? @@ -51,10 +52,13 @@ function _instance.new(kind, name, program) local instance = table.inherit(_instance, toolclass) -- save name, kind and program - instance._NAME = name - instance._KIND = kind - instance._PROGRAM = program - instance._INFO = {} + instance._NAME = name + instance._KIND = kind + instance._PROGRAM = program + instance._PLAT = plat + instance._ARCH = arch + instance._TOOLCHAIN = toolchain_inst + instance._INFO = {} -- init instance if instance.init then @@ -78,11 +82,31 @@ function _instance:kind() return self._KIND end +-- get the tool platform +function _instance:plat() + return self._PLAT +end + +-- get the tool architecture +function _instance:arch() + return self._ARCH +end + -- get the tool program function _instance:program() return self._PROGRAM end +-- get the toolchain of this tool +function _instance:toolchain() + return self._TOOLCHAIN +end + +-- get run environments +function _instance:runenvs() + return self:toolchain() and self:toolchain():runenvs() +end + -- set the value to the platform info function _instance:set(name, ...) self._INFO[name] = table.unwrap({...}) @@ -123,25 +147,39 @@ function _instance:has_flags(flags, flagkind, opt) -- import has_flags() self._has_flags = self._has_flags or import("lib.detect.has_flags", {anonymous = true}) + -- bind the run environments + opt.envs = self:runenvs() + -- has flags? return self._has_flags(self:name(), flags, opt) end -- load the given tool from the given kind -- --- @param kind the tool kind e.g. cc, cxx, mm, mxx, as, ar, ld, sh, .. --- @param program the tool program, e.g. /xxx/arm-linux-gcc, [email protected], (optional) --- @param toolname gcc, clang, .. (optional) +-- @param kind the tool kind e.g. cc, cxx, mm, mxx, as, ar, ld, sh, .. +-- @param opt.program the tool program, e.g. /xxx/arm-linux-gcc, [email protected], (optional) +-- @param opt.toolname gcc, clang, .. (optional) +-- @param opt.toolchain_info the toolchain info (optional) -- -function tool.load(kind, program, toolname) +function tool.load(kind, opt) + + -- get tool information + opt = opt or {} + local program = opt.program + local toolname = opt.toolname + local toolchain_info = opt.toolchain_info or {} + + -- get platform and architecture + local plat = toolchain_info.plat or config.get("plat") or os.host() + local arch = toolchain_info.arch or config.get("arch") or os.arch() - -- init key - local key = kind .. (program or "") .. (config.get("arch") or os.arch()) + -- init cachekey + local cachekey = kind .. (program or "") .. plat .. arch -- get it directly from cache dirst tool._TOOLS = tool._TOOLS or {} - if tool._TOOLS[key] then - return tool._TOOLS[key] + if tool._TOOLS[cachekey] then + return tool._TOOLS[cachekey] end -- contain toolname? parse it, e.g. '[email protected]' @@ -155,7 +193,11 @@ function tool.load(kind, program, toolname) -- get the tool program and name if not program then - program, toolname = platform.tool(kind) + program, toolname, toolchain_info = platform.tool(kind, plat, arch) + if toolchain_info then + assert(toolchain_info.plat == plat) + assert(toolchain_info.arch == arch) + end end if not program then return nil, string.format("cannot get program for %s", kind) @@ -176,14 +218,20 @@ function tool.load(kind, program, toolname) return nil, string.format("cannot find known tool script for %s", toolname or program) end + -- load toolchain instance + local toolchain_inst + if toolchain_info and toolchain_info.name then + toolchain_inst = toolchain.load(toolchain_info.name, {plat = plat, arch = arch}) + end + -- new an instance - local instance, errors = _instance.new(kind, name, program) + local instance, errors = _instance.new(kind, name, program, plat, arch, toolchain_inst) if not instance then return nil, errors end -- save instance to the cache - tool._TOOLS[key] = instance + tool._TOOLS[cachekey] = instance -- ok return instance diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua index 6e48ef836..f6eafa94b 100644 --- a/xmake/core/tool/toolchain.lua +++ b/xmake/core/tool/toolchain.lua @@ -36,9 +36,11 @@ local sandbox = require("sandbox/sandbox") local sandbox_module = require("sandbox/modules/import/core/sandbox/module") -- new an instance -function _instance.new(name, info) +function _instance.new(name, plat, arch, info) local instance = table.inherit(_instance) instance._NAME = name + instance._PLAT = plat + instance._ARCH = arch instance._INFO = info return instance end @@ -50,12 +52,32 @@ end -- get toolchain platform function _instance:plat() - return config.get("plat") or os.host() + return self._PLAT end -- get toolchain architecture function _instance:arch() - return config.get("arch") or os.arch() + return self._ARCH +end + +-- the current platform is belong to the given platforms? +function _instance:is_plat(...) + local plat = self:plat() + for _, v in ipairs(table.join(...)) do + if v and plat == v then + return true + end + end +end + +-- the current architecture is belong to the given architectures? +function _instance:is_arch(...) + local arch = self:arch() + for _, v in ipairs(table.join(...)) do + if v and arch:find("^" .. v:gsub("%-", "%%-") .. "$") then + return true + end + end end -- get toolchain info @@ -111,6 +133,26 @@ function _instance:standalone() return self:kind() == "standalone" end +-- get the run environments +function _instance:runenvs() + local runenvs = self._RUNENVS + if runenvs == nil then + local toolchain_runenvs = self:get("runenvs") + if toolchain_runenvs then + runenvs = {} + for name, values in pairs(toolchain_runenvs) do + if type(values) == "table" then + values = path.joinenv(values) + end + runenvs[name] = values + end + end + runenvs = runenvs or false + self._RUNENVS = runenvs + end + return runenvs or nil +end + -- get the program and name of the given tool kind function _instance:tool(toolkind) local toolpathes = self:get("toolset." .. toolkind) @@ -139,23 +181,6 @@ function _instance:sdkdir() return config.get("sdk") or self:get("sdkdir") end --- do load, @note we need load it repeatly for each architectures -function _instance:_load() - local info = self:info() - if not info:get("__loaded") and not info:get("__loading") then - local on_load = info:get("load") - if on_load then - info:set("__loading", true) - local ok, errors = sandbox.load(on_load, self) - info:set("__loading", false) - if not ok then - os.raise(errors) - end - end - info:set("__loaded", true) - end -end - -- do check, we only check it once for all architectures function _instance:check() local checkok = true @@ -174,6 +199,23 @@ function _instance:check() return checkok end +-- do load, @note we need load it repeatly for each architectures +function _instance:_load() + local info = self:info() + if not info:get("__loaded") and not info:get("__loading") then + local on_load = info:get("load") + if on_load then + info:set("__loading", true) + local ok, errors = sandbox.load(on_load, self) + info:set("__loading", false) + if not ok then + os.raise(errors) + end + end + info:set("__loaded", true) + end +end + -- get the tool description from the tool kind function _instance:_description(toolkind) local descriptions = self._DESCRIPTIONS @@ -240,7 +282,7 @@ function _instance:_checktool(toolkind, toolpath) -- find tool program local program, toolname - local tool = find_tool(toolpath, {program = toolpath, pathes = self:bindir()}) + local tool = find_tool(toolpath, {program = toolpath, pathes = self:bindir(), envs = self:get("runenvs")}) if tool then program = tool.program toolname = tool.name @@ -318,24 +360,26 @@ end -- get toolchain directories function toolchain.directories() - - -- init directories local dirs = toolchain._DIRS or { path.join(global.directory(), "toolchains") , path.join(os.programdir(), "toolchains") } - - -- save directories to cache toolchain._DIRS = dirs return dirs end -- load the given toolchain -function toolchain.load(name) +function toolchain.load(name, opt) + + -- init cache key + opt = opt or {} + local plat = opt.plat or config.get("plat") or os.host() + local arch = opt.arch or config.get("arch") or os.arch() + local cachekey = name .. plat .. arch -- get it directly from cache dirst toolchain._TOOLCHAINS = toolchain._TOOLCHAINS or {} - if toolchain._TOOLCHAINS[name] then - return toolchain._TOOLCHAINS[name] + if toolchain._TOOLCHAINS[cachekey] then + return toolchain._TOOLCHAINS[cachekey] end -- find the toolchain script path @@ -372,8 +416,8 @@ function toolchain.load(name) end -- save instance to the cache - local instance = _instance.new(name, result) - toolchain._TOOLCHAINS[name] = instance + local instance = _instance.new(name, plat, arch, result) + toolchain._TOOLCHAINS[cachekey] = instance return instance end |
