OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Adaptor script called through build/isolate.gypi. | 6 """Adaptor script called through build/isolate.gypi. |
7 | 7 |
8 Creates a wrapping .isolate which 'includes' the original one, that can be | 8 Creates a wrapping .isolate which 'includes' the original one, that can be |
9 consumed by tools/swarming_client/isolate.py. Path variables are determined | 9 consumed by tools/swarming_client/isolate.py. Path variables are determined |
10 based on the current working directory. The relative_cwd in the .isolated file | 10 based on the current working directory. The relative_cwd in the .isolated file |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 | 106 |
107 | 107 |
108 def using_blacklist(item): | 108 def using_blacklist(item): |
109 """Returns True if an item should be analyzed. | 109 """Returns True if an item should be analyzed. |
110 | 110 |
111 Ignores many rules that are assumed to not depend on a dynamic library. If | 111 Ignores many rules that are assumed to not depend on a dynamic library. If |
112 the assumption doesn't hold true anymore for a file format, remove it from | 112 the assumption doesn't hold true anymore for a file format, remove it from |
113 this list. This is simply an optimization. | 113 this list. This is simply an optimization. |
114 """ | 114 """ |
115 IGNORED = ( | 115 IGNORED = ( |
116 '.a', '.cc', '.css', '.def', '.h', '.html', '.js', '.json', '.manifest', | 116 '.a', '.cc', '.css', '.def', '.frag', '.h', '.html', '.js', '.json', |
117 '.o', '.obj', '.pak', '.png', '.pdb', '.strings', '.txt', | 117 '.manifest', '.o', '.obj', '.pak', '.png', '.pdb', '.strings', '.test', |
118 '.txt', '.vert', | |
118 ) | 119 ) |
119 # ninja files use native path format. | 120 # ninja files use native path format. |
120 ext = os.path.splitext(item)[1] | 121 ext = os.path.splitext(item)[1] |
121 if ext in IGNORED: | 122 if ext in IGNORED: |
122 return False | 123 return False |
123 # Special case Windows, keep .dll.lib but discard .lib. | 124 # Special case Windows, keep .dll.lib but discard .lib. |
124 if item.endswith('.dll.lib'): | 125 if item.endswith('.dll.lib'): |
125 return True | 126 return True |
126 if ext == '.lib': | 127 if ext == '.lib': |
127 return False | 128 return False |
128 return item not in ('', '|', '||') | 129 return item not in ('', '|', '||') |
129 | 130 |
130 | 131 |
131 def raw_build_to_deps(item): | 132 def raw_build_to_deps(item): |
132 """Converts a raw ninja build statement into the list of interesting | 133 """Converts a raw ninja build statement into the list of interesting |
133 dependencies. | 134 dependencies. |
134 """ | 135 """ |
135 # TODO(maruel): Use a whitelist instead? .stamp, .so.TOC, .dylib.TOC, | 136 # TODO(maruel): Use a whitelist instead? .stamp, .so.TOC, .dylib.TOC, |
136 # .dll.lib, .exe and empty. | 137 # .dll.lib, .exe and empty. |
137 # The first item is the build rule, e.g. 'link', 'cxx', 'phony', etc. | 138 # The first item is the build rule, e.g. 'link', 'cxx', 'phony', etc. |
138 return filter(using_blacklist, item.split(' ')[1:]) | 139 return filter(using_blacklist, item.split(' ')[1:]) |
139 | 140 |
140 | 141 |
141 def recurse(target, build_steps, rules_seen): | 142 def recurse(target, build_steps, rules_seen, dependencies_added): |
Vadim Sh.
2014/05/30 22:15:25
Please make this function _not_ to return anything
Ken Russell (switch to Gerrit)
2014/05/30 22:43:49
Thanks for the good suggestion. Done.
| |
142 """Recursively returns all the interesting dependencies for root_item.""" | 143 """Recursively returns all the interesting dependencies for root_item.""" |
143 out = [] | |
144 if rules_seen is None: | 144 if rules_seen is None: |
145 rules_seen = set() | 145 rules_seen = set() |
146 if dependencies_added is None: | |
147 dependencies_added = set() | |
146 if target in rules_seen: | 148 if target in rules_seen: |
147 # TODO(maruel): Figure out how it happens. | 149 # TODO(maruel): Figure out how it happens. |
148 logging.warning('Circular dependency for %s!', target) | 150 logging.warning('Circular dependency for %s!', target) |
149 return [] | 151 return dependencies_added |
150 rules_seen.add(target) | 152 rules_seen.add(target) |
151 try: | 153 try: |
152 dependencies = raw_build_to_deps(build_steps[target]) | 154 dependencies = raw_build_to_deps(build_steps[target]) |
153 except KeyError: | 155 except KeyError: |
154 logging.info('Failed to find a build step to generate: %s', target) | 156 logging.info('Failed to find a build step to generate: %s', target) |
155 return [] | 157 return dependencies_added |
156 logging.debug('recurse(%s) -> %s', target, dependencies) | 158 logging.debug('recurse(%s) -> %s', target, dependencies) |
157 for dependency in dependencies: | 159 for dependency in dependencies: |
158 out.append(dependency) | 160 dependencies_added.add(dependency) |
159 dependency_raw_dependencies = build_steps.get(dependency) | 161 recurse(dependency, build_steps, rules_seen, dependencies_added) |
160 if dependency_raw_dependencies: | 162 return dependencies_added |
161 for i in raw_build_to_deps(dependency_raw_dependencies): | |
162 out.extend(recurse(i, build_steps, rules_seen)) | |
163 else: | |
164 logging.info('Failed to find a build step to generate: %s', dependency) | |
165 return out | |
166 | 163 |
167 | 164 |
168 def post_process_deps(build_dir, dependencies): | 165 def post_process_deps(build_dir, dependencies): |
169 """Processes the dependency list with OS specific rules.""" | 166 """Processes the dependency list with OS specific rules.""" |
170 def filter_item(i): | 167 def filter_item(i): |
171 if i.endswith('.so.TOC'): | 168 if i.endswith('.so.TOC'): |
172 # Remove only the suffix .TOC, not the .so! | 169 # Remove only the suffix .TOC, not the .so! |
173 return i[:-4] | 170 return i[:-4] |
174 if i.endswith('.dylib.TOC'): | 171 if i.endswith('.dylib.TOC'): |
175 # Remove only the suffix .TOC, not the .dylib! | 172 # Remove only the suffix .TOC, not the .dylib! |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
212 | 209 |
213 # Relative path between the new and old .isolate file. | 210 # Relative path between the new and old .isolate file. |
214 isolate_relpath = os.path.relpath( | 211 isolate_relpath = os.path.relpath( |
215 '.', temp_isolate_dir).replace(os.path.sep, '/') | 212 '.', temp_isolate_dir).replace(os.path.sep, '/') |
216 | 213 |
217 # It's a big assumption here that the name of the isolate file matches the | 214 # It's a big assumption here that the name of the isolate file matches the |
218 # primary target '_run'. Fix accordingly if this doesn't hold true, e.g. | 215 # primary target '_run'. Fix accordingly if this doesn't hold true, e.g. |
219 # complain to maruel@. | 216 # complain to maruel@. |
220 target = isolate[:-len('.isolate')] + '_run' | 217 target = isolate[:-len('.isolate')] + '_run' |
221 build_steps = load_ninja(build_dir) | 218 build_steps = load_ninja(build_dir) |
222 binary_deps = post_process_deps(build_dir, recurse(target, build_steps, None)) | 219 binary_deps = post_process_deps(build_dir, recurse( |
Vadim Sh.
2014/05/30 22:15:25
and then:
binary_deps = set()
collect_deps(target,
Ken Russell (switch to Gerrit)
2014/05/30 22:43:49
Done. I switched the order of the dependencies_add
| |
220 target, build_steps, None, None)) | |
223 logging.debug( | 221 logging.debug( |
224 'Binary dependencies:%s', ''.join('\n ' + i for i in binary_deps)) | 222 'Binary dependencies:%s', ''.join('\n ' + i for i in binary_deps)) |
225 | 223 |
226 # Now do actual wrapping .isolate. | 224 # Now do actual wrapping .isolate. |
227 isolate_dict = { | 225 isolate_dict = { |
228 'includes': [ | 226 'includes': [ |
229 posixpath.join(isolate_relpath, isolate), | 227 posixpath.join(isolate_relpath, isolate), |
230 ], | 228 ], |
231 'variables': { | 229 'variables': { |
232 # Will look like ['<(PRODUCT_DIR)/lib/flibuser_prefs.so']. | 230 # Will look like ['<(PRODUCT_DIR)/lib/flibuser_prefs.so']. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
272 | 270 |
273 swarming_client = os.path.join(SRC_DIR, 'tools', 'swarming_client') | 271 swarming_client = os.path.join(SRC_DIR, 'tools', 'swarming_client') |
274 sys.stdout.flush() | 272 sys.stdout.flush() |
275 result = subprocess.call( | 273 result = subprocess.call( |
276 [sys.executable, os.path.join(swarming_client, 'isolate.py')] + args) | 274 [sys.executable, os.path.join(swarming_client, 'isolate.py')] + args) |
277 return result | 275 return result |
278 | 276 |
279 | 277 |
280 if __name__ == '__main__': | 278 if __name__ == '__main__': |
281 sys.exit(main()) | 279 sys.exit(main()) |
OLD | NEW |