libinstaller/lib/dependency.py

104 lines
3.7 KiB
Python
Raw Permalink Normal View History

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