diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-29 04:41:38 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-29 04:41:38 +0000 |
commit | 7b6e527f440cd7e6f8be2b07cee320ee6ca18786 (patch) | |
tree | 4a2738d69fa2814659fdadddf5826282e73d81f4 /mesonbuild/scripts/meson_exe.py | |
parent | Initial commit. (diff) | |
download | meson-7b6e527f440cd7e6f8be2b07cee320ee6ca18786.tar.xz meson-7b6e527f440cd7e6f8be2b07cee320ee6ca18786.zip |
Adding upstream version 1.0.1.upstream/1.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mesonbuild/scripts/meson_exe.py')
-rw-r--r-- | mesonbuild/scripts/meson_exe.py | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/mesonbuild/scripts/meson_exe.py b/mesonbuild/scripts/meson_exe.py new file mode 100644 index 0000000..33408d8 --- /dev/null +++ b/mesonbuild/scripts/meson_exe.py @@ -0,0 +1,124 @@ +# Copyright 2013-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import sys +import argparse +import pickle +import subprocess +import typing as T +import locale + +from ..utils.core import ExecutableSerialisation + +def buildparser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description='Custom executable wrapper for Meson. Do not run on your own, mmm\'kay?') + parser.add_argument('--unpickle') + parser.add_argument('--capture') + parser.add_argument('--feed') + return parser + +def run_exe(exe: ExecutableSerialisation, extra_env: T.Optional[T.Dict[str, str]] = None) -> int: + if exe.exe_wrapper: + if not exe.exe_wrapper.found(): + raise AssertionError('BUG: Can\'t run cross-compiled exe {!r} with not-found ' + 'wrapper {!r}'.format(exe.cmd_args[0], exe.exe_wrapper.get_path())) + cmd_args = exe.exe_wrapper.get_command() + exe.cmd_args + else: + cmd_args = exe.cmd_args + child_env = os.environ.copy() + if extra_env: + child_env.update(extra_env) + if exe.env: + child_env = exe.env.get_env(child_env) + if exe.extra_paths: + child_env['PATH'] = (os.pathsep.join(exe.extra_paths + ['']) + + child_env['PATH']) + if exe.exe_wrapper and any('wine' in i for i in exe.exe_wrapper.get_command()): + from .. import mesonlib + child_env['WINEPATH'] = mesonlib.get_wine_shortpath( + exe.exe_wrapper.get_command(), + ['Z:' + p for p in exe.extra_paths] + child_env.get('WINEPATH', '').split(';'), + exe.workdir + ) + + stdin = None + if exe.feed: + stdin = open(exe.feed, 'rb') + + pipe = subprocess.PIPE + if exe.verbose: + assert not exe.capture, 'Cannot capture and print to console at the same time' + pipe = None + + p = subprocess.Popen(cmd_args, env=child_env, cwd=exe.workdir, + close_fds=False, stdin=stdin, stdout=pipe, stderr=pipe) + stdout, stderr = p.communicate() + + if stdin is not None: + stdin.close() + + if p.returncode == 0xc0000135: + # STATUS_DLL_NOT_FOUND on Windows indicating a common problem that is otherwise hard to diagnose + raise FileNotFoundError('due to missing DLLs') + + if p.returncode != 0: + if exe.pickled: + print(f'while executing {cmd_args!r}') + if exe.verbose: + return p.returncode + encoding = locale.getpreferredencoding() + if not exe.capture: + print('--- stdout ---') + print(stdout.decode(encoding=encoding, errors='replace')) + print('--- stderr ---') + print(stderr.decode(encoding=encoding, errors='replace')) + return p.returncode + + if exe.capture: + skip_write = False + try: + with open(exe.capture, 'rb') as cur: + skip_write = cur.read() == stdout + except OSError: + pass + if not skip_write: + with open(exe.capture, 'wb') as output: + output.write(stdout) + + return 0 + +def run(args: T.List[str]) -> int: + parser = buildparser() + options, cmd_args = parser.parse_known_args(args) + # argparse supports double dash to separate options and positional arguments, + # but the user has to remove it manually. + if cmd_args and cmd_args[0] == '--': + cmd_args = cmd_args[1:] + if not options.unpickle and not cmd_args: + parser.error('either --unpickle or executable and arguments are required') + if options.unpickle: + if cmd_args or options.capture or options.feed: + parser.error('no other arguments can be used with --unpickle') + with open(options.unpickle, 'rb') as f: + exe = pickle.load(f) + exe.pickled = True + else: + exe = ExecutableSerialisation(cmd_args, capture=options.capture, feed=options.feed) + + return run_exe(exe) + +if __name__ == '__main__': + sys.exit(run(sys.argv[1:])) |