compilers: Improve manual library searching

We can now specify the library type we want to search for, and whether
we want to prefer static libraries over shared ones or the other way
around. This functionality is not exposed to build files yet.
pull/2611/head
Nirbheek Chauhan 7 years ago
parent 4405a1297b
commit d2a250412c
  1. 2
      mesonbuild/build.py
  2. 59
      mesonbuild/compilers/c.py
  3. 5
      mesonbuild/dependencies/ui.py
  4. 44
      mesonbuild/environment.py
  5. 36
      mesonbuild/mesonlib.py

@ -22,7 +22,7 @@ from . import mlog
from .mesonlib import File, MesonException, listify, extract_as_list from .mesonlib import File, MesonException, listify, extract_as_list
from .mesonlib import typeslistify, stringlistify, classify_unity_sources from .mesonlib import typeslistify, stringlistify, classify_unity_sources
from .mesonlib import get_filenames_templates_dict, substitute_values from .mesonlib import get_filenames_templates_dict, substitute_values
from .environment import for_windows, for_darwin, for_cygwin from .mesonlib import for_windows, for_darwin, for_cygwin
from .compilers import is_object, clike_langs, sort_clike, lang_suffixes from .compilers import is_object, clike_langs, sort_clike, lang_suffixes
known_basic_kwargs = {'install': True, known_basic_kwargs = {'install': True,

@ -17,6 +17,7 @@ import subprocess, os.path, tempfile
from .. import mlog from .. import mlog
from .. import coredata from .. import coredata
from ..mesonlib import EnvironmentException, version_compare, Popen_safe, listify from ..mesonlib import EnvironmentException, version_compare, Popen_safe, listify
from ..mesonlib import for_windows, for_darwin, for_cygwin
from .compilers import ( from .compilers import (
GCC_MINGW, GCC_MINGW,
@ -710,7 +711,45 @@ class CCompiler(Compiler):
return False return False
raise RuntimeError('BUG: {!r} check failed unexpectedly'.format(n)) raise RuntimeError('BUG: {!r} check failed unexpectedly'.format(n))
def find_library(self, libname, env, extra_dirs): def get_library_naming(self, env, libtype):
'''
Get library prefixes and suffixes for the target platform ordered by
priority
'''
stlibext = ['a']
# We've always allowed libname to be both `foo` and `libfoo`,
# and now people depend on it
prefixes = ['lib', '']
# Library suffixes and prefixes
if for_darwin(env.is_cross_build(), env):
shlibext = ['dylib']
elif for_windows(env.is_cross_build(), env):
if self.id == 'msvc':
shlibext = ['lib']
else:
shlibext = ['dll', 'dll.a', 'lib']
# Yep, static libraries can also be foo.lib
stlibext += ['lib']
elif for_cygwin(env.is_cross_build(), env):
shlibext = ['dll', 'dll.a']
prefixes = ['cyg'] + prefixes
else:
# Linux/BSDs
shlibext = ['so']
# Search priority
if libtype in ('default', 'shared-static'):
suffixes = shlibext + stlibext
elif libtype == 'static-shared':
suffixes = stlibext + shlibext
elif libtype == 'shared':
suffixes = shlibext
elif libtype == 'static':
suffixes = stlibext
else:
raise AssertionError('BUG: unknown libtype {!r}'.format(libtype))
return prefixes, suffixes
def find_library(self, libname, env, extra_dirs, libtype='default'):
# These libraries are either built-in or invalid # These libraries are either built-in or invalid
if libname in self.ignore_libs: if libname in self.ignore_libs:
return [] return []
@ -720,21 +759,21 @@ class CCompiler(Compiler):
extra_dirs = [extra_dirs] extra_dirs = [extra_dirs]
# Gcc + co seem to prefer builtin lib dirs to -L dirs. # Gcc + co seem to prefer builtin lib dirs to -L dirs.
# Only try to find std libs if no extra dirs specified. # Only try to find std libs if no extra dirs specified.
if not extra_dirs: if not extra_dirs and libtype == 'default':
args = ['-l' + libname] args = ['-l' + libname]
if self.links(code, env, extra_args=args): if self.links(code, env, extra_args=args):
return args return args
# Not found? Try to find the library file itself. # Not found or we want to use a specific libtype? Try to find the
# library file itself.
extra_dirs += self.get_library_dirs() extra_dirs += self.get_library_dirs()
suffixes = ['so', 'dylib', 'lib', 'dll', 'a'] prefixes, suffixes = self.get_library_naming(env, libtype)
# Triply-nested loop!
for d in extra_dirs: for d in extra_dirs:
for suffix in suffixes: for suffix in suffixes:
trial = os.path.join(d, 'lib' + libname + '.' + suffix) for prefix in prefixes:
if os.path.isfile(trial): trial = os.path.join(d, prefix + libname + '.' + suffix)
return [trial] if os.path.isfile(trial):
trial2 = os.path.join(d, libname + '.' + suffix) return [trial]
if os.path.isfile(trial2):
return [trial2]
return None return None
def thread_flags(self): def thread_flags(self):

@ -23,8 +23,9 @@ from collections import OrderedDict
from .. import mlog from .. import mlog
from .. import mesonlib from .. import mesonlib
from ..mesonlib import MesonException, Popen_safe, version_compare, extract_as_list from ..mesonlib import MesonException, Popen_safe, version_compare
from ..environment import for_windows, detect_cpu from ..mesonlib import extract_as_list, for_windows
from ..environment import detect_cpu
from .base import DependencyException, DependencyMethods from .base import DependencyException, DependencyMethods
from .base import ExternalDependency, ExternalProgram from .base import ExternalDependency, ExternalProgram

@ -219,46 +219,6 @@ def detect_system():
return 'cygwin' return 'cygwin'
return system return system
def for_windows(is_cross, env):
"""
Host machine is windows?
Note: 'host' is the machine on which compiled binaries will run
"""
if not is_cross:
return mesonlib.is_windows()
elif env.cross_info.has_host():
return env.cross_info.config['host_machine']['system'] == 'windows'
return False
def for_cygwin(is_cross, env):
"""
Host machine is cygwin?
Note: 'host' is the machine on which compiled binaries will run
"""
if not is_cross:
return mesonlib.is_cygwin()
elif env.cross_info.has_host():
return env.cross_info.config['host_machine']['system'] == 'cygwin'
return False
def for_darwin(is_cross, env):
"""
Host machine is Darwin (iOS/OS X)?
Note: 'host' is the machine on which compiled binaries will run
"""
if not is_cross:
return mesonlib.is_osx()
elif env.cross_info.has_host():
return env.cross_info.config['host_machine']['system'] == 'darwin'
return False
def search_version(text): def search_version(text):
# Usually of the type 4.1.4 but compiler output may contain # Usually of the type 4.1.4 but compiler output may contain
# stuff like this: # stuff like this:
@ -550,9 +510,9 @@ class Environment:
cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler
return cls(ccache + compiler, version, gtype, is_cross, exe_wrap, defines) return cls(ccache + compiler, version, gtype, is_cross, exe_wrap, defines)
if 'clang' in out: if 'clang' in out:
if 'Apple' in out or for_darwin(want_cross, self): if 'Apple' in out or mesonlib.for_darwin(want_cross, self):
cltype = CLANG_OSX cltype = CLANG_OSX
elif 'windows' in out or for_windows(want_cross, self): elif 'windows' in out or mesonlib.for_windows(want_cross, self):
cltype = CLANG_WIN cltype = CLANG_WIN
else: else:
cltype = CLANG_STANDARD cltype = CLANG_STANDARD

@ -219,6 +219,42 @@ def is_cygwin():
def is_debianlike(): def is_debianlike():
return os.path.isfile('/etc/debian_version') return os.path.isfile('/etc/debian_version')
def for_windows(is_cross, env):
"""
Host machine is windows?
Note: 'host' is the machine on which compiled binaries will run
"""
if not is_cross:
return is_windows()
elif env.cross_info.has_host():
return env.cross_info.config['host_machine']['system'] == 'windows'
return False
def for_cygwin(is_cross, env):
"""
Host machine is cygwin?
Note: 'host' is the machine on which compiled binaries will run
"""
if not is_cross:
return is_cygwin()
elif env.cross_info.has_host():
return env.cross_info.config['host_machine']['system'] == 'cygwin'
return False
def for_darwin(is_cross, env):
"""
Host machine is Darwin (iOS/OS X)?
Note: 'host' is the machine on which compiled binaries will run
"""
if not is_cross:
return is_osx()
elif env.cross_info.has_host():
return env.cross_info.config['host_machine']['system'] == 'darwin'
return False
def exe_exists(arglist): def exe_exists(arglist):
try: try:
p = subprocess.Popen(arglist, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p = subprocess.Popen(arglist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Loading…
Cancel
Save