#!/usr/bin/env python3

import sys
import libetrace
import json
import re

nfsdb = libetrace.nfsdb()
nfsdb.load(sys.argv[1],quiet=True)

# Getting linked lk path
L = [e.linked_file for e in nfsdb if e.is_linking() and e.linked_file.endswith("lk.elf")]

# Getting file dependencies for vmlinux kernel module and all loadable modules
mdeps = {}
for f in L:
	excl_patterns = ["/dev/*"]
	mdeps[f]=set(nfsdb.fdeps(f,exclude_patterns=excl_patterns)[1])
deps = set()
for x in mdeps.values():
	deps|=x
print ("Total dependencies: %d"%(len(deps)))

cmap = {}
h = re.compile("^/dev/.*")
for e in nfsdb:
	if e.has_compilations():
		for cf in e.compilation_info.files:
			if not h.match(cf):
				if cf not in cmap:
					cmap[cf] = e

comps = set()
for f in deps:
	if f in cmap:
		comps.add((cmap[f].eid.pid,cmap[f].eid.index))			
print ("Number of compilations: %d"%(len(comps)))

# Generate compilation database
def json_command(cmd):
	return json.dumps(" ".join([x.rstrip().replace("\\","\\\\").replace("\"","\\\"").replace(" ","\\ ") for x in cmd]))

json_vals = list()
for C in comps:
	e = nfsdb[C]
	json_vals.append( "{\"directory\":%s,\"command\":%s,\"file\":%s}"%(json.dumps(e.cwd),json_command(e.argv),json.dumps(e.compilation_info.files[0])) )
with open("compile_commands.json","w") as f:
	f.write(json.dumps(json.loads("[%s]"%",".join(json_vals)), indent=4, sort_keys=False))
print ("created compilation database file (compile_commands.json)")

# Generate compilation dependency map
cdm = {}
for m,deplist in mdeps.items():
	cdm[m] = []
	for f in deplist:
		if f in cmap:
			cdm[m].append(f)
with open("cdm.json","w") as f:
	f.write(json.dumps(cdm, indent=4, sort_keys=False))
print ("created compilation dependency map file (cdm.json)")

# Generate reverse dependency map file
rdm = {}
for m,deplist in mdeps.items():
	for f in deplist:
		if f in rdm:
			rdm[f].append(m)
		else:
			rdm[f] = [m]
with open("rdm.json","w") as f:
	f.write(json.dumps(rdm, indent=4, sort_keys=False))
print ("created reverse dependency map file (rdm.json)")