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

Side by Side Diff: pylib/gyp/generator/ninja.py

Issue 8400082: Ninja: separate dependencies for compile steps vs actions/rules/copies (Closed) Base URL: http://gyp.googlecode.com/svn/trunk
Patch Set: copyright year Created 9 years, 1 month 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 | test/ninja/action_dependencies/gyptest-action-dependencies.py » ('j') | 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/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
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,
282 order_only=actions_depends)
269 if self.name != output and self.toolset == 'target': 283 if self.name != output and self.toolset == 'target':
270 # Write a short name to build this target. This benefits both the 284 # 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 285 # "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. 286 # able to run actions and build libraries by their short name.
273 self.ninja.build(self.name, 'phony', output) 287 self.ninja.build(self.name, 'phony', output)
274 return output 288 return output, compile_depends
275 289
276 def WriteActionsRulesCopies(self, spec, extra_sources, prebuild): 290 def WriteActionsRulesCopies(self, spec, extra_sources, prebuild):
277 """Write out the Actions, Rules, and Copies steps. Return any outputs 291 """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).""" 292 of these steps (or a stamp file if there are lots of outputs)."""
279 outputs = [] 293 outputs = []
280 294
281 if 'actions' in spec: 295 if 'actions' in spec:
282 outputs += self.WriteActions(spec['actions'], extra_sources, prebuild) 296 outputs += self.WriteActions(spec['actions'], extra_sources, prebuild)
283 if 'rules' in spec: 297 if 'rules' in spec:
284 outputs += self.WriteRules(spec['rules'], extra_sources, prebuild) 298 outputs += self.WriteRules(spec['rules'], extra_sources, prebuild)
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 # TODO: should we assert here on unexpected extensions? 455 # TODO: should we assert here on unexpected extensions?
442 continue 456 continue
443 input = self.GypPathToNinja(source) 457 input = self.GypPathToNinja(source)
444 output = self.GypPathToUniqueOutput(filename + '.o') 458 output = self.GypPathToUniqueOutput(filename + '.o')
445 self.ninja.build(output, command, input, 459 self.ninja.build(output, command, input,
446 order_only=predepends) 460 order_only=predepends)
447 outputs.append(output) 461 outputs.append(output)
448 self.ninja.newline() 462 self.ninja.newline()
449 return outputs 463 return outputs
450 464
451 def WriteTarget(self, spec, config, final_deps): 465 def WriteTarget(self, spec, config, final_deps, order_only):
452 if spec['type'] == 'none': 466 if spec['type'] == 'none':
453 # This target doesn't have any explicit final output, but is instead 467 # This target doesn't have any explicit final output, but is instead
454 # used for its effects before the final output (e.g. copies steps). 468 # used for its effects before the final output (e.g. copies steps).
455 # Reuse the existing output if it's easy. 469 # Reuse the existing output if it's easy.
456 if len(final_deps) == 1: 470 if len(final_deps) == 1:
457 return final_deps[0] 471 return final_deps[0]
458 # Otherwise, fall through to writing out a stamp file. 472 # Otherwise, fall through to writing out a stamp file.
459 473
460 output = self.ComputeOutput(spec) 474 output = self.ComputeOutput(spec)
461 475
462 output_uses_linker = spec['type'] in ('executable', 'loadable_module', 476 output_uses_linker = spec['type'] in ('executable', 'loadable_module',
463 'shared_library') 477 'shared_library')
464 478
465 implicit_deps = set() 479 implicit_deps = set()
466 if 'dependencies' in spec: 480 if 'dependencies' in spec:
467 # Two kinds of dependencies: 481 # Two kinds of dependencies:
468 # - Linkable dependencies (like a .a or a .so): add them to the link line. 482 # - 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 483 # - Non-linkable dependencies (like a rule that generates a file
470 # and writes a stamp file): add them to implicit_deps 484 # and writes a stamp file): add them to implicit_deps
471 if output_uses_linker: 485 if output_uses_linker:
472 extra_deps = set() 486 extra_deps = set()
473 for dep in spec['dependencies']: 487 for dep in spec['dependencies']:
474 input, linkable = self.target_outputs.get(dep, (None, False)) 488 input, _, linkable = self.target_outputs.get(dep, (None, [], False))
475 if not input: 489 if not input:
476 continue 490 continue
477 if linkable: 491 if linkable:
478 extra_deps.add(input) 492 extra_deps.add(input)
479 else: 493 else:
480 # TODO: Chrome-specific HACK. Chrome runs this lastchange rule on 494 # TODO: Chrome-specific HACK. Chrome runs this lastchange rule on
481 # every build, but we don't want to rebuild when it runs. 495 # every build, but we don't want to rebuild when it runs.
482 if 'lastchange' not in input: 496 if 'lastchange' not in input:
483 implicit_deps.add(input) 497 implicit_deps.add(input)
484 final_deps.extend(list(extra_deps)) 498 final_deps.extend(list(extra_deps))
(...skipping 13 matching lines...) Expand all
498 self.WriteVariableList('libs', 512 self.WriteVariableList('libs',
499 gyp.common.uniquer(map(self.ExpandSpecial, 513 gyp.common.uniquer(map(self.ExpandSpecial,
500 spec.get('libraries', [])))) 514 spec.get('libraries', []))))
501 515
502 extra_bindings = [] 516 extra_bindings = []
503 if command in ('solink', 'solink_module'): 517 if command in ('solink', 'solink_module'):
504 extra_bindings.append(('soname', os.path.split(output)[1])) 518 extra_bindings.append(('soname', os.path.split(output)[1]))
505 519
506 self.ninja.build(output, command, final_deps, 520 self.ninja.build(output, command, final_deps,
507 implicit=list(implicit_deps), 521 implicit=list(implicit_deps),
522 order_only=order_only,
508 variables=extra_bindings) 523 variables=extra_bindings)
509 524
510 return output 525 return output
511 526
512 def ComputeOutputFileName(self, spec): 527 def ComputeOutputFileName(self, spec):
513 """Compute the filename of the final output for the current target.""" 528 """Compute the filename of the final output for the current target."""
514 529
515 # Compute filename prefix: the product prefix, or a default for 530 # Compute filename prefix: the product prefix, or a default for
516 # the product type. 531 # the product type.
517 DEFAULT_PREFIX = { 532 DEFAULT_PREFIX = {
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 output_file = os.path.join(obj, base_path, name + '.ninja') 730 output_file = os.path.join(obj, base_path, name + '.ninja')
716 spec = target_dicts[qualified_target] 731 spec = target_dicts[qualified_target]
717 config = spec['configurations'][config_name] 732 config = spec['configurations'][config_name]
718 733
719 writer = NinjaWriter(target_outputs, base_path, builddir, 734 writer = NinjaWriter(target_outputs, base_path, builddir,
720 OpenOutput(os.path.join(options.toplevel_dir, 735 OpenOutput(os.path.join(options.toplevel_dir,
721 builddir, 736 builddir,
722 output_file))) 737 output_file)))
723 master_ninja.subninja(output_file) 738 master_ninja.subninja(output_file)
724 739
725 output = writer.WriteSpec(spec, config) 740 output, compile_depends = writer.WriteSpec(spec, config)
726 if output: 741 if output:
727 linkable = spec['type'] in ('static_library', 'shared_library') 742 linkable = spec['type'] in ('static_library', 'shared_library')
728 target_outputs[qualified_target] = (output, linkable) 743 target_outputs[qualified_target] = (output, compile_depends, linkable)
729 744
730 if qualified_target in all_targets: 745 if qualified_target in all_targets:
731 all_outputs.add(output) 746 all_outputs.add(output)
732 747
733 if all_outputs: 748 if all_outputs:
734 master_ninja.build('all', 'phony', list(all_outputs)) 749 master_ninja.build('all', 'phony', list(all_outputs))
OLDNEW
« no previous file with comments | « no previous file | test/ninja/action_dependencies/gyptest-action-dependencies.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698