OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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) |
OLD | NEW |