OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/python | |
2 | |
3 # Copyright 2014 Google Inc. | |
4 # | |
5 # Use of this source code is governed by a BSD-style license that can be | |
6 # found in the LICENSE file. | |
7 | |
8 """ | |
9 Functions for parsing the gypd output from gyp. | |
10 """ | |
11 | |
12 import vars_dict_lib | |
13 | |
14 def parse_dictionary(var_dict, d, current_target_name): | |
15 """ | |
16 Helper function to get the meaningful entries in a dictionary. | |
17 @param var_dict VarsDict object for storing the results of the parsing. | |
epoger
2014/02/03 17:26:32
I think it's unusual for Python functions to take
scroggo
2014/02/03 23:22:31
Hmm. The reason I do it this way is because this f
epoger
2014/02/04 15:00:12
I guess the alternative would be to collect multip
| |
18 @param d Dictionary object to parse. | |
19 @param current_target_name The current target being parsed. If this | |
20 dictionary is a target, this will be its entry | |
21 'target_name'. Otherwise, this will be the name of | |
22 the target which contains this dictionary. | |
23 """ | |
24 for source in d.get('sources', []): | |
25 if source.endswith('.h'): | |
epoger
2014/02/03 17:26:32
Do we need to worry about capitalization? (Is it
scroggo
2014/02/03 23:22:31
Well, someone could easily rewrite our gyp files t
| |
26 # Android.mk does not need the header files. | |
27 continue | |
28 if source.endswith('gypi'): | |
29 # The gypi files are included in sources, but the sources they included | |
30 # are also included. No need to parse them again. | |
31 continue | |
32 # The path is relative to the gyp folder, but Android wants the path | |
33 # relative to the root. | |
34 source = source.replace('../src', 'src', 1) | |
epoger
2014/02/03 17:26:32
Does this modify the dictionary in place? If so,
scroggo
2014/02/03 23:22:31
That's correct. And I do not call d.set :)
| |
35 var_dict.LOCAL_SRC_FILES.add(source) | |
36 | |
37 for lib in d.get('libraries', []): | |
38 if lib.endswith('.a'): | |
39 # Remove the '.a' | |
40 lib = lib[:-2] | |
41 # Add 'lib', if necessary | |
42 if not lib.startswith('lib'): | |
43 lib = 'lib' + lib | |
44 var_dict.LOCAL_STATIC_LIBRARIES.add(lib) | |
45 else: | |
46 # lib will be in the form of '-l<name>'. Change it to 'lib<name>' | |
47 lib = lib.replace('-l', 'lib', 1) | |
48 var_dict.LOCAL_SHARED_LIBRARIES.add(lib) | |
49 | |
50 for dependency in d.get('dependencies', []): | |
51 # Each dependency is listed as | |
52 # <path_to_file>:<target>#target | |
53 li = dependency.split(':') | |
54 assert(len(li) <= 2 and len(li) >= 1) | |
55 sub_targets = [] | |
56 if len(li) == 2 and li[1] != '*': | |
57 sub_targets.append(li[1].split('#')[0]) | |
58 sub_path = li[0] | |
59 assert(sub_path.endswith('.gyp')) | |
60 # Although the original reference is to a .gyp, parse the corresponding | |
61 # gypd file, which was constructed by gyp. | |
62 sub_path = sub_path + 'd' | |
63 parse_gypd(var_dict, sub_path, sub_targets) | |
64 | |
65 if 'default_configuration' in d: | |
66 config_name = d['default_configuration'] | |
67 # default_configuration is meaningless without configurations | |
68 assert('configurations' in d) | |
69 config = d['configurations'][config_name] | |
70 parse_dictionary(var_dict, config, current_target_name) | |
71 | |
72 for flag in d.get('cflags', []): | |
73 var_dict.LOCAL_CFLAGS.add(flag) | |
74 for flag in d.get('cflags_cc', []): | |
75 var_dict.LOCAL_CPPFLAGS.add(flag) | |
76 | |
77 for include in d.get('include_dirs', []): | |
78 # The input path will be relative to gyp/, but Android wants relative to | |
epoger
2014/02/03 17:26:32
I worry that some of these adjustments will prove
| |
79 # LOCAL_PATH | |
80 include = include.replace('..', '$(LOCAL_PATH)', 1) | |
81 # Remove a trailing slash, if present. | |
82 if include.endswith('/'): | |
83 include = include[:-1] | |
84 var_dict.LOCAL_C_INCLUDES.add(include) | |
85 # For the top level, libskia, include directories should be exported. | |
86 if current_target_name == 'libskia': | |
87 var_dict.LOCAL_EXPORT_C_INCLUDE_DIRS.add(include) | |
88 | |
89 for define in d.get('defines', []): | |
90 var_dict.LOCAL_CFLAGS.add('-D' + define) | |
91 | |
92 | |
93 def parse_gypd(var_dict, path, desired_targets=None): | |
94 """ | |
95 Parse a gypd file. | |
96 @param var_dict VarsDict object for storing the result of the parse. | |
97 @param path Path to gypd file. | |
98 @param desired_targets List of targets to be parsed from this file. If empty, | |
99 parse all targets. | |
100 """ | |
101 d = {} | |
102 with open(path, 'r') as f: | |
103 # Read the entire file as a dictionary | |
104 d = eval(f.read()) | |
105 # The gypd file is structured such that the top level dictionary has an entry | |
106 # named 'targets' | |
epoger
2014/02/03 17:26:32
And if it doesn't have a 'targets' entry, shouldn'
scroggo
2014/02/03 23:22:31
Done.
| |
107 if 'targets' not in d: | |
108 return | |
109 targets = d['targets'] | |
110 for target in targets: | |
111 target_name = target['target_name'] | |
112 if target_name in var_dict.KNOWN_TARGETS: | |
113 # Avoid circular dependencies | |
114 continue | |
115 if desired_targets and target_name not in desired_targets: | |
116 # Our caller does not depend on this one | |
117 continue | |
118 # Add it to our known targets so we don't parse it again | |
119 var_dict.KNOWN_TARGETS.add(target_name) | |
120 | |
121 parse_dictionary(var_dict, target, target_name) | |
122 | |
OLD | NEW |