X-Git-Url: https://git.distorted.org.uk/~mdw/termux-packages/blobdiff_plain/da6299f059dec490b39615144353b403fb4de379..c21955b6465cea979afd94a93ec0819e30846260:/buildorder.py diff --git a/buildorder.py b/buildorder.py index bb248a95..fa02f7a9 100755 --- a/buildorder.py +++ b/buildorder.py @@ -4,13 +4,31 @@ import os import sys +from itertools import filterfalse -def die(msg): - sys.exit('ERROR: ' + msg) + +# https://docs.python.org/3/library/itertools.html#itertools-recipes + +def unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element -if len(sys.argv) != 1: - die('buildorder.py takes no arguments') +def die(msg): + sys.exit('ERROR: ' + msg) class TermuxBuildFile(object): @@ -136,7 +154,9 @@ def populate(): dep_pkg.needed_by.add(pkg) -def buildorder(): +def generate_full_buildorder(): + build_order = [] + # List of all TermuxPackages without dependencies leaf_pkgs = [pkg for name, pkg in pkgs_map.items() if not pkg.deps] @@ -148,36 +168,27 @@ def buildorder(): pkg_queue = sorted(leaf_pkgs, key=lambda p: '' if p.name == 'libandroid-support' else p.name) # Topological sorting - build_order = [] visited = set() while pkg_queue: pkg = pkg_queue.pop(0) if pkg.name in visited: continue - visited.add(pkg.name) # print("Processing {}:".format(pkg.name), pkg.needed_by) - + visited.add(pkg.name) build_order.append(pkg) for other_pkg in sorted(pkg.needed_by, key=lambda p: p.name): - # Mark this package as done + # Remove this pkg from deps remaining_deps[other_pkg.name].discard(pkg.name) - # ... and all its subpackages remaining_deps[other_pkg.name].difference_update( [subpkg.name for subpkg in pkg.subpkgs] ) - if not remaining_deps[other_pkg.name]: # all deps were pruned? - pkg_queue.append(other_pkg) - - return build_order - - -def generate_and_print_buildorder(): - build_order = buildorder() + if not remaining_deps[other_pkg.name]: # all deps were already appended? + pkg_queue.append(other_pkg) # should be processed if set(pkgs_map.values()) != set(build_order): print("ERROR: Cycle exists. Remaining: ") @@ -187,11 +198,34 @@ def generate_and_print_buildorder(): sys.exit(1) - for pkg in build_order: - print(pkg.name) + return build_order + + +def deps_then_me(pkg): + l = [] + + for dep in sorted(pkg.deps): + l += deps_then_me(pkgs_map[dep]) + l += [pkg] - sys.exit(0) + return l + + +def generate_targets_buildorder(targetnames): + buildorder = [] + + for pkgname in targetnames: + buildorder += deps_then_me(pkgs_map[pkgname]) + + return unique_everseen(buildorder) if __name__ == '__main__': populate() - generate_and_print_buildorder() + + if len(sys.argv) == 1: + bo = generate_full_buildorder() + else: + bo = generate_targets_buildorder(sys.argv[1:]) + + for pkg in bo: + print(pkg.name)