Edit

kc3-lang/angle/scripts/gen_angle_gn_info_json.py

Branch :

  • Show log

    Commit

  • Author : Courtney Goeltzenleuchter
    Date : 2018-03-20 10:08:05
    Hash : ed8d5ec7
    Message : Add json build file generation gen_angle_gn_info_json.py can be used to generate a json description of the build for given targets. This information can then be used to generate build files for other tool chains (e.g. Android blueprint) Bug: angleproject:2418 Change-Id: Ief8f43e30ae1f469e3fcfa795306675e29a90a2f Reviewed-on: https://chromium-review.googlesource.com/967225 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org>

  • scripts/gen_angle_gn_info_json.py
  • #!/usr/bin/env python
    
    #  Copyright 2018 The ANGLE Project Authors. All rights reserved.
    #  Use of this source code is governed by a BSD-style license that can be
    #  found in the LICENSE file.
    
    # This tool will create a json description of the GN build environment that
    # can then be used by gen_angle_android_bp.py to build an Android.bp file for
    # the Android Soong build system.
    # The input to this tool is a list of GN labels for which to capture the build
    # information in json:
    #
    # Generating angle.json needs to be done from within a Chromium build:
    #   cd <chromium>/src
    #   gen_angle_gn_info_json.py //third_party/angle:libGLESv2 //third_party/angle:libEGL
    #
    # This will output an angle.json that can be copied to the angle directory
    # within Android.
    #
    # Optional arguments:
    #  --gn_out <file>  GN output config to use (e.g., out/Default or out/Debug.)
    #  --output <file>  json file to create, default is angle.json
    #
    
    import argparse
    import json
    import logging
    import subprocess
    import sys
    
    
    def get_json_description(gn_out, target_name):
        try:
            text_desc = subprocess.check_output(
                ['gn', 'desc', '--format=json', gn_out, target_name])
        except subprocess.CalledProcessError as e:
            logging.error("e.retcode = %s" % e.returncode)
            logging.error("e.cmd = %s" % e.cmd)
            logging.error("e.output = %s" % e.output)
        try:
            json_out = json.loads(text_desc)
        except ValueError:
            raise ValueError("Unable to decode JSON\ncmd: %s\noutput:\n%s" %
                             (subprocess.list2cmdline(['gn', 'desc', '--format=json',
                                                       gn_out, target_name]), text_desc))
    
        return json_out
    
    def load_json_deps(desc, gn_out, target_name, all_desc, indent="  "):
        """Extracts dependencies from the given target json description
           and recursively extracts json descriptions.
    
           desc: json description for target_name that includes dependencies
           gn_out: GN output file with configuration info
           target_name: name of target in desc to lookup deps
           all_desc: dependent descriptions added here
           indent: Print with indent to show recursion depth
        """
        target = desc[target_name]
        text_descriptions = []
        for dep in target.get('deps', []):
            if dep not in all_desc:
                logging.debug("dep: %s%s" % (indent,dep))
                new_desc = get_json_description(gn_out, dep)
                all_desc[dep] = new_desc[dep]
                load_json_deps(new_desc, gn_out, dep, all_desc, indent+"  ")
            else:
                logging.debug("dup: %s%s" % (indent,dep))
    
    def create_build_description(gn_out, targets):
        """Creates the JSON build description by running GN."""
    
        logging.debug("targets = %s" % targets)
        json_descriptions = {}
        for target in targets:
            logging.debug("target: %s" % (target))
            target_desc = get_json_description(gn_out, target)
            if (target in target_desc and target not in json_descriptions):
                json_descriptions[target] = target_desc[target]
                load_json_deps(target_desc, gn_out, target, json_descriptions)
            else:
                logging.debug("Invalid target: %s" % target)
        return json_descriptions
    
    
    def main():
        logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
        parser = argparse.ArgumentParser(
            description='Generate json build information from a GN description.')
        parser.add_argument(
            '--gn_out',
            help=
            'GN output config to use (e.g., out/Default or out/Debug.)',
            default='out/Default',
        )
        parser.add_argument(
            '--output',
            help='json file to create',
            default='angle.json',
        )
        parser.add_argument(
            'targets',
            nargs=argparse.REMAINDER,
            help='Targets to include in the json (e.g., "//libEGL")')
        args = parser.parse_args()
    
        desc = create_build_description(args.gn_out, args.targets)
        fh = open(args.output,"w")
        fh.write(json.dumps(desc, indent=4, sort_keys=True))
        fh.close()
    
        print("Output written to: %s" % args.output)
    
    
    if __name__ == '__main__':
        sys.exit(main())