diff options
| author | ruki <[email protected]> | 2017-02-27 10:48:13 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2017-02-27 10:48:13 +0800 |
| commit | 92c6f33e0d4a9c4e657f2f30ef277795062e2fc4 (patch) | |
| tree | f552a523ec46e02318c5897d667d5335d727a70f | |
| parent | b468766f9a45ffb721dd82363f44539644d3d08d (diff) | |
fix mix linking
| -rw-r--r-- | xmake/core/language/language.lua | 63 | ||||
| -rw-r--r-- | xmake/core/tool/linker.lua | 35 | ||||
| -rwxr-xr-x | xmake/languages/dlang/xmake.lua | 2 |
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"} |
