AOSP Build Include Graph
In AOSP Project one of biggest thing is the build system, it is using soong, ninja, kati, blueprint etc., During the build, the AndroidProducts.mk and BoardConfig.mk files get read by the build system to configure it. 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.
Python Script to Create the Graph
build_include.py #!/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/ | python3 build_include.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 ( " \t rankdir=LR" )
for ( k , v ) in nodes . items ():
print ( " \t n {} [label= \" {} \" shape=box]" . format ( v , k ))
for ( mfile , minclude ) in pairs :
print ( " \t n {} -> n {} " . format ( nodes [ mfile ], nodes [ minclude ]))
print ( "}" )
How to Run the Script
In Your AOSP source code goto build/make/ directory and save this script in the same location as build_include.py and execute the following command.
egrep -R '(inherit|include)' target/ | python3 build_include.py | dot -Tpng > build-includes.png
By running the above script one build-includes.png file will get saved in the current directory.
if you want to save as pdf you run the below command.
egrep -R '(inherit|include)' target/ | python3 build_include.py | dot -Tpdf > build-includes.pdf
Python Script for Any Folder in the AOSP Source tree
build_include.py #!/usr/bin/env python
# Convert AOSP build include egrep output to visual graph via graphviz
# ---
# In device/google/, run something like:
# egrep -R '(inherit|include)' * | python3 build_include.py | dot -Tpng > build-includes.png
import os
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 = os . path . join ( os . getcwd (), m . group ( 1 ))
minclude = os . path . join ( os . getcwd (), 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 ( " \t rankdir=LR" )
for ( k , v ) in nodes . items ():
label = k . replace ( os . getcwd () + "/" , "" )
print ( " \t n {} [label= \" {} \" shape=box]" . format ( v , label ))
for ( mfile , minclude ) in pairs :
print ( " \t n {} -> n {} " . format ( nodes [ mfile ], nodes [ minclude ]))
print ( "}" )
Run the script with following command
Run the script with following command
egrep -R '(inherit|include)' . | python3 build_include.py | dot -Tpng > build-includes.png
below command is for to generate the output in pdf format.
egrep -R '(inherit|include)' . | python3 build_include.py | dot -Tpdf > build-includes.pdf
NOTE: Replace the .
with your desired path in which you want to create the graph of all mk files.