diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2018-02-16 00:10:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-16 00:10:16 +0200 |
commit | 6257fe9e35eb0e547709309b1b9e6a40a6ad1149 (patch) | |
tree | 608c13981e69daea66820f5cafd5c40a955f4dd7 | |
parent | ff1146bc8c3b489fafce5746ce9d3c5f1d80fd96 (diff) | |
parent | ab377272891a9320ca53d213c15ee44e85755db5 (diff) | |
download | meson-6257fe9e35eb0e547709309b1b9e6a40a6ad1149.zip meson-6257fe9e35eb0e547709309b1b9e6a40a6ad1149.tar.gz meson-6257fe9e35eb0e547709309b1b9e6a40a6ad1149.tar.bz2 |
Merge pull request #3004 from bredelings/clean-boost
Factor out code for windows abi tags.
-rw-r--r-- | mesonbuild/dependencies/misc.py | 206 |
1 files changed, 125 insertions, 81 deletions
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index af80160..9e9441f 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -18,7 +18,6 @@ import glob import os import re import shlex -import shutil import sysconfig from pathlib import Path @@ -44,6 +43,10 @@ from .base import ( # - $BOOST_ROOT/boost/*.hpp # - $BOOST_ROOT/lib<arch>-<compiler>/*.lib where arch=32/64 and compiler=msvc-14.1 # +# Note that we should also try to support: +# mingw-w64 / Windows : libboost_<module>-mt.a (location = <prefix>/mingw64/lib/) +# libboost_<module>-mt.dll.a +# # Library names supported: # - libboost_<module>-<compiler>-mt-gd-x_x.lib (static) # - boost_<module>-<compiler>-mt-gd-x_x.lib|.dll (shared) @@ -97,18 +100,13 @@ from .base import ( # 2.2. Find boost libraries with unknown suffixes using file-name globbing. # TODO: Unix: Don't assume we know where the boost dir is, rely on -Idir and -Ldir being set. -# TODO: Determine a suffix (e.g. "-mt" or "") and use it. -# TODO: Get_win_link_args( ) and get_link_args( ) -# TODO: Genericize: 'args += ['-L' + dir] => args += self.compiler.get_linker_search_args(dir) # TODO: Allow user to specify suffix in BOOST_SUFFIX, or add specific options like BOOST_DEBUG for 'd' for debug. -# TODO: fix cross: -# is_windows() -> for_windows(self.want_cross, self.env) -# is_osx() and self.want_cross -> for_darwin(self.want_cross, self.env) class BoostDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('boost', environment, 'cpp', kwargs) self.need_static_link = ['boost_exception', 'boost_test_exec_monitor'] + # FIXME: is this the right way to find the build type? self.is_debug = environment.cmd_line_options.buildtype.startswith('debug') threading = kwargs.get("threading", "multi") self.is_multithreading = threading == "multi" @@ -131,42 +129,34 @@ class BoostDependency(ExternalDependency): self.libdir = os.environ['BOOST_LIBRARYDIR'] if self.boost_root is None: - if mesonlib.is_windows(): + if mesonlib.for_windows(self.want_cross, self.env): self.boost_roots = self.detect_win_roots() else: self.boost_roots = self.detect_nix_roots() - if self.boost_root is None and not self.boost_roots: - self.log_fail() - return - if self.incdir is None: - if mesonlib.is_windows(): + if mesonlib.for_windows(self.want_cross, self.env): self.incdir = self.detect_win_incdir() else: self.incdir = self.detect_nix_incdir() - if self.incdir is None and mesonlib.is_windows(): - self.log_fail() - return - if self.check_invalid_modules(): + self.log_fail() return mlog.debug('Boost library root dir is', mlog.bold(self.boost_root)) mlog.debug('Boost include directory is', mlog.bold(self.incdir)) - self.lib_modules = {} - self.detect_version() + # 1. check if we can find BOOST headers. + self.detect_headers_and_version() + + # 2. check if we can find BOOST libraries. if self.is_found: self.detect_lib_modules() mlog.debug('Boost library directory is', mlog.bold(self.libdir)) - for m in self.requested_modules: - if 'boost_' + m not in self.lib_modules: - mlog.debug('Requested Boost library {!r} not found'.format(m)) - self.log_fail() - self.is_found = False - return + + # 3. Report success or failure + if self.is_found: self.log_success() else: self.log_fail() @@ -187,7 +177,6 @@ class BoostDependency(ExternalDependency): if invalid_modules: mlog.log(mlog.red('ERROR:'), 'Invalid Boost modules: ' + ', '.join(invalid_modules)) - self.log_fail() return True else: return False @@ -275,7 +264,7 @@ class BoostDependency(ExternalDependency): raise DependencyException('Boost module argument is not a string.') return candidates - def detect_version(self): + def detect_headers_and_version(self): try: version = self.compiler.get_define('BOOST_LIB_VERSION', '#include <boost/version.hpp>', self.env, self.get_compile_args(), []) except mesonlib.EnvironmentException: @@ -289,9 +278,23 @@ class BoostDependency(ExternalDependency): self.is_found = True def detect_lib_modules(self): - if mesonlib.is_windows(): - return self.detect_lib_modules_win() - return self.detect_lib_modules_nix() + self.lib_modules = {} + + # 1. Try to find modules using compiler.find_library( ) + if self.find_libraries_with_abi_tags(self.abi_tags()): + pass + # 2. Fall back to the old method + else: + if mesonlib.for_windows(self.want_cross, self.env): + self.detect_lib_modules_win() + else: + self.detect_lib_modules_nix() + + # 3. Check if we can find the modules + for m in self.requested_modules: + if 'boost_' + m not in self.lib_modules: + mlog.debug('Requested Boost library {!r} not found'.format(m)) + self.is_found = False def modname_from_filename(self, filename): modname = os.path.basename(filename) @@ -301,20 +304,94 @@ class BoostDependency(ExternalDependency): modname = modname[3:] return modname - def detect_lib_modules_win(self): - arch = detect_cpu_family(self.env.coredata.compilers) + def compiler_tag(self): + tag = None + compiler = self.env.detect_cpp_compiler(self.want_cross) + if mesonlib.for_windows(self.want_cross, self.env): + if compiler.get_id() == 'msvc': + comp_ts_version = compiler.get_toolset_version() + compiler_ts = comp_ts_version.split('.') + # FIXME - what about other compilers? + tag = '-vc{}{}'.format(compiler_ts[0], compiler_ts[1]) + else: + tag = '' + return tag + + def threading_tag(self): + if not self.is_multithreading: + return '' + + if mesonlib.for_darwin(self.want_cross, self.env): + # - Mac: requires -mt for multithreading, so should not fall back to non-mt libraries. + return '-mt' + elif mesonlib.for_windows(self.want_cross, self.env): + # - Windows: requires -mt for multithreading, so should not fall back to non-mt libraries. + return '-mt' + else: + # - Linux: leaves off -mt but libraries are multithreading-aware. + # - Cygwin: leaves off -mt but libraries are multithreading-aware. + return '' + + def version_tag(self): + return '-' + self.version.replace('.', '_') + + def debug_tag(self): + return '-gd' if self.is_debug else '' + + def versioned_abi_tag(self): + return self.compiler_tag() + self.threading_tag() + self.debug_tag() + self.version_tag() + + # FIXME - how to handle different distributions, e.g. for Mac? Currently we handle homebrew and macports, but not fink. + def abi_tags(self): + if mesonlib.for_windows(self.want_cross, self.env): + return [self.versioned_abi_tag(), self.threading_tag()] + else: + return [self.threading_tag()] + + def sourceforge_dir(self): + if self.env.detect_cpp_compiler(self.want_cross).get_id() != 'msvc': + return None comp_ts_version = self.env.detect_cpp_compiler(self.want_cross).get_toolset_version() - compiler_ts = comp_ts_version.split('.') - compiler = 'vc{}{}'.format(compiler_ts[0], compiler_ts[1]) + arch = detect_cpu_family(self.env.coredata.compilers) + if arch == 'x86': + return 'lib32-msvc-{}'.format(comp_ts_version) + elif arch == 'x86_64': + return 'lib64-msvc-{}'.format(comp_ts_version) + else: + # Does anyone do Boost cross-compiling to other archs on Windows? + return None + + def find_libraries_with_abi_tag(self, tag): + + # All modules should have the same tag + self.lib_modules = {} + + all_found = True + + for module in self.requested_modules: + libname = 'boost_' + module + tag + + args = self.compiler.find_library(libname, self.env, self.extra_lib_dirs()) + if args is None: + mlog.debug("Couldn\'t find library '{}' for boost module '{}' (ABI tag = '{}')".format(libname, module, tag)) + all_found = False + else: + mlog.debug('Link args for boost module "{}" are {}'.format(module, args)) + self.lib_modules['boost_' + module] = args + + return all_found + + def find_libraries_with_abi_tags(self, tags): + for tag in tags: + if self.find_libraries_with_abi_tag(tag): + return True + return False + + def detect_lib_modules_win(self): if not self.libdir: # The libdirs in the distributed binaries (from sf) - if arch == 'x86': - lib_sf = 'lib32-msvc-{}'.format(comp_ts_version) - elif arch == 'x86_64': - lib_sf = 'lib64-msvc-{}'.format(comp_ts_version) - else: - # Does anyone do Boost cross-compiling to other archs on Windows? - lib_sf = None + lib_sf = self.sourceforge_dir() + if self.boost_root: roots = [self.boost_root] else: @@ -335,12 +412,8 @@ class BoostDependency(ExternalDependency): return for name in self.need_static_link: - libname = "lib{}".format(name) + '-' + compiler - if self.is_multithreading: - libname = libname + '-mt' - if self.is_debug: - libname = libname + '-gd' - libname = libname + "-{}.lib".format(self.version.replace('.', '_')) + # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a + libname = 'lib' + name + self.versioned_abi_tag() + '.lib' if os.path.isfile(os.path.join(self.libdir, libname)): self.lib_modules[self.modname_from_filename(libname)] = [libname] else: @@ -351,52 +424,23 @@ class BoostDependency(ExternalDependency): # globber1 applies to a layout=system installation # globber2 applies to a layout=versioned installation globber1 = 'libboost_*' if self.static else 'boost_*' - globber2 = globber1 + '-' + compiler - if self.is_multithreading: - globber2 = globber2 + '-mt' - if self.is_debug: - globber2 = globber2 + '-gd' - globber2 = globber2 + '-{}'.format(self.version.replace('.', '_')) + globber2 = globber1 + self.versioned_abi_tag() + # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a globber2_matches = glob.glob(os.path.join(self.libdir, globber2 + '.lib')) for entry in globber2_matches: fname = os.path.basename(entry) self.lib_modules[self.modname_from_filename(fname)] = [fname] if len(globber2_matches) == 0: + # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a for entry in glob.glob(os.path.join(self.libdir, globber1 + '.lib')): if self.static: fname = os.path.basename(entry) self.lib_modules[self.modname_from_filename(fname)] = [fname] - # - Linux leaves off -mt but libraries are multithreading-aware. - # - Cygwin leaves off -mt but libraries are multithreading-aware. - # - Mac requires -mt for multithreading, so should not fall back - # to non-mt libraries. - def abi_tag(self): - if mesonlib.for_windows(self.want_cross, self.env): - return None - if self.is_multithreading and mesonlib.for_darwin(self.want_cross, self.env): - return '-mt' - else: - return '' - def detect_lib_modules_nix(self): - all_found = True - for module in self.requested_modules: - libname = 'boost_' + module + self.abi_tag() - - args = self.compiler.find_library(libname, self.env, self.extra_lib_dirs()) - if args is None: - mlog.debug('Couldn\'t find library "{}" for boost module "{}"'.format(module, libname)) - all_found = False - else: - mlog.debug('Link args for boost module "{}" are {}'.format(module, args)) - self.lib_modules['boost_' + module] = args - if all_found: - return - if self.static: libsuffix = 'a' - elif mesonlib.is_osx() and not self.want_cross: + elif mesonlib.for_darwin(self.want_cross, self.env): libsuffix = 'dylib' else: libsuffix = 'so' @@ -442,7 +486,7 @@ class BoostDependency(ExternalDependency): def get_link_args(self): args = [] for dir in self.extra_lib_dirs(): - args += self.compiler.get_linker_search_args(self.libdir) + args += self.compiler.get_linker_search_args(dir) for lib in self.requested_modules: args += self.lib_modules['boost_' + lib] return args |