summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2023-03-06 09:18:58 +0800
committerGitHub <[email protected]>2023-03-06 09:18:58 +0800
commit8bb23ca24aebe4c2dde25183a4eee7cda76e3438 (patch)
tree245c23d3a0a946bd346da6ba088bf81ba941b13f
parentd13d228fea199fe566aebf891bd26b627e547bb3 (diff)
parentcd25c0d22f73ef7ca2cdf8ac61df828523d5078d (diff)
Merge pull request #3435 from xmake-io/flags
improve has_flags
-rw-r--r--xmake/core/tool/compiler.lua75
-rw-r--r--xmake/core/tool/linker.lua101
-rw-r--r--xmake/core/tool/tool.lua70
-rw-r--r--xmake/modules/core/tools/gcc.lua2
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