summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2023-03-05 21:58:26 +0800
committerruki <[email protected]>2023-03-05 21:59:27 +0800
commitcd25c0d22f73ef7ca2cdf8ac61df828523d5078d (patch)
tree6659b5809981b4de5db494d223cfcc62a511d4ec
parent447834d2be36ecc810c76e39ed868d1a0c62039d (diff)
fix load tool
-rw-r--r--xmake/core/tool/compiler.lua75
-rw-r--r--xmake/core/tool/linker.lua101
-rw-r--r--xmake/core/tool/tool.lua4
3 files changed, 95 insertions, 85 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 33c8296a1..c3c256396 100644
--- a/xmake/core/tool/tool.lua
+++ b/xmake/core/tool/tool.lua
@@ -168,8 +168,8 @@ function _instance:has_flags(flags, flagkind, opt)
return self._has_flags(self:name(), flags, opt)
end
--- load tool
-function _instance:_load()
+-- 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)