aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2018-02-16 00:10:16 +0200
committerGitHub <noreply@github.com>2018-02-16 00:10:16 +0200
commit6257fe9e35eb0e547709309b1b9e6a40a6ad1149 (patch)
tree608c13981e69daea66820f5cafd5c40a955f4dd7
parentff1146bc8c3b489fafce5746ce9d3c5f1d80fd96 (diff)
parentab377272891a9320ca53d213c15ee44e85755db5 (diff)
downloadmeson-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.py206
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