[OE-core] [PATCH 6/7] meson: handle exe wrappers

Martin Kelly mkelly at xevo.com
Wed May 30 23:14:06 UTC 2018


Add patches to enable meson to handle being wrapped with a shell script.  This
will enable us to do so for supporting the SDK, which requires us to setup env
vars and point to a meson.cross file inside the SDK.

These patches are all merged upstream, so we can drop them soon.

Signed-off-by: Martin Kelly <mkelly at xevo.com>
---
 ...ke-ExternalProgram-get_path-a-bit-smarter.patch |  58 ++++++
 ...mandrunner-make-run-handle-python-options.patch |  53 +++++
 .../0006-mesonlib-handle-meson-exe-wrappers.patch  | 231 +++++++++++++++++++++
 meta/recipes-devtools/meson/meson_0.46.1.bb        |   3 +
 4 files changed, 345 insertions(+)
 create mode 100644 meta/recipes-devtools/meson/meson/0004-make-ExternalProgram-get_path-a-bit-smarter.patch
 create mode 100644 meta/recipes-devtools/meson/meson/0005-commandrunner-make-run-handle-python-options.patch
 create mode 100644 meta/recipes-devtools/meson/meson/0006-mesonlib-handle-meson-exe-wrappers.patch

diff --git a/meta/recipes-devtools/meson/meson/0004-make-ExternalProgram-get_path-a-bit-smarter.patch b/meta/recipes-devtools/meson/meson/0004-make-ExternalProgram-get_path-a-bit-smarter.patch
new file mode 100644
index 0000000000..fdab7e67dc
--- /dev/null
+++ b/meta/recipes-devtools/meson/meson/0004-make-ExternalProgram-get_path-a-bit-smarter.patch
@@ -0,0 +1,58 @@
+From 2c0273abecbdcef8411a6e513c7435ca4e7bd620 Mon Sep 17 00:00:00 2001
+From: Martin Kelly <mkelly at xevo.com>
+Date: Tue, 24 Apr 2018 16:53:18 -0700
+Subject: [PATCH] make ExternalProgram get_path() a bit smarter
+
+Currently, ExternalProgram get_path() assumes the last component in the
+path is always the actual command path. However, this is not always
+right. For example, in the command "python -u", we should return
+"python" and not "-u". However, in other cases, like "python script.py",
+then the last component is the right one.
+
+The heuristic that seems to capture this is to use the last argument
+that is still a file. This means options get ignored, but "python
+script.py" still works. Let's use this heuristic, at least for now.
+
+Upstream-Status: Accepted [https://github.com/mesonbuild/meson/pull/3393]
+Should be in the 0.47.0 release.
+
+Signed-off-by: Martin Kelly <mkelly at xevo.com>
+---
+ mesonbuild/dependencies/base.py | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
+index f4f19c57..18f04892 100644
+--- a/mesonbuild/dependencies/base.py
++++ b/mesonbuild/dependencies/base.py
+@@ -745,6 +745,17 @@ class ExternalProgram:
+             self.command = listify(command)
+         else:
+             self.command = self._search(name, search_dir)
++
++        # Set path to be the last item that is actually a file (in order to
++        # skip options in something like ['python', '-u', 'file.py']. If we
++        # can't find any components, default to the last component of the path.
++        self.path = self.command[-1]
++        for i in range(len(self.command) - 1, -1, -1):
++            arg = self.command[i]
++            if arg is not None and os.path.isfile(arg):
++                self.path = arg
++                break
++
+         if not silent:
+             if self.found():
+                 mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'),
+@@ -892,11 +903,7 @@ class ExternalProgram:
+         return self.command[:]
+ 
+     def get_path(self):
+-        if self.found():
+-            # Assume that the last element is the full path to the script or
+-            # binary being run
+-            return self.command[-1]
+-        return None
++        return self.path
+ 
+     def get_name(self):
+         return self.name
diff --git a/meta/recipes-devtools/meson/meson/0005-commandrunner-make-run-handle-python-options.patch b/meta/recipes-devtools/meson/meson/0005-commandrunner-make-run-handle-python-options.patch
new file mode 100644
index 0000000000..876ace22f8
--- /dev/null
+++ b/meta/recipes-devtools/meson/meson/0005-commandrunner-make-run-handle-python-options.patch
@@ -0,0 +1,53 @@
+From 0f54849523c812bca57d2182af92afe58c44f850 Mon Sep 17 00:00:00 2001
+From: Martin Kelly <mkelly at xevo.com>
+Date: Tue, 24 Apr 2018 16:55:12 -0700
+Subject: [PATCH] commandrunner: make run handle python options
+
+Currently, commandrunner breaks when we give options to python because
+it assumes python commands are in the form "python script.py", rather
+than "python -u script.py" or "python -u -m module script.py". Extend it
+to be more resilient and correctly parse python options.
+
+Upstream-Status: Accepted [https://github.com/mesonbuild/meson/pull/3393]
+Should be in the 0.47.0 release.
+
+Signed-off-by: Martin Kelly <mkelly at xevo.com>
+---
+ mesonbuild/scripts/commandrunner.py | 24 +++++++++++++++++++++---
+ 1 file changed, 21 insertions(+), 3 deletions(-)
+
+diff --git a/mesonbuild/scripts/commandrunner.py b/mesonbuild/scripts/commandrunner.py
+index fc65e5b6..5922c64e 100644
+--- a/mesonbuild/scripts/commandrunner.py
++++ b/mesonbuild/scripts/commandrunner.py
+@@ -59,9 +59,27 @@ def run(args):
+     subdir = args[2]
+     meson_command = args[3]
+     if 'python' in meson_command: # Hack.
+-        meson_command = [meson_command, args[4]]
+-        command = args[5]
+-        arguments = args[6:]
++        # Handle any of these:
++        # python meson.py ...
++        # python -m mesonbuild.mesonmain ...
++        # python ARGS -m mesonbuild.mesonmain ...
++        # python -m mesonbuild.mesonmain ARGS ...
++        i = 4
++        while i < len(args):
++            arg = args[i]
++            # Skip past optional arguments.
++            if arg[0] == '-':
++                if arg == '-m':
++                    # Skip past -m PYTHONFILE.
++                    i += 2
++                else:
++                    i += 1
++            else:
++                break
++        end = i
++        meson_command = args[3:end]
++        command = args[end]
++        arguments = args[end + 1:]
+     else:
+         meson_command = [meson_command]
+         command = args[4]
diff --git a/meta/recipes-devtools/meson/meson/0006-mesonlib-handle-meson-exe-wrappers.patch b/meta/recipes-devtools/meson/meson/0006-mesonlib-handle-meson-exe-wrappers.patch
new file mode 100644
index 0000000000..19901d3a97
--- /dev/null
+++ b/meta/recipes-devtools/meson/meson/0006-mesonlib-handle-meson-exe-wrappers.patch
@@ -0,0 +1,231 @@
+From 3d86e7b48407bd85d96305ebc8aa48cb1131cad2 Mon Sep 17 00:00:00 2001
+From: Martin Kelly <mkelly at xevo.com>
+Date: Tue, 24 Apr 2018 16:57:18 -0700
+Subject: [PATCH] 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.
+
+Upstream-Status: Accepted [https://github.com/mesonbuild/meson/pull/3393]
+Should be in the 0.47.0 release.
+
+Signed-off-by: Martin Kelly <mkelly at xevo.com>
+---
+ meson.py                |  9 ++-------
+ mesonbuild/mesonlib.py  | 48 +-----------------------------------------------
+ mesonbuild/mesonmain.py |  8 ++++++++
+ run_cross_test.py       |  2 ++
+ run_project_tests.py    |  4 ++--
+ run_tests.py            | 22 ++++++++++++++++++++++
+ run_unittests.py        |  3 ++-
+ 7 files changed, 39 insertions(+), 57 deletions(-)
+
+diff --git a/meson.py b/meson.py
+index abbac6f4..8f944c7c 100755
+--- a/meson.py
++++ b/meson.py
+@@ -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 2a3b920b..0b9279c7 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 2b6281d7..39d64d2f 100644
+--- a/mesonbuild/mesonmain.py
++++ b/mesonbuild/mesonmain.py
+@@ -381,3 +381,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 e285e218..99230d1c 100755
+--- a/run_cross_test.py
++++ b/run_cross_test.py
+@@ -26,6 +26,7 @@ import sys, os
+ 
+ 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('test cases/common'), False)]
+@@ -44,5 +45,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 8c02a9ee..0bf55cc0 100755
+--- a/run_project_tests.py
++++ b/run_project_tests.py
+@@ -33,7 +33,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):
+@@ -316,7 +316,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 = os.path.join(test_build_dir, 'meson-logs/meson-log.txt')
+         with open(logfile, encoding='utf-8', errors='ignore') as f:
+diff --git a/run_tests.py b/run_tests.py
+index 648e6ce1..731d864f 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 6d4e0339..f5766613 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):
+@@ -3180,6 +3180,7 @@ def unset_envs():
+ 
+ if __name__ == '__main__':
+     unset_envs()
++    setup_pythonpath()
+     cases = ['InternalTests', 'AllPlatformTests', 'FailureTests', 'PythonTests']
+     if not is_windows():
+         cases += ['LinuxlikeTests']
diff --git a/meta/recipes-devtools/meson/meson_0.46.1.bb b/meta/recipes-devtools/meson/meson_0.46.1.bb
index a18cab81f4..a1c9035e85 100644
--- a/meta/recipes-devtools/meson/meson_0.46.1.bb
+++ b/meta/recipes-devtools/meson/meson_0.46.1.bb
@@ -9,6 +9,9 @@ SRC_URI = "https://github.com/mesonbuild/meson/releases/download/${PV}/${BP}.tar
            file://0002-gobject-introspection-determine-g-ir-scanner-and-g-i.patch \
            file://0001-Linker-rules-move-cross_args-in-front-of-output_args.patch \
            file://0003-native_bindir.patch \
+           file://0004-make-ExternalProgram-get_path-a-bit-smarter.patch \
+           file://0005-commandrunner-make-run-handle-python-options.patch \
+           file://0006-mesonlib-handle-meson-exe-wrappers.patch \
            "
 SRC_URI[md5sum] = "1698f6526574839de5dcdc45e3f7d582"
 SRC_URI[sha256sum] = "19497a03e7e5b303d8d11f98789a79aba59b5ad4a81bd00f4d099be0212cee78"
-- 
2.11.0




More information about the Openembedded-core mailing list