[DEV] add a dependency graph generator

lutin dependency:LD ; dot -Tsvg dependency.dot -o dependency.svg ; firefox dependency.svg
This commit is contained in:
Edouard DUPIN 2016-10-28 00:06:05 +02:00
parent f2060d4c97
commit 44dbcdd56d
3 changed files with 160 additions and 19 deletions

View File

@ -69,6 +69,15 @@ def usage(full=False):
print(" clean all (same as previous)")
print(" " + color['green'] + "dump" + color['default'])
print(" Dump all the module dependency and properties")
print(" " + color['green'] + "dependency" + color['default'])
print(" generate a file dependency.dot that represent all the dependency link")
print(" Select what in included: 'dependency:LPBDK'")
print(" L: Library")
print(" P: Pre-build")
print(" D: Data")
print(" B: Binary")
print(" K: Package")
print(" eg: lutin dependency:LD ; dot -Tsvg dependency.dot -o dependency.svg ; firefox dependency.svg")
print(" " + color['green'] + "gcov" + color['default'])
print(" Parse all the code of the library with the gcov resolution")
listOfAllModule = module.list_all_module_with_desc()
@ -169,18 +178,18 @@ def check_boolean(value):
def parseGenericArg(argument, active):
debug.extreme_verbose("parse arg : " + argument.get_option_name() + " " + argument.get_arg() + " active=" + str(active))
if argument.get_option_name() == "help":
if active==False:
if active == False:
usage()
return True
if argument.get_option_name() == "HELP":
if active==False:
if active == False:
usage(True)
return True
if argument.get_option_name() == "list-module":
if active==False:
listOfModule = module.list_all_module()
if active == False:
list_of_module = module.list_all_module()
retValue = ""
for moduleName in listOfModule:
for moduleName in list_of_module:
if retValue != "":
retValue += " "
retValue += moduleName
@ -188,10 +197,10 @@ def parseGenericArg(argument, active):
exit(0)
return True
if argument.get_option_name() == "list-target":
if active==False:
listOfTarget = target.list_all_target()
if active == False:
list_of_target = target.list_all_target()
retValue = ""
for targetName in listOfTarget:
for targetName in list_of_target:
if retValue != "":
retValue += " "
retValue += targetName
@ -199,61 +208,61 @@ def parseGenericArg(argument, active):
exit(0)
return True
elif argument.get_option_name()=="jobs":
if active==True:
if active == True:
multiprocess.set_core_number(int(argument.get_arg()))
return True
elif argument.get_option_name()=="depth":
if active==True:
if active == True:
env.set_parse_depth(int(argument.get_arg()))
return True
elif argument.get_option_name() == "verbose":
if active==True:
if active == True:
debug.set_level(int(argument.get_arg()))
return True
elif argument.get_option_name() == "color":
if active==True:
if active == True:
if check_boolean(argument.get_arg()) == True:
debug.enable_color()
else:
debug.disable_color()
return True
elif argument.get_option_name() == "force-build":
if active==True:
if active == True:
if check_boolean(argument.get_arg()) == True:
env.set_force_mode(True)
else:
env.set_force_mode(False)
return True
elif argument.get_option_name() == "pretty":
if active==True:
if active == True:
if check_boolean(argument.get_arg()) == True:
env.set_print_pretty_mode(True)
else:
env.set_print_pretty_mode(False)
return True
elif argument.get_option_name() == "force-optimisation":
if active==True:
if active == True:
if check_boolean(argument.get_arg()) == True:
env.set_force_optimisation(True)
else:
env.set_force_optimisation(False)
return True
elif argument.get_option_name() == "isolate-system":
if active==True:
if active == True:
if check_boolean(argument.get_arg()) == True:
env.set_isolate_system(True)
else:
env.set_isolate_system(False)
return True
elif argument.get_option_name() == "force-strip":
if active==True:
if active == True:
if check_boolean(argument.get_arg()) == True:
env.set_force_strip_mode(True)
else:
env.set_force_strip_mode(False)
return True
elif argument.get_option_name() == "warning":
if active==True:
if active == True:
if check_boolean(argument.get_arg()) == True:
env.set_warning_mode(True)
else:

View File

@ -1285,6 +1285,107 @@ class Module:
print('-----------------------------------------------')
return True
def check_rules(self, type, rules):
if ( ( type == 'LIBRARY' \
or type == 'LIBRARY_DYNAMIC' \
or type == 'LIBRARY_STATIC' ) \
and "L" not in rules ) \
or ( type == 'DATA' \
and "D" not in rules ) \
or ( type == 'PREBUILD'\
and "P" not in rules ) \
or ( type == 'PACKAGE'\
and "K" not in rules) \
or ( ( type == 'BINARY' \
or type == 'BINARY_SHARED' \
or type == 'BINARY_STAND_ALONE')\
and "B" not in rules ) :
return True
return False
# TODO: Add to simplify the display the possibility to check if an element already depend in dependency of an element ???
def dependency_generate(self, target, tmp_file, step, rules):
debug.print_element("dot", "dependency.dot", "<<<", self._name)
if self.check_rules(self._type, rules) == True:
return
if step == 1:
if self._type == 'DATA':
tmp_file.write(' node [\n');
tmp_file.write(' shape=Mdiamond;\n');
tmp_file.write(' style=filled;\n');
tmp_file.write(' color=red;\n');
tmp_file.write(' ];\n');
elif self._type == 'PREBUILD':
tmp_file.write(' node [\n');
tmp_file.write(' shape=square;\n');
tmp_file.write(' style=filled;\n');
tmp_file.write(' color=gray;\n');
tmp_file.write(' ];\n');
elif self._type == 'LIBRARY' \
or self._type == 'LIBRARY_DYNAMIC' \
or self._type == 'LIBRARY_STATIC':
tmp_file.write(' node [\n');
tmp_file.write(' shape=ellipse;\n');
tmp_file.write(' style=filled;\n');
tmp_file.write(' color=lightblue;\n');
tmp_file.write(' ];\n');
elif self._type == 'BINARY' \
or self._type == 'BINARY_SHARED' \
or self._type == 'BINARY_STAND_ALONE':
tmp_file.write(' node [\n');
tmp_file.write(' shape=rectangle;\n');
tmp_file.write(' style=filled;\n');
tmp_file.write(' color=green;\n');
tmp_file.write(' ];\n');
elif self._type == 'PACKAGE':
return
tmp_file.write(' ' + copy.deepcopy(self._name).replace('-','_')+ ';\n');
else:
for elem in self._depends:
debug.verbose("add depend on: " + elem);
tmp_module = None
try:
tmp_module = target.get_module(elem)
except:
target.load_if_needed(elem, optionnal=True)
try:
tmp_module = target.get_module(elem)
except:
debug.verbose(" ==> get error");
if tmp_module == None:
debug.verbose(" ==> notFound");
continue
if self.check_rules(tmp_module._type, rules) == True:
debug.verbose(" ==> not in rules");
continue
tmp_file.write(' ' + copy.deepcopy(self._name).replace('-','_') + ' -> ' + copy.deepcopy(elem).replace('-','_') + ';\n');
for elem in self._depends_optionnal:
elem = elem[0]
debug.verbose("add depend on: " + elem);
tmp_module = None
try:
tmp_module = target.get_module(elem)
except:
target.load_if_needed(elem, optionnal=True)
try:
tmp_module = target.get_module(elem)
except:
debug.verbose(" ==> get error");
if tmp_module == None:
debug.verbose(" ==> notFound");
continue
if self.check_rules(tmp_module._type, rules) == True:
debug.verbose(" ==> not in rules");
continue
tmp_file.write(' ' + copy.deepcopy(self._name).replace('-','_') + ' -> ' + copy.deepcopy(elem).replace('-','_') + ';\n');
"""
tmp_file.write(' module_' + self._name.replace('-','_') + ' {\n');
tmp_file.write(' style=filled;\n');
tmp_file.write(' color=blue;\n');
tmp_file.write(' label="' + self._name + '";\n');
tmp_file.write(' }\n');
"""
##
## @brief Get packaging property variable
## @param[in] self (handle) Class handle

View File

@ -653,11 +653,42 @@ class Target:
for mod in self.module_list:
mod.display()
return
if name[:10] == "dependency":
if len(name) > 10:
rules = name.split(":")[1]
else:
rules = "LBDPK"
# L for library
# B for binary
# D for Data
# P for prebuild
# K for package
debug.print_element("dot", "", "---", "dependency.dot")
self.load_all()
tmp_file = open("dependency.dot", 'w')
tmp_file.write('digraph G {\n')
tmp_file.write(' rankdir=\"LR\";\n')
for mod in self.module_list:
mod.dependency_generate(self, tmp_file, 1, rules)
# TODO : do it better ==> system library hook (do a oad of all avillable system library)
tmp_file.write(' node [\n');
tmp_file.write(' shape=square;\n');
tmp_file.write(' style=filled;\n');
tmp_file.write(' color=gray;\n');
tmp_file.write(' ];\n');
# TODO : End hook
for mod in self.module_list:
mod.dependency_generate(self, tmp_file, 2, rules)
tmp_file.write('}\n')
tmp_file.flush()
tmp_file.close()
debug.print_element("dot", "", "---", "dependency.dot")
return
if name == "all":
debug.info("build all")
self.load_all()
for mod in self.module_list:
if self._name=="Android":
if self._name == "Android":
if mod.get_type() == "PACKAGE":
mod.build(self, None)
else: