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

Side by Side Diff: pylib/gyp/input.py

Issue 7034007: Teach gyp about configurable filter commands, add "pymod_do_main" filter (Closed) Base URL: http://gyp.googlecode.com/svn/trunk/
Patch Set: '' Created 9 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 | no next file » | 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 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
Mark Mentovai 2011/05/25 02:12:34 shlex was already in here. LGTM for a quick follow
21 import subprocess 21 import subprocess
22 import shlex
tony 2011/05/24 23:31:39 Nit: alphabetize
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
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
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
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':
TVL 2011/05/24 23:44:03 drive by - should we also support pymod_main for t
Nico 2011/05/25 00:41:26 We can add this once we need it I think.
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 list 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 '%s'." %
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('')
tony 2011/05/24 23:31:39 Nit: no () on the left side
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
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]
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698