PkgConfigDependency: Don't try to resolve internal compiler libs

-lc -lm -ldl -lrt -lpthread are special linker arguments that should
never be resolved to on-disk libraries.

Closes https://github.com/mesonbuild/meson/issues/3879
pull/4014/head
Nirbheek Chauhan 7 years ago committed by Nirbheek Chauhan
parent 9ddc305e07
commit ae5ebd258f
  1. 11
      mesonbuild/compilers/c.py
  2. 3
      mesonbuild/compilers/compilers.py
  3. 12
      mesonbuild/dependencies/base.py
  4. 25
      run_unittests.py

@ -47,11 +47,14 @@ from .compilers import (
RunResult,
)
gnu_compiler_internal_libs = ('m', 'c', 'pthread', 'dl', 'rt')
class CCompiler(Compiler):
library_dirs_cache = {}
program_dirs_cache = {}
find_library_cache = {}
internal_libs = gnu_compiler_internal_libs
def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs):
# If a child ObjC or CPP class has already set it, don't set it ourselves
@ -905,10 +908,13 @@ class CCompiler(Compiler):
# First try if we can just add the library as -l.
# Gcc + co seem to prefer builtin lib dirs to -L dirs.
# Only try to find std libs if no extra dirs specified.
if not extra_dirs:
if not extra_dirs or libname in self.internal_libs:
args = ['-l' + libname]
if self.links(code, env, extra_args=args):
return args
# Don't do a manual search for internal libs
if libname in self.internal_libs:
return None
# Not found or we want to use a specific libtype? Try to find the
# library file itself.
patterns = self.get_library_naming(env, libtype)
@ -1188,7 +1194,8 @@ class IntelCCompiler(IntelCompiler, CCompiler):
class VisualStudioCCompiler(CCompiler):
std_warn_args = ['/W3']
std_opt_args = ['/O2']
ignore_libs = ('m', 'c', 'pthread')
ignore_libs = gnu_compiler_internal_libs
internal_libs = ()
def __init__(self, exelist, version, is_cross, exe_wrap, is_64):
CCompiler.__init__(self, exelist, version, is_cross, exe_wrap)

@ -661,6 +661,9 @@ class Compiler:
# Libraries to ignore in find_library() since they are provided by the
# compiler or the C library. Currently only used for MSVC.
ignore_libs = ()
# Libraries that are internal compiler implementations, and must not be
# manually searched.
internal_libs = ()
# Cache for the result of compiler checks which can be cached
compiler_check_cache = {}

@ -623,12 +623,16 @@ class PkgConfigDependency(ExternalDependency):
# arguments as-is and then adding the libpaths at the end.
else:
args = None
if args:
if args is not None:
libs_found.add(lib)
# Replace -l arg with full path to library if available
# else, library is provided by the compiler and can't be resolved
if not args[0].startswith('-l'):
lib = args[0]
# else, library is either to be ignored, or is provided by
# the compiler, can't be resolved, and should be used as-is
if args:
if not args[0].startswith('-l'):
lib = args[0]
else:
continue
else:
# Library wasn't found, maybe we're looking in the wrong
# places or the library will be provided with LDFLAGS or

@ -51,11 +51,15 @@ from run_tests import get_builddir_target_args, get_backend_commands, Backend
from run_tests import ensure_backend_detects_changes, run_configure_inprocess
from run_tests import run_mtest_inprocess
# Fake class for mocking
# Fake classes for mocking
class FakeBuild:
def __init__(self, env):
self.environment = env
class FakeCompilerOptions:
def __init__(self):
self.value = []
def get_dynamic_section_entry(fname, entry):
if is_cygwin() or is_osx():
raise unittest.SkipTest('Test only applicable to ELF platforms')
@ -605,6 +609,7 @@ class InternalTests(unittest.TestCase):
env = Environment('', '', get_fake_options(''))
compiler = env.detect_c_compiler(False)
env.coredata.compilers = {'c': compiler}
env.coredata.compiler_options['c_link_args'] = FakeCompilerOptions()
p1 = Path(tmpdir) / '1'
p2 = Path(tmpdir) / '2'
p1.mkdir()
@ -614,6 +619,12 @@ class InternalTests(unittest.TestCase):
# libbar.a is in both prefixes
(p1 / 'libbar.a').open('w').close()
(p2 / 'libbar.a').open('w').close()
# Ensure that we never statically link to these
(p1 / 'libpthread.a').open('w').close()
(p1 / 'libm.a').open('w').close()
(p1 / 'libc.a').open('w').close()
(p1 / 'libdl.a').open('w').close()
(p1 / 'librt.a').open('w').close()
def fake_call_pkgbin(self, args, env=None):
if '--libs' not in args:
@ -622,6 +633,8 @@ class InternalTests(unittest.TestCase):
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())
if args[0] == 'internal':
return 0, '-L{} -lpthread -lm -lc -lrt -ldl'.format(p1.as_posix())
old_call = PkgConfigDependency._call_pkgbin
old_check = PkgConfigDependency.check_pkgconfig
@ -634,6 +647,14 @@ class InternalTests(unittest.TestCase):
[(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()])
internal_dep = PkgConfigDependency('internal', env, kwargs)
if compiler.get_id() == 'msvc':
self.assertEqual(internal_dep.get_link_args(), [])
else:
link_args = internal_dep.get_link_args()
for link_arg in link_args:
for lib in ('pthread', 'm', 'c', 'dl', 'rt'):
self.assertNotIn('lib{}.a'.format(lib), link_arg, msg=link_args)
# Test ends
PkgConfigDependency._call_pkgbin = old_call
PkgConfigDependency.check_pkgconfig = old_check
@ -2797,7 +2818,7 @@ class WindowsTests(BasePlatformTests):
if cc.id != 'msvc':
raise unittest.SkipTest('Not using MSVC')
# To force people to update this test, and also test
self.assertEqual(set(cc.ignore_libs), {'c', 'm', 'pthread'})
self.assertEqual(set(cc.ignore_libs), {'c', 'm', 'pthread', 'dl', 'rt'})
for l in cc.ignore_libs:
self.assertEqual(cc.find_library(l, env, []), [])

Loading…
Cancel
Save