| OLD | NEW |
| 1 """SCons.Action | 1 """SCons.Action |
| 2 | 2 |
| 3 This encapsulates information about executing any sort of action that | 3 This encapsulates information about executing any sort of action that |
| 4 can build one or more target Nodes (typically files) from one or more | 4 can build one or more target Nodes (typically files) from one or more |
| 5 source Nodes (also typically files) given a specific Environment. | 5 source Nodes (also typically files) given a specific Environment. |
| 6 | 6 |
| 7 The base class here is ActionBase. The base class supplies just a few | 7 The base class here is ActionBase. The base class supplies just a few |
| 8 OO utility methods and some generic methods for displaying information | 8 OO utility methods and some generic methods for displaying information |
| 9 about an Action in response to the various commands that control printing. | 9 about an Action in response to the various commands that control printing. |
| 10 | 10 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 There is a related independent ActionCaller class that looks like a | 69 There is a related independent ActionCaller class that looks like a |
| 70 regular Action, and which serves as a wrapper for arbitrary functions | 70 regular Action, and which serves as a wrapper for arbitrary functions |
| 71 that we want to let the user specify the arguments to now, but actually | 71 that we want to let the user specify the arguments to now, but actually |
| 72 execute later (when an out-of-date check determines that it's needed to | 72 execute later (when an out-of-date check determines that it's needed to |
| 73 be executed, for example). Objects of this class are returned by an | 73 be executed, for example). Objects of this class are returned by an |
| 74 ActionFactory class that provides a __call__() method as a convenient | 74 ActionFactory class that provides a __call__() method as a convenient |
| 75 way for wrapping up the functions. | 75 way for wrapping up the functions. |
| 76 | 76 |
| 77 """ | 77 """ |
| 78 | 78 |
| 79 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundat
ion | 79 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons F
oundation |
| 80 # | 80 # |
| 81 # Permission is hereby granted, free of charge, to any person obtaining | 81 # Permission is hereby granted, free of charge, to any person obtaining |
| 82 # a copy of this software and associated documentation files (the | 82 # a copy of this software and associated documentation files (the |
| 83 # "Software"), to deal in the Software without restriction, including | 83 # "Software"), to deal in the Software without restriction, including |
| 84 # without limitation the rights to use, copy, modify, merge, publish, | 84 # without limitation the rights to use, copy, modify, merge, publish, |
| 85 # distribute, sublicense, and/or sell copies of the Software, and to | 85 # distribute, sublicense, and/or sell copies of the Software, and to |
| 86 # permit persons to whom the Software is furnished to do so, subject to | 86 # permit persons to whom the Software is furnished to do so, subject to |
| 87 # the following conditions: | 87 # the following conditions: |
| 88 # | 88 # |
| 89 # The above copyright notice and this permission notice shall be included | 89 # The above copyright notice and this permission notice shall be included |
| 90 # in all copies or substantial portions of the Software. | 90 # in all copies or substantial portions of the Software. |
| 91 # | 91 # |
| 92 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY | 92 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
| 93 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | 93 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
| 94 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 94 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 95 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | 95 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 96 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | 96 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 97 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | 97 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 98 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 98 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 99 | 99 |
| 100 __revision__ = "src/engine/SCons/Action.py 3842 2008/12/20 22:59:52 scons" | 100 __revision__ = "src/engine/SCons/Action.py 3897 2009/01/13 06:45:54 scons" |
| 101 | 101 |
| 102 import cPickle | 102 import cPickle |
| 103 import dis | 103 import dis |
| 104 import os | 104 import os |
| 105 import string | 105 import string |
| 106 import sys | 106 import sys |
| 107 import subprocess | 107 import subprocess |
| 108 | 108 |
| 109 from SCons.Debug import logInstanceCreation | 109 from SCons.Debug import logInstanceCreation |
| 110 import SCons.Errors | 110 import SCons.Errors |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 return None | 385 return None |
| 386 | 386 |
| 387 def _do_create_list_action(act, kw): | 387 def _do_create_list_action(act, kw): |
| 388 """A factory for list actions. Convert the input list into Actions | 388 """A factory for list actions. Convert the input list into Actions |
| 389 and then wrap them in a ListAction.""" | 389 and then wrap them in a ListAction.""" |
| 390 acts = [] | 390 acts = [] |
| 391 for a in act: | 391 for a in act: |
| 392 aa = _do_create_action(a, kw) | 392 aa = _do_create_action(a, kw) |
| 393 if aa is not None: acts.append(aa) | 393 if aa is not None: acts.append(aa) |
| 394 if not acts: | 394 if not acts: |
| 395 return None | 395 return ListAction([]) |
| 396 elif len(acts) == 1: | 396 elif len(acts) == 1: |
| 397 return acts[0] | 397 return acts[0] |
| 398 else: | 398 else: |
| 399 return ListAction(acts) | 399 return ListAction(acts) |
| 400 | 400 |
| 401 def Action(act, *args, **kw): | 401 def Action(act, *args, **kw): |
| 402 """A factory for action objects.""" | 402 """A factory for action objects.""" |
| 403 # Really simple: the _do_create_* routines do the heavy lifting. | 403 # Really simple: the _do_create_* routines do the heavy lifting. |
| 404 _do_create_keywords(args, kw) | 404 _do_create_keywords(args, kw) |
| 405 if is_List(act): | 405 if is_List(act): |
| 406 return _do_create_list_action(act, kw) | 406 return _do_create_list_action(act, kw) |
| 407 return _do_create_action(act, kw) | 407 return _do_create_action(act, kw) |
| 408 | 408 |
| 409 class ActionBase: | 409 class ActionBase: |
| 410 """Base class for all types of action objects that can be held by | 410 """Base class for all types of action objects that can be held by |
| 411 other objects (Builders, Executors, etc.) This provides the | 411 other objects (Builders, Executors, etc.) This provides the |
| 412 common methods for manipulating and combining those actions.""" | 412 common methods for manipulating and combining those actions.""" |
| 413 | 413 |
| 414 def __cmp__(self, other): | 414 def __cmp__(self, other): |
| 415 return cmp(self.__dict__, other) | 415 return cmp(self.__dict__, other) |
| 416 | 416 |
| 417 def no_batch_key(self, env, target, source): |
| 418 return None |
| 419 |
| 420 batch_key = no_batch_key |
| 421 |
| 417 def genstring(self, target, source, env): | 422 def genstring(self, target, source, env): |
| 418 return str(self) | 423 return str(self) |
| 419 | 424 |
| 420 def get_contents(self, target, source, env): | 425 def get_contents(self, target, source, env): |
| 421 result = [ self.get_presig(target, source, env) ] | 426 result = [ self.get_presig(target, source, env) ] |
| 422 # This should never happen, as the Action() factory should wrap | 427 # This should never happen, as the Action() factory should wrap |
| 423 # the varlist, but just in case an action is created directly, | 428 # the varlist, but just in case an action is created directly, |
| 424 # we duplicate this check here. | 429 # we duplicate this check here. |
| 425 vl = self.varlist | 430 vl = self.varlist |
| 426 if is_String(vl): vl = (vl,) | 431 if is_String(vl): vl = (vl,) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 439 # in order to return the proper string here, since | 444 # in order to return the proper string here, since |
| 440 # it may call LazyAction, which looks up a key | 445 # it may call LazyAction, which looks up a key |
| 441 # in that env. So we temporarily remember the env here, | 446 # in that env. So we temporarily remember the env here, |
| 442 # and CommandGeneratorAction will use this env | 447 # and CommandGeneratorAction will use this env |
| 443 # when it calls its _generate method. | 448 # when it calls its _generate method. |
| 444 self.presub_env = env | 449 self.presub_env = env |
| 445 lines = string.split(str(self), '\n') | 450 lines = string.split(str(self), '\n') |
| 446 self.presub_env = None # don't need this any more | 451 self.presub_env = None # don't need this any more |
| 447 return lines | 452 return lines |
| 448 | 453 |
| 449 def get_executor(self, env, overrides, tlist, slist, executor_kw): | 454 def get_targets(self, env, executor): |
| 450 """Return the Executor for this Action.""" | 455 """ |
| 451 return SCons.Executor.Executor(self, env, overrides, | 456 Returns the type of targets ($TARGETS, $CHANGED_TARGETS) used |
| 452 tlist, slist, executor_kw) | 457 by this action. |
| 458 """ |
| 459 return self.targets |
| 453 | 460 |
| 454 class _ActionAction(ActionBase): | 461 class _ActionAction(ActionBase): |
| 455 """Base class for actions that create output objects.""" | 462 """Base class for actions that create output objects.""" |
| 456 def __init__(self, cmdstr=_null, strfunction=_null, varlist=(), | 463 def __init__(self, cmdstr=_null, strfunction=_null, varlist=(), |
| 457 presub=_null, chdir=None, exitstatfunc=None, | 464 presub=_null, chdir=None, exitstatfunc=None, |
| 465 batch_key=None, targets='$TARGETS', |
| 458 **kw): | 466 **kw): |
| 459 self.cmdstr = cmdstr | 467 self.cmdstr = cmdstr |
| 460 if strfunction is not _null: | 468 if strfunction is not _null: |
| 461 if strfunction is None: | 469 if strfunction is None: |
| 462 self.cmdstr = None | 470 self.cmdstr = None |
| 463 else: | 471 else: |
| 464 self.strfunction = strfunction | 472 self.strfunction = strfunction |
| 465 self.varlist = varlist | 473 self.varlist = varlist |
| 466 self.presub = presub | 474 self.presub = presub |
| 467 self.chdir = chdir | 475 self.chdir = chdir |
| 468 if not exitstatfunc: | 476 if not exitstatfunc: |
| 469 exitstatfunc = default_exitstatfunc | 477 exitstatfunc = default_exitstatfunc |
| 470 self.exitstatfunc = exitstatfunc | 478 self.exitstatfunc = exitstatfunc |
| 471 | 479 |
| 480 self.targets = targets |
| 481 |
| 482 if batch_key: |
| 483 if not callable(batch_key): |
| 484 # They have set batch_key, but not to their own |
| 485 # callable. The default behavior here will batch |
| 486 # *all* targets+sources using this action, separated |
| 487 # for each construction environment. |
| 488 def default_batch_key(self, env, target, source): |
| 489 return (id(self), id(env)) |
| 490 batch_key = default_batch_key |
| 491 SCons.Util.AddMethod(self, batch_key, 'batch_key') |
| 492 |
| 472 def print_cmd_line(self, s, target, source, env): | 493 def print_cmd_line(self, s, target, source, env): |
| 473 sys.stdout.write(s + "\n") | 494 sys.stdout.write(s + "\n") |
| 474 | 495 |
| 475 def __call__(self, target, source, env, | 496 def __call__(self, target, source, env, |
| 476 exitstatfunc=_null, | 497 exitstatfunc=_null, |
| 477 presub=_null, | 498 presub=_null, |
| 478 show=_null, | 499 show=_null, |
| 479 execute=_null, | 500 execute=_null, |
| 480 chdir=_null): | 501 chdir=_null, |
| 502 executor=None): |
| 481 if not is_List(target): | 503 if not is_List(target): |
| 482 target = [target] | 504 target = [target] |
| 483 if not is_List(source): | 505 if not is_List(source): |
| 484 source = [source] | 506 source = [source] |
| 485 | 507 |
| 486 if presub is _null: | 508 if presub is _null: |
| 487 presub = self.presub | 509 presub = self.presub |
| 488 if presub is _null: | 510 if presub is _null: |
| 489 presub = print_actions_presub | 511 presub = print_actions_presub |
| 490 if exitstatfunc is _null: exitstatfunc = self.exitstatfunc | 512 if exitstatfunc is _null: exitstatfunc = self.exitstatfunc |
| 491 if show is _null: show = print_actions | 513 if show is _null: show = print_actions |
| 492 if execute is _null: execute = execute_actions | 514 if execute is _null: execute = execute_actions |
| 493 if chdir is _null: chdir = self.chdir | 515 if chdir is _null: chdir = self.chdir |
| 494 save_cwd = None | 516 save_cwd = None |
| 495 if chdir: | 517 if chdir: |
| 496 save_cwd = os.getcwd() | 518 save_cwd = os.getcwd() |
| 497 try: | 519 try: |
| 498 chdir = str(chdir.abspath) | 520 chdir = str(chdir.abspath) |
| 499 except AttributeError: | 521 except AttributeError: |
| 500 if not is_String(chdir): | 522 if not is_String(chdir): |
| 501 chdir = str(target[0].dir) | 523 if executor: |
| 524 chdir = str(executor.batches[0].targets[0].dir) |
| 525 else: |
| 526 chdir = str(target[0].dir) |
| 502 if presub: | 527 if presub: |
| 528 if executor: |
| 529 target = executor.get_all_targets() |
| 530 source = executor.get_all_sources() |
| 503 t = string.join(map(str, target), ' and ') | 531 t = string.join(map(str, target), ' and ') |
| 504 l = string.join(self.presub_lines(env), '\n ') | 532 l = string.join(self.presub_lines(env), '\n ') |
| 505 out = "Building %s with action:\n %s\n" % (t, l) | 533 out = "Building %s with action:\n %s\n" % (t, l) |
| 506 sys.stdout.write(out) | 534 sys.stdout.write(out) |
| 507 cmd = None | 535 cmd = None |
| 508 if show and self.strfunction: | 536 if show and self.strfunction: |
| 509 cmd = self.strfunction(target, source, env) | 537 if executor: |
| 538 target = executor.get_all_targets() |
| 539 source = executor.get_all_sources() |
| 540 try: |
| 541 cmd = self.strfunction(target, source, env, executor) |
| 542 except TypeError: |
| 543 cmd = self.strfunction(target, source, env) |
| 510 if cmd: | 544 if cmd: |
| 511 if chdir: | 545 if chdir: |
| 512 cmd = ('os.chdir(%s)\n' % repr(chdir)) + cmd | 546 cmd = ('os.chdir(%s)\n' % repr(chdir)) + cmd |
| 513 try: | 547 try: |
| 514 get = env.get | 548 get = env.get |
| 515 except AttributeError: | 549 except AttributeError: |
| 516 print_func = self.print_cmd_line | 550 print_func = self.print_cmd_line |
| 517 else: | 551 else: |
| 518 print_func = get('PRINT_CMD_LINE_FUNC') | 552 print_func = get('PRINT_CMD_LINE_FUNC') |
| 519 if not print_func: | 553 if not print_func: |
| 520 print_func = self.print_cmd_line | 554 print_func = self.print_cmd_line |
| 521 print_func(cmd, target, source, env) | 555 print_func(cmd, target, source, env) |
| 522 stat = 0 | 556 stat = 0 |
| 523 if execute: | 557 if execute: |
| 524 if chdir: | 558 if chdir: |
| 525 os.chdir(chdir) | 559 os.chdir(chdir) |
| 526 try: | 560 try: |
| 527 stat = self.execute(target, source, env) | 561 stat = self.execute(target, source, env, executor=executor) |
| 528 if isinstance(stat, SCons.Errors.BuildError): | 562 if isinstance(stat, SCons.Errors.BuildError): |
| 529 s = exitstatfunc(stat.status) | 563 s = exitstatfunc(stat.status) |
| 530 if s: | 564 if s: |
| 531 stat.status = s | 565 stat.status = s |
| 532 else: | 566 else: |
| 533 stat = s | 567 stat = s |
| 534 else: | 568 else: |
| 535 stat = exitstatfunc(stat) | 569 stat = exitstatfunc(stat) |
| 536 finally: | 570 finally: |
| 537 if save_cwd: | 571 if save_cwd: |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 if filter(is_List, cmd): | 684 if filter(is_List, cmd): |
| 651 raise TypeError, "CommandAction should be given only " \ | 685 raise TypeError, "CommandAction should be given only " \ |
| 652 "a single command" | 686 "a single command" |
| 653 self.cmd_list = cmd | 687 self.cmd_list = cmd |
| 654 | 688 |
| 655 def __str__(self): | 689 def __str__(self): |
| 656 if is_List(self.cmd_list): | 690 if is_List(self.cmd_list): |
| 657 return string.join(map(str, self.cmd_list), ' ') | 691 return string.join(map(str, self.cmd_list), ' ') |
| 658 return str(self.cmd_list) | 692 return str(self.cmd_list) |
| 659 | 693 |
| 660 def process(self, target, source, env): | 694 def process(self, target, source, env, executor=None): |
| 661 result = env.subst_list(self.cmd_list, 0, target, source) | 695 if executor: |
| 696 result = env.subst_list(self.cmd_list, 0, executor=executor) |
| 697 else: |
| 698 result = env.subst_list(self.cmd_list, 0, target, source) |
| 662 silent = None | 699 silent = None |
| 663 ignore = None | 700 ignore = None |
| 664 while 1: | 701 while 1: |
| 665 try: c = result[0][0][0] | 702 try: c = result[0][0][0] |
| 666 except IndexError: c = None | 703 except IndexError: c = None |
| 667 if c == '@': silent = 1 | 704 if c == '@': silent = 1 |
| 668 elif c == '-': ignore = 1 | 705 elif c == '-': ignore = 1 |
| 669 else: break | 706 else: break |
| 670 result[0][0] = result[0][0][1:] | 707 result[0][0] = result[0][0][1:] |
| 671 try: | 708 try: |
| 672 if not result[0][0]: | 709 if not result[0][0]: |
| 673 result[0] = result[0][1:] | 710 result[0] = result[0][1:] |
| 674 except IndexError: | 711 except IndexError: |
| 675 pass | 712 pass |
| 676 return result, ignore, silent | 713 return result, ignore, silent |
| 677 | 714 |
| 678 def strfunction(self, target, source, env): | 715 def strfunction(self, target, source, env, executor=None): |
| 679 if self.cmdstr is None: | 716 if self.cmdstr is None: |
| 680 return None | 717 return None |
| 681 if self.cmdstr is not _null: | 718 if self.cmdstr is not _null: |
| 682 from SCons.Subst import SUBST_RAW | 719 from SCons.Subst import SUBST_RAW |
| 683 c = env.subst(self.cmdstr, SUBST_RAW, target, source) | 720 if executor: |
| 721 c = env.subst(self.cmdstr, SUBST_RAW, executor=executor) |
| 722 else: |
| 723 c = env.subst(self.cmdstr, SUBST_RAW, target, source) |
| 684 if c: | 724 if c: |
| 685 return c | 725 return c |
| 686 cmd_list, ignore, silent = self.process(target, source, env) | 726 cmd_list, ignore, silent = self.process(target, source, env, executor) |
| 687 if silent: | 727 if silent: |
| 688 return '' | 728 return '' |
| 689 return _string_from_cmd_list(cmd_list[0]) | 729 return _string_from_cmd_list(cmd_list[0]) |
| 690 | 730 |
| 691 def execute(self, target, source, env): | 731 def execute(self, target, source, env, executor=None): |
| 692 """Execute a command action. | 732 """Execute a command action. |
| 693 | 733 |
| 694 This will handle lists of commands as well as individual commands, | 734 This will handle lists of commands as well as individual commands, |
| 695 because construction variable substitution may turn a single | 735 because construction variable substitution may turn a single |
| 696 "command" into a list. This means that this class can actually | 736 "command" into a list. This means that this class can actually |
| 697 handle lists of commands, even though that's not how we use it | 737 handle lists of commands, even though that's not how we use it |
| 698 externally. | 738 externally. |
| 699 """ | 739 """ |
| 700 escape_list = SCons.Subst.escape_list | 740 escape_list = SCons.Subst.escape_list |
| 701 flatten_sequence = SCons.Util.flatten_sequence | 741 flatten_sequence = SCons.Util.flatten_sequence |
| (...skipping 24 matching lines...) Expand all Loading... |
| 726 # value to stick in an environment variable: | 766 # value to stick in an environment variable: |
| 727 value = flatten_sequence(value) | 767 value = flatten_sequence(value) |
| 728 ENV[key] = string.join(map(str, value), os.pathsep) | 768 ENV[key] = string.join(map(str, value), os.pathsep) |
| 729 else: | 769 else: |
| 730 # If it isn't a string or a list, then we just coerce | 770 # If it isn't a string or a list, then we just coerce |
| 731 # it to a string, which is the proper way to handle | 771 # it to a string, which is the proper way to handle |
| 732 # Dir and File instances and will produce something | 772 # Dir and File instances and will produce something |
| 733 # reasonable for just about everything else: | 773 # reasonable for just about everything else: |
| 734 ENV[key] = str(value) | 774 ENV[key] = str(value) |
| 735 | 775 |
| 736 cmd_list, ignore, silent = self.process(target, map(rfile, source), env) | 776 if executor: |
| 777 target = executor.get_all_targets() |
| 778 source = executor.get_all_sources() |
| 779 cmd_list, ignore, silent = self.process(target, map(rfile, source), env,
executor) |
| 737 | 780 |
| 738 # Use len() to filter out any "command" that's zero-length. | 781 # Use len() to filter out any "command" that's zero-length. |
| 739 for cmd_line in filter(len, cmd_list): | 782 for cmd_line in filter(len, cmd_list): |
| 740 # Escape the command line for the interpreter we are using. | 783 # Escape the command line for the interpreter we are using. |
| 741 cmd_line = escape_list(cmd_line, escape) | 784 cmd_line = escape_list(cmd_line, escape) |
| 742 result = spawn(shell, escape, cmd_line[0], cmd_line, ENV) | 785 result = spawn(shell, escape, cmd_line[0], cmd_line, ENV) |
| 743 if not ignore and result: | 786 if not ignore and result: |
| 744 msg = "Error %s" % result | 787 msg = "Error %s" % result |
| 745 return SCons.Errors.BuildError(errstr=msg, | 788 return SCons.Errors.BuildError(errstr=msg, |
| 746 status=result, | 789 status=result, |
| 747 action=self, | 790 action=self, |
| 748 command=cmd_line) | 791 command=cmd_line) |
| 749 return 0 | 792 return 0 |
| 750 | 793 |
| 751 def get_presig(self, target, source, env): | 794 def get_presig(self, target, source, env, executor=None): |
| 752 """Return the signature contents of this action's command line. | 795 """Return the signature contents of this action's command line. |
| 753 | 796 |
| 754 This strips $(-$) and everything in between the string, | 797 This strips $(-$) and everything in between the string, |
| 755 since those parts don't affect signatures. | 798 since those parts don't affect signatures. |
| 756 """ | 799 """ |
| 757 from SCons.Subst import SUBST_SIG | 800 from SCons.Subst import SUBST_SIG |
| 758 cmd = self.cmd_list | 801 cmd = self.cmd_list |
| 759 if is_List(cmd): | 802 if is_List(cmd): |
| 760 cmd = string.join(map(str, cmd)) | 803 cmd = string.join(map(str, cmd)) |
| 761 else: | 804 else: |
| 762 cmd = str(cmd) | 805 cmd = str(cmd) |
| 763 return env.subst_target_source(cmd, SUBST_SIG, target, source) | 806 if executor: |
| 807 return env.subst_target_source(cmd, SUBST_SIG, executor=executor) |
| 808 else: |
| 809 return env.subst_target_source(cmd, SUBST_SIG, target, source) |
| 764 | 810 |
| 765 def get_implicit_deps(self, target, source, env): | 811 def get_implicit_deps(self, target, source, env, executor=None): |
| 766 icd = env.get('IMPLICIT_COMMAND_DEPENDENCIES', True) | 812 icd = env.get('IMPLICIT_COMMAND_DEPENDENCIES', True) |
| 767 if is_String(icd) and icd[:1] == '$': | 813 if is_String(icd) and icd[:1] == '$': |
| 768 icd = env.subst(icd) | 814 icd = env.subst(icd) |
| 769 if not icd or icd in ('0', 'None'): | 815 if not icd or icd in ('0', 'None'): |
| 770 return [] | 816 return [] |
| 771 from SCons.Subst import SUBST_SIG | 817 from SCons.Subst import SUBST_SIG |
| 772 cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, target, source) | 818 if executor: |
| 819 cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, executor=executo
r) |
| 820 else: |
| 821 cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, target, source) |
| 773 res = [] | 822 res = [] |
| 774 for cmd_line in cmd_list: | 823 for cmd_line in cmd_list: |
| 775 if cmd_line: | 824 if cmd_line: |
| 776 d = env.WhereIs(str(cmd_line[0])) | 825 d = env.WhereIs(str(cmd_line[0])) |
| 777 if d: | 826 if d: |
| 778 res.append(env.fs.File(d)) | 827 res.append(env.fs.File(d)) |
| 779 return res | 828 return res |
| 780 | 829 |
| 781 class CommandGeneratorAction(ActionBase): | 830 class CommandGeneratorAction(ActionBase): |
| 782 """Class for command-generator actions.""" | 831 """Class for command-generator actions.""" |
| 783 def __init__(self, generator, kw): | 832 def __init__(self, generator, kw): |
| 784 if __debug__: logInstanceCreation(self, 'Action.CommandGeneratorAction') | 833 if __debug__: logInstanceCreation(self, 'Action.CommandGeneratorAction') |
| 785 self.generator = generator | 834 self.generator = generator |
| 786 self.gen_kw = kw | 835 self.gen_kw = kw |
| 787 self.varlist = kw.get('varlist', ()) | 836 self.varlist = kw.get('varlist', ()) |
| 837 self.targets = kw.get('targets', '$TARGETS') |
| 788 | 838 |
| 789 def _generate(self, target, source, env, for_signature): | 839 def _generate(self, target, source, env, for_signature, executor=None): |
| 790 # ensure that target is a list, to make it easier to write | 840 # ensure that target is a list, to make it easier to write |
| 791 # generator functions: | 841 # generator functions: |
| 792 if not is_List(target): | 842 if not is_List(target): |
| 793 target = [target] | 843 target = [target] |
| 794 | 844 |
| 795 ret = self.generator(target=target, source=source, env=env, for_signatur
e=for_signature) | 845 if executor: |
| 846 target = executor.get_all_targets() |
| 847 source = executor.get_all_sources() |
| 848 ret = self.generator(target=target, |
| 849 source=source, |
| 850 env=env, |
| 851 for_signature=for_signature) |
| 796 #TODO(1.5) gen_cmd = Action(ret, **self.gen_kw) | 852 #TODO(1.5) gen_cmd = Action(ret, **self.gen_kw) |
| 797 gen_cmd = apply(Action, (ret,), self.gen_kw) | 853 gen_cmd = apply(Action, (ret,), self.gen_kw) |
| 798 if not gen_cmd: | 854 if not gen_cmd: |
| 799 raise SCons.Errors.UserError("Object returned from command generator
: %s cannot be used to create an Action." % repr(ret)) | 855 raise SCons.Errors.UserError("Object returned from command generator
: %s cannot be used to create an Action." % repr(ret)) |
| 800 return gen_cmd | 856 return gen_cmd |
| 801 | 857 |
| 802 def __str__(self): | 858 def __str__(self): |
| 803 try: | 859 try: |
| 804 env = self.presub_env | 860 env = self.presub_env |
| 805 except AttributeError: | 861 except AttributeError: |
| 806 env = None | 862 env = None |
| 807 if env is None: | 863 if env is None: |
| 808 env = SCons.Defaults.DefaultEnvironment() | 864 env = SCons.Defaults.DefaultEnvironment() |
| 809 act = self._generate([], [], env, 1) | 865 act = self._generate([], [], env, 1) |
| 810 return str(act) | 866 return str(act) |
| 811 | 867 |
| 812 def genstring(self, target, source, env): | 868 def batch_key(self, env, target, source): |
| 813 return self._generate(target, source, env, 1).genstring(target, source,
env) | 869 return self._generate(target, source, env, 1).batch_key(env, target, sou
rce) |
| 870 |
| 871 def genstring(self, target, source, env, executor=None): |
| 872 return self._generate(target, source, env, 1, executor).genstring(target
, source, env) |
| 814 | 873 |
| 815 def __call__(self, target, source, env, exitstatfunc=_null, presub=_null, | 874 def __call__(self, target, source, env, exitstatfunc=_null, presub=_null, |
| 816 show=_null, execute=_null, chdir=_null): | 875 show=_null, execute=_null, chdir=_null, executor=None): |
| 817 act = self._generate(target, source, env, 0) | 876 act = self._generate(target, source, env, 0, executor) |
| 877 if act is None: |
| 878 raise UserError("While building `%s': Cannot deduce file extension f
rom source files: %s" % (repr(map(str, target)), repr(map(str, source)))) |
| 818 return act(target, source, env, exitstatfunc, presub, | 879 return act(target, source, env, exitstatfunc, presub, |
| 819 show, execute, chdir) | 880 show, execute, chdir, executor) |
| 820 | 881 |
| 821 def get_presig(self, target, source, env): | 882 def get_presig(self, target, source, env, executor=None): |
| 822 """Return the signature contents of this action's command line. | 883 """Return the signature contents of this action's command line. |
| 823 | 884 |
| 824 This strips $(-$) and everything in between the string, | 885 This strips $(-$) and everything in between the string, |
| 825 since those parts don't affect signatures. | 886 since those parts don't affect signatures. |
| 826 """ | 887 """ |
| 827 return self._generate(target, source, env, 1).get_presig(target, source,
env) | 888 return self._generate(target, source, env, 1, executor).get_presig(targe
t, source, env) |
| 828 | 889 |
| 829 def get_implicit_deps(self, target, source, env): | 890 def get_implicit_deps(self, target, source, env, executor=None): |
| 830 return self._generate(target, source, env, 1).get_implicit_deps(target,
source, env) | 891 return self._generate(target, source, env, 1, executor).get_implicit_dep
s(target, source, env) |
| 892 |
| 893 def get_targets(self, env, executor): |
| 894 return self._generate(None, None, env, 1, executor).get_targets(env, exe
cutor) |
| 831 | 895 |
| 832 | 896 |
| 833 | 897 |
| 834 # A LazyAction is a kind of hybrid generator and command action for | 898 # A LazyAction is a kind of hybrid generator and command action for |
| 835 # strings of the form "$VAR". These strings normally expand to other | 899 # strings of the form "$VAR". These strings normally expand to other |
| 836 # strings (think "$CCCOM" to "$CC -c -o $TARGET $SOURCE"), but we also | 900 # strings (think "$CCCOM" to "$CC -c -o $TARGET $SOURCE"), but we also |
| 837 # want to be able to replace them with functions in the construction | 901 # want to be able to replace them with functions in the construction |
| 838 # environment. Consequently, we want lazy evaluation and creation of | 902 # environment. Consequently, we want lazy evaluation and creation of |
| 839 # an Action in the case of the function, but that's overkill in the more | 903 # an Action in the case of the function, but that's overkill in the more |
| 840 # normal case of expansion to other strings. | 904 # normal case of expansion to other strings. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 857 self.var = SCons.Util.to_String(var) | 921 self.var = SCons.Util.to_String(var) |
| 858 self.gen_kw = kw | 922 self.gen_kw = kw |
| 859 | 923 |
| 860 def get_parent_class(self, env): | 924 def get_parent_class(self, env): |
| 861 c = env.get(self.var) | 925 c = env.get(self.var) |
| 862 if is_String(c) and not '\n' in c: | 926 if is_String(c) and not '\n' in c: |
| 863 return CommandAction | 927 return CommandAction |
| 864 return CommandGeneratorAction | 928 return CommandGeneratorAction |
| 865 | 929 |
| 866 def _generate_cache(self, env): | 930 def _generate_cache(self, env): |
| 867 c = env.get(self.var, '') | 931 if env: |
| 932 c = env.get(self.var, '') |
| 933 else: |
| 934 c = '' |
| 868 #TODO(1.5) gen_cmd = Action(c, **self.gen_kw) | 935 #TODO(1.5) gen_cmd = Action(c, **self.gen_kw) |
| 869 gen_cmd = apply(Action, (c,), self.gen_kw) | 936 gen_cmd = apply(Action, (c,), self.gen_kw) |
| 870 if not gen_cmd: | 937 if not gen_cmd: |
| 871 raise SCons.Errors.UserError("$%s value %s cannot be used to create
an Action." % (self.var, repr(c))) | 938 raise SCons.Errors.UserError("$%s value %s cannot be used to create
an Action." % (self.var, repr(c))) |
| 872 return gen_cmd | 939 return gen_cmd |
| 873 | 940 |
| 874 def _generate(self, target, source, env, for_signature): | 941 def _generate(self, target, source, env, for_signature, executor=None): |
| 875 return self._generate_cache(env) | 942 return self._generate_cache(env) |
| 876 | 943 |
| 877 def __call__(self, target, source, env, *args, **kw): | 944 def __call__(self, target, source, env, *args, **kw): |
| 878 args = (self, target, source, env) + args | 945 args = (self, target, source, env) + args |
| 879 c = self.get_parent_class(env) | 946 c = self.get_parent_class(env) |
| 880 #TODO(1.5) return c.__call__(*args, **kw) | 947 #TODO(1.5) return c.__call__(*args, **kw) |
| 881 return apply(c.__call__, args, kw) | 948 return apply(c.__call__, args, kw) |
| 882 | 949 |
| 883 def get_presig(self, target, source, env): | 950 def get_presig(self, target, source, env): |
| 884 c = self.get_parent_class(env) | 951 c = self.get_parent_class(env) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 908 | 975 |
| 909 def function_name(self): | 976 def function_name(self): |
| 910 try: | 977 try: |
| 911 return self.execfunction.__name__ | 978 return self.execfunction.__name__ |
| 912 except AttributeError: | 979 except AttributeError: |
| 913 try: | 980 try: |
| 914 return self.execfunction.__class__.__name__ | 981 return self.execfunction.__class__.__name__ |
| 915 except AttributeError: | 982 except AttributeError: |
| 916 return "unknown_python_function" | 983 return "unknown_python_function" |
| 917 | 984 |
| 918 def strfunction(self, target, source, env): | 985 def strfunction(self, target, source, env, executor=None): |
| 919 if self.cmdstr is None: | 986 if self.cmdstr is None: |
| 920 return None | 987 return None |
| 921 if self.cmdstr is not _null: | 988 if self.cmdstr is not _null: |
| 922 from SCons.Subst import SUBST_RAW | 989 from SCons.Subst import SUBST_RAW |
| 923 c = env.subst(self.cmdstr, SUBST_RAW, target, source) | 990 if executor: |
| 991 c = env.subst(self.cmdstr, SUBST_RAW, executor=executor) |
| 992 else: |
| 993 c = env.subst(self.cmdstr, SUBST_RAW, target, source) |
| 924 if c: | 994 if c: |
| 925 return c | 995 return c |
| 926 def array(a): | 996 def array(a): |
| 927 def quote(s): | 997 def quote(s): |
| 928 try: | 998 try: |
| 929 str_for_display = s.str_for_display | 999 str_for_display = s.str_for_display |
| 930 except AttributeError: | 1000 except AttributeError: |
| 931 s = repr(s) | 1001 s = repr(s) |
| 932 else: | 1002 else: |
| 933 s = str_for_display() | 1003 s = str_for_display() |
| (...skipping 12 matching lines...) Expand all Loading... |
| 946 tstr = array(target) | 1016 tstr = array(target) |
| 947 sstr = array(source) | 1017 sstr = array(source) |
| 948 return "%s(%s, %s)" % (name, tstr, sstr) | 1018 return "%s(%s, %s)" % (name, tstr, sstr) |
| 949 | 1019 |
| 950 def __str__(self): | 1020 def __str__(self): |
| 951 name = self.function_name() | 1021 name = self.function_name() |
| 952 if name == 'ActionCaller': | 1022 if name == 'ActionCaller': |
| 953 return str(self.execfunction) | 1023 return str(self.execfunction) |
| 954 return "%s(target, source, env)" % name | 1024 return "%s(target, source, env)" % name |
| 955 | 1025 |
| 956 def execute(self, target, source, env): | 1026 def execute(self, target, source, env, executor=None): |
| 957 exc_info = (None,None,None) | 1027 exc_info = (None,None,None) |
| 958 try: | 1028 try: |
| 1029 if executor: |
| 1030 target = executor.get_all_targets() |
| 1031 source = executor.get_all_sources() |
| 959 rsources = map(rfile, source) | 1032 rsources = map(rfile, source) |
| 960 try: | 1033 try: |
| 961 result = self.execfunction(target=target, source=rsources, env=e
nv) | 1034 result = self.execfunction(target=target, source=rsources, env=e
nv) |
| 962 except KeyboardInterrupt, e: | 1035 except KeyboardInterrupt, e: |
| 963 raise | 1036 raise |
| 964 except SystemExit, e: | 1037 except SystemExit, e: |
| 965 raise | 1038 raise |
| 966 except Exception, e: | 1039 except Exception, e: |
| 967 result = e | 1040 result = e |
| 968 exc_info = sys.exc_info() | 1041 exc_info = sys.exc_info() |
| 969 | 1042 |
| 970 if result: | 1043 if result: |
| 971 result = SCons.Errors.convert_to_BuildError(result, exc_info) | 1044 result = SCons.Errors.convert_to_BuildError(result, exc_info) |
| 972 result.node=target | 1045 result.node=target |
| 973 result.action=self | 1046 result.action=self |
| 974 result.command=self.strfunction(target, source, env) | 1047 try: |
| 1048 result.command=self.strfunction(target, source, env, executo
r) |
| 1049 except TypeError: |
| 1050 result.command=self.strfunction(target, source, env) |
| 975 | 1051 |
| 976 # FIXME: This maintains backward compatibility with respect to | 1052 # FIXME: This maintains backward compatibility with respect to |
| 977 # which type of exceptions were returned by raising an | 1053 # which type of exceptions were returned by raising an |
| 978 # exception and which ones were returned by value. It would | 1054 # exception and which ones were returned by value. It would |
| 979 # probably be best to always return them by value here, but | 1055 # probably be best to always return them by value here, but |
| 980 # some codes do not check the return value of Actions and I do | 1056 # some codes do not check the return value of Actions and I do |
| 981 # not have the time to modify them at this point. | 1057 # not have the time to modify them at this point. |
| 982 if (exc_info[1] and | 1058 if (exc_info[1] and |
| 983 not isinstance(exc_info[1],EnvironmentError)): | 1059 not isinstance(exc_info[1],EnvironmentError)): |
| 984 raise result | 1060 raise result |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1006 def __init__(self, list): | 1082 def __init__(self, list): |
| 1007 if __debug__: logInstanceCreation(self, 'Action.ListAction') | 1083 if __debug__: logInstanceCreation(self, 'Action.ListAction') |
| 1008 def list_of_actions(x): | 1084 def list_of_actions(x): |
| 1009 if isinstance(x, ActionBase): | 1085 if isinstance(x, ActionBase): |
| 1010 return x | 1086 return x |
| 1011 return Action(x) | 1087 return Action(x) |
| 1012 self.list = map(list_of_actions, list) | 1088 self.list = map(list_of_actions, list) |
| 1013 # our children will have had any varlist | 1089 # our children will have had any varlist |
| 1014 # applied; we don't need to do it again | 1090 # applied; we don't need to do it again |
| 1015 self.varlist = () | 1091 self.varlist = () |
| 1092 self.targets = '$TARGETS' |
| 1016 | 1093 |
| 1017 def genstring(self, target, source, env): | 1094 def genstring(self, target, source, env): |
| 1018 return string.join(map(lambda a, t=target, s=source, e=env: | 1095 return string.join(map(lambda a, t=target, s=source, e=env: |
| 1019 a.genstring(t, s, e), | 1096 a.genstring(t, s, e), |
| 1020 self.list), | 1097 self.list), |
| 1021 '\n') | 1098 '\n') |
| 1022 | 1099 |
| 1023 def __str__(self): | 1100 def __str__(self): |
| 1024 return string.join(map(str, self.list), '\n') | 1101 return string.join(map(str, self.list), '\n') |
| 1025 | 1102 |
| 1026 def presub_lines(self, env): | 1103 def presub_lines(self, env): |
| 1027 return SCons.Util.flatten_sequence( | 1104 return SCons.Util.flatten_sequence( |
| 1028 map(lambda a, env=env: a.presub_lines(env), self.list)) | 1105 map(lambda a, env=env: a.presub_lines(env), self.list)) |
| 1029 | 1106 |
| 1030 def get_presig(self, target, source, env): | 1107 def get_presig(self, target, source, env): |
| 1031 """Return the signature contents of this action list. | 1108 """Return the signature contents of this action list. |
| 1032 | 1109 |
| 1033 Simple concatenation of the signatures of the elements. | 1110 Simple concatenation of the signatures of the elements. |
| 1034 """ | 1111 """ |
| 1035 return string.join(map(lambda x, t=target, s=source, e=env: | 1112 return string.join(map(lambda x, t=target, s=source, e=env: |
| 1036 x.get_contents(t, s, e), | 1113 x.get_contents(t, s, e), |
| 1037 self.list), | 1114 self.list), |
| 1038 "") | 1115 "") |
| 1039 | 1116 |
| 1040 def __call__(self, target, source, env, exitstatfunc=_null, presub=_null, | 1117 def __call__(self, target, source, env, exitstatfunc=_null, presub=_null, |
| 1041 show=_null, execute=_null, chdir=_null): | 1118 show=_null, execute=_null, chdir=_null, executor=None): |
| 1119 if executor: |
| 1120 target = executor.get_all_targets() |
| 1121 source = executor.get_all_sources() |
| 1042 for act in self.list: | 1122 for act in self.list: |
| 1043 stat = act(target, source, env, exitstatfunc, presub, | 1123 stat = act(target, source, env, exitstatfunc, presub, |
| 1044 show, execute, chdir) | 1124 show, execute, chdir, executor) |
| 1045 if stat: | 1125 if stat: |
| 1046 return stat | 1126 return stat |
| 1047 return 0 | 1127 return 0 |
| 1048 | 1128 |
| 1049 def get_implicit_deps(self, target, source, env): | 1129 def get_implicit_deps(self, target, source, env): |
| 1050 result = [] | 1130 result = [] |
| 1051 for act in self.list: | 1131 for act in self.list: |
| 1052 result.extend(act.get_implicit_deps(target, source, env)) | 1132 result.extend(act.get_implicit_deps(target, source, env)) |
| 1053 return result | 1133 return result |
| 1054 | 1134 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1104 return map(lambda x, self=self, t=target, s=source, e=env: | 1184 return map(lambda x, self=self, t=target, s=source, e=env: |
| 1105 self.subst(x, t, s, e), | 1185 self.subst(x, t, s, e), |
| 1106 self.args) | 1186 self.args) |
| 1107 | 1187 |
| 1108 def subst_kw(self, target, source, env): | 1188 def subst_kw(self, target, source, env): |
| 1109 kw = {} | 1189 kw = {} |
| 1110 for key in self.kw.keys(): | 1190 for key in self.kw.keys(): |
| 1111 kw[key] = self.subst(self.kw[key], target, source, env) | 1191 kw[key] = self.subst(self.kw[key], target, source, env) |
| 1112 return kw | 1192 return kw |
| 1113 | 1193 |
| 1114 def __call__(self, target, source, env): | 1194 def __call__(self, target, source, env, executor=None): |
| 1115 args = self.subst_args(target, source, env) | 1195 args = self.subst_args(target, source, env) |
| 1116 kw = self.subst_kw(target, source, env) | 1196 kw = self.subst_kw(target, source, env) |
| 1117 #TODO(1.5) return self.parent.actfunc(*args, **kw) | 1197 #TODO(1.5) return self.parent.actfunc(*args, **kw) |
| 1118 return apply(self.parent.actfunc, args, kw) | 1198 return apply(self.parent.actfunc, args, kw) |
| 1119 | 1199 |
| 1120 def strfunction(self, target, source, env): | 1200 def strfunction(self, target, source, env): |
| 1121 args = self.subst_args(target, source, env) | 1201 args = self.subst_args(target, source, env) |
| 1122 kw = self.subst_kw(target, source, env) | 1202 kw = self.subst_kw(target, source, env) |
| 1123 #TODO(1.5) return self.parent.strfunc(*args, **kw) | 1203 #TODO(1.5) return self.parent.strfunc(*args, **kw) |
| 1124 return apply(self.parent.strfunc, args, kw) | 1204 return apply(self.parent.strfunc, args, kw) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1138 """ | 1218 """ |
| 1139 def __init__(self, actfunc, strfunc, convert=lambda x: x): | 1219 def __init__(self, actfunc, strfunc, convert=lambda x: x): |
| 1140 self.actfunc = actfunc | 1220 self.actfunc = actfunc |
| 1141 self.strfunc = strfunc | 1221 self.strfunc = strfunc |
| 1142 self.convert = convert | 1222 self.convert = convert |
| 1143 | 1223 |
| 1144 def __call__(self, *args, **kw): | 1224 def __call__(self, *args, **kw): |
| 1145 ac = ActionCaller(self, args, kw) | 1225 ac = ActionCaller(self, args, kw) |
| 1146 action = Action(ac, strfunction=ac.strfunction) | 1226 action = Action(ac, strfunction=ac.strfunction) |
| 1147 return action | 1227 return action |
| OLD | NEW |