aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2018-08-08 04:08:32 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2018-08-24 03:18:20 +0530
commit131e4d7422b99a7751c2337edbe313288498c4f8 (patch)
treee9bab6fb0790aad1fe83bef4280012459b0684eb
parentdfbecb2629a24cdefcbab8828dac9d5492541b81 (diff)
downloadmeson-131e4d7422b99a7751c2337edbe313288498c4f8.zip
meson-131e4d7422b99a7751c2337edbe313288498c4f8.tar.gz
meson-131e4d7422b99a7751c2337edbe313288498c4f8.tar.bz2
PkgConfigDependency: Fix library path search order
We were searching the library paths in the reverse order, which meant that we'd pick libraries from the wrong prefix. Closes https://github.com/mesonbuild/meson/issues/3951
-rw-r--r--mesonbuild/compilers/c.py7
-rw-r--r--mesonbuild/dependencies/base.py51
-rw-r--r--mesonbuild/mesonlib.py3
-rwxr-xr-xrun_unittests.py44
4 files changed, 77 insertions, 28 deletions
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index dbbbed2..47cb568 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -16,6 +16,7 @@ import re
import glob
import os.path
import subprocess
+from pathlib import Path
from .. import mlog
from .. import coredata
@@ -883,13 +884,13 @@ class CCompiler(Compiler):
@classmethod
def _get_trials_from_pattern(cls, pattern, directory, libname):
- f = os.path.join(directory, pattern.format(libname))
+ f = Path(directory) / pattern.format(libname)
# Globbing for OpenBSD
if '*' in pattern:
# NOTE: globbing matches directories and broken symlinks
# so we have to do an isfile test on it later
- return cls._sort_shlibs_openbsd(glob.glob(f))
- return [f]
+ return cls._sort_shlibs_openbsd(glob.glob(str(f)))
+ return [f.as_posix()]
@staticmethod
def _get_file_from_list(files):
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 63b817a..f087db6 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -584,26 +584,7 @@ class PkgConfigDependency(ExternalDependency):
(self.name, out))
self.compile_args = self._convert_mingw_paths(shlex.split(out))
- def _set_libs(self):
- env = None
- libcmd = [self.name, '--libs']
- if self.static:
- libcmd.append('--static')
- # Force pkg-config to output -L fields even if they are system
- # paths so we can do manual searching with cc.find_library() later.
- env = os.environ.copy()
- env['PKG_CONFIG_ALLOW_SYSTEM_LIBS'] = '1'
- ret, out = self._call_pkgbin(libcmd, env=env)
- if ret != 0:
- raise DependencyException('Could not generate libs for %s:\n\n%s' %
- (self.name, out))
- # Also get the 'raw' output without -Lfoo system paths for usage when
- # a library can't be found, and also in gnome.generate_gir
- # + gnome.gtkdoc which need -L -l arguments.
- ret, out_raw = self._call_pkgbin(libcmd)
- if ret != 0:
- raise DependencyException('Could not generate libs for %s:\n\n%s' %
- (self.name, out_raw))
+ def _search_libs(self, out, out_raw):
link_args = []
raw_link_args = []
# Library paths should be safe to de-dup
@@ -634,7 +615,7 @@ class PkgConfigDependency(ExternalDependency):
continue
if self.clib_compiler:
args = self.clib_compiler.find_library(lib[2:], self.env,
- list(libpaths), libtype)
+ list(reversed(libpaths)), libtype)
# If the project only uses a non-clib language such as D, Rust,
# C#, Python, etc, all we can do is limp along by adding the
# arguments as-is and then adding the libpaths at the end.
@@ -679,14 +660,34 @@ class PkgConfigDependency(ExternalDependency):
if lib.startswith('-L') and not lib.startswith(('-L-l', '-L-L')):
raw_libpaths.add(lib[2:])
raw_link_args.append(lib)
- # Set everything
- self.link_args = link_args
- self.raw_link_args = raw_link_args
# Add all -Lbar args if we have -lfoo args in link_args
if libs_notfound:
# Order of -L flags doesn't matter with ld, but it might with other
# linkers such as MSVC, so prepend them.
- self.link_args = ['-L' + lp for lp in raw_libpaths] + self.link_args
+ link_args = ['-L' + lp for lp in raw_libpaths] + link_args
+ return link_args, raw_link_args
+
+ def _set_libs(self):
+ env = None
+ libcmd = [self.name, '--libs']
+ if self.static:
+ libcmd.append('--static')
+ # Force pkg-config to output -L fields even if they are system
+ # paths so we can do manual searching with cc.find_library() later.
+ env = os.environ.copy()
+ env['PKG_CONFIG_ALLOW_SYSTEM_LIBS'] = '1'
+ ret, out = self._call_pkgbin(libcmd, env=env)
+ if ret != 0:
+ raise DependencyException('Could not generate libs for %s:\n\n%s' %
+ (self.name, out))
+ # Also get the 'raw' output without -Lfoo system paths for adding -L
+ # args with -lfoo when a library can't be found, and also in
+ # gnome.generate_gir + gnome.gtkdoc which need -L -l arguments.
+ ret, out_raw = self._call_pkgbin(libcmd)
+ if ret != 0:
+ raise DependencyException('Could not generate libs for %s:\n\n%s' %
+ (self.name, out_raw))
+ self.link_args, self.raw_link_args = self._search_libs(out, out_raw)
def get_pkgconfig_variable(self, variable_name, kwargs):
options = ['--variable=' + variable_name, self.name]
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index ab03e00..de85ae6 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -1094,6 +1094,9 @@ class OrderedSet(collections.MutableSet):
'", "'.join(repr(e) for e in self.__container.keys()))
return 'OrderedSet()'
+ def __reversed__(self):
+ return reversed(self.__container)
+
def add(self, value):
self.__container[value] = None
diff --git a/run_unittests.py b/run_unittests.py
index 806390c..7c8c595 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -601,6 +601,50 @@ class InternalTests(unittest.TestCase):
'mesonbuild.compilers.c.for_windows', true):
self._test_all_naming(cc, env, patterns, 'windows-msvc')
+ def test_pkgconfig_parse_libs(self):
+ '''
+ Unit test for parsing of pkg-config output to search for libraries
+
+ https://github.com/mesonbuild/meson/issues/3951
+ '''
+ with tempfile.TemporaryDirectory() as tmpdir:
+ pkgbin = ExternalProgram('pkg-config', command=['pkg-config'], silent=True)
+ env = Environment('', '', get_fake_options(''))
+ compiler = env.detect_c_compiler(False)
+ env.coredata.compilers = {'c': compiler}
+ p1 = Path(tmpdir) / '1'
+ p2 = Path(tmpdir) / '2'
+ p1.mkdir()
+ p2.mkdir()
+ # libfoo.a is in one prefix
+ (p1 / 'libfoo.a').open('w').close()
+ # libbar.a is in both prefixes
+ (p1 / 'libbar.a').open('w').close()
+ (p2 / 'libbar.a').open('w').close()
+
+ def fake_call_pkgbin(self, args, env=None):
+ if '--libs' not in args:
+ return 0, ''
+ if args[0] == 'foo':
+ return 0, '-L{} -lfoo -L{} -lbar'.format(p1.as_posix(), p2.as_posix())
+ if args[0] == 'bar':
+ return 0, '-L{} -lbar'.format(p2.as_posix())
+
+ old_call = PkgConfigDependency._call_pkgbin
+ old_check = PkgConfigDependency.check_pkgconfig
+ PkgConfigDependency._call_pkgbin = fake_call_pkgbin
+ PkgConfigDependency.check_pkgconfig = lambda x: pkgbin
+ # Test begins
+ kwargs = {'required': True, 'silent': True}
+ foo_dep = PkgConfigDependency('foo', env, kwargs)
+ self.assertEqual(foo_dep.get_link_args(),
+ [(p1 / 'libfoo.a').as_posix(), (p2 / 'libbar.a').as_posix()])
+ bar_dep = PkgConfigDependency('bar', env, kwargs)
+ self.assertEqual(bar_dep.get_link_args(), [(p2 / 'libbar.a').as_posix()])
+ # Test ends
+ PkgConfigDependency._call_pkgbin = old_call
+ PkgConfigDependency.check_pkgconfig = old_check
+
class BasePlatformTests(unittest.TestCase):
def setUp(self):