Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import networkx as nx
import matplotlib.pyplot as plt
from os import getcwd, walk
from os.path import join, exists, split
from sys import argv
import json
import logging
def collects_packages_path(start_dir):
'''collect all paths for better runtime performance'''
collector = {}
for current_dir, dirs, files in walk(start_dir):
#skip git directories
if ".git" in dirs:
dirs.remove(".git")
#O(1) instead of O(n) for looking in files
full_path = join(current_dir, "Android.mk")
if exists(full_path):
collector[split(current_dir)[-1]] = full_path
return collector
def get_dependency(file_name):
''''extract written requirements from Android.mk'''
depend = []
with open(file_name) as make_file:
for line in make_file:
line = line.strip()
if line.startswith("#") or not line:
continue
prefix = line.split()[0]
if prefix in ("PRODUCT_PACKAGES"):#, "LOCAL_SHARED_LIBRARIES"):#, "LOCAL_JAVA_LIBRARIES"):
while True:
line = make_file.next().strip()
if line:
depend.append(line.split("\\")[0].strip())
else:
break
elif prefix in ("LOCAL_REQUIRED_MODULES"):#, "LOCAL_WHOLE_STATIC_LIBRARIES"):
line = make_file.next().strip()
#element right from ":=", separated from " " and trimmed spaces
depend.extend(map(lambda x: x.strip(), line.split(":=")[-1].split()))
return depend
def save(package_name, data):
'''save package dependency to json'''
file_name = "%s_%04d.json" % (package_name, len(data) - 1)
with open(file_name, "w") as dump:
dump.write(json.dumps(data))
def save_img(name, package_dependency):
'''create graph and store as image'''
g = nx.Graph()
logging.info("create %d nodes" % len(package_dependency))
for node in package_dependency:
g.add_node(node)
logging.info("create edges")
for key in package_dependency:
for neighbour in package_dependency[key]:
g.add_edge(key, neighbour)
file_name = "%s.png" % name
logging.info("save image %s" % file_name)
nx.draw(g)
plt.savefig(file_name)
def main():
if argv[1:]:
package_dependency = {}
package_name = argv[1]
start_dir = getcwd()
logging.basicConfig(filename="depend.log")
logging.info("collect package paths")
dirs = collects_packages_path(start_dir)
logging.info("collect recursive dependencies")
package_path = package_name
if package_name.endswith(".mk"):
#relative to android sdk root directory
package_path = join("build/target/product", package_name)
if exists(package_path):
dirs[package_name] = package_path
if package_name in dirs:
logging.info("module %s found" % package_name)
queue = get_dependency(dirs[package_name])
package_dependency[package_name] = queue[:]
while queue:
if queue[0] not in package_dependency:
logging.info("module %s found" % queue[0])
dependencies = get_dependency(dirs[queue[0]])
package_dependency[queue[0]] = dependencies
keys = set(package_dependency.keys())
new_entries = set(dependencies).difference(set(package_dependency.keys()))
logging.info("found for node %s new dependencies %s" % (
queue[0], new_entries))
queue.extend(new_entries)
queue.pop(0)
logging.info("save structure as json file")
save(package_name, package_dependency)
logging.info("create image from dependency graph")
save_img(package_name, package_dependency)
else:
logging.error("package name not recognised")
else:
logging.error("missing package name")
if __name__ == "__main__":
main()