|
5 | 5 | from __future__ import print_function
|
6 | 6 |
|
7 | 7 | import ast
|
8 |
| -from collections import OrderedDict |
9 | 8 | import os.path
|
10 | 9 | import re
|
11 | 10 | import shlex
|
12 |
| -import signal |
13 | 11 | import subprocess
|
14 | 12 | import sys
|
15 | 13 | import traceback
|
| 14 | +from collections import OrderedDict |
| 15 | + |
16 | 16 | import gyp.common
|
17 | 17 | import gyp.lib.simple_copy
|
18 | 18 | from gyp.common import GypError, OrderedSet
|
19 | 19 |
|
20 | 20 | if not 'unicode' in __builtins__:
|
21 | 21 | unicode = str
|
| 22 | + basestring = str |
22 | 23 |
|
23 | 24 | # A list of types that are treated as linkable.
|
24 | 25 | linkable_types = [
|
@@ -434,96 +435,6 @@ def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, de
|
434 | 435 | return (build_file_path, dependencies)
|
435 | 436 |
|
436 | 437 |
|
437 |
| -def CallLoadTargetBuildFile(global_flags, build_file_path, variables, includes, depth, generator_input_info): |
438 |
| - """Wrapper around LoadTargetBuildFile for parallel processing. |
439 |
| -
|
440 |
| - This wrapper is used when LoadTargetBuildFile is executed in |
441 |
| - a worker process. |
442 |
| - """ |
443 |
| - |
444 |
| - try: |
445 |
| - signal.signal(signal.SIGINT, signal.SIG_IGN) |
446 |
| - |
447 |
| - # Apply globals so that the worker process behaves the same. |
448 |
| - for key, value in global_flags.items(): |
449 |
| - globals()[key] = value |
450 |
| - |
451 |
| - SetGeneratorGlobals(generator_input_info) |
452 |
| - result = LoadTargetBuildFile(build_file_path, per_process_data, per_process_aux_data, variables, includes, depth, False) |
453 |
| - if not result: |
454 |
| - return result |
455 |
| - |
456 |
| - (build_file_path, dependencies) = result |
457 |
| - |
458 |
| - # We can safely pop the build_file_data from per_process_data because it |
459 |
| - # will never be referenced by this process again, so we don't need to keep |
460 |
| - # it in the cache. |
461 |
| - build_file_data = per_process_data.pop(build_file_path) |
462 |
| - |
463 |
| - # This gets serialized and sent back to the main process via a pipe. |
464 |
| - # It's handled in LoadTargetBuildFileCallback. |
465 |
| - return (build_file_path, build_file_data, dependencies) |
466 |
| - except GypError as e: |
467 |
| - sys.stderr.write("gyp: %s\n" % e) |
468 |
| - return None |
469 |
| - except Exception as e: |
470 |
| - print('Exception:', e, file=sys.stderr) |
471 |
| - print(traceback.format_exc(), file=sys.stderr) |
472 |
| - return None |
473 |
| - |
474 |
| - |
475 |
| -class ParallelProcessingError(Exception): |
476 |
| - pass |
477 |
| - |
478 |
| - |
479 |
| -class ParallelState(object): |
480 |
| - """Class to keep track of state when processing input files in parallel. |
481 |
| -
|
482 |
| - If build files are loaded in parallel, use this to keep track of |
483 |
| - state during farming out and processing parallel jobs. It's stored |
484 |
| - in a global so that the callback function can have access to it. |
485 |
| - """ |
486 |
| - |
487 |
| - def __init__(self): |
488 |
| - # The multiprocessing pool. |
489 |
| - self.pool = None |
490 |
| - # The condition variable used to protect this object and notify |
491 |
| - # the main loop when there might be more data to process. |
492 |
| - self.condition = None |
493 |
| - # The "data" dict that was passed to LoadTargetBuildFileParallel |
494 |
| - self.data = None |
495 |
| - # The number of parallel calls outstanding; decremented when a response |
496 |
| - # was received. |
497 |
| - self.pending = 0 |
498 |
| - # The set of all build files that have been scheduled, so we don't |
499 |
| - # schedule the same one twice. |
500 |
| - self.scheduled = set() |
501 |
| - # A list of dependency build file paths that haven't been scheduled yet. |
502 |
| - self.dependencies = [] |
503 |
| - # Flag to indicate if there was an error in a child process. |
504 |
| - self.error = False |
505 |
| - |
506 |
| - def LoadTargetBuildFileCallback(self, result): |
507 |
| - """Handle the results of running LoadTargetBuildFile in another process. |
508 |
| - """ |
509 |
| - self.condition.acquire() |
510 |
| - if not result: |
511 |
| - self.error = True |
512 |
| - self.condition.notify() |
513 |
| - self.condition.release() |
514 |
| - return |
515 |
| - (build_file_path0, build_file_data0, dependencies0) = result |
516 |
| - self.data[build_file_path0] = build_file_data0 |
517 |
| - self.data['target_build_files'].add(build_file_path0) |
518 |
| - for new_dependency in dependencies0: |
519 |
| - if new_dependency not in self.scheduled: |
520 |
| - self.scheduled.add(new_dependency) |
521 |
| - self.dependencies.append(new_dependency) |
522 |
| - self.pending -= 1 |
523 |
| - self.condition.notify() |
524 |
| - self.condition.release() |
525 |
| - |
526 |
| - |
527 | 438 | # Look for the bracket that matches the first bracket seen in a
|
528 | 439 | # string, and return the start and end as a tuple. For example, if
|
529 | 440 | # the input is something like "<(foo <(bar)) blah", then it would
|
@@ -773,30 +684,25 @@ def ExpandVariables(input, phase, variables, build_file):
|
773 | 684 | gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Executing command '%s' in directory '%s'", contents, build_file_dir)
|
774 | 685 |
|
775 | 686 | if command_string == 'pymod_do_main':
|
776 |
| - # <!pymod_do_main(modulename param eters) loads |modulename| as a |
777 |
| - # python module and then calls that module's DoMain() function, |
778 |
| - # passing ["param", "eters"] as a single list argument. For modules |
779 |
| - # that don't load quickly, this can be faster than |
780 |
| - # <!(python modulename param eters). Do this in |build_file_dir|. |
781 |
| - oldwd = os.getcwd() # Python doesn't like os.open('.'): no fchdir. |
782 |
| - if build_file_dir is not None: # build_file_dir may be None (see above). |
783 |
| - # noinspection PyTypeChecker |
784 |
| - os.chdir(build_file_dir) |
| 687 | + # <!pymod_do_main(modulename foo bar) loads |modulename| as a python module and then calls that module's DoMain() function, passing ["foo", "bar"] as a single list argument. |
| 688 | + # For modules that don't load quickly, this can be faster than <!(python modulename foo bar). Do this in |build_file_dir|. |
| 689 | + old_cwd = os.getcwd() |
| 690 | + # Wrap the following with `try` for unwinding state in `finally` |
785 | 691 | try:
|
786 |
| - parsed_contents = shlex.split(contents) |
| 692 | + # changing process state, to be unwind in the `finally` |
| 693 | + build_file_dir and os.chdir(build_file_dir) |
| 694 | + sys.path.append(os.getcwd()) |
| 695 | + parts = shlex.split(contents) |
| 696 | + modulename, params = parts[0], parts[1:] |
787 | 697 | try:
|
788 |
| - py_module = __import__(parsed_contents[0]) |
| 698 | + py_module = __import__(modulename) |
789 | 699 | except ImportError as e:
|
790 |
| - raise GypError("Error importing pymod_do_main module (%s): %s" % (parsed_contents[0], e)) |
791 |
| - replacement = str(py_module.DoMain(parsed_contents[1:])).rstrip() |
792 |
| - except Exception as e: |
793 |
| - err_info = traceback.format_exc() |
794 |
| - print(e, file=sys.stderr) |
795 |
| - print(err_info, file=sys.stderr) |
796 |
| - |
797 |
| - |
| 700 | + raise GypError("Error importing pymod_do_main module (%s): %s" % (modulename, e)) |
| 701 | + mod_ret = py_module.DoMain(params) |
| 702 | + replacement = str(mod_ret).rstrip() |
798 | 703 | finally:
|
799 |
| - os.chdir(oldwd) |
| 704 | + sys.path.pop() |
| 705 | + os.chdir(old_cwd) |
800 | 706 | assert replacement is not None
|
801 | 707 | elif command_string:
|
802 | 708 | raise GypError("Unknown command string '%s' in '%s'." % (command_string, contents))
|
@@ -888,14 +794,11 @@ def ExpandVariables(input, phase, variables, build_file):
|
888 | 794 | if output == input:
|
889 | 795 | gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Found only identity matches on %r, avoiding infinite recursion.", output)
|
890 | 796 | else:
|
891 |
| - # Look for more matches now that we've replaced some, to deal with |
892 |
| - # expanding local variables (variables defined in the same |
893 |
| - # variables block as this one). |
| 797 | + # Look for more matches now that we've replaced some, to deal with expanding local variables (variables defined in the same variables block as this one). |
894 | 798 | gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Found output %r, recursing.", output)
|
895 | 799 | if type(output) is list:
|
896 | 800 | if output and type(output[0]) is list:
|
897 |
| - # Leave output alone if it's a list of lists. |
898 |
| - # We don't want such lists to be stringified. |
| 801 | + # Leave output alone if it's a list of lists. We don't want such lists to be stringified. |
899 | 802 | pass
|
900 | 803 | else:
|
901 | 804 | new_output = []
|
|
0 commit comments