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

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

Issue 10381103: ninja: rules chained only by output of first one failing Base URL: https://gyp.googlecode.com/svn/trunk
Patch Set: exclude make Created 8 years, 7 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 | test/chained-rules/action.input » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 Google Inc. All rights reserved. 1 # Copyright (c) 2012 Google Inc. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import copy 5 import copy
6 import gyp 6 import gyp
7 import gyp.common 7 import gyp.common
8 import gyp.msvs_emulation 8 import gyp.msvs_emulation
9 import gyp.MSVSVersion 9 import gyp.MSVSVersion
10 import gyp.system_test 10 import gyp.system_test
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 307
308 assert targets == filter(None, targets), targets 308 assert targets == filter(None, targets), targets
309 if len(targets) == 0: 309 if len(targets) == 0:
310 return None 310 return None
311 if len(targets) > 1: 311 if len(targets) > 1:
312 stamp = self.GypPathToUniqueOutput(name + '.stamp') 312 stamp = self.GypPathToUniqueOutput(name + '.stamp')
313 targets = self.ninja.build(stamp, 'stamp', targets) 313 targets = self.ninja.build(stamp, 'stamp', targets)
314 self.ninja.newline() 314 self.ninja.newline()
315 return targets[0] 315 return targets[0]
316 316
317 def _SourcesHandledByRule(self, rule, sources):
318 """Get a list of files that from |sources| that |rule| handles."""
319 rule_ext = rule['extension']
320 result = []
321 for source in sources:
322 if source.endswith('.' + rule_ext):
323 inputs, outputs = self._GetInputsAndOutputsForRule(rule, source)
324 if source in outputs:
325 # Don't include the outputs of this rule, even if by extension we
326 # ought to.
327 continue
328 result.append(source)
329 return result
330
331 def _GetInputsAndOutputsForRule(self, rule, source):
332 """Get the expanded inputs and outputs of the given |rule| for a
333 particular |source|."""
334 dirname, basename = os.path.split(source)
335 root, ext = os.path.splitext(basename)
336 outputs = [self.ExpandRuleVariables(o, root, dirname,
337 source, ext, basename)
338 for o in rule['outputs']]
339 inputs = [self.ExpandRuleVariables(i, root, dirname,
340 source, ext, basename)
341 for i in rule.get('inputs', [])]
342 return inputs, outputs
343
344 def _GetSources(self, spec):
345 """Get all sources for the given |spec|. In addition to the sources
346 directly specified in the gyp file, it includes sources generated by
347 actions and copies. Outputs of rules are not included because otherwise
348 rules that generate the same extension as they process cause much
349 confusion. Rule outputs are added when the rule is processed."""
350 sources = spec.get('sources', [])
351 for action in spec.get('actions', []):
352 if int(action.get('process_outputs_as_sources', False)):
353 sources.extend(action.get('outputs', []))
354 for copy in spec.get('copies', []):
355 sources.extend(copy.get('files', []))
356 return set(sources)
357
358
317 def WriteSpec(self, spec, config_name, generator_flags): 359 def WriteSpec(self, spec, config_name, generator_flags):
318 """The main entry point for NinjaWriter: write the build rules for a spec. 360 """The main entry point for NinjaWriter: write the build rules for a spec.
319 361
320 Returns a Target object, which represents the output paths for this spec. 362 Returns a Target object, which represents the output paths for this spec.
321 Returns None if there are no outputs (e.g. a settings-only 'none' type 363 Returns None if there are no outputs (e.g. a settings-only 'none' type
322 target).""" 364 target)."""
323 365
324 self.config_name = config_name 366 self.config_name = config_name
325 self.name = spec['target_name'] 367 self.name = spec['target_name']
326 self.toolset = spec['toolset'] 368 self.toolset = spec['toolset']
(...skipping 25 matching lines...) Expand all
352 compile_depends.append(target.PreCompileInput()) 394 compile_depends.append(target.PreCompileInput())
353 actions_depends = filter(None, actions_depends) 395 actions_depends = filter(None, actions_depends)
354 compile_depends = filter(None, compile_depends) 396 compile_depends = filter(None, compile_depends)
355 actions_depends = self.WriteCollapsedDependencies('actions_depends', 397 actions_depends = self.WriteCollapsedDependencies('actions_depends',
356 actions_depends) 398 actions_depends)
357 compile_depends = self.WriteCollapsedDependencies('compile_depends', 399 compile_depends = self.WriteCollapsedDependencies('compile_depends',
358 compile_depends) 400 compile_depends)
359 self.target.preaction_stamp = actions_depends 401 self.target.preaction_stamp = actions_depends
360 self.target.precompile_stamp = compile_depends 402 self.target.precompile_stamp = compile_depends
361 403
404 # Build a list of sources. We do this as a pre-process so that we have
405 # access to generated outputs for actions for other actions and rules.
406 sources = self._GetSources(spec)
407
362 # Write out actions, rules, and copies. These must happen before we 408 # Write out actions, rules, and copies. These must happen before we
363 # compile any sources, so compute a list of predependencies for sources 409 # compile any sources, so compute a list of predependencies for sources
364 # while we do it. 410 # while we do it.
365 extra_sources = []
366 mac_bundle_depends = [] 411 mac_bundle_depends = []
367 self.target.actions_stamp = self.WriteActionsRulesCopies( 412 self.target.actions_stamp = self.WriteActionsRulesCopies(
368 spec, extra_sources, actions_depends, mac_bundle_depends) 413 spec, sources, actions_depends, mac_bundle_depends)
369 414
370 # If we have actions/rules/copies, we depend directly on those, but 415 # If we have actions/rules/copies, we depend directly on those, but
371 # otherwise we depend on dependent target's actions/rules/copies etc. 416 # otherwise we depend on dependent target's actions/rules/copies etc.
372 # We never need to explicitly depend on previous target's link steps, 417 # We never need to explicitly depend on previous target's link steps,
373 # because no compile ever depends on them. 418 # because no compile ever depends on them.
374 compile_depends_stamp = (self.target.actions_stamp or compile_depends) 419 compile_depends_stamp = (self.target.actions_stamp or compile_depends)
375 420
376 # Write out the compilation steps, if any. 421 # Write out the compilation steps, if any.
377 link_deps = [] 422 link_deps = []
378 sources = spec.get('sources', []) + extra_sources
379 if sources: 423 if sources:
380 link_deps = self.WriteSources( 424 link_deps = self.WriteSources(
381 config_name, config, sources, compile_depends_stamp, 425 config_name, config, sources, compile_depends_stamp,
382 gyp.xcode_emulation.MacPrefixHeader( 426 gyp.xcode_emulation.MacPrefixHeader(
383 self.xcode_settings, self.GypPathToNinja, 427 self.xcode_settings, self.GypPathToNinja,
384 lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang))) 428 lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang)))
385 # Some actions/rules output 'sources' that are already object files. 429 # Some actions/rules output 'sources' that are already object files.
386 link_deps += [self.GypPathToNinja(f) 430 link_deps += [self.GypPathToNinja(f)
387 for f in sources if f.endswith(self.obj_ext)] 431 for f in sources if f.endswith(self.obj_ext)]
388 432
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 def WriteWinIdlFiles(self, spec, prebuild): 484 def WriteWinIdlFiles(self, spec, prebuild):
441 """Writes rules to match MSVS's implicit idl handling.""" 485 """Writes rules to match MSVS's implicit idl handling."""
442 assert self.flavor == 'win' 486 assert self.flavor == 'win'
443 if self.msvs_settings.HasExplicitIdlRules(spec): 487 if self.msvs_settings.HasExplicitIdlRules(spec):
444 return [] 488 return []
445 outputs = [] 489 outputs = []
446 for source in filter(lambda x: x.endswith('.idl'), spec['sources']): 490 for source in filter(lambda x: x.endswith('.idl'), spec['sources']):
447 self._WinIdlRule(source, prebuild, outputs) 491 self._WinIdlRule(source, prebuild, outputs)
448 return outputs 492 return outputs
449 493
450 def WriteActionsRulesCopies(self, spec, extra_sources, prebuild, 494 def WriteActionsRulesCopies(self, spec, sources, prebuild,
451 mac_bundle_depends): 495 mac_bundle_depends):
452 """Write out the Actions, Rules, and Copies steps. Return a path 496 """Write out the Actions, Rules, and Copies steps. Return a path
453 representing the outputs of these steps.""" 497 representing the outputs of these steps."""
454 outputs = [] 498 outputs = []
455 extra_mac_bundle_resources = [] 499 extra_mac_bundle_resources = []
456 500
457 if 'actions' in spec: 501 if 'actions' in spec:
458 outputs += self.WriteActions(spec['actions'], extra_sources, prebuild, 502 outputs += self.WriteActions(spec['actions'], sources, prebuild,
459 extra_mac_bundle_resources) 503 extra_mac_bundle_resources)
460 if 'rules' in spec: 504 if 'rules' in spec:
461 outputs += self.WriteRules(spec['rules'], extra_sources, prebuild, 505 outputs += self.WriteRules(spec['rules'], sources, prebuild,
462 extra_mac_bundle_resources) 506 extra_mac_bundle_resources)
463 if 'copies' in spec: 507 if 'copies' in spec:
464 outputs += self.WriteCopies(spec['copies'], prebuild) 508 outputs += self.WriteCopies(spec['copies'], prebuild)
465 509
466 if 'sources' in spec and self.flavor == 'win': 510 if 'sources' in spec and self.flavor == 'win':
467 outputs += self.WriteWinIdlFiles(spec, prebuild) 511 outputs += self.WriteWinIdlFiles(spec, prebuild)
468 512
469 stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs) 513 stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs)
470 514
471 if self.is_mac_bundle: 515 if self.is_mac_bundle:
(...skipping 11 matching lines...) Expand all
483 |message| is a hand-written description, or None if not available. 527 |message| is a hand-written description, or None if not available.
484 |fallback| is the gyp-level name of the step, usable as a fallback. 528 |fallback| is the gyp-level name of the step, usable as a fallback.
485 """ 529 """
486 if self.toolset != 'target': 530 if self.toolset != 'target':
487 verb += '(%s)' % self.toolset 531 verb += '(%s)' % self.toolset
488 if message: 532 if message:
489 return '%s %s' % (verb, self.ExpandSpecial(message)) 533 return '%s %s' % (verb, self.ExpandSpecial(message))
490 else: 534 else:
491 return '%s %s: %s' % (verb, self.name, fallback) 535 return '%s %s: %s' % (verb, self.name, fallback)
492 536
493 def WriteActions(self, actions, extra_sources, prebuild, 537 def WriteActions(self, actions, sources, prebuild,
494 extra_mac_bundle_resources): 538 extra_mac_bundle_resources):
495 # Actions cd into the base directory. 539 # Actions cd into the base directory.
496 env = self.GetXcodeEnv() 540 env = self.GetXcodeEnv()
497 if self.flavor == 'win': 541 if self.flavor == 'win':
498 env = self.msvs_settings.GetVSMacroEnv('$!PRODUCT_DIR') 542 env = self.msvs_settings.GetVSMacroEnv('$!PRODUCT_DIR')
499 all_outputs = [] 543 all_outputs = []
500 for action in actions: 544 for action in actions:
501 # First write out a rule for the action. 545 # First write out a rule for the action.
502 name = re.sub(r'[ {}$]', '_', action['action_name']) 546 name = re.sub(r'[ {}$]', '_', action['action_name'])
503 description = self.GenerateDescription('ACTION', 547 description = self.GenerateDescription('ACTION',
504 action.get('message', None), 548 action.get('message', None),
505 name) 549 name)
506 is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(action) 550 is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(action)
507 if self.flavor == 'win' else False) 551 if self.flavor == 'win' else False)
508 args = action['action'] 552 args = action['action']
509 args = [self.msvs_settings.ConvertVSMacros(arg, self.base_to_build) 553 args = [self.msvs_settings.ConvertVSMacros(arg, self.base_to_build)
510 for arg in args] if self.flavor == 'win' else args 554 for arg in args] if self.flavor == 'win' else args
511 rule_name = self.WriteNewNinjaRule(name, args, description, 555 rule_name = self.WriteNewNinjaRule(name, args, description,
512 is_cygwin, env=env) 556 is_cygwin, env=env)
513 557
514 inputs = [self.GypPathToNinja(i, env) for i in action['inputs']] 558 inputs = [self.GypPathToNinja(i, env) for i in action['inputs']]
515 if int(action.get('process_outputs_as_sources', False)):
516 extra_sources += action['outputs']
517 if int(action.get('process_outputs_as_mac_bundle_resources', False)): 559 if int(action.get('process_outputs_as_mac_bundle_resources', False)):
518 extra_mac_bundle_resources += action['outputs'] 560 extra_mac_bundle_resources += action['outputs']
519 outputs = [self.GypPathToNinja(o, env) for o in action['outputs']] 561 outputs = [self.GypPathToNinja(o, env) for o in action['outputs']]
520 562
521 # Then write out an edge using the rule. 563 # Then write out an edge using the rule.
522 self.ninja.build(outputs, rule_name, inputs, 564 self.ninja.build(outputs, rule_name, inputs,
523 order_only=prebuild) 565 order_only=prebuild)
524 all_outputs += outputs 566 all_outputs += outputs
525 567
526 self.ninja.newline() 568 self.ninja.newline()
527 569
528 return all_outputs 570 return all_outputs
529 571
530 def WriteRules(self, rules, extra_sources, prebuild, 572 def WriteRules(self, rules, sources, prebuild, extra_mac_bundle_resources):
531 extra_mac_bundle_resources):
532 all_outputs = [] 573 all_outputs = []
533 for rule in rules: 574 for rule in rules:
534 # First write out a rule for the rule action. 575 # First write out a rule for the rule action.
535 name = rule['rule_name'] 576 name = rule['rule_name']
536 args = rule['action'] 577 args = rule['action']
537 description = self.GenerateDescription( 578 description = self.GenerateDescription(
538 'RULE', 579 'RULE',
539 rule.get('message', None), 580 rule.get('message', None),
540 ('%s ' + generator_default_variables['RULE_INPUT_PATH']) % name) 581 ('%s ' + generator_default_variables['RULE_INPUT_PATH']) % name)
541 is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(rule) 582 is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(rule)
(...skipping 13 matching lines...) Expand all
555 for argument in args: 596 for argument in args:
556 for var in special_locals: 597 for var in special_locals:
557 if ('${%s}' % var) in argument: 598 if ('${%s}' % var) in argument:
558 needed_variables.add(var) 599 needed_variables.add(var)
559 600
560 def cygwin_munge(path): 601 def cygwin_munge(path):
561 if is_cygwin: 602 if is_cygwin:
562 return path.replace('\\', '/') 603 return path.replace('\\', '/')
563 return path 604 return path
564 605
606 rule_sources = self._SourcesHandledByRule(rule, sources)
565 # For each source file, write an edge that generates all the outputs. 607 # For each source file, write an edge that generates all the outputs.
566 for source in rule.get('rule_sources', []): 608 for source in rule_sources:
567 dirname, basename = os.path.split(source) 609 dirname, basename = os.path.split(source)
568 root, ext = os.path.splitext(basename) 610 root, ext = os.path.splitext(basename)
569 611 inputs, outputs = self._GetInputsAndOutputsForRule(rule, source)
570 # Gather the list of inputs and outputs, expanding $vars if possible.
571 outputs = [self.ExpandRuleVariables(o, root, dirname,
572 source, ext, basename)
573 for o in rule['outputs']]
574 inputs = [self.ExpandRuleVariables(i, root, dirname,
575 source, ext, basename)
576 for i in rule.get('inputs', [])]
577 612
578 if int(rule.get('process_outputs_as_sources', False)): 613 if int(rule.get('process_outputs_as_sources', False)):
579 extra_sources += outputs 614 sources.update(outputs)
580 if int(rule.get('process_outputs_as_mac_bundle_resources', False)): 615 if int(rule.get('process_outputs_as_mac_bundle_resources', False)):
581 extra_mac_bundle_resources += outputs 616 extra_mac_bundle_resources += outputs
582 617
583 extra_bindings = [] 618 extra_bindings = []
584 for var in needed_variables: 619 for var in needed_variables:
585 if var == 'root': 620 if var == 'root':
586 extra_bindings.append(('root', cygwin_munge(root))) 621 extra_bindings.append(('root', cygwin_munge(root)))
587 elif var == 'dirname': 622 elif var == 'dirname':
588 extra_bindings.append(('dirname', cygwin_munge(dirname))) 623 extra_bindings.append(('dirname', cygwin_munge(dirname)))
589 elif var == 'source': 624 elif var == 'source':
(...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after
1495 1530
1496 user_config = params.get('generator_flags', {}).get('config', None) 1531 user_config = params.get('generator_flags', {}).get('config', None)
1497 if user_config: 1532 if user_config:
1498 GenerateOutputForConfig(target_list, target_dicts, data, params, 1533 GenerateOutputForConfig(target_list, target_dicts, data, params,
1499 user_config) 1534 user_config)
1500 else: 1535 else:
1501 config_names = target_dicts[target_list[0]]['configurations'].keys() 1536 config_names = target_dicts[target_list[0]]['configurations'].keys()
1502 for config_name in config_names: 1537 for config_name in config_names:
1503 GenerateOutputForConfig(target_list, target_dicts, data, params, 1538 GenerateOutputForConfig(target_list, target_dicts, data, params,
1504 config_name) 1539 config_name)
OLDNEW
« no previous file with comments | « no previous file | test/chained-rules/action.input » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698