
This adds SPDX license headers in place of the wide assortment of things currently in our script headers. We default to GPL-2.0-only except for the oeqa code where it was clearly submitted and marked as MIT on the most part or some scripts which had the "or later" GPL versioning. The patch also drops other obsolete bits of file headers where they were encoountered such as editor modelines, obsolete maintainer information or the phrase "All rights reserved" which is now obsolete and not required in copyright headers (in this case its actually confusing for licensing as all rights were not reserved). More work is needed for OE-Core but this takes care of the bulk of the scripts and meta/lib directories. The top level LICENSE files are tweaked to match the new structure and the SPDX naming. (From OE-Core rev: f8c9c511b5f1b7dbd45b77f345cb6c048ae6763e) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
5.6 KiB
Executable File
#!/usr/bin/env python3
Copyright (C) 2018 Wind River Systems, Inc.
SPDX-License-Identifier: GPL-2.0-only
import os import sys import argparse import logging import re
class Dot(object): def init(self): parser = argparse.ArgumentParser( description="Analyse recipe-depends.dot generated by bitbake -g", epilog="Use %(prog)s --help to get help") parser.add_argument("dotfile", help = "Specify the dotfile", nargs = 1, action='store', default='') parser.add_argument("-k", "--key", help = "Specify the key, e.g., recipe name", action="store", default='') parser.add_argument("-d", "--depends", help = "Print the key's dependencies", action="store_true", default=False) parser.add_argument("-w", "--why", help = "Print why the key is built", action="store_true", default=False) parser.add_argument("-r", "--remove", help = "Remove duplicated dependencies to reduce the size of the dot files." " For example, A->B, B->C, A->C, then A->C can be removed.", action="store_true", default=False)
self.args = parser.parse_args()
if len(sys.argv) != 3 and len(sys.argv) < 5:
print('ERROR: Not enough args, see --help for usage')
@staticmethod
def insert_dep_chain(chain, rdeps, alldeps):
"""
insert elements to chain from rdeps, according to alldeps
"""
# chain should at least contain one element
if len(chain) == 0:
raise
inserted_elements = []
for rdep in rdeps:
if rdep in chain:
continue
else:
for i in range(0, len(chain)-1):
if chain[i] in alldeps[rdep] and rdep in alldeps[chain[i+1]]:
chain.insert(i+1, rdep)
inserted_elements.append(rdep)
break
if chain[-1] in alldeps[rdep] and rdep not in chain:
chain.append(rdep)
inserted_elements.append(rdep)
return inserted_elements
@staticmethod
def print_dep_chains(key, rdeps, alldeps):
rlist = rdeps.copy()
chain = []
removed_rdeps = [] # hold rdeps removed from rlist
chain.append(key)
while (len(rlist) != 0):
# insert chain from rlist
inserted_elements = Dot.insert_dep_chain(chain, rlist, alldeps)
if not inserted_elements:
if chain[-1] in rlist:
rlist.remove(chain[-1])
removed_rdeps.append(chain[-1])
chain.pop()
continue
else:
# insert chain from removed_rdeps
Dot.insert_dep_chain(chain, removed_rdeps, alldeps)
print(' -> '.join(list(reversed(chain))))
def main(self):
#print(self.args.dotfile[0])
# The format is {key: depends}
depends = {}
with open(self.args.dotfile[0], 'r') as f:
for line in f.readlines():
if ' -> ' not in line:
continue
line_no_quotes = line.replace('"', '')
m = re.match("(.*) -> (.*)", line_no_quotes)
if not m:
print('WARNING: Found unexpected line: %s' % line)
continue
key = m.group(1)
if key == "meta-world-pkgdata":
continue
dep = m.group(2)
if key in depends:
if not key in depends[key]:
depends[key].add(dep)
else:
print('WARNING: Fonud duplicated line: %s' % line)
else:
depends[key] = set()
depends[key].add(dep)
if self.args.remove:
reduced_depends = {}
for k, deps in depends.items():
child_deps = set()
added = set()
# Both direct and indirect depends are already in the dict, so
# we don't have to do this recursively.
for dep in deps:
if dep in depends:
child_deps |= depends[dep]
reduced_depends[k] = deps - child_deps
outfile= '%s-reduced%s' % (self.args.dotfile[0][:-4], self.args.dotfile[0][-4:])
with open(outfile, 'w') as f:
print('Saving reduced dot file to %s' % outfile)
f.write('digraph depends {\n')
for k, v in reduced_depends.items():
for dep in v:
f.write('"%s" -> "%s"\n' % (k, dep))
f.write('}\n')
sys.exit(0)
if self.args.key not in depends:
print("ERROR: Can't find key %s in %s" % (self.args.key, self.args.dotfile[0]))
sys.exit(1)
if self.args.depends:
if self.args.key in depends:
print('Depends: %s' % ' '.join(depends[self.args.key]))
reverse_deps = []
if self.args.why:
for k, v in depends.items():
if self.args.key in v and not k in reverse_deps:
reverse_deps.append(k)
print('Because: %s' % ' '.join(reverse_deps))
Dot.print_dep_chains(self.args.key, reverse_deps, depends)
if name == "main": try: dot = Dot() ret = dot.main() except Exception as esc: ret = 1 import traceback traceback.print_exc() sys.exit(ret)