Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | import os |
| 4 | import re |
| 5 | import tempfile |
| 6 | import shutil |
| 7 | import sys |
| 8 | import subprocess |
| 9 | import zipfile |
| 10 | |
| 11 | PYTHON_BINARY = '%interpreter%' |
| 12 | MAIN_FILE = '%main%' |
| 13 | PYTHON_PATH = 'PYTHONPATH' |
Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 14 | |
yangbill | 7265e5f | 2019-01-04 18:10:32 +0800 | [diff] [blame] | 15 | # Don't imply 'import site' on initialization |
| 16 | PYTHON_ARG = '-S' |
| 17 | |
Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 18 | def SearchPathEnv(name): |
| 19 | search_path = os.getenv('PATH', os.defpath).split(os.pathsep) |
| 20 | for directory in search_path: |
| 21 | if directory == '': continue |
| 22 | path = os.path.join(directory, name) |
Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 23 | # Check if path is actual executable file. |
| 24 | if os.path.isfile(path) and os.access(path, os.X_OK): |
| 25 | return path |
| 26 | return None |
| 27 | |
| 28 | def FindPythonBinary(): |
| 29 | if PYTHON_BINARY.startswith('/'): |
| 30 | # Case 1: Python interpreter is directly provided with absolute path. |
| 31 | return PYTHON_BINARY |
| 32 | else: |
| 33 | # Case 2: Find Python interpreter through environment variable: PATH. |
| 34 | return SearchPathEnv(PYTHON_BINARY) |
| 35 | |
| 36 | # Create the runfiles tree by extracting the zip file |
| 37 | def ExtractRunfiles(): |
| 38 | temp_dir = tempfile.mkdtemp("", "Soong.python_") |
| 39 | zf = zipfile.ZipFile(os.path.dirname(__file__)) |
| 40 | zf.extractall(temp_dir) |
Nan Zhang | bea0975 | 2018-05-31 12:49:33 -0700 | [diff] [blame] | 41 | return temp_dir |
Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 42 | |
| 43 | def Main(): |
| 44 | args = sys.argv[1:] |
| 45 | |
| 46 | new_env = {} |
Nicolas Geoffray | 6e1bf2b | 2018-10-11 15:18:42 +0100 | [diff] [blame] | 47 | runfiles_path = None |
Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 48 | |
| 49 | try: |
| 50 | runfiles_path = ExtractRunfiles() |
| 51 | |
| 52 | # Add runfiles path to PYTHONPATH. |
| 53 | python_path_entries = [runfiles_path] |
| 54 | |
| 55 | # Add top dirs within runfiles path to PYTHONPATH. |
| 56 | top_entries = [os.path.join(runfiles_path, i) for i in os.listdir(runfiles_path)] |
| 57 | top_pkg_dirs = [i for i in top_entries if os.path.isdir(i)] |
| 58 | python_path_entries += top_pkg_dirs |
| 59 | |
| 60 | old_python_path = os.environ.get(PYTHON_PATH) |
| 61 | separator = ':' |
| 62 | new_python_path = separator.join(python_path_entries) |
| 63 | |
| 64 | # Copy old PYTHONPATH. |
| 65 | if old_python_path: |
| 66 | new_python_path += separator + old_python_path |
| 67 | new_env[PYTHON_PATH] = new_python_path |
| 68 | |
| 69 | # Now look for main python source file. |
| 70 | main_filepath = os.path.join(runfiles_path, MAIN_FILE) |
| 71 | assert os.path.exists(main_filepath), \ |
| 72 | 'Cannot exec() %r: file not found.' % main_filepath |
| 73 | assert os.access(main_filepath, os.R_OK), \ |
| 74 | 'Cannot exec() %r: file not readable.' % main_filepath |
| 75 | |
| 76 | python_program = FindPythonBinary() |
| 77 | if python_program is None: |
| 78 | raise AssertionError('Could not find python binary: ' + PYTHON_BINARY) |
yangbill | 7265e5f | 2019-01-04 18:10:32 +0800 | [diff] [blame] | 79 | args = [python_program, PYTHON_ARG, main_filepath] + args |
Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 80 | |
| 81 | os.environ.update(new_env) |
| 82 | |
| 83 | sys.stdout.flush() |
| 84 | retCode = subprocess.call(args) |
| 85 | exit(retCode) |
| 86 | except: |
| 87 | raise |
| 88 | finally: |
Nicolas Geoffray | 6e1bf2b | 2018-10-11 15:18:42 +0100 | [diff] [blame] | 89 | if runfiles_path is not None: |
| 90 | shutil.rmtree(runfiles_path, True) |
Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 91 | |
| 92 | if __name__ == '__main__': |
| 93 | Main() |