| 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 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 Loading... |
| 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 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 |