diff options
author | Nicolas Noble <nnoble@google.com> | 2015-01-06 18:08:25 -0800 |
---|---|---|
committer | Nicolas Noble <nnoble@google.com> | 2015-01-06 18:08:25 -0800 |
commit | ddef24620a67fa352d94415dc56121c01e3d8af8 (patch) | |
tree | f2383ee6e84a21e92f1524d23436ab28cfe04756 /tools/buildgen | |
parent | 9f2b09e112f5b95e843de786d7d3ecfd026170b6 (diff) |
Adding the tools directory to the git export.
Diffstat (limited to 'tools/buildgen')
-rwxr-xr-x | tools/buildgen/bunch.py | 37 | ||||
-rwxr-xr-x | tools/buildgen/generate_projects.sh | 48 | ||||
-rwxr-xr-x | tools/buildgen/mako_renderer.py | 105 | ||||
-rwxr-xr-x | tools/buildgen/plugins/expand_filegroups.py | 45 | ||||
-rwxr-xr-x | tools/buildgen/plugins/list_protos.py | 41 |
5 files changed, 276 insertions, 0 deletions
diff --git a/tools/buildgen/bunch.py b/tools/buildgen/bunch.py new file mode 100755 index 0000000000..e859d53388 --- /dev/null +++ b/tools/buildgen/bunch.py @@ -0,0 +1,37 @@ +"""Allows dot-accessible dictionaries.""" + + +class Bunch(dict): + + def __init__(self, d): + dict.__init__(self, d) + self.__dict__.update(d) + + +# Converts any kind of variable to a Bunch +def to_bunch(var): + if isinstance(var, list): + return [to_bunch(i) for i in var] + if isinstance(var, dict): + ret = {} + for k, v in var.items(): + if isinstance(v, (list, dict)): + v = to_bunch(v) + ret[k] = v + return Bunch(ret) + else: + return var + + +# Merges JSON 'add' into JSON 'dst' +def merge_json(dst, add): + if isinstance(dst, dict) and isinstance(add, dict): + for k, v in add.items(): + if k in dst: + merge_json(dst[k], v) + else: + dst[k] = v + elif isinstance(dst, list) and isinstance(add, list): + dst.extend(add) + else: + raise Exception('Tried to merge incompatible objects %r, %r' % (dst, add)) diff --git a/tools/buildgen/generate_projects.sh b/tools/buildgen/generate_projects.sh new file mode 100755 index 0000000000..f4e367d620 --- /dev/null +++ b/tools/buildgen/generate_projects.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +set -ex + +if [ "x$TEST" == "x" ] ; then + TEST=false +fi + + +cd `dirname $0`/.. +mako_renderer=tools/buildgen/mako_renderer.py +gen_build_json=test/core/end2end/gen_build_json.py + +end2end_test_build=`mktemp` +$gen_build_json > $end2end_test_build + +global_plugins=`find ./tools/buildgen/plugins -name '*.py' | + sort | grep -v __init__ | + while read p ; do echo -n "-p $p " ; done` + +for dir in . ; do + local_plugins=`find $dir/templates -name '*.py' | + sort | grep -v __init__ | + while read p ; do echo -n "-p $p " ; done` + + plugins="$global_plugins $local_plugins" + + find -L $dir/templates -type f -and -name *.template | while read file ; do + out=${dir}/${file#$dir/templates/} # strip templates dir prefix + out=${out%.*} # strip template extension + json_files="build.json $end2end_test_build" + data=`for i in $json_files; do echo -n "-d $i "; done` + if [ $TEST == true ] ; then + actual_out=$out + out=`mktemp` + else + g4 open $out || true + fi + $mako_renderer $plugins $data -o $out $file + if [ $TEST == true ] ; then + diff -q $out $actual_out + rm $out + fi + done +done + +rm $end2end_test_build + diff --git a/tools/buildgen/mako_renderer.py b/tools/buildgen/mako_renderer.py new file mode 100755 index 0000000000..29c7cf0307 --- /dev/null +++ b/tools/buildgen/mako_renderer.py @@ -0,0 +1,105 @@ +#!/usr/bin/python + +"""Simple Mako renderer. + +Just a wrapper around the mako rendering library. + +""" + +import getopt +import imp +import os +import sys + + +from mako.lookup import TemplateLookup +from mako.runtime import Context +from mako.template import Template +import simplejson +import bunch + + +# Imports a plugin +def import_plugin(name): + _, base_ex = os.path.split(name) + base, _ = os.path.splitext(base_ex) + + with open(name, 'r') as plugin_file: + plugin_code = plugin_file.read() + plugin_module = imp.new_module(base) + exec plugin_code in plugin_module.__dict__ + return plugin_module + + +def out(msg): + print >> sys.stderr, msg + + +def showhelp(): + out('mako-renderer.py [-o out] [-m cache] [-d dict] [-d dict...] template') + + +def main(argv): + got_input = False + module_directory = None + dictionary = {} + json_dict = {} + got_output = False + output_file = sys.stdout + plugins = [] + + try: + opts, args = getopt.getopt(argv, 'hm:d:o:p:') + except getopt.GetoptError: + out('Unknown option') + showhelp() + sys.exit(2) + + for opt, arg in opts: + if opt == '-h': + out('Displaying showhelp') + showhelp() + sys.exit() + elif opt == '-o': + if got_output: + out('Got more than one output') + showhelp() + sys.exit(3) + got_output = True + output_file = open(arg, 'w') + elif opt == '-m': + if module_directory is not None: + out('Got more than one cache directory') + showhelp() + sys.exit(4) + module_directory = arg + elif opt == '-d': + dict_file = open(arg, 'r') + bunch.merge_json(json_dict, simplejson.loads(dict_file.read())) + dict_file.close() + elif opt == '-p': + plugins.append(import_plugin(arg)) + + for plugin in plugins: + plugin.mako_plugin(json_dict) + + for k, v in json_dict.items(): + dictionary[k] = bunch.to_bunch(v) + + ctx = Context(output_file, **dictionary) + + for arg in args: + got_input = True + template = Template(filename=arg, + module_directory=module_directory, + lookup=TemplateLookup(directories=['.'])) + template.render_context(ctx) + + if not got_input: + out('Got nothing to do') + showhelp() + + output_file.close() + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/tools/buildgen/plugins/expand_filegroups.py b/tools/buildgen/plugins/expand_filegroups.py new file mode 100755 index 0000000000..108debefd5 --- /dev/null +++ b/tools/buildgen/plugins/expand_filegroups.py @@ -0,0 +1,45 @@ +"""Buildgen expand filegroups plugin. + +This takes the list of libs from our json dictionary, +and expands any and all filegroup. + +""" + + +def excluded(filename, exclude_res): + for r in exclude_res: + if r.search(filename): + return True + return False + + +def mako_plugin(dictionary): + """The exported plugin code for expand_filegroups. + + The list of libs in the build.json file can contain "filegroups" tags. + These refer to the filegroups in the root object. We will expand and + merge filegroups on the src, headers and public_headers properties. + + """ + libs = dictionary.get('libs') + filegroups_list = dictionary.get('filegroups') + filegroups = {} + + for fg in filegroups_list: + filegroups[fg['name']] = fg + + for lib in libs: + for fg_name in lib.get('filegroups', []): + fg = filegroups[fg_name] + + src = lib.get('src', []) + src.extend(fg.get('src', [])) + lib['src'] = src + + headers = lib.get('headers', []) + headers.extend(fg.get('headers', [])) + lib['headers'] = headers + + public_headers = lib.get('public_headers', []) + public_headers.extend(fg.get('public_headers', [])) + lib['public_headers'] = public_headers diff --git a/tools/buildgen/plugins/list_protos.py b/tools/buildgen/plugins/list_protos.py new file mode 100755 index 0000000000..c5a09dd4d0 --- /dev/null +++ b/tools/buildgen/plugins/list_protos.py @@ -0,0 +1,41 @@ +"""Buildgen .proto files list plugin. + +This parses the list of targets from the json build file, and creates +a list called "protos" that contains all of the proto file names. + +""" + + +import re + + +def mako_plugin(dictionary): + """The exported plugin code for list_protos. + + Some projects generators may want to get the full list of unique .proto files + that are being included in a project. This code extracts all files referenced + in any library or target that ends in .proto, and builds and exports that as + a list called "protos". + + """ + + libs = dictionary.get('libs', []) + targets = dictionary.get('targets', []) + + proto_re = re.compile('(.*)\\.proto') + + protos = set() + for lib in libs: + for src in lib.get('src', []): + m = proto_re.match(src) + if m: + protos.add(m.group(1)) + for tgt in targets: + for src in tgt.get('src', []): + m = proto_re.match(src) + if m: + protos.add(m.group(1)) + + protos = sorted(protos) + + dictionary['protos'] = protos |