diff options
author | Martin Kelly <mkelly@xevo.com> | 2018-04-24 16:57:18 -0700 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek.chauhan@gmail.com> | 2018-05-30 18:29:16 +0000 |
commit | 0627e9d616dc311b7c9b0ef17301f680ac9e78a7 (patch) | |
tree | d58d446c9fa19d5ad4be7dc8b7fbdbed105a076d | |
parent | ab599b5733539130db5c4d17c664744f4d5aacaf (diff) | |
download | meson-0627e9d616dc311b7c9b0ef17301f680ac9e78a7.zip meson-0627e9d616dc311b7c9b0ef17301f680ac9e78a7.tar.gz meson-0627e9d616dc311b7c9b0ef17301f680ac9e78a7.tar.bz2 |
mesonlib: handle meson exe wrappers
There are cases when it is useful to wrap the main meson executable with
a script that sets up environment variables, passes --cross-file, etc.
For example, in a Yocto SDK, we need to point to the right meson.cross
so that everything "just works", and we need to alter CC, CXX, etc. In
such cases, it can happen that the "meson" found in the path is actually
a wrapper script that invokes the real meson, which may be in another
location (e.g. "meson.real" or similar).
Currently, in such a situation, meson gets confused because it tries to
invoke itself using the "meson" executable (which points to the wrapper
script) instead of the actual meson (which may be called "meson.real" or
similar). In fact, the wrapper script is not necessarily even Python, so
the whole thing fails.
Fix this by using Python imports to directly find mesonmain.py instead
of trying to detect it heuristically. In addition to fixing the wrapper
issue, this should make the detection logic much more robust.
-rwxr-xr-x | meson.py | 9 | ||||
-rw-r--r-- | mesonbuild/mesonlib.py | 48 | ||||
-rw-r--r-- | mesonbuild/mesonmain.py | 8 | ||||
-rwxr-xr-x | run_cross_test.py | 2 | ||||
-rwxr-xr-x | run_project_tests.py | 13 | ||||
-rwxr-xr-x | run_tests.py | 22 | ||||
-rwxr-xr-x | run_unittests.py | 3 |
7 files changed, 41 insertions, 64 deletions
@@ -15,12 +15,7 @@ # limitations under the License. from mesonbuild import mesonmain -import sys, os - -def main(): - # Always resolve the command path so Ninja can find it for regen, tests, etc. - launcher = os.path.realpath(sys.argv[0]) - return mesonmain.run(sys.argv[1:], launcher) +import sys if __name__ == '__main__': - sys.exit(main()) + sys.exit(mesonmain.main()) diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index fe426c5..28ae7b5 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -38,58 +38,12 @@ except Exception: from glob import glob -def detect_meson_py_location(): - c = sys.argv[0] - c_dir, c_fname = os.path.split(c) - - # get the absolute path to the <mesontool> folder - m_dir = None - if os.path.isabs(c): - # $ /foo/<mesontool>.py <args> - m_dir = c_dir - elif c_dir == '': - # $ <mesontool> <args> (gets run from /usr/bin/<mesontool>) - in_path_exe = shutil.which(c_fname) - if in_path_exe: - if not os.path.isabs(in_path_exe): - m_dir = os.getcwd() - c_fname = in_path_exe - else: - m_dir, c_fname = os.path.split(in_path_exe) - else: - m_dir = os.path.abspath(c_dir) - - # find meson in m_dir - if m_dir is not None: - for fname in ['meson', 'meson.py']: - m_path = os.path.join(m_dir, fname) - if os.path.exists(m_path): - return m_path - - # No meson found, which means that either: - # a) meson is not installed - # b) meson is installed to a non-standard location - # c) the script that invoked mesonlib is not the one of meson tools (e.g. run_unittests.py) - fname = os.path.normpath(os.path.join(os.path.dirname(__file__), '..', 'meson.py')) - if os.path.exists(fname): - return fname - # If meson is still not found, we might be imported by out-of-source tests - # https://github.com/mesonbuild/meson/issues/3015 - exe = shutil.which('meson') - if exe is None: - exe = shutil.which('meson.py') - if exe is not None: - return exe - # Give up. - raise RuntimeError('Could not determine how to run Meson. Please file a bug with details.') - if os.path.basename(sys.executable) == 'meson.exe': # In Windows and using the MSI installed executable. - meson_command = [sys.executable] python_command = [sys.executable, 'runpython'] else: python_command = [sys.executable] - meson_command = python_command + [detect_meson_py_location()] +meson_command = python_command + ['-m', 'mesonbuild.mesonmain'] def is_ascii_string(astring): try: diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index 4a977a1..d77d148 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -382,3 +382,11 @@ def run(original_args, mainfile=None): mlog.shutdown() return 0 + +def main(): + # Always resolve the command path so Ninja can find it for regen, tests, etc. + launcher = os.path.realpath(sys.argv[0]) + return run(sys.argv[1:], launcher) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/run_cross_test.py b/run_cross_test.py index 7191402..22e1972 100755 --- a/run_cross_test.py +++ b/run_cross_test.py @@ -28,6 +28,7 @@ from pathlib import Path from run_project_tests import gather_tests, run_tests, StopException, setup_commands from run_project_tests import failing_logs +from run_tests import setup_pythonpath def runtests(cross_file): commontests = [('common', gather_tests(Path('test cases', 'common')), False)] @@ -46,5 +47,6 @@ def runtests(cross_file): if __name__ == '__main__': setup_commands('ninja') + setup_pythonpath() cross_file = sys.argv[1] runtests(cross_file) diff --git a/run_project_tests.py b/run_project_tests.py index 3801432..644c6c3 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -41,7 +41,7 @@ import re from run_unittests import get_fake_options, run_configure from run_tests import get_backend_commands, get_backend_args_for_dir, Backend -from run_tests import ensure_backend_detects_changes +from run_tests import ensure_backend_detects_changes, setup_pythonpath class BuildStep(Enum): @@ -88,12 +88,6 @@ no_meson_log_msg = 'No meson-log.txt found.' system_compiler = None -meson_command = os.path.join(os.getcwd(), 'meson') -if not os.path.exists(meson_command): - meson_command += '.py' - if not os.path.exists(meson_command): - raise RuntimeError('Could not find main Meson script to run.') - class StopException(Exception): def __init__(self): super().__init__('Stopped by user') @@ -324,7 +318,7 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen if pass_libdir_to_test(testdir): gen_args += ['--libdir', 'lib'] gen_args += [testdir, test_build_dir] + flags + test_args + extra_args - (returncode, stdo, stde) = run_configure(meson_command, gen_args) + (returncode, stdo, stde) = run_configure(mesonlib.meson_command, gen_args) try: logfile = Path(test_build_dir, 'meson-logs', 'meson-log.txt') mesonlog = logfile.open(errors='ignore', encoding='utf-8').read() @@ -647,7 +641,7 @@ def check_format(): check_file(fullname) def check_meson_commands_work(): - global backend, meson_command, compile_commands, test_commands, install_commands + global backend, compile_commands, test_commands, install_commands testdir = PurePath('test cases', 'common', '1 trivial').as_posix() with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: print('Checking that configuring works...') @@ -692,6 +686,7 @@ if __name__ == '__main__': setup_commands(options.backend) detect_system_compiler() + setup_pythonpath() script_dir = os.path.split(__file__)[0] if script_dir != '': os.chdir(script_dir) diff --git a/run_tests.py b/run_tests.py index 648e6ce..731d864 100755 --- a/run_tests.py +++ b/run_tests.py @@ -42,6 +42,28 @@ if mesonlib.is_windows() or mesonlib.is_cygwin(): else: exe_suffix = '' +def setup_pythonpath(): + # Make sure python can import mesonbuild, even if we change directories as + # some tests do. Since sys.path is the final product of fairly complex code + # in site.py, it's hard to tell where each entry came from just by looking + # at sys.path, so we don't know if a given entry was set from a relative or + # absolute path. If an entry was set from a relative path, it won't + # continue to work if we change directories. Instead of trying to guess + # where a given entry came from, just add the known-good mesonbuild to + # PYTHONPATH so that it will continue to be importable from other + # directories. + import mesonbuild + meson_dir = os.path.dirname(os.path.abspath(mesonbuild.__file__)) + meson_root = os.path.realpath(os.path.join(meson_dir, os.pardir)) + try: + python_path = os.environ['PYTHONPATH'] + except KeyError: + python_path = meson_root + else: + paths = python_path.split(os.pathsep) + [meson_root] + python_path = os.pathsep.join(paths) + os.environ['PYTHONPATH'] = python_path + def get_backend_args_for_dir(backend, builddir): ''' Visual Studio backend needs to be given the solution to build diff --git a/run_unittests.py b/run_unittests.py index 552769b..2d4bd27 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -47,7 +47,7 @@ import mesonbuild.modules.pkgconfig from run_tests import exe_suffix, get_fake_options from run_tests import get_builddir_target_args, get_backend_commands, Backend from run_tests import ensure_backend_detects_changes, run_configure, meson_exe -from run_tests import should_run_linux_cross_tests +from run_tests import should_run_linux_cross_tests, setup_pythonpath def get_dynamic_section_entry(fname, entry): @@ -3313,6 +3313,7 @@ def unset_envs(): if __name__ == '__main__': unset_envs() + setup_pythonpath() cases = ['InternalTests', 'AllPlatformTests', 'FailureTests', 'PythonTests'] if not is_windows(): cases += ['LinuxlikeTests'] |