[jhbuild/wip/lantw/core-deps-latest-update-meson-to-0.52.0-and-fix-library-path-issues] core-deps-latest: Update meson to 0.52.0 and fix library path issues



commit 72d9c356ff3a16622ef48749225d6d5a280e73eb
Author: Ting-Wei Lan <lantw src gnome org>
Date:   Wed Oct 9 00:15:46 2019 +0800

    core-deps-latest: Update meson to 0.52.0 and fix library path issues
    
    Meson 0.47 changes the way to handle external dependencies on shared
    libraries significantly. Instead of just putting arguments provided by
    pkg-config on the linker command line, meson tries to convert -L and -l
    arguments into absolute paths to .so files by itself. This should make
    library handling more reliable because an absolute path is less likely
    to go wrong than an ordered list of search paths. However, due to the
    big change, a few regressions is still introduced, causing modules to
    fail to build in a JHBuild environment from time to time.
    
    Ideally regressions should be fixed in a few weeks and made available in
    subsequent releases. Unfortunately, I can't get my patches merged
    upstream in one year, and I have to remember to patch meson manually
    every time JHBuild updates meson. This is annoying because there are
    always modules failing to build because of these known bugs if I forget
    to patch it. Therefore, I think it is time to submit these patches to
    JHBuild, so it can be applied automatically.
    
    These patches have been added to FreeBSD ports since Meson 0.48. The CI
    runner currently used to test GLib on FreeBSD also uses it. Given that
    they has been used for one year without issues, it should be safe to
    use them to JHBuild as well.
    
    https://github.com/mesonbuild/meson/issues/4270
    https://github.com/mesonbuild/meson/pull/4324
    
    https://github.com/mesonbuild/meson/issues/4271
    https://github.com/mesonbuild/meson/pull/4325

 modulesets/gnome-suites-core-deps-latest.modules   |   6 +-
 .../meson-dont-use-rpath-on-pkg-config-deps.patch  |  62 +++++++++
 .../meson-sort-libpaths-with-pkg-config-path.patch | 155 +++++++++++++++++++++
 3 files changed, 221 insertions(+), 2 deletions(-)
---
diff --git a/modulesets/gnome-suites-core-deps-latest.modules 
b/modulesets/gnome-suites-core-deps-latest.modules
index d75aad90..d3a4aea7 100644
--- a/modulesets/gnome-suites-core-deps-latest.modules
+++ b/modulesets/gnome-suites-core-deps-latest.modules
@@ -1727,10 +1727,12 @@
 
   <distutils id="meson" python3="1">
     <branch repo="github-tar"
-            version="0.51.2"
+            version="0.52.0"
             module="mesonbuild/meson/releases/download/${version}/meson-${version}.tar.gz"
             checkoutdir="meson-${version}"
-            hash="sha256:23688f0fc90be623d98e80e1defeea92bbb7103bf9336a5f5b9865d36e892d76">
+            hash="sha256:d60f75f0dedcc4fd249dbc7519d6f3ce6df490033d276ef1cf27453ef4938d32">
+      <patch file="meson-dont-use-rpath-on-pkg-config-deps.patch" strip="1"/>
+      <patch file="meson-sort-libpaths-with-pkg-config-path.patch" strip="1"/>
     </branch>
     <dependencies>
       <dep package="ninja"/>
diff --git a/patches/meson-dont-use-rpath-on-pkg-config-deps.patch 
b/patches/meson-dont-use-rpath-on-pkg-config-deps.patch
new file mode 100644
index 00000000..b2f7bcc2
--- /dev/null
+++ b/patches/meson-dont-use-rpath-on-pkg-config-deps.patch
@@ -0,0 +1,62 @@
+From 24eb4c9248c34f482a9a1d166f779d91456ac536 Mon Sep 17 00:00:00 2001
+From: Ting-Wei Lan <lantw src gnome org>
+Date: Thu, 4 Oct 2018 23:03:30 +0800
+Subject: [PATCH 1/2] backends: Use raw_link_args to check for the need of
+ RPATH
+
+Function rpaths_for_bundled_shared_libraries assumes it needs RPATH when
+linking arguments of an external dependency has exactly one argument and
+the only argument is an absolute path to a library file. This was mostly
+fine because almost all .pc files use a -L -l pair instead of the full
+path of the library, which means pkg-config dependencies almost always
+have at least two arguments. However, there are patches landed in the
+meson 0.47 cycle which convert -L -l pair returned by pkg-config to the
+absolute path of library. If the output of pkg-config includes exactly
+one -L argument and one -l argument, it will be converted to exactly one
+absolute path by meson and rpaths_for_bundled_shared_libraries will
+assume it needs RPATH. Since meson passes both -rpath and -rpath-link to
+the linker and -rpath-link has precedence over LD_LIBRARY_PATH, it
+changes the search order of dependent libraries in an unexpected way and
+it causes a lot of linking troubles in JHBuild environments on FreeBSD.
+
+To make the method behave like the old way of using -L -l pairs and
+avoid library path order problems, we use raw_link_args instead of
+link_args here. raw_link_args stores the unmodified output of pkg-config
+and it is much less likely to accidentally match the rule currently used
+by the method.
+
+Works around https://github.com/mesonbuild/meson/issues/4270.
+---
+ mesonbuild/backend/backends.py | 2 +-
+ run_unittests.py               | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
+index 4d3f5d9b..6d39e1cb 100644
+--- a/mesonbuild/backend/backends.py
++++ b/mesonbuild/backend/backends.py
+@@ -402,7 +402,7 @@ class Backend:
+         for dep in target.external_deps:
+             if not isinstance(dep, (dependencies.ExternalLibrary, dependencies.PkgConfigDependency)):
+                 continue
+-            la = dep.link_args
++            la = dep.get_link_args(raw=True)
+             if len(la) != 1 or not os.path.isabs(la[0]):
+                 continue
+             # The only link argument is an absolute path to a library file.
+diff --git a/run_unittests.py b/run_unittests.py
+index bfd7a546..29226fa9 100755
+--- a/run_unittests.py
++++ b/run_unittests.py
+@@ -5680,7 +5680,7 @@ c = ['{0}']
+         # Test that installed libraries works
+         self.new_builddir()
+         self.prefix = oldprefix
+-        meson_args = ['-Dc_link_args=-L{}'.format(libdir),
++        meson_args = ['-Dc_link_args=-L{} -Wl,-rpath,{}'.format(libdir, libdir),
+                       '--fatal-meson-warnings']
+         testdir = os.path.join(self.unit_test_dir, '69 static link')
+         env = {'PKG_CONFIG_LIBDIR': os.path.join(libdir, 'pkgconfig')}
+-- 
+2.23.0
+
diff --git a/patches/meson-sort-libpaths-with-pkg-config-path.patch 
b/patches/meson-sort-libpaths-with-pkg-config-path.patch
new file mode 100644
index 00000000..bf8c5d3b
--- /dev/null
+++ b/patches/meson-sort-libpaths-with-pkg-config-path.patch
@@ -0,0 +1,155 @@
+From 93a432534c954ab43cee901fcb1a35f98a99da93 Mon Sep 17 00:00:00 2001
+From: Ting-Wei Lan <lantw src gnome org>
+Date: Thu, 4 Oct 2018 23:30:28 +0800
+Subject: [PATCH 2/2] PkgConfigDependency: Sort -L flags according to
+ PKG_CONFIG_PATH
+
+When there is more than one path in PKG_CONFIG_PATH. It is almost always
+preferred to find things in the order specified by PKG_CONFIG_PATH
+instead of assuming pkg-config returns flags in a meaningful order.
+
+For example:
+
+/usr/local/lib/libgtk-3.so.0
+/usr/local/lib/pkgconfig/gtk+-3.0.pc
+/usr/local/lib/libcanberra-gtk3.so
+/usr/local/lib/pkgconfig/libcanberra-gtk3.pc
+/home/mesonuser/.local/lib/libgtk-3.so.0
+/home/mesonuser/.local/lib/pkgconfig/gtk+-3.0.pc
+
+PKG_CONFIG_PATH="/home/mesonuser/.local/lib/pkgconfig:/usr/local/lib/pkgconfig"
+
+libcanberra-gtk3 is a library which depends on gtk+-3.0. The dependency
+is mentioned in the .pc file with 'Requires', so flags from gtk+-3.0 are
+used in both dynamic and static linking.
+
+Assume the user wants to compile an application which needs both
+libcanberra-gtk3 and gtk+-3.0. The application depends on features added
+in the latest version of gtk+-3.0, which can be found in the home
+directory of the user but not in /usr/local. When meson asks pkg-config
+for linker flags of libcanberra-gtk3, pkg-config picks
+/usr/local/lib/pkgconfig/libcanberra-gtk3.pc and
+/home/mesonuser/.local/lib/pkgconfig/gtk+-3.0.pc. Since these two
+libraries come from different prefixes, there will be two -L arguments
+in the output of pkg-config. If -L/usr/local/lib is put before
+-L/home/mesonuser/.local/lib, meson will find both libraries in
+/usr/local/lib instead of picking libgtk-3.so.0 from the home directory.
+
+This can result in linking failure such as undefined references error
+when meson decides to put linker arguments of libcanberra-gtk3 before
+linker arguments of gtk+-3.0. When both /usr/local/lib/libgtk-3.so.0 and
+/home/mesonuser/.local/lib/libgtk-3.so.0 are present on the command
+line, the linker chooses the first one and ignores the second one. If
+the application needs new symbols that are only available in the second
+one, the linker will throw an error because of missing symbols.
+
+To resolve the issue, we should reorder -L flags according to
+PKG_CONFIG_PATH ourselves before using it to find the full path of
+library files. This makes sure that we always follow the preferences of
+users, without depending on the unreliable part of pkg-config output.
+
+Fixes https://github.com/mesonbuild/meson/issues/4271.
+---
+ mesonbuild/dependencies/base.py | 40 +++++++++++++++++++++++++++++++++
+ run_unittests.py                | 20 +++++++++++++++++
+ 2 files changed, 60 insertions(+)
+
+diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
+index 3c55a56b..61485905 100644
+--- a/mesonbuild/dependencies/base.py
++++ b/mesonbuild/dependencies/base.py
+@@ -784,6 +784,22 @@ class PkgConfigDependency(ExternalDependency):
+                     # Resolve the path as a compiler in the build directory would
+                     path = os.path.join(self.env.get_build_dir(), path)
+                 prefix_libpaths.add(path)
++        # Library paths are not always ordered in a meaningful way
++        #
++        # Instead of relying on pkg-config or pkgconf to provide -L flags in a
++        # specific order, we reorder library paths ourselves, according to th
++        # order specified in PKG_CONFIG_PATH. See:
++        # https://github.com/mesonbuild/meson/issues/4271
++        #
++        # Only prefix_libpaths are reordered here because there should not be
++        # too many system_libpaths to cause library version issues.
++        pkg_config_path = os.environ.get('PKG_CONFIG_PATH')
++        if pkg_config_path:
++            pkg_config_path = pkg_config_path.split(os.pathsep)
++        else:
++            pkg_config_path = []
++        pkg_config_path = self._convert_mingw_paths(pkg_config_path)
++        prefix_libpaths = sort_libpaths(prefix_libpaths, pkg_config_path)
+         system_libpaths = OrderedSet()
+         full_args = self._convert_mingw_paths(self._split_args(out))
+         for arg in full_args:
+@@ -2286,6 +2302,30 @@ def _build_external_dependency_list(name, env: Environment, kwargs: Dict[str, An
+     return candidates
+ 
+ 
++def sort_libpaths(libpaths: List[str], refpaths: List[str]) -> List[str]:
++    """Sort <libpaths> according to <refpaths>
++
++    It is intended to be used to sort -L flags returned by pkg-config.
++    Pkg-config returns flags in random order which cannot be relied on.
++    """
++    if len(refpaths) == 0:
++        return list(libpaths)
++
++    def key_func(libpath):
++        common_lengths = []
++        for refpath in refpaths:
++            try:
++                common_path = os.path.commonpath([libpath, refpath])
++            except ValueError:
++                common_path = ''
++            common_lengths.append(len(common_path))
++        max_length = max(common_lengths)
++        max_index = common_lengths.index(max_length)
++        reversed_max_length = len(refpaths[max_index]) - max_length
++        return (max_index, reversed_max_length)
++    return sorted(libpaths, key=key_func)
++
++
+ def strip_system_libdirs(environment, for_machine: MachineChoice, link_args):
+     """Remove -L<system path> arguments.
+ 
+diff --git a/run_unittests.py b/run_unittests.py
+index 29226fa9..17b23ab3 100755
+--- a/run_unittests.py
++++ b/run_unittests.py
+@@ -57,6 +57,7 @@ from mesonbuild.mesonlib import (
+ from mesonbuild.environment import detect_ninja
+ from mesonbuild.mesonlib import MesonException, EnvironmentException
+ from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram
++import mesonbuild.dependencies.base
+ from mesonbuild.build import Target
+ import mesonbuild.modules.pkgconfig
+ 
+@@ -1164,6 +1165,25 @@ class InternalTests(unittest.TestCase):
+             deps = d.get_all_dependencies(target)
+             self.assertEqual(deps, expdeps)
+ 
++    def test_sort_libpaths(self):
++        sort_libpaths = mesonbuild.dependencies.base.sort_libpaths
++        self.assertEqual(sort_libpaths(
++            ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib'],
++            ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']),
++            ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib'])
++        self.assertEqual(sort_libpaths(
++            ['/usr/local/lib', '/home/mesonuser/.local/lib', '/usr/lib'],
++            ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']),
++            ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib'])
++        self.assertEqual(sort_libpaths(
++            ['/usr/lib', '/usr/local/lib', '/home/mesonuser/.local/lib'],
++            ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']),
++            ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib'])
++        self.assertEqual(sort_libpaths(
++            ['/usr/lib', '/usr/local/lib', '/home/mesonuser/.local/lib'],
++            ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/libdata/pkgconfig']),
++            ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib'])
++
+ 
+ @unittest.skipIf(is_tarball(), 'Skipping because this is a tarball release')
+ class DataTests(unittest.TestCase):
+-- 
+2.23.0
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]