One of my projects had me working with the Android 9 build system. Unfortunately, it's a mess of indirection and new/old build code. In Android 9, an image is built with Soong, Kati, Blueprint, and Ninja. During the build, the AndroidProducts.mk
and BoardConfig.mk
files get read by the build system to configure it. When creating your own build, you presumably include fragments found in build/make/target
to set up standard apps. However, if you look into it, where to start isn't clear. At least it wasn't to me. Reading the mk
files gets unwieldy with all the indirection so I created a small script to graph out how things are included.
Here, it's easier to see which parts are at the top of the tree and how one include affects another.
The Python code to generate the graph is:
#!/usr/bin/env python
# Convert AOSP build include egrep output to visual graph via graphviz
# ---
# In aosp/build/make/, run something like:
# egrep -R '(inherit|include)' target/ | $DEV/tools/graph-bulid-includes.py | dot -Tpng > build-includes.png
import re
import sys
lines = sys.stdin.readlines()
nodes = {}
pairs = []
for l in lines:
l = l.replace("$(SRC_TARGET_DIR)", "target")
l = l.replace("build/make/target", "target")
m = re.match('^([-\.\w/_]+):(([\s ,-]|include|\$\(call|inherit|product|if|exists))*([-\.\w/_]+\.mk)\)?', l)
if m:
mfile = m.group(1)
minclude = m.group(4)
for k in (mfile,minclude):
if not k in nodes:
nodes[k] = len(nodes)
pairs.append((mfile,minclude))
else:
sys.stderr.write('Dropped line: {}\n'.format(l))
print("strict digraph includes {")
print("\trankdir=LR")
for (k,v) in nodes.items():
print("\tn{} [label=\"{}\" shape=box]".format(v, k))
for (mfile,minclude) in pairs:
print("\tn{} -> n{}").format(nodes[mfile], nodes[minclude])
print("}")
Thought I'd whip this up while I was waiting for the build system to complete my build. Hope it's helpful to someone.