summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2017-02-27 10:48:13 +0800
committerruki <[email protected]>2017-02-27 10:48:13 +0800
commit92c6f33e0d4a9c4e657f2f30ef277795062e2fc4 (patch)
treef552a523ec46e02318c5897d667d5335d727a70f
parentb468766f9a45ffb721dd82363f44539644d3d08d (diff)
fix mix linking
-rw-r--r--xmake/core/language/language.lua63
-rw-r--r--xmake/core/tool/linker.lua35
-rwxr-xr-xxmake/languages/dlang/xmake.lua2
3 files changed, 58 insertions, 42 deletions
diff --git a/xmake/core/language/language.lua b/xmake/core/language/language.lua
index 4b0ee358c..97c7d555f 100644
--- a/xmake/core/language/language.lua
+++ b/xmake/core/language/language.lua
@@ -554,12 +554,12 @@ function language.sourcekind_of(sourcefile)
return sourcekind
end
--- get linker info(kind and flag) of the target kind and the source kinds
-function language.linkerinfo_of(targetkind, sourcekinds)
+-- get linker infos(kind and flag) of the target kind and the source kinds
+function language.linkerinfos_of(targetkind, sourcekinds)
- -- load linkerkinds
- local linkerkinds = language._LINKERKINDS
- if not linkerkinds then
+ -- load linkerinfos
+ local linkerinfos = language._LINKERINFOS
+ if not linkerinfos then
-- load all languages
local languages, errors = language.load()
@@ -567,48 +567,53 @@ function language.linkerinfo_of(targetkind, sourcekinds)
return nil, errors
end
- -- make linker kinds
- linkerkinds = {}
+ -- make linker infos
+ linkerinfos = {}
for name, instance in pairs(languages) do
for sourcekind, _ in pairs(instance:sourcekinds()) do
local targetflags = instance:targetflags()
for _targetkind, linkerkind in pairs(instance:targetkinds()) do
- -- make linker info
- local linkerinfo = {kind = linkerkind}
+ -- init linker info
+ linkerinfos[_targetkind] = linkerinfos[_targetkind] or {}
+ linkerinfos[_targetkind][linkerkind] = linkerinfos[_targetkind][linkerkind] or {}
+ local linkerinfo = linkerinfos[_targetkind][linkerkind]
+
+ -- sve linker info
local linkerflag = targetflags[_targetkind]
+ linkerinfo.linkerkind = linkerkind
if linkerflag then
- linkerinfo.flag = linkerflag
+ linkerinfo.linkerflag = linkerflag
end
-
- -- save linker info
- linkerkinds[_targetkind] = linkerkinds[_targetkind] or {}
- linkerkinds[_targetkind][sourcekind] = linkerinfo
+ linkerinfo.sourcekinds = linkerinfo.sourcekinds or {}
+ linkerinfo.sourcekinds[sourcekind] = 1
+ linkerinfo.sourcecount = (linkerinfo.sourcecount or 0) + 1
end
end
end
-- cache it
- language._LINKERKINDS = linkerkinds
+ language._LINKERINFOS = linkerinfos
end
- -- compute the scores of the linker kinds
- local linkerscores = {}
- for _, sourcekind in ipairs(sourcekinds) do
- local linkerinfo = linkerkinds[targetkind][sourcekind]
- if linkerinfo then
- local key = linkerinfo.kind .. (linkerinfo.flag or "")
- linkerscores[key] = linkerscores[key] or {score = 0, info = linkerinfo}
- linkerscores[key].score = linkerscores[key].score + 1
- end
- end
+ -- find suitable linkers
+ local results = {}
+ for _, linkerinfo in pairs(linkerinfos[targetkind]) do
- -- select the suitable linker kind
- for _, linkerscore in pairs(linkerscores) do
- if #sourcekinds == linkerscore.score then
- return linkerscore.info
+ -- match all source kinds?
+ local count = 0
+ for _, sourcekind in ipairs(sourcekinds) do
+ count = count + (linkerinfo.sourcekinds[sourcekind] or 0)
+ end
+ if count == #sourcekinds then
+ table.insert(results, linkerinfo)
end
end
+ if #results > 0 then
+ -- sort it by most matches
+ table.sort(results, function(a, b) return a.sourcecount > b.sourcecount end)
+ return results
+ end
-- not suitable linker
return nil, string.format("no suitable linker for %s.{%s}", targetkind, table.concat(sourcekinds, ' '))
diff --git a/xmake/core/tool/linker.lua b/xmake/core/tool/linker.lua
index 7b9afdbbe..04daaf6b1 100644
--- a/xmake/core/tool/linker.lua
+++ b/xmake/core/tool/linker.lua
@@ -83,27 +83,38 @@ function linker.load(targetkind, sourcekinds)
-- wrap sourcekinds first
sourcekinds = table.wrap(sourcekinds)
- -- get the linker info
- local linkerinfo, errors = language.linkerinfo_of(targetkind, sourcekinds)
+ -- get the linker infos
+ local linkerinfos, errors = language.linkerinfos_of(targetkind, sourcekinds)
+ if not linkerinfos then
+ return nil, errors
+ end
+
+ -- select the linker
+ local linkerinfo = nil
+ local linkertool = nil
+ for _, _linkerinfo in ipairs(linkerinfos) do
+ -- load the linker tool from the linker kind
+ linkertool, errors = tool.load(_linkerinfo.linkerkind)
+ if linkertool then
+ linkerinfo = _linkerinfo
+ break
+ end
+ end
if not linkerinfo then
return nil, errors
end
-- get it directly from cache dirst
builder._INSTANCES = builder._INSTANCES or {}
- if builder._INSTANCES[linkerinfo.kind] then
- return builder._INSTANCES[linkerinfo.kind]
+ if builder._INSTANCES[linkerinfo.linkerkind] then
+ return builder._INSTANCES[linkerinfo.linkerkind]
end
-- new instance
local instance = table.inherit(linker, builder)
- -- load the linker tool from the source file type
- local result, errors = tool.load(linkerinfo.kind)
- if not result then
- return nil, errors
- end
- instance._TOOL = result
+ -- save linker tool
+ instance._TOOL = linkertool
-- load the name flags of archiver
local nameflags = {}
@@ -131,10 +142,10 @@ function linker.load(targetkind, sourcekinds)
instance._TARGETKIND = targetkind
-- init flag kinds
- instance._FLAGKINDS = {linkerinfo.flag}
+ instance._FLAGKINDS = {linkerinfo.linkerflag}
-- save this instance
- builder._INSTANCES[linkerinfo.kind] = instance
+ builder._INSTANCES[linkerinfo.linkerkind] = instance
-- ok
return instance
diff --git a/xmake/languages/dlang/xmake.lua b/xmake/languages/dlang/xmake.lua
index efc8f9d4c..c8ae07fb2 100755
--- a/xmake/languages/dlang/xmake.lua
+++ b/xmake/languages/dlang/xmake.lua
@@ -26,7 +26,7 @@
language("dlang")
-- set source file kinds
- set_sourcekinds {dc = ".d"}
+ set_sourcekinds {dc = ".d", cc = ".c", cxx = {".cc", ".cpp", ".cxx"}}
-- set source file flags
set_sourceflags {dc = "dcflags"}