Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2011 The Chromium Authors. 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 from compiler.ast import Const | 7 from compiler.ast import Const |
| 8 from compiler.ast import Dict | 8 from compiler.ast import Dict |
| 9 from compiler.ast import Discard | 9 from compiler.ast import Discard |
| 10 from compiler.ast import List | 10 from compiler.ast import List |
| 11 from compiler.ast import Module | 11 from compiler.ast import Module |
| 12 from compiler.ast import Node | 12 from compiler.ast import Node |
| 13 from compiler.ast import Stmt | 13 from compiler.ast import Stmt |
| 14 import compiler | 14 import compiler |
| 15 import copy | 15 import copy |
| 16 import gyp.common | 16 import gyp.common |
| 17 import optparse | 17 import optparse |
| 18 import os.path | 18 import os.path |
| 19 import re | 19 import re |
| 20 import shlex | 20 import shlex |
| 21 import subprocess | 21 import subprocess |
| 22 import shlex | |
| 22 import sys | 23 import sys |
| 23 | 24 |
| 24 | 25 |
| 25 # A list of types that are treated as linkable. | 26 # A list of types that are treated as linkable. |
| 26 linkable_types = ['executable', 'shared_library', 'loadable_module'] | 27 linkable_types = ['executable', 'shared_library', 'loadable_module'] |
| 27 | 28 |
| 28 # A list of sections that contain links to other targets. | 29 # A list of sections that contain links to other targets. |
| 29 dependency_sections = ['dependencies', 'export_dependent_settings'] | 30 dependency_sections = ['dependencies', 'export_dependent_settings'] |
| 30 | 31 |
| 31 # base_path_sections is a list of sections defined by GYP that contain | 32 # base_path_sections is a list of sections defined by GYP that contain |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 """Returns True if |string| is in its canonical integer form. | 465 """Returns True if |string| is in its canonical integer form. |
| 465 | 466 |
| 466 The canonical form is such that str(int(string)) == string. | 467 The canonical form is such that str(int(string)) == string. |
| 467 """ | 468 """ |
| 468 if not isinstance(string, str) or not canonical_int_re.match(string): | 469 if not isinstance(string, str) or not canonical_int_re.match(string): |
| 469 return False | 470 return False |
| 470 | 471 |
| 471 return True | 472 return True |
| 472 | 473 |
| 473 | 474 |
| 474 early_variable_re = re.compile('(?P<replace>(?P<type><((!?@?)|\|)?)' | 475 # This matches things like "<(asdf)", "<!(cmd)", "<!@(cmd)", "<|(list)", |
| 475 '\((?P<is_array>\s*\[?)' | 476 # "<!interpreter(arguments)", "<([list])", and even "<([)" and "<(<())". |
| 476 '(?P<content>.*?)(\]?)\))') | 477 # In the last case, the inner "<()" is captured in match['content']. |
| 477 late_variable_re = re.compile('(?P<replace>(?P<type>>((!?@?)|\|)?)' | 478 early_variable_re = re.compile( |
| 478 '\((?P<is_array>\s*\[?)' | 479 '(?P<replace>(?P<type><(?:(?:!?@?)|\|)?)' |
| 479 '(?P<content>.*?)(\]?)\))') | 480 '(?P<command_string>[-a-zA-Z0-9_.]+)?' |
| 481 '\((?P<is_array>\s*\[?)' | |
| 482 '(?P<content>.*?)(\]?)\))') | |
| 483 | |
| 484 # This matches the same as early_variable_re, but with '>' instead of '<'. | |
| 485 late_variable_re = re.compile( | |
| 486 '(?P<replace>(?P<type>>(?:(?:!?@?)|\|)?)' | |
| 487 '(?P<command_string>[-a-zA-Z0-9_.]+)?' | |
| 488 '\((?P<is_array>\s*\[?)' | |
| 489 '(?P<content>.*?)(\]?)\))') | |
| 480 | 490 |
| 481 # Global cache of results from running commands so they don't have to be run | 491 # Global cache of results from running commands so they don't have to be run |
| 482 # more then once. | 492 # more then once. |
| 483 cached_command_results = {} | 493 cached_command_results = {} |
| 484 | 494 |
| 485 | 495 |
| 486 def FixupPlatformCommand(cmd): | 496 def FixupPlatformCommand(cmd): |
| 487 if sys.platform == 'win32': | 497 if sys.platform == 'win32': |
| 488 if type(cmd) == list: | 498 if type(cmd) == list: |
| 489 cmd = [re.sub('^cat ', 'type ', cmd[0])] + cmd[1:] | 499 cmd = [re.sub('^cat ', 'type ', cmd[0])] + cmd[1:] |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 518 # of what's intended for replacement. | 528 # of what's intended for replacement. |
| 519 matches.reverse() | 529 matches.reverse() |
| 520 for match_group in matches: | 530 for match_group in matches: |
| 521 match = match_group.groupdict() | 531 match = match_group.groupdict() |
| 522 gyp.DebugOutput(gyp.DEBUG_VARIABLES, | 532 gyp.DebugOutput(gyp.DEBUG_VARIABLES, |
| 523 "Matches: %s" % repr(match)) | 533 "Matches: %s" % repr(match)) |
| 524 # match['replace'] is the substring to look for, match['type'] | 534 # match['replace'] is the substring to look for, match['type'] |
| 525 # is the character code for the replacement type (< > <! >! <| >| <@ | 535 # is the character code for the replacement type (< > <! >! <| >| <@ |
| 526 # >@ <!@ >!@), match['is_array'] contains a '[' for command | 536 # >@ <!@ >!@), match['is_array'] contains a '[' for command |
| 527 # arrays, and match['content'] is the name of the variable (< >) | 537 # arrays, and match['content'] is the name of the variable (< >) |
| 528 # or command to run (<! >!). | 538 # or command to run (<! >!). match['command_string'] is an optional |
| 539 # command string. Currently, only 'pymod_do_main' is supported. | |
| 529 | 540 |
| 530 # run_command is true if a ! variant is used. | 541 # run_command is true if a ! variant is used. |
| 531 run_command = '!' in match['type'] | 542 run_command = '!' in match['type'] |
| 543 command_string = match['command_string'] | |
| 532 | 544 |
| 533 # file_list is true if a | variant is used. | 545 # file_list is true if a | variant is used. |
| 534 file_list = '|' in match['type'] | 546 file_list = '|' in match['type'] |
| 535 | 547 |
| 536 # Capture these now so we can adjust them later. | 548 # Capture these now so we can adjust them later. |
| 537 replace_start = match_group.start('replace') | 549 replace_start = match_group.start('replace') |
| 538 replace_end = match_group.end('replace') | 550 replace_end = match_group.end('replace') |
| 539 | 551 |
| 540 # Find the ending paren, and re-evaluate the contained string. | 552 # Find the ending paren, and re-evaluate the contained string. |
| 541 (c_start, c_end) = FindEnclosingBracketGroup(input_str[replace_start:]) | 553 (c_start, c_end) = FindEnclosingBracketGroup(input_str[replace_start:]) |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 627 # is invoked it produces different output by design. When the need | 639 # is invoked it produces different output by design. When the need |
| 628 # arises, the syntax should be extended to support no caching off a | 640 # arises, the syntax should be extended to support no caching off a |
| 629 # command's output so it is run every time. | 641 # command's output so it is run every time. |
| 630 cache_key = str(contents) | 642 cache_key = str(contents) |
| 631 cached_value = cached_command_results.get(cache_key, None) | 643 cached_value = cached_command_results.get(cache_key, None) |
| 632 if cached_value is None: | 644 if cached_value is None: |
| 633 gyp.DebugOutput(gyp.DEBUG_VARIABLES, | 645 gyp.DebugOutput(gyp.DEBUG_VARIABLES, |
| 634 "Executing command '%s' in directory '%s'" % | 646 "Executing command '%s' in directory '%s'" % |
| 635 (contents,build_file_dir)) | 647 (contents,build_file_dir)) |
| 636 | 648 |
| 637 # Fix up command with platform specific workarounds. | 649 replacement = '' |
| 638 contents = FixupPlatformCommand(contents) | |
| 639 p = subprocess.Popen(contents, shell=use_shell, | |
| 640 stdout=subprocess.PIPE, | |
| 641 stderr=subprocess.PIPE, | |
| 642 stdin=subprocess.PIPE, | |
| 643 cwd=build_file_dir) | |
| 644 | 650 |
| 645 (p_stdout, p_stderr) = p.communicate('') | 651 if command_string == 'pymod_do_main': |
| 652 # <!pymod_do_main(modulename param eters) loads |modulename| as a | |
| 653 # python module and then calls that module's DoMain() function, | |
| 654 # passing "param eters" as a single string argument. For modules | |
| 655 # that don't load quickly, this can be faster than | |
| 656 # <!(python modulename param eters). Do this in |build_file_dir|. | |
| 657 oldwd = os.getcwd() # Python doesn't like os.open('.'): no fchdir. | |
| 658 os.chdir(build_file_dir) | |
| 646 | 659 |
| 647 if p.wait() != 0 or p_stderr: | 660 parsed_contents = shlex.split(contents) |
| 648 sys.stderr.write(p_stderr) | 661 py_module = __import__(parsed_contents[0]) |
| 649 # Simulate check_call behavior, since check_call only exists | 662 replacement = str(py_module.DoMain(parsed_contents[1:])).rstrip() |
| 650 # in python 2.5 and later. | 663 |
| 651 raise Exception("Call to '%s' returned exit status %d." % | 664 os.chdir(oldwd) |
| 652 (contents, p.returncode)) | 665 assert replacement != None |
| 653 replacement = p_stdout.rstrip() | 666 elif command_string: |
| 667 raise Exception("Unknown command string '%s' in action '%s'." % | |
|
Mark Mentovai
2011/05/24 22:06:26
Let’s not overload the word “action” any further.
Nico
2011/05/24 22:09:52
Acted.
| |
| 668 (command_string, contents)) | |
| 669 else: | |
| 670 # Fix up command with platform specific workarounds. | |
| 671 contents = FixupPlatformCommand(contents) | |
| 672 p = subprocess.Popen(contents, shell=use_shell, | |
| 673 stdout=subprocess.PIPE, | |
| 674 stderr=subprocess.PIPE, | |
| 675 stdin=subprocess.PIPE, | |
| 676 cwd=build_file_dir) | |
| 677 | |
| 678 (p_stdout, p_stderr) = p.communicate('') | |
| 679 | |
| 680 if p.wait() != 0 or p_stderr: | |
| 681 sys.stderr.write(p_stderr) | |
| 682 # Simulate check_call behavior, since check_call only exists | |
| 683 # in python 2.5 and later. | |
| 684 raise Exception("Call to '%s' returned exit status %d." % | |
| 685 (contents, p.returncode)) | |
| 686 replacement = p_stdout.rstrip() | |
| 654 | 687 |
| 655 cached_command_results[cache_key] = replacement | 688 cached_command_results[cache_key] = replacement |
| 656 else: | 689 else: |
| 657 gyp.DebugOutput(gyp.DEBUG_VARIABLES, | 690 gyp.DebugOutput(gyp.DEBUG_VARIABLES, |
| 658 "Had cache value for command '%s' in directory '%s'" % | 691 "Had cache value for command '%s' in directory '%s'" % |
| 659 (contents,build_file_dir)) | 692 (contents,build_file_dir)) |
| 660 replacement = cached_value | 693 replacement = cached_value |
| 661 | 694 |
| 662 else: | 695 else: |
| 663 if not contents in variables: | 696 if not contents in variables: |
| (...skipping 1577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2241 ValidateRunAsInTarget(target, target_dict, build_file) | 2274 ValidateRunAsInTarget(target, target_dict, build_file) |
| 2242 ValidateActionsInTarget(target, target_dict, build_file) | 2275 ValidateActionsInTarget(target, target_dict, build_file) |
| 2243 | 2276 |
| 2244 # Generators might not expect ints. Turn them into strs. | 2277 # Generators might not expect ints. Turn them into strs. |
| 2245 TurnIntIntoStrInDict(data) | 2278 TurnIntIntoStrInDict(data) |
| 2246 | 2279 |
| 2247 # TODO(mark): Return |data| for now because the generator needs a list of | 2280 # TODO(mark): Return |data| for now because the generator needs a list of |
| 2248 # build files that came in. In the future, maybe it should just accept | 2281 # build files that came in. In the future, maybe it should just accept |
| 2249 # a list, and not the whole data dict. | 2282 # a list, and not the whole data dict. |
| 2250 return [flat_list, targets, data] | 2283 return [flat_list, targets, data] |
| OLD | NEW |