diff options
| author | Arthur LAURENT <[email protected]> | 2024-02-02 12:52:06 +0100 |
|---|---|---|
| committer | Arthur LAURENT <[email protected]> | 2024-02-02 12:52:06 +0100 |
| commit | b64836f09b250e1d77773cb9e0c53c33ecaaa9de (patch) | |
| tree | e8f28abbc539a1d1cbafe435d1c3c4d2c28c90b3 /xmake/rules/c++/modules/modules_support | |
| parent | e449836c75d31664d14ad237c65d8416447bbf87 (diff) | |
improve module circular dependency detection
we're already doing a DFS to sort modules and it already check for
circular imports, so instead of rolling a custom detection afterward
just signal the circular dependency when detected in the DFS
Diffstat (limited to 'xmake/rules/c++/modules/modules_support')
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/dependency_scanner.lua | 109 |
1 files changed, 44 insertions, 65 deletions
diff --git a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua index 46d53577a..d07884b19 100644 --- a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua +++ b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua @@ -169,77 +169,56 @@ function _parse_dependencies_data(target, moduleinfos) return modules end +function _topological_sort_get_edges(node, nodes, modules) + local edges = {} --- check circular dependencies for the given module -function _check_circular_dependencies_of_module(name, moduledeps, modulesources, depspath) - for _, dep in ipairs(moduledeps[name]) do - local depinfo = moduledeps[dep] - if depinfo then - local depspath_sub - if depspath then - for idx, name in ipairs(depspath) do - if name == dep then - local circular_deps = table.slice(depspath, idx) - table.insert(circular_deps, dep) - local sourceinfo = "" - for _, circular_depname in ipairs(circular_deps) do - local sourcefile = modulesources[circular_depname] - if sourcefile then - sourceinfo = sourceinfo .. ("\n -> module(%s) in %s"):format(circular_depname, sourcefile) - end - end - os.raise("circular modules dependency(%s) detected!%s", table.concat(circular_deps, ", "), sourceinfo) - end - end - depspath_sub = table.join(depspath, dep) - end - _check_circular_dependencies_of_module(dep, moduledeps, modulesources, depspath_sub) - end - end -end + local module = modules[node.objectfile] + local _, provide, _ = compiler_support.get_provided_module(module) --- check circular dependencies --- @see https://github.com/xmake-io/xmake/issues/3031 -function _check_circular_dependencies(modules) - local moduledeps = {} - local modulesources = {} - for _, mod in pairs(modules) do - if mod then - if mod.provides and mod.requires then - for name, provide in pairs(mod.provides) do - modulesources[name] = provide.sourcefile - local deps = moduledeps[name] - if deps then - table.join2(deps, mod.requires) - else - moduledeps[name] = table.keys(mod.requires) - end - end - end - end - end - for name, _ in pairs(moduledeps) do - _check_circular_dependencies_of_module(name, moduledeps, modulesources, {name}) - end + if provide and module.requires then + for required, _ in pairs(module.requires) do + for objectfile, dep in pairs(modules) do + local name, _, _ = compiler_support.get_provided_module(dep) + if name and name == required then + local edge + for _, n in ipairs(nodes) do + if n.objectfile == objectfile then + edge = n + break + end + end + + table.insert(edges, edge) + break + end + end + end + end + + return edges end function _topological_sort_visit(node, nodes, modules, output) if node.marked then return end - assert(not node.tempmarked) + + local module = modules[node.objectfile] + local name, _, _ = compiler_support.get_provided_module(module) + + if node.tempmarked then + return {name} + end + + local edges = _topological_sort_get_edges(node, nodes, modules) + node.tempmarked = true - local m1 = modules[node.objectfile] - for _, n in ipairs(nodes) do - if not n.tempmarked then - local m2 = modules[n.objectfile] - if m2 then - for name, _ in pairs(m1.provides) do - if m2.requires and m2.requires[name] then - _topological_sort_visit(n, nodes, modules, output) - end - end - end + for _, edge in ipairs(edges) do + -- check circular dependencies + -- @see https://github.com/xmake-io/xmake/issues/3031 + local circular_dependency = _topological_sort_visit(edge, nodes, modules, output) + if circular_dependency then + return table.join(name, circular_dependency) end end node.tempmarked = false @@ -258,7 +237,7 @@ end function _topological_sort_get_first_unmarked_node(nodes) for _, node in ipairs(nodes) do - if not node.marked and not node.tempmarked then + if not node.marked then return node end end @@ -301,9 +280,9 @@ function get_module_dependencies(target, sourcebatch, opt) local moduleinfos = compiler_support.load_moduleinfos(target, sourcebatch) modules = _parse_dependencies_data(target, moduleinfos) if modules then - _check_circular_dependencies(modules) + -- _check_circular_dependencies(modules) + modules = cull_unused_modules(target, modules) end - modules = cull_unused_modules(target, modules) compiler_support.localcache():set2("modules", cachekey, modules) compiler_support.localcache():save() end |
