OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 # Copyright (c) 2011 Google Inc. All rights reserved. | 3 # Copyright (c) 2011 Google Inc. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 import gyp | 7 import gyp |
8 import gyp.common | 8 import gyp.common |
9 import gyp.system_test | 9 import gyp.system_test |
10 import os.path | 10 import os.path |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
213 | 213 |
214 if len(targets) > 1: | 214 if len(targets) > 1: |
215 stamp = self.GypPathToUniqueOutput(name + '.stamp') | 215 stamp = self.GypPathToUniqueOutput(name + '.stamp') |
216 targets = self.ninja.build(stamp, 'stamp', targets) | 216 targets = self.ninja.build(stamp, 'stamp', targets) |
217 self.ninja.newline() | 217 self.ninja.newline() |
218 return targets | 218 return targets |
219 | 219 |
220 def WriteSpec(self, spec, config): | 220 def WriteSpec(self, spec, config): |
221 """The main entry point for NinjaWriter: write the build rules for a spec. | 221 """The main entry point for NinjaWriter: write the build rules for a spec. |
222 | 222 |
223 Returns the path to the build output, or None.""" | 223 Returns the path to the build output, or None, and a list of targets for |
224 dependencies of its compile steps.""" | |
224 | 225 |
225 self.name = spec['target_name'] | 226 self.name = spec['target_name'] |
226 self.toolset = spec['toolset'] | 227 self.toolset = spec['toolset'] |
227 | 228 |
228 if spec['type'] == 'settings': | 229 if spec['type'] == 'settings': |
229 # TODO: 'settings' is not actually part of gyp; it was | 230 # TODO: 'settings' is not actually part of gyp; it was |
230 # accidentally introduced somehow into just the Linux build files. | 231 # accidentally introduced somehow into just the Linux build files. |
231 # Remove this (or make it an error) once all the users are fixed. | 232 # Remove this (or make it an error) once all the users are fixed. |
232 print ("WARNING: %s uses invalid type 'settings'. " % self.name + | 233 print ("WARNING: %s uses invalid type 'settings'. " % self.name + |
233 "Please fix the source gyp file to use type 'none'.") | 234 "Please fix the source gyp file to use type 'none'.") |
234 print "See http://code.google.com/p/chromium/issues/detail?id=96629 ." | 235 print "See http://code.google.com/p/chromium/issues/detail?id=96629 ." |
235 spec['type'] = 'none' | 236 spec['type'] = 'none' |
236 | 237 |
237 # Compute predepends for all rules. | 238 # Compute predepends for all rules. |
238 # prebuild is the dependencies this target depends on before | 239 # actions_depends is the dependencies this target depends on before running |
239 # running any of its internal steps. | 240 # any of its action/rule/copy steps. |
240 prebuild = [] | 241 # compile_depends is the dependencies this target depends on before running |
242 # any of its compile steps. | |
243 actions_depends = [] | |
244 compile_depends = [] | |
241 if 'dependencies' in spec: | 245 if 'dependencies' in spec: |
242 for dep in spec['dependencies']: | 246 for dep in spec['dependencies']: |
243 if dep in self.target_outputs: | 247 if dep in self.target_outputs: |
244 prebuild.append(self.target_outputs[dep][0]) | 248 input, precompile_input, linkable = self.target_outputs[dep] |
245 prebuild = self.WriteCollapsedDependencies('predepends', prebuild) | 249 actions_depends.append(input) |
250 compile_depends.extend(precompile_input) | |
251 actions_depends = self.WriteCollapsedDependencies('actions_depends', | |
252 actions_depends) | |
246 | 253 |
247 # Write out actions, rules, and copies. These must happen before we | 254 # Write out actions, rules, and copies. These must happen before we |
248 # compile any sources, so compute a list of predependencies for sources | 255 # compile any sources, so compute a list of predependencies for sources |
249 # while we do it. | 256 # while we do it. |
250 extra_sources = [] | 257 extra_sources = [] |
251 sources_predepends = self.WriteActionsRulesCopies(spec, extra_sources, | 258 sources_depends = self.WriteActionsRulesCopies(spec, extra_sources, |
252 prebuild) | 259 actions_depends) |
260 | |
261 # If we have actions/rules/copies, we depend directly on those, but | |
262 # otherwise we depend on dependent target's actions/rules/copies etc. | |
263 # We never need to explicitly depend on previous target's link steps, | |
264 # because no compile ever depends on them. | |
265 compile_depends = self.WriteCollapsedDependencies('compile_depends', | |
266 sources_depends or compile_depends) | |
253 | 267 |
254 # Write out the compilation steps, if any. | 268 # Write out the compilation steps, if any. |
255 link_deps = [] | 269 link_deps = [] |
256 sources = spec.get('sources', []) + extra_sources | 270 sources = spec.get('sources', []) + extra_sources |
257 if sources: | 271 if sources: |
258 link_deps = self.WriteSources(config, sources, | 272 link_deps = self.WriteSources(config, sources, compile_depends) |
259 sources_predepends or prebuild) | |
260 # Some actions/rules output 'sources' that are already object files. | 273 # Some actions/rules output 'sources' that are already object files. |
261 link_deps += [self.GypPathToNinja(f) for f in sources if f.endswith('.o')] | 274 link_deps += [self.GypPathToNinja(f) for f in sources if f.endswith('.o')] |
262 | 275 |
263 # The final output of our target depends on the last output of the | 276 # The final output of our target depends on the last output of the |
264 # above steps. | 277 # above steps. |
265 output = None | 278 output = None |
266 final_deps = link_deps or sources_predepends or prebuild | 279 final_deps = link_deps or sources_depends or actions_depends |
267 if final_deps: | 280 if final_deps: |
268 output = self.WriteTarget(spec, config, final_deps) | 281 output = self.WriteTarget(spec, config, final_deps) |
269 if self.name != output and self.toolset == 'target': | 282 if self.name != output and self.toolset == 'target': |
270 # Write a short name to build this target. This benefits both the | 283 # Write a short name to build this target. This benefits both the |
271 # "build chrome" case as well as the gyp tests, which expect to be | 284 # "build chrome" case as well as the gyp tests, which expect to be |
272 # able to run actions and build libraries by their short name. | 285 # able to run actions and build libraries by their short name. |
273 self.ninja.build(self.name, 'phony', output) | 286 self.ninja.build(self.name, 'phony', output) |
274 return output | 287 return output, compile_depends |
275 | 288 |
276 def WriteActionsRulesCopies(self, spec, extra_sources, prebuild): | 289 def WriteActionsRulesCopies(self, spec, extra_sources, prebuild): |
277 """Write out the Actions, Rules, and Copies steps. Return any outputs | 290 """Write out the Actions, Rules, and Copies steps. Return any outputs |
278 of these steps (or a stamp file if there are lots of outputs).""" | 291 of these steps (or a stamp file if there are lots of outputs).""" |
279 outputs = [] | 292 outputs = [] |
280 | 293 |
281 if 'actions' in spec: | 294 if 'actions' in spec: |
282 outputs += self.WriteActions(spec['actions'], extra_sources, prebuild) | 295 outputs += self.WriteActions(spec['actions'], extra_sources, prebuild) |
283 if 'rules' in spec: | 296 if 'rules' in spec: |
284 outputs += self.WriteRules(spec['rules'], extra_sources, prebuild) | 297 outputs += self.WriteRules(spec['rules'], extra_sources, prebuild) |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
464 | 477 |
465 implicit_deps = set() | 478 implicit_deps = set() |
466 if 'dependencies' in spec: | 479 if 'dependencies' in spec: |
467 # Two kinds of dependencies: | 480 # Two kinds of dependencies: |
468 # - Linkable dependencies (like a .a or a .so): add them to the link line. | 481 # - Linkable dependencies (like a .a or a .so): add them to the link line. |
469 # - Non-linkable dependencies (like a rule that generates a file | 482 # - Non-linkable dependencies (like a rule that generates a file |
470 # and writes a stamp file): add them to implicit_deps | 483 # and writes a stamp file): add them to implicit_deps |
471 if output_uses_linker: | 484 if output_uses_linker: |
472 extra_deps = set() | 485 extra_deps = set() |
473 for dep in spec['dependencies']: | 486 for dep in spec['dependencies']: |
474 input, linkable = self.target_outputs.get(dep, (None, False)) | 487 input, _, linkable = self.target_outputs.get( dep, (None, [], False)) |
tony
2011/11/03 23:55:30
Nit: extra space before |dep|?
piman
2011/11/04 03:51:52
Done.
| |
475 if not input: | 488 if not input: |
476 continue | 489 continue |
477 if linkable: | 490 if linkable: |
478 extra_deps.add(input) | 491 extra_deps.add(input) |
479 else: | 492 else: |
480 # TODO: Chrome-specific HACK. Chrome runs this lastchange rule on | 493 # TODO: Chrome-specific HACK. Chrome runs this lastchange rule on |
481 # every build, but we don't want to rebuild when it runs. | 494 # every build, but we don't want to rebuild when it runs. |
482 if 'lastchange' not in input: | 495 if 'lastchange' not in input: |
483 implicit_deps.add(input) | 496 implicit_deps.add(input) |
484 final_deps.extend(list(extra_deps)) | 497 final_deps.extend(list(extra_deps)) |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
715 output_file = os.path.join(obj, base_path, name + '.ninja') | 728 output_file = os.path.join(obj, base_path, name + '.ninja') |
716 spec = target_dicts[qualified_target] | 729 spec = target_dicts[qualified_target] |
717 config = spec['configurations'][config_name] | 730 config = spec['configurations'][config_name] |
718 | 731 |
719 writer = NinjaWriter(target_outputs, base_path, builddir, | 732 writer = NinjaWriter(target_outputs, base_path, builddir, |
720 OpenOutput(os.path.join(options.toplevel_dir, | 733 OpenOutput(os.path.join(options.toplevel_dir, |
721 builddir, | 734 builddir, |
722 output_file))) | 735 output_file))) |
723 master_ninja.subninja(output_file) | 736 master_ninja.subninja(output_file) |
724 | 737 |
725 output = writer.WriteSpec(spec, config) | 738 output, compile_depends = writer.WriteSpec(spec, config) |
726 if output: | 739 if output: |
727 linkable = spec['type'] in ('static_library', 'shared_library') | 740 linkable = spec['type'] in ('static_library', 'shared_library') |
728 target_outputs[qualified_target] = (output, linkable) | 741 target_outputs[qualified_target] = (output, compile_depends, linkable) |
729 | 742 |
730 if qualified_target in all_targets: | 743 if qualified_target in all_targets: |
731 all_outputs.add(output) | 744 all_outputs.add(output) |
732 | 745 |
733 if all_outputs: | 746 if all_outputs: |
734 master_ninja.build('all', 'phony', list(all_outputs)) | 747 master_ninja.build('all', 'phony', list(all_outputs)) |
OLD | NEW |