diff options
| author | ruki <[email protected]> | 2023-03-06 09:18:58 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-03-06 09:18:58 +0800 |
| commit | 8bb23ca24aebe4c2dde25183a4eee7cda76e3438 (patch) | |
| tree | 245c23d3a0a946bd346da6ba088bf81ba941b13f | |
| parent | d13d228fea199fe566aebf891bd26b627e547bb3 (diff) | |
| parent | cd25c0d22f73ef7ca2cdf8ac61df828523d5078d (diff) | |
Merge pull request #3435 from xmake-io/flags
improve has_flags
| -rw-r--r-- | xmake/core/tool/compiler.lua | 75 | ||||
| -rw-r--r-- | xmake/core/tool/linker.lua | 101 | ||||
| -rw-r--r-- | xmake/core/tool/tool.lua | 70 | ||||
| -rw-r--r-- | xmake/modules/core/tools/gcc.lua | 2 |
4 files changed, 144 insertions, 104 deletions
diff --git a/xmake/core/tool/compiler.lua b/xmake/core/tool/compiler.lua index b20591d3c..bf5dead36 100644 --- a/xmake/core/tool/compiler.lua +++ b/xmake/core/tool/compiler.lua @@ -124,57 +124,62 @@ function compiler.load(sourcekind, target) -- get it directly from cache dirst compiler._INSTANCES = compiler._INSTANCES or {} - if compiler._INSTANCES[cachekey] then - return compiler._INSTANCES[cachekey] - end + local instance = compiler._INSTANCES[cachekey] + if not instance then - -- new instance - local instance = table.inherit(compiler, builder) + -- new instance + instance = table.inherit(compiler, builder) - -- save the compiler tool - instance._TOOL = compiler_tool + -- save the compiler tool + instance._TOOL = compiler_tool - -- load the compiler language from the source kind - local result, errors = language.load_sk(sourcekind) - if not result then - return nil, errors - end - instance._LANGUAGE = result + -- load the compiler language from the source kind + local result, errors = language.load_sk(sourcekind) + if not result then + return nil, errors + end + instance._LANGUAGE = result - -- init target (optional) - instance._TARGET = target + -- init target (optional) + instance._TARGET = target - -- init target kind - instance._TARGETKIND = "object" + -- init target kind + instance._TARGETKIND = "object" - -- init name flags - instance._NAMEFLAGS = result:nameflags()[instance:_targetkind()] + -- init name flags + instance._NAMEFLAGS = result:nameflags()[instance:_targetkind()] - -- init flag kinds - instance._FLAGKINDS = table.wrap(result:sourceflags()[sourcekind]) + -- init flag kinds + instance._FLAGKINDS = table.wrap(result:sourceflags()[sourcekind]) - -- add toolchains flags to the compiler tool, e.g. gcc.cxflags or cxflags - local toolname = compiler_tool:name() - if target and target.toolconfig then - for _, flagkind in ipairs(instance:_flagkinds()) do - compiler_tool:add(flagkind, target:toolconfig(toolname .. '.' .. flagkind) or target:toolconfig(flagkind)) - end - else - for _, flagkind in ipairs(instance:_flagkinds()) do - compiler_tool:add(flagkind, platform.toolconfig(toolname .. '.' .. flagkind) or platform.toolconfig(flagkind)) + -- add toolchains flags to the compiler tool, e.g. gcc.cxflags or cxflags + local toolname = compiler_tool:name() + if target and target.toolconfig then + for _, flagkind in ipairs(instance:_flagkinds()) do + compiler_tool:add(flagkind, target:toolconfig(toolname .. '.' .. flagkind) or target:toolconfig(flagkind)) + end + else + for _, flagkind in ipairs(instance:_flagkinds()) do + compiler_tool:add(flagkind, platform.toolconfig(toolname .. '.' .. flagkind) or platform.toolconfig(flagkind)) + end end + + -- @note we can't call _load_once before caching the instance, + -- it may call has_flags to trigger the concurrent scheduling. + -- + -- this will result in more compiler/linker instances being created at the same time, + -- and they will access the same tool instance at the same time. + -- + -- @see https://github.com/xmake-io/xmake/issues/3429 + compiler._INSTANCES[cachekey] = instance end -- we need to load it at the end because in tool.load(). -- because we may need to call has_flags, which requires the full platform toolchain flags - local ok, errors = compiler_tool:_load() + local ok, errors = compiler_tool:_load_once() if not ok then return nil, errors end - - -- @note we have to save it after the load to avoid - -- other concurrent processes going ahead and getting an incomplete instance of the tool. - compiler._INSTANCES[cachekey] = instance return instance end diff --git a/xmake/core/tool/linker.lua b/xmake/core/tool/linker.lua index 717936b6c..09436aeee 100644 --- a/xmake/core/tool/linker.lua +++ b/xmake/core/tool/linker.lua @@ -136,73 +136,78 @@ function linker.load(targetkind, sourcekinds, target) -- get it directly from cache dirst builder._INSTANCES = builder._INSTANCES or {} - if builder._INSTANCES[cachekey] then - return builder._INSTANCES[cachekey] - end + local instance = builder._INSTANCES[cachekey] + if not instance then - -- new instance - local instance = table.inherit(linker, builder) + -- new instance + instance = table.inherit(linker, builder) - -- save linker tool - instance._TOOL = linkertool + -- save linker tool + instance._TOOL = linkertool - -- load the name flags of archiver - local nameflags = {} - local nameflags_exists = {} - for _, sourcekind in ipairs(sourcekinds) do + -- load the name flags of archiver + local nameflags = {} + local nameflags_exists = {} + for _, sourcekind in ipairs(sourcekinds) do - -- load language - local result, errors = language.load_sk(sourcekind) - if not result then - return nil, errors - end + -- load language + local result, errors = language.load_sk(sourcekind) + if not result then + return nil, errors + end - -- merge name flags - for _, flaginfo in ipairs(table.wrap(result:nameflags()[targetkind])) do - local key = flaginfo[1] .. flaginfo[2] - if not nameflags_exists[key] then - table.insert(nameflags, flaginfo) - nameflags_exists[key] = flaginfo + -- merge name flags + for _, flaginfo in ipairs(table.wrap(result:nameflags()[targetkind])) do + local key = flaginfo[1] .. flaginfo[2] + if not nameflags_exists[key] then + table.insert(nameflags, flaginfo) + nameflags_exists[key] = flaginfo + end end end - end - instance._NAMEFLAGS = nameflags + instance._NAMEFLAGS = nameflags - -- init target (optional) - instance._TARGET = target + -- init target (optional) + instance._TARGET = target - -- init target kind - instance._TARGETKIND = targetkind + -- init target kind + instance._TARGETKIND = targetkind - -- init flag kinds - instance._FLAGKINDS = {linkerinfo.linkerflag} + -- init flag kinds + instance._FLAGKINDS = {linkerinfo.linkerflag} - -- add toolchains flags to the linker tool - -- add special lanugage flags first, e.g. go.gcldflags or gcc.ldflags or gcldflags or ldflags - local toolkind = linkertool:kind() - local toolname = linkertool:name() - if target and target.toolconfig then - for _, flagkind in ipairs(instance:_flagkinds()) do - linkertool:add(toolkind .. 'flags', target:toolconfig(toolname .. '.' .. toolkind .. 'flags') or target:toolconfig(toolkind .. 'flags')) - linkertool:add(flagkind, target:toolconfig(toolname .. '.' .. flagkind) or target:toolconfig(flagkind)) - end - else - for _, flagkind in ipairs(instance:_flagkinds()) do - linkertool:add(toolkind .. 'flags', platform.toolconfig(toolname .. '.' .. toolkind .. 'flags') or platform.toolconfig(toolkind .. 'flags')) - linkertool:add(flagkind, platform.toolconfig(toolname .. '.' .. flagkind) or platform.toolconfig(flagkind)) + -- add toolchains flags to the linker tool + -- add special lanugage flags first, e.g. go.gcldflags or gcc.ldflags or gcldflags or ldflags + local toolkind = linkertool:kind() + local toolname = linkertool:name() + if target and target.toolconfig then + for _, flagkind in ipairs(instance:_flagkinds()) do + linkertool:add(toolkind .. 'flags', target:toolconfig(toolname .. '.' .. toolkind .. 'flags') or target:toolconfig(toolkind .. 'flags')) + linkertool:add(flagkind, target:toolconfig(toolname .. '.' .. flagkind) or target:toolconfig(flagkind)) + end + else + for _, flagkind in ipairs(instance:_flagkinds()) do + linkertool:add(toolkind .. 'flags', platform.toolconfig(toolname .. '.' .. toolkind .. 'flags') or platform.toolconfig(toolkind .. 'flags')) + linkertool:add(flagkind, platform.toolconfig(toolname .. '.' .. flagkind) or platform.toolconfig(flagkind)) + end end + + -- @note we can't call _load_once before caching the instance, + -- it may call has_flags to trigger the concurrent scheduling. + -- + -- this will result in more compiler/linker instances being created at the same time, + -- and they will access the same tool instance at the same time. + -- + -- @see https://github.com/xmake-io/xmake/issues/3429 + builder._INSTANCES[cachekey] = instance end -- we need to load it at the end because in tool.load(). -- because we may need to call has_flags, which requires the full platform toolchain flags - local ok, errors = linkertool:_load() + local ok, errors = linkertool:_load_once() if not ok then return nil, errors end - - -- @note we have to save it after the load to avoid - -- other concurrent processes going ahead and getting an incomplete instance of the tool. - builder._INSTANCES[cachekey] = instance return instance end diff --git a/xmake/core/tool/tool.lua b/xmake/core/tool/tool.lua index 9d94bc375..c3c256396 100644 --- a/xmake/core/tool/tool.lua +++ b/xmake/core/tool/tool.lua @@ -32,6 +32,7 @@ local config = require("project/config") local sandbox = require("sandbox/sandbox") local toolchain = require("tool/toolchain") local platform = require("platform/platform") +local language = require("language/language") local import = require("sandbox/modules/import") -- new an instance @@ -70,20 +71,6 @@ function _instance.new(kind, name, program, plat, arch, toolchain_inst) return instance end --- load tool -function _instance:_load() - if not self._LOADED then - if self.load then - local ok, errors = sandbox.load(self.load, self) - if not ok then - return false, errors - end - end - self._LOADED = true - end - return true -end - -- get the tool name function _instance:name() return self._NAME @@ -169,12 +156,7 @@ function _instance:has_flags(flags, flagkind, opt) opt.program = opt.program or self:program() opt.toolkind = opt.toolkind or self:kind() opt.flagkind = opt.flagkind or flagkind - - -- get system flags - opt.sysflags = opt.sysflags or self:get(self:kind() .. 'flags') - if not opt.sysflags and opt.flagkind then - opt.sysflags = self:get(opt.flagkind) - end + opt.sysflags = opt.sysflags or self:_sysflags(opt.toolkind, opt.flagkind) -- import has_flags() self._has_flags = self._has_flags or import("lib.detect.has_flags", {anonymous = true}) @@ -186,6 +168,54 @@ function _instance:has_flags(flags, flagkind, opt) return self._has_flags(self:name(), flags, opt) end +-- load tool only once +function _instance:_load_once() + if not self._LOADED then + if self.load then + local ok, errors = sandbox.load(self.load, self) + if not ok then + return false, errors + end + end + self._LOADED = true + end + return true +end + +-- get system flags from toolchains +-- @see https://github.com/xmake-io/xmake/issues/3429 +function _instance:_sysflags(toolkind, flagkind) + local sysflags = {} + local sourceflags = language.sourceflags()[toolkind] + if not sourceflags and flagkind then + sourceflags = {flagkind} + if flagkind == "cflags" or flagkind == "cxxflags" then + table.insert(sourceflags, "cxflags") + elseif flagkind == "cxflags" then + table.insert(sourceflags, "cxxflags") + elseif flagkind == "mflags" or flagkind == "mxxflags" then + table.insert(sourceflags, "mxflags") + elseif flagkind == "mxflags" then + table.insert(sourceflags, "mxxflags") + end + end + if sourceflags then + for _, flagname in ipairs(table.wrap(sourceflags)) do + local flags = self:get(flagname) + if flags then + table.join2(sysflags, flags) + end + end + end + -- maybe it's linker flags, ld -> ldflags, dcld -> dcldflags + if #sysflags == 0 then + table.join2(sysflags, self:get(toolkind .. "flags")) + end + if #sysflags > 0 then + return sysflags + end +end + -- load the given tool from the given kind -- -- @param kind the tool kind e.g. cc, cxx, mm, mxx, as, ar, ld, sh, .. diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 0d33decb4..f6dd6f55b 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -74,7 +74,7 @@ function load(self) -- we need check it for clang/gcc with window target -- @see https://github.com/xmake-io/xmake/issues/1392 -- - if not self:is_plat("windows", "mingw") and self:has_flags("-fPIC", "cxflags") then + if not self:is_plat("windows", "mingw") and self:has_flags("-fPIC") then self:add("shflags", "-fPIC") self:add("shared.cxflags", "-fPIC") end |
