diff --git a/utilities/moduleDependenciesToDot.py b/utilities/moduleDependenciesToDot.py new file mode 100755 index 0000000000000000000000000000000000000000..2fa4fd6775e8ed6d61900a784f9a15856747bcc1 --- /dev/null +++ b/utilities/moduleDependenciesToDot.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 + +import argparse +import re +from pathlib import Path + +def is_walberla_root(walberla_root): + return (walberla_root / 'src' / 'walberla.h').exists() + +def trace_dependencies(modules, base_modules): + deps = base_modules.copy() + for mod in base_modules: + deps |= modules.get(mod, set()) + if deps == base_modules: + return deps + else: + return trace_dependencies(modules, deps) + +def get_module_dependencies(module_dir): + with open(module_dir / 'CMakeLists.txt', 'r') as fin: + m = re.search(r'DEPENDS([\w\s]*)', fin.read()) + if m is not None: + stripped = {x.strip() for x in m.group(1).split(' ') if x!=''} + return (module_dir.name, {x for x in stripped if (x not in ['', 'BUILD_ONLY_IF_FOUND'])}) + return (module_dir.name, set()) + +def get_dependency_graph(walberla_root): + modules_dir = walberla_root / 'src' + modules = (get_module_dependencies(x) for x in modules_dir.iterdir() if x.is_dir()) + return {i:v for i,v in modules} + +def color_dependencies(fout, dependencies, base_module): + for dep in trace_dependencies(dependencies, {base_module}): + if (dep == base_module): + fout.write(f' {dep}[fillcolor=limegreen, style="filled"];\n') + continue + if (dep in dependencies[base_module]): + fout.write(f' {dep}[fillcolor=gold, style="filled"];\n') + continue + fout.write(f' {dep}[fillcolor=brown1, style="filled"];\n') + +def write_dependency_graph(fout, dependencies): + for module, deps in dependencies.items(): + for dep in deps: + fout.write(f' {dep} -> {module};\n') + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Generates a dot file containing the waLBerla dependency graph.') + parser.add_argument('-d', default='..', help='waLBerla root directory', type=Path) + parser.add_argument('-o', default='module_dependencies.dot', help='output dot file') + parser.add_argument('--trace', default=None, help='Colors all direct and indirect dependencies of TRACE.') + args = parser.parse_args() + + if not is_walberla_root(args.d): + raise ValueError(f'{args.d} is not a waLBerla root directory!') + + dependencies = get_dependency_graph(args.d) + + with open(args.o, 'w') as fout: + fout.write('digraph module_dependencies {\n') + write_dependency_graph(fout, dependencies) + if args.trace is not None: + color_dependencies(fout, dependencies, args.trace) + fout.write('}\n') + +