Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(515)

Side by Side Diff: tools/isolate_driver.py

Issue 304993006: Fixed bug in dependency recursion in isolate_driver.py. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed review feedback from vadimsh. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 collect_deps(target, build_steps, dependencies_added, rules_seen):
142 """Recursively returns all the interesting dependencies for root_item.""" 143 """Recursively adds all the interesting dependencies for |target|
143 out = [] 144 into |dependencies_added|.
145 """
144 if rules_seen is None: 146 if rules_seen is None:
145 rules_seen = set() 147 rules_seen = 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
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
156 logging.debug('recurse(%s) -> %s', target, dependencies) 158 logging.debug('collect_deps(%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 collect_deps(dependency, build_steps, dependencies_added, rules_seen)
160 if dependency_raw_dependencies:
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 162
167 163
168 def post_process_deps(build_dir, dependencies): 164 def post_process_deps(build_dir, dependencies):
169 """Processes the dependency list with OS specific rules.""" 165 """Processes the dependency list with OS specific rules."""
170 def filter_item(i): 166 def filter_item(i):
171 if i.endswith('.so.TOC'): 167 if i.endswith('.so.TOC'):
172 # Remove only the suffix .TOC, not the .so! 168 # Remove only the suffix .TOC, not the .so!
173 return i[:-4] 169 return i[:-4]
174 if i.endswith('.dylib.TOC'): 170 if i.endswith('.dylib.TOC'):
175 # Remove only the suffix .TOC, not the .dylib! 171 # Remove only the suffix .TOC, not the .dylib!
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 208
213 # Relative path between the new and old .isolate file. 209 # Relative path between the new and old .isolate file.
214 isolate_relpath = os.path.relpath( 210 isolate_relpath = os.path.relpath(
215 '.', temp_isolate_dir).replace(os.path.sep, '/') 211 '.', temp_isolate_dir).replace(os.path.sep, '/')
216 212
217 # It's a big assumption here that the name of the isolate file matches the 213 # 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. 214 # primary target '_run'. Fix accordingly if this doesn't hold true, e.g.
219 # complain to maruel@. 215 # complain to maruel@.
220 target = isolate[:-len('.isolate')] + '_run' 216 target = isolate[:-len('.isolate')] + '_run'
221 build_steps = load_ninja(build_dir) 217 build_steps = load_ninja(build_dir)
222 binary_deps = post_process_deps(build_dir, recurse(target, build_steps, None)) 218 binary_deps = set()
219 collect_deps(target, build_steps, binary_deps, None)
220 binary_deps = post_process_deps(build_dir, binary_deps)
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
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())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698