import os from lib.io import load_lib_data def topological_sort(source): pending = [(name, set(deps)) for name, deps in source] emitted = [] while pending: next_pending = [] next_emitted = [] for entry in pending: name, deps = entry deps.difference_update(set((name,)), emitted) if deps: next_pending.append(entry) else: yield name emitted.append(name) next_emitted.append(name) if not next_emitted: raise ValueError("cyclic dependancy detected: %s %r" % (name, (next_pending,))) pending = next_pending emitted = next_emitted return emitted def sort_libs_by_dependencies(selected_libs): # no need for sorting in case of only one lib if len(selected_libs) < 2: return selected_libs lib_names = [] for lib in selected_libs: lib_names.append(lib['name']) deplist = [] for lib in selected_libs: name = lib['name'] # only sort after dependencies that are actually present to avoid cyclic dependencies deps = [] for dep in lib['dependencies'].split(','): if dep in lib_names: deps.append(dep) dependencies = set(deps) if dependencies == {''}: dependencies = {} deplist.append([name, dependencies]) sorted_deplist = topological_sort(deplist) sorted = [] for entry in sorted_deplist: for lib in selected_libs: if lib['name'] == entry: sorted.append(lib) return sorted def load_dependencies(library, selected_libs, config_dir): lib_names = [] for lib in selected_libs: lib_names.append(lib['name']) dependencies = library['dependencies'].split(',') for dep in dependencies: if len(dep) > 1: if dep not in lib_names: config_file = config_dir + "/" + dep + ".json" if os.path.exists(config_file): dep_data = load_lib_data(config_file) dep_data['version'] = dep_data['default version'] selected_libs.append(dep_data) else: print("Warning - library " + lib['name'] + " depends on " + dep + " for which no configration file was found. Presence in LD_LIBRARY_PATH is assumed.") # load library data from names in argparse result def load_selected_libs(config_dir, arg_namespace, args, install_all_libs, ignore_deps): selected_libs = [] if install_all_libs: for config_file in glob.glob(config_dir+"/*.json"): data = load_lib_data(config_file) #with open(cf, 'r') as f: #data = json.load(f) data['version'] = data['default version'] selected_libs.append(data) else: ignore_names = ["config", "mpi", "compiler", "prefix", "src", "work", "keep_work", "threads", "verbose", "version", "disable_shared", "ignore_deps"] for lib_name in args: if lib_name not in ignore_names and "version" not in lib_name: install = getattr(arg_namespace, lib_name) if install: version = getattr(arg_namespace, lib_name + "_version") lib_name = lib_name.replace('_','-') config_file = config_dir + "/" + lib_name + ".json" data = load_lib_data(config_file) data['version'] = version selected_libs.append(data) if not ignore_deps: # also add all dependencies to the install list for lib in selected_libs: load_dependencies(lib, selected_libs, config_dir) return selected_libs