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