Index: platform_tools/android/gyp_gen/gypd_parser.py |
diff --git a/platform_tools/android/gyp_gen/gypd_parser.py b/platform_tools/android/gyp_gen/gypd_parser.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b547c42525c298ccce5f0a1655c058cdb571ebf7 |
--- /dev/null |
+++ b/platform_tools/android/gyp_gen/gypd_parser.py |
@@ -0,0 +1,122 @@ |
+#!/usr/bin/python |
+ |
+# Copyright 2014 Google Inc. |
+# |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+""" |
+Functions for parsing the gypd output from gyp. |
+""" |
+ |
+import vars_dict_lib |
+ |
+def parse_dictionary(var_dict, d, current_target_name): |
+ """ |
+ Helper function to get the meaningful entries in a dictionary. |
+ @param var_dict VarsDict object for storing the results of the parsing. |
+ @param d Dictionary object to parse. |
+ @param current_target_name The current target being parsed. If this |
+ dictionary is a target, this will be its entry |
+ 'target_name'. Otherwise, this will be the name of |
+ the target which contains this dictionary. |
+ """ |
+ for source in d.get('sources', []): |
+ # Compare against a lowercase version, in case files are named .H or .GYPI |
+ lowercase_source = source.lower() |
+ if lowercase_source.endswith('.h'): |
+ # Android.mk does not need the header files. |
+ continue |
+ if lowercase_source.endswith('gypi'): |
+ # The gypi files are included in sources, but the sources they included |
+ # are also included. No need to parse them again. |
+ continue |
+ # The path is relative to the gyp folder, but Android wants the path |
+ # relative to the root. |
+ source = source.replace('../src', 'src', 1) |
+ var_dict.LOCAL_SRC_FILES.add(source) |
+ |
+ for lib in d.get('libraries', []): |
+ if lib.endswith('.a'): |
+ # Remove the '.a' |
+ lib = lib[:-2] |
+ # Add 'lib', if necessary |
+ if not lib.startswith('lib'): |
+ lib = 'lib' + lib |
+ var_dict.LOCAL_STATIC_LIBRARIES.add(lib) |
+ else: |
+ # lib will be in the form of '-l<name>'. Change it to 'lib<name>' |
+ lib = lib.replace('-l', 'lib', 1) |
+ var_dict.LOCAL_SHARED_LIBRARIES.add(lib) |
+ |
+ for dependency in d.get('dependencies', []): |
+ # Each dependency is listed as |
+ # <path_to_file>:<target>#target |
+ li = dependency.split(':') |
+ assert(len(li) <= 2 and len(li) >= 1) |
+ sub_targets = [] |
+ if len(li) == 2 and li[1] != '*': |
+ sub_targets.append(li[1].split('#')[0]) |
+ sub_path = li[0] |
+ assert(sub_path.endswith('.gyp')) |
+ # Although the original reference is to a .gyp, parse the corresponding |
+ # gypd file, which was constructed by gyp. |
+ sub_path = sub_path + 'd' |
+ parse_gypd(var_dict, sub_path, sub_targets) |
+ |
+ if 'default_configuration' in d: |
+ config_name = d['default_configuration'] |
+ # default_configuration is meaningless without configurations |
+ assert('configurations' in d) |
+ config = d['configurations'][config_name] |
+ parse_dictionary(var_dict, config, current_target_name) |
+ |
+ for flag in d.get('cflags', []): |
+ var_dict.LOCAL_CFLAGS.add(flag) |
+ for flag in d.get('cflags_cc', []): |
+ var_dict.LOCAL_CPPFLAGS.add(flag) |
+ |
+ for include in d.get('include_dirs', []): |
+ # The input path will be relative to gyp/, but Android wants relative to |
+ # LOCAL_PATH |
+ include = include.replace('..', '$(LOCAL_PATH)', 1) |
+ # Remove a trailing slash, if present. |
+ if include.endswith('/'): |
+ include = include[:-1] |
+ var_dict.LOCAL_C_INCLUDES.add(include) |
+ # For the top level, libskia, include directories should be exported. |
+ if current_target_name == 'libskia': |
+ var_dict.LOCAL_EXPORT_C_INCLUDE_DIRS.add(include) |
+ |
+ for define in d.get('defines', []): |
+ var_dict.LOCAL_CFLAGS.add('-D' + define) |
+ |
+ |
+def parse_gypd(var_dict, path, desired_targets=None): |
+ """ |
+ Parse a gypd file. |
+ @param var_dict VarsDict object for storing the result of the parse. |
+ @param path Path to gypd file. |
+ @param desired_targets List of targets to be parsed from this file. If empty, |
+ parse all targets. |
+ """ |
+ d = {} |
+ with open(path, 'r') as f: |
+ # Read the entire file as a dictionary |
+ d = eval(f.read()) |
+ |
+ # The gypd file is structured such that the top level dictionary has an entry |
+ # named 'targets' |
+ for target in d['targets']: |
+ target_name = target['target_name'] |
+ if target_name in var_dict.KNOWN_TARGETS: |
+ # Avoid circular dependencies |
+ continue |
+ if desired_targets and target_name not in desired_targets: |
+ # Our caller does not depend on this one |
+ continue |
+ # Add it to our known targets so we don't parse it again |
+ var_dict.KNOWN_TARGETS.add(target_name) |
+ |
+ parse_dictionary(var_dict, target, target_name) |
+ |