am f72e34eb: Merge changes I9d3a3c16,I17b5d441,I29e27505,Ia5ca233e,I0a0b200b,I6f412ed4,I623821df,Ifec8e63e,I12d0a847,Idac551e5,I59a88027,I2498139d,I6bd93a87

* commit 'f72e34ebf49ed2a06fe9e37d134f2088e2c0c0e4':
  Move the old user tagged modules over to base.mk so mini and core both share them.
  More product debugging.
  build system changes for jb-aah-dev merge
  Fail when a non-vendor product references a vendor module.
  Remove support for user tags in the build system.
  List the user modules explicitly, and we can get rid of the support for the user tag!
  Dump the user tagged modules.
  host modules don't need LOCAL_MODULE_TAGS
  Don't give the user tag to host modules automatically.
  Add a phony "nothing" goal that reads the makefiles but doesn't try to build anything.
  Add tool to parse make dependency info from new --deps flag.
  Use a more modern -j flag.
  make product-graph now filtered
This commit is contained in:
Joe Onorato
2012-08-16 23:50:34 -07:00
committed by Android Git Automerger
16 changed files with 749 additions and 610 deletions

View File

@@ -41,7 +41,7 @@ function do_builds
do
rm -rf $TEST_BUILD_DIR/$PREFIX-$1
make PRODUCT-$(echo $1 | sed "s/-.*//" )-installclean
make -j6 PRODUCT-$1 dist DIST_DIR=$TEST_BUILD_DIR/$PREFIX-$1
make -j16 PRODUCT-$1 dist DIST_DIR=$TEST_BUILD_DIR/$PREFIX-$1
if [ $? -ne 0 ] ; then
echo FAILED
return

68
tools/filter-product-graph.py Executable file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env python
# vim: ts=2 sw=2 nocindent
import re
import sys
def choose_regex(regs, line):
for func,reg in regs:
m = reg.match(line)
if m:
return (func,m)
return (None,None)
def gather(included, deps):
result = set()
for inc in included:
result.add(inc)
for d in deps:
if inc == d[1]:
result.add(d[0])
return result
def main():
deps = []
infos = []
def dependency(m):
deps.append((m.group(1), m.group(2)))
def info(m):
infos.append((m.group(1), m.group(2)))
REGS = [
(dependency, re.compile(r'"(.*)"\s*->\s*"(.*)"')),
(info, re.compile(r'"(.*)"(\s*\[.*\])')),
]
lines = sys.stdin.readlines()
lines = [line.strip() for line in lines]
for line in lines:
func,m = choose_regex(REGS, line)
if func:
func(m)
# filter
sys.stderr.write("argv: " + str(sys.argv) + "\n")
if not (len(sys.argv) == 2 and sys.argv[1] == "--all"):
targets = sys.argv[1:]
included = set(targets)
prevLen = -1
while prevLen != len(included):
prevLen = len(included)
included = gather(included, deps)
deps = [dep for dep in deps if dep[1] in included]
infos = [info for info in infos if info[0] in included]
print "digraph {"
print "graph [ ratio=.5 ];"
for dep in deps:
print '"%s" -> "%s"' % dep
for info in infos:
print '"%s"%s' % info
print "}"
if __name__ == "__main__":
main()

View File

@@ -18,6 +18,5 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := fs_config.c
LOCAL_MODULE := fs_config
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_TAGS := eng
include $(BUILD_HOST_EXECUTABLE)

151
tools/parsedeps.py Executable file
View File

@@ -0,0 +1,151 @@
#!/usr/bin/env python
# vim: ts=2 sw=2
import optparse
import re
import sys
class Dependency:
def __init__(self, tgt):
self.tgt = tgt
self.pos = ""
self.prereqs = set()
self.visit = 0
def add(self, prereq):
self.prereqs.add(prereq)
class Dependencies:
def __init__(self):
self.lines = {}
self.__visit = 0
self.count = 0
def add(self, tgt, prereq):
t = self.lines.get(tgt)
if not t:
t = Dependency(tgt)
self.lines[tgt] = t
p = self.lines.get(prereq)
if not p:
p = Dependency(prereq)
self.lines[prereq] = p
t.add(p)
self.count = self.count + 1
def setPos(self, tgt, pos):
t = self.lines.get(tgt)
if not t:
t = Dependency(tgt)
self.lines[tgt] = t
t.pos = pos
def get(self, tgt):
if self.lines.has_key(tgt):
return self.lines[tgt]
else:
return None
def __iter__(self):
return self.lines.iteritems()
def trace(self, tgt, prereq):
self.__visit = self.__visit + 1
d = self.lines.get(tgt)
if not d:
return
return self.__trace(d, prereq)
def __trace(self, d, prereq):
if d.visit == self.__visit:
return d.trace
if d.tgt == prereq:
return [ [ d ], ]
d.visit = self.__visit
result = []
for pre in d.prereqs:
recursed = self.__trace(pre, prereq)
for r in recursed:
result.append([ d ] + r)
d.trace = result
return result
def help():
print "Commands:"
print " dep TARGET Print the prerequisites for TARGET"
print " trace TARGET PREREQ Print the paths from TARGET to PREREQ"
def main(argv):
opts = optparse.OptionParser()
opts.add_option("-i", "--interactive", action="store_true", dest="interactive",
help="Interactive mode")
(options, args) = opts.parse_args()
deps = Dependencies()
filename = args[0]
print "Reading %s" % filename
if True:
f = open(filename)
for line in f:
line = line.strip()
if len(line) > 0:
if line[0] == '#':
pos,tgt = line.rsplit(":", 1)
pos = pos[1:].strip()
tgt = tgt.strip()
deps.setPos(tgt, pos)
else:
(tgt,prereq) = line.split(':', 1)
tgt = tgt.strip()
prereq = prereq.strip()
deps.add(tgt, prereq)
f.close()
print "Read %d dependencies. %d targets." % (deps.count, len(deps.lines))
while True:
line = raw_input("target> ")
if not line.strip():
continue
split = line.split()
cmd = split[0]
if len(split) == 2 and cmd == "dep":
tgt = split[1]
d = deps.get(tgt)
if d:
for prereq in d.prereqs:
print prereq.tgt
elif len(split) == 3 and cmd == "trace":
tgt = split[1]
prereq = split[2]
if False:
print "from %s to %s" % (tgt, prereq)
trace = deps.trace(tgt, prereq)
if trace:
width = 0
for g in trace:
for t in g:
if len(t.tgt) > width:
width = len(t.tgt)
for g in trace:
for t in g:
if t.pos:
print t.tgt, " " * (width-len(t.tgt)), " #", t.pos
else:
print t.tgt
print
else:
help()
if __name__ == "__main__":
try:
main(sys.argv)
except KeyboardInterrupt:
print
except EOFError:
print

160
tools/product_debug.py Executable file
View File

@@ -0,0 +1,160 @@
#!/usr/bin/env python
#
# Copyright (C) 2012 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import re
import sys
def break_lines(key, val):
# these don't get split
if key in ("PRODUCT_MODEL"):
return (key,val)
return (key, "\n".join(val.split()))
def split_line(line):
words = line.split("=", 1)
if len(words) == 1:
return (words[0], "")
else:
return (words[0], words[1])
def sort_lines(text):
lines = text.split()
lines.sort()
return "\n".join(lines)
def parse_variables(lines):
return [split_line(line) for line in lines if line.strip()]
def render_variables(variables):
variables = dict(variables)
del variables["FILE"]
variables = list(variables.iteritems())
variables.sort(lambda a, b: cmp(a[0], b[0]))
return ("<table id='variables'>"
+ "\n".join([ "<tr><th>%(key)s</th><td>%(val)s</td></tr>" % { "key": key, "val": val }
for key,val in variables])
+"</table>")
def linkify_inherit(variables, text, func_name):
groups = re.split("(\\$\\(call " + func_name + ",.*\\))", text)
result = ""
for i in range(0,len(groups)/2):
i = i * 2
result = result + groups[i]
s = groups[i+1]
href = s.split(",", 1)[1].strip()[:-1]
href = href.replace("$(SRC_TARGET_DIR)", "build/target")
href = ("../" * variables["FILE"].count("/")) + href + ".html"
result = result + "<a href=\"%s\">%s</a>" % (href,s)
result = result + groups[-1]
return result
def render_original(variables, text):
text = linkify_inherit(variables, text, "inherit-product")
text = linkify_inherit(variables, text, "inherit-product-if-exists")
return text
def read_file(fn):
f = file(fn)
text = f.read()
f.close()
return text
def main(argv):
# read the variables
lines = sys.stdin.readlines()
variables = parse_variables(lines)
# format the variables
variables = [break_lines(key,val) for key,val in variables]
# now it's a dict
variables = dict(variables)
sorted_vars = (
"PRODUCT_COPY_FILES",
"PRODUCT_PACKAGES",
"PRODUCT_LOCALES",
"PRODUCT_FACTORY_RAMDISK_MODULES",
"PRODUCT_PROPERTY_OVERRIDES",
)
for key in sorted_vars:
variables[key] = sort_lines(variables[key])
# the original file
original = read_file(variables["FILE"])
# formatting
values = dict(variables)
values.update({
"variables": render_variables(variables),
"original": render_original(variables, original),
})
print """<html>
<head>
<title>%(FILE)s</title>
<style type="text/css">
body {
font-family: Helvetica, Arial, sans-serif;
padding-bottom: 20px;
}
#variables {
border-collapse: collapse;
}
#variables th, #variables td {
vertical-align: top;
text-align: left;
border-top: 1px solid #c5cdde;
border-bottom: 1px solid #c5cdde;
padding: 2px 10px 2px 10px;
}
#variables th {
font-size: 10pt;
background-color: #e2ecff
}
#variables td {
background-color: #ebf2ff;
white-space: pre;
font-size: 10pt;
}
#original {
background-color: #ebf2ff;
border-top: 1px solid #c5cdde;
border-bottom: 1px solid #c5cdde;
padding: 2px 10px 2px 10px;
white-space: pre;
font-size: 10pt;
}
</style>
</head>
<body>
<h1>%(FILE)s</h1>
<a href="#Original">Original</a>
<a href="#Variables">Variables</a>
<h2><a name="Original"></a>Original</h2>
<div id="original">%(original)s</div>
<h2><a name="Variables"></a>Variables</h2>
%(variables)s
</body>
</html>
""" % values
if __name__ == "__main__":
main(sys.argv)