diff options
author | Elliott Sales de Andrade <quantum.analyst@gmail.com> | 2017-04-15 16:58:46 -0400 |
---|---|---|
committer | Elliott Sales de Andrade <quantum.analyst@gmail.com> | 2017-05-09 18:28:05 -0400 |
commit | d3caadb6759e49ad2ed4a9bdecbdcc3c6079dfe8 (patch) | |
tree | c9cab6c38139e2c9d24c450847e8942c09a1b5e3 | |
parent | cb24c2d58afce68aeb0ed8ffd369e90998ad83a3 (diff) | |
download | meson-d3caadb6759e49ad2ed4a9bdecbdcc3c6079dfe8.zip meson-d3caadb6759e49ad2ed4a9bdecbdcc3c6079dfe8.tar.gz meson-d3caadb6759e49ad2ed4a9bdecbdcc3c6079dfe8.tar.bz2 |
Split misc dependencies into their own file.
-rw-r--r-- | mesonbuild/dependencies/__init__.py | 6 | ||||
-rw-r--r-- | mesonbuild/dependencies/base.py | 362 | ||||
-rw-r--r-- | mesonbuild/dependencies/misc.py | 382 |
3 files changed, 390 insertions, 360 deletions
diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py index 62301f8..1af81fd 100644 --- a/mesonbuild/dependencies/__init__.py +++ b/mesonbuild/dependencies/__init__.py @@ -14,6 +14,7 @@ from .base import * from .dev import GMockDependency, GTestDependency, LLVMDependency, ValgrindDependency +from .misc import BoostDependency, Python3Dependency, ThreadDependency from .platform import AppleFrameworks from .ui import GLDependency, GnuStepDependency, Qt4Dependency, Qt5Dependency, SDL2Dependency, WxDependency @@ -25,6 +26,11 @@ packages.update({ 'llvm': LLVMDependency, 'valgrind': ValgrindDependency, + # From misc: + 'boost': BoostDependency, + 'python3': Python3Dependency, + 'threads': ThreadDependency, + # From platform: 'appleframeworks': AppleFrameworks, diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 4bdb989..4854b94 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -20,13 +20,11 @@ # package before this gets too big. import sys -import os, stat, glob, shutil -import sysconfig +import os, stat, shutil from enum import Enum from .. import mlog from .. import mesonlib from ..mesonlib import MesonException, flatten, version_compare_many, Popen_safe -from ..environment import detect_cpu_family class DependencyException(MesonException): @@ -533,259 +531,6 @@ class ExternalLibrary(Dependency): return self.lang_args[lang] return [] -class BoostDependency(Dependency): - # Some boost libraries have different names for - # their sources and libraries. This dict maps - # between the two. - name2lib = {'test': 'unit_test_framework'} - - def __init__(self, environment, kwargs): - Dependency.__init__(self, 'boost', kwargs) - self.name = 'boost' - self.environment = environment - self.libdir = '' - if 'native' in kwargs and environment.is_cross_build(): - self.want_cross = not kwargs['native'] - else: - self.want_cross = environment.is_cross_build() - try: - self.boost_root = os.environ['BOOST_ROOT'] - if not os.path.isabs(self.boost_root): - raise DependencyException('BOOST_ROOT must be an absolute path.') - except KeyError: - self.boost_root = None - if self.boost_root is None: - if self.want_cross: - if 'BOOST_INCLUDEDIR' in os.environ: - self.incdir = os.environ['BOOST_INCLUDEDIR'] - else: - raise DependencyException('BOOST_ROOT or BOOST_INCLUDEDIR is needed while cross-compiling') - if mesonlib.is_windows(): - self.boost_root = self.detect_win_root() - self.incdir = self.boost_root - else: - if 'BOOST_INCLUDEDIR' in os.environ: - self.incdir = os.environ['BOOST_INCLUDEDIR'] - else: - self.incdir = '/usr/include' - else: - self.incdir = os.path.join(self.boost_root, 'include') - self.boost_inc_subdir = os.path.join(self.incdir, 'boost') - mlog.debug('Boost library root dir is', self.boost_root) - self.src_modules = {} - self.lib_modules = {} - self.lib_modules_mt = {} - self.detect_version() - self.requested_modules = self.get_requested(kwargs) - module_str = ', '.join(self.requested_modules) - if self.version is not None: - self.detect_src_modules() - self.detect_lib_modules() - self.validate_requested() - if self.boost_root is not None: - info = self.version + ', ' + self.boost_root - else: - info = self.version - mlog.log('Dependency Boost (%s) found:' % module_str, mlog.green('YES'), info) - else: - mlog.log("Dependency Boost (%s) found:" % module_str, mlog.red('NO')) - if 'cpp' not in self.environment.coredata.compilers: - raise DependencyException('Tried to use Boost but a C++ compiler is not defined.') - self.cpp_compiler = self.environment.coredata.compilers['cpp'] - - def detect_win_root(self): - globtext = 'c:\\local\\boost_*' - files = glob.glob(globtext) - if len(files) > 0: - return files[0] - return 'C:\\' - - def get_compile_args(self): - args = [] - include_dir = '' - if self.boost_root is not None: - if mesonlib.is_windows(): - include_dir = self.boost_root - else: - include_dir = os.path.join(self.boost_root, 'include') - else: - include_dir = self.incdir - - # Use "-isystem" when including boost headers instead of "-I" - # to avoid compiler warnings/failures when "-Werror" is used - - # Careful not to use "-isystem" on default include dirs as it - # breaks some of the headers for certain gcc versions - - # For example, doing g++ -isystem /usr/include on a simple - # "int main()" source results in the error: - # "/usr/include/c++/6.3.1/cstdlib:75:25: fatal error: stdlib.h: No such file or directory" - - # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70129 - # and http://stackoverflow.com/questions/37218953/isystem-on-a-system-include-directory-causes-errors - # for more details - - # TODO: The correct solution would probably be to ask the - # compiler for it's default include paths (ie: "gcc -xc++ -E - # -v -") and avoid including those with -isystem - - # For now, use -isystem for all includes except for some - # typical defaults (which don't need to be included at all - # since they are in the default include paths) - if include_dir != '/usr/include' and include_dir != '/usr/local/include': - args.append("".join(self.cpp_compiler.get_include_args(include_dir, True))) - return args - - def get_requested(self, kwargs): - candidates = kwargs.get('modules', []) - if isinstance(candidates, str): - return [candidates] - for c in candidates: - if not isinstance(c, str): - raise DependencyException('Boost module argument is not a string.') - return candidates - - def validate_requested(self): - for m in self.requested_modules: - if m not in self.src_modules: - raise DependencyException('Requested Boost module "%s" not found.' % m) - - def found(self): - return self.version is not None - - def get_version(self): - return self.version - - def detect_version(self): - try: - ifile = open(os.path.join(self.boost_inc_subdir, 'version.hpp')) - except FileNotFoundError: - self.version = None - return - with ifile: - for line in ifile: - if line.startswith("#define") and 'BOOST_LIB_VERSION' in line: - ver = line.split()[-1] - ver = ver[1:-1] - self.version = ver.replace('_', '.') - return - self.version = None - - def detect_src_modules(self): - for entry in os.listdir(self.boost_inc_subdir): - entry = os.path.join(self.boost_inc_subdir, entry) - if stat.S_ISDIR(os.stat(entry).st_mode): - self.src_modules[os.path.split(entry)[-1]] = True - - def detect_lib_modules(self): - if mesonlib.is_windows(): - return self.detect_lib_modules_win() - return self.detect_lib_modules_nix() - - def detect_lib_modules_win(self): - arch = detect_cpu_family(self.environment.coredata.compilers) - # Guess the libdir - if arch == 'x86': - gl = 'lib32*' - elif arch == 'x86_64': - gl = 'lib64*' - else: - # Does anyone do Boost cross-compiling to other archs on Windows? - gl = None - # See if the libdir is valid - if gl: - libdir = glob.glob(os.path.join(self.boost_root, gl)) - else: - libdir = [] - # Can't find libdir, bail - if not libdir: - return - libdir = libdir[0] - self.libdir = libdir - globber = 'boost_*-gd-*.lib' # FIXME - for entry in glob.glob(os.path.join(libdir, globber)): - (_, fname) = os.path.split(entry) - base = fname.split('_', 1)[1] - modname = base.split('-', 1)[0] - self.lib_modules_mt[modname] = fname - - def detect_lib_modules_nix(self): - if mesonlib.is_osx(): - libsuffix = 'dylib' - else: - libsuffix = 'so' - - globber = 'libboost_*.{}'.format(libsuffix) - if 'BOOST_LIBRARYDIR' in os.environ: - libdirs = [os.environ['BOOST_LIBRARYDIR']] - elif self.boost_root is None: - libdirs = mesonlib.get_library_dirs() - else: - libdirs = [os.path.join(self.boost_root, 'lib')] - for libdir in libdirs: - for entry in glob.glob(os.path.join(libdir, globber)): - lib = os.path.basename(entry) - name = lib.split('.')[0].split('_', 1)[-1] - # I'm not 100% sure what to do here. Some distros - # have modules such as thread only as -mt versions. - if entry.endswith('-mt.so'): - self.lib_modules_mt[name] = True - else: - self.lib_modules[name] = True - - def get_win_link_args(self): - args = [] - if self.boost_root: - args.append('-L' + self.libdir) - for module in self.requested_modules: - module = BoostDependency.name2lib.get(module, module) - if module in self.lib_modules_mt: - args.append(self.lib_modules_mt[module]) - return args - - def get_link_args(self): - if mesonlib.is_windows(): - return self.get_win_link_args() - args = [] - if self.boost_root: - args.append('-L' + os.path.join(self.boost_root, 'lib')) - elif 'BOOST_LIBRARYDIR' in os.environ: - args.append('-L' + os.environ['BOOST_LIBRARYDIR']) - for module in self.requested_modules: - module = BoostDependency.name2lib.get(module, module) - libname = 'boost_' + module - # The compiler's library detector is the most reliable so use that first. - default_detect = self.cpp_compiler.find_library(libname, self.environment, []) - if default_detect is not None: - if module == 'unit_testing_framework': - emon_args = self.cpp_compiler.find_library('boost_test_exec_monitor') - else: - emon_args = None - args += default_detect - if emon_args is not None: - args += emon_args - elif module in self.lib_modules or module in self.lib_modules_mt: - linkcmd = '-l' + libname - args.append(linkcmd) - # FIXME a hack, but Boost's testing framework has a lot of - # different options and it's hard to determine what to do - # without feedback from actual users. Update this - # as we get more bug reports. - if module == 'unit_testing_framework': - args.append('-lboost_test_exec_monitor') - elif module + '-mt' in self.lib_modules_mt: - linkcmd = '-lboost_' + module + '-mt' - args.append(linkcmd) - if module == 'unit_testing_framework': - args.append('-lboost_test_exec_monitor-mt') - return args - - def get_sources(self): - return [] - - def need_threads(self): - return 'thread' in self.requested_modules - class ExtraFrameworkDependency(Dependency): def __init__(self, name, required, path, kwargs): @@ -831,106 +576,6 @@ class ExtraFrameworkDependency(Dependency): def get_version(self): return 'unknown' -class ThreadDependency(Dependency): - def __init__(self, environment, kwargs): - super().__init__('threads', {}) - self.name = 'threads' - self.is_found = True - mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES')) - - def need_threads(self): - return True - - def get_version(self): - return 'unknown' - -class Python3Dependency(Dependency): - def __init__(self, environment, kwargs): - super().__init__('python3', kwargs) - self.name = 'python3' - self.is_found = False - # We can only be sure that it is Python 3 at this point - self.version = '3' - if DependencyMethods.PKGCONFIG in self.methods: - try: - pkgdep = PkgConfigDependency('python3', environment, kwargs) - if pkgdep.found(): - self.cargs = pkgdep.cargs - self.libs = pkgdep.libs - self.version = pkgdep.get_version() - self.is_found = True - return - except Exception: - pass - if not self.is_found: - if mesonlib.is_windows() and DependencyMethods.SYSCONFIG in self.methods: - self._find_libpy3_windows(environment) - elif mesonlib.is_osx() and DependencyMethods.EXTRAFRAMEWORK in self.methods: - # In OSX the Python 3 framework does not have a version - # number in its name. - fw = ExtraFrameworkDependency('python', False, None, kwargs) - if fw.found(): - self.cargs = fw.get_compile_args() - self.libs = fw.get_link_args() - self.is_found = True - if self.is_found: - mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES')) - else: - mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.red('NO')) - - def _find_libpy3_windows(self, env): - ''' - Find python3 libraries on Windows and also verify that the arch matches - what we are building for. - ''' - pyarch = sysconfig.get_platform() - arch = detect_cpu_family(env.coredata.compilers) - if arch == 'x86': - arch = '32' - elif arch == 'x86_64': - arch = '64' - else: - # We can't cross-compile Python 3 dependencies on Windows yet - mlog.log('Unknown architecture {!r} for'.format(arch), - mlog.bold(self.name)) - self.is_found = False - return - # Pyarch ends in '32' or '64' - if arch != pyarch[-2:]: - mlog.log('Need', mlog.bold(self.name), - 'for {}-bit, but found {}-bit'.format(arch, pyarch[-2:])) - self.is_found = False - return - inc = sysconfig.get_path('include') - platinc = sysconfig.get_path('platinclude') - self.cargs = ['-I' + inc] - if inc != platinc: - self.cargs.append('-I' + platinc) - # Nothing exposes this directly that I coulf find - basedir = sysconfig.get_config_var('base') - vernum = sysconfig.get_config_var('py_version_nodot') - self.libs = ['-L{}/libs'.format(basedir), - '-lpython{}'.format(vernum)] - self.version = sysconfig.get_config_var('py_version_short') - self.is_found = True - - def get_compile_args(self): - return self.cargs - - def get_link_args(self): - return self.libs - - def get_methods(self): - if mesonlib.is_windows(): - return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSCONFIG] - elif mesonlib.is_osx(): - return [DependencyMethods.PKGCONFIG, DependencyMethods.EXTRAFRAMEWORK] - else: - return [DependencyMethods.PKGCONFIG] - - def get_version(self): - return self.version - def get_dep_identifier(name, kwargs, want_cross): # Need immutable objects since the identifier will be used as a dict key @@ -986,7 +631,4 @@ def find_external_dependency(name, environment, kwargs): # This has to be at the end so the classes it references # are defined. -packages = {'boost': BoostDependency, - 'threads': ThreadDependency, - 'python3': Python3Dependency, - } +packages = {} diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py new file mode 100644 index 0000000..3374c6e --- /dev/null +++ b/mesonbuild/dependencies/misc.py @@ -0,0 +1,382 @@ +# Copyright 2013-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file contains the detection logic for miscellaneous external dependencies. + +import glob +import os +import stat +import sysconfig + +from .. import mlog +from .. import mesonlib +from ..environment import detect_cpu_family + +from .base import Dependency, DependencyException, DependencyMethods, ExtraFrameworkDependency, PkgConfigDependency + + +class BoostDependency(Dependency): + # Some boost libraries have different names for + # their sources and libraries. This dict maps + # between the two. + name2lib = {'test': 'unit_test_framework'} + + def __init__(self, environment, kwargs): + Dependency.__init__(self, 'boost', kwargs) + self.name = 'boost' + self.environment = environment + self.libdir = '' + if 'native' in kwargs and environment.is_cross_build(): + self.want_cross = not kwargs['native'] + else: + self.want_cross = environment.is_cross_build() + try: + self.boost_root = os.environ['BOOST_ROOT'] + if not os.path.isabs(self.boost_root): + raise DependencyException('BOOST_ROOT must be an absolute path.') + except KeyError: + self.boost_root = None + if self.boost_root is None: + if self.want_cross: + if 'BOOST_INCLUDEDIR' in os.environ: + self.incdir = os.environ['BOOST_INCLUDEDIR'] + else: + raise DependencyException('BOOST_ROOT or BOOST_INCLUDEDIR is needed while cross-compiling') + if mesonlib.is_windows(): + self.boost_root = self.detect_win_root() + self.incdir = self.boost_root + else: + if 'BOOST_INCLUDEDIR' in os.environ: + self.incdir = os.environ['BOOST_INCLUDEDIR'] + else: + self.incdir = '/usr/include' + else: + self.incdir = os.path.join(self.boost_root, 'include') + self.boost_inc_subdir = os.path.join(self.incdir, 'boost') + mlog.debug('Boost library root dir is', self.boost_root) + self.src_modules = {} + self.lib_modules = {} + self.lib_modules_mt = {} + self.detect_version() + self.requested_modules = self.get_requested(kwargs) + module_str = ', '.join(self.requested_modules) + if self.version is not None: + self.detect_src_modules() + self.detect_lib_modules() + self.validate_requested() + if self.boost_root is not None: + info = self.version + ', ' + self.boost_root + else: + info = self.version + mlog.log('Dependency Boost (%s) found:' % module_str, mlog.green('YES'), info) + else: + mlog.log("Dependency Boost (%s) found:" % module_str, mlog.red('NO')) + if 'cpp' not in self.environment.coredata.compilers: + raise DependencyException('Tried to use Boost but a C++ compiler is not defined.') + self.cpp_compiler = self.environment.coredata.compilers['cpp'] + + def detect_win_root(self): + globtext = 'c:\\local\\boost_*' + files = glob.glob(globtext) + if len(files) > 0: + return files[0] + return 'C:\\' + + def get_compile_args(self): + args = [] + include_dir = '' + if self.boost_root is not None: + if mesonlib.is_windows(): + include_dir = self.boost_root + else: + include_dir = os.path.join(self.boost_root, 'include') + else: + include_dir = self.incdir + + # Use "-isystem" when including boost headers instead of "-I" + # to avoid compiler warnings/failures when "-Werror" is used + + # Careful not to use "-isystem" on default include dirs as it + # breaks some of the headers for certain gcc versions + + # For example, doing g++ -isystem /usr/include on a simple + # "int main()" source results in the error: + # "/usr/include/c++/6.3.1/cstdlib:75:25: fatal error: stdlib.h: No such file or directory" + + # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70129 + # and http://stackoverflow.com/questions/37218953/isystem-on-a-system-include-directory-causes-errors + # for more details + + # TODO: The correct solution would probably be to ask the + # compiler for it's default include paths (ie: "gcc -xc++ -E + # -v -") and avoid including those with -isystem + + # For now, use -isystem for all includes except for some + # typical defaults (which don't need to be included at all + # since they are in the default include paths) + if include_dir != '/usr/include' and include_dir != '/usr/local/include': + args.append("".join(self.cpp_compiler.get_include_args(include_dir, True))) + return args + + def get_requested(self, kwargs): + candidates = kwargs.get('modules', []) + if isinstance(candidates, str): + return [candidates] + for c in candidates: + if not isinstance(c, str): + raise DependencyException('Boost module argument is not a string.') + return candidates + + def validate_requested(self): + for m in self.requested_modules: + if m not in self.src_modules: + raise DependencyException('Requested Boost module "%s" not found.' % m) + + def found(self): + return self.version is not None + + def get_version(self): + return self.version + + def detect_version(self): + try: + ifile = open(os.path.join(self.boost_inc_subdir, 'version.hpp')) + except FileNotFoundError: + self.version = None + return + with ifile: + for line in ifile: + if line.startswith("#define") and 'BOOST_LIB_VERSION' in line: + ver = line.split()[-1] + ver = ver[1:-1] + self.version = ver.replace('_', '.') + return + self.version = None + + def detect_src_modules(self): + for entry in os.listdir(self.boost_inc_subdir): + entry = os.path.join(self.boost_inc_subdir, entry) + if stat.S_ISDIR(os.stat(entry).st_mode): + self.src_modules[os.path.split(entry)[-1]] = True + + def detect_lib_modules(self): + if mesonlib.is_windows(): + return self.detect_lib_modules_win() + return self.detect_lib_modules_nix() + + def detect_lib_modules_win(self): + arch = detect_cpu_family(self.environment.coredata.compilers) + # Guess the libdir + if arch == 'x86': + gl = 'lib32*' + elif arch == 'x86_64': + gl = 'lib64*' + else: + # Does anyone do Boost cross-compiling to other archs on Windows? + gl = None + # See if the libdir is valid + if gl: + libdir = glob.glob(os.path.join(self.boost_root, gl)) + else: + libdir = [] + # Can't find libdir, bail + if not libdir: + return + libdir = libdir[0] + self.libdir = libdir + globber = 'boost_*-gd-*.lib' # FIXME + for entry in glob.glob(os.path.join(libdir, globber)): + (_, fname) = os.path.split(entry) + base = fname.split('_', 1)[1] + modname = base.split('-', 1)[0] + self.lib_modules_mt[modname] = fname + + def detect_lib_modules_nix(self): + if mesonlib.is_osx(): + libsuffix = 'dylib' + else: + libsuffix = 'so' + + globber = 'libboost_*.{}'.format(libsuffix) + if 'BOOST_LIBRARYDIR' in os.environ: + libdirs = [os.environ['BOOST_LIBRARYDIR']] + elif self.boost_root is None: + libdirs = mesonlib.get_library_dirs() + else: + libdirs = [os.path.join(self.boost_root, 'lib')] + for libdir in libdirs: + for entry in glob.glob(os.path.join(libdir, globber)): + lib = os.path.basename(entry) + name = lib.split('.')[0].split('_', 1)[-1] + # I'm not 100% sure what to do here. Some distros + # have modules such as thread only as -mt versions. + if entry.endswith('-mt.so'): + self.lib_modules_mt[name] = True + else: + self.lib_modules[name] = True + + def get_win_link_args(self): + args = [] + if self.boost_root: + args.append('-L' + self.libdir) + for module in self.requested_modules: + module = BoostDependency.name2lib.get(module, module) + if module in self.lib_modules_mt: + args.append(self.lib_modules_mt[module]) + return args + + def get_link_args(self): + if mesonlib.is_windows(): + return self.get_win_link_args() + args = [] + if self.boost_root: + args.append('-L' + os.path.join(self.boost_root, 'lib')) + elif 'BOOST_LIBRARYDIR' in os.environ: + args.append('-L' + os.environ['BOOST_LIBRARYDIR']) + for module in self.requested_modules: + module = BoostDependency.name2lib.get(module, module) + libname = 'boost_' + module + # The compiler's library detector is the most reliable so use that first. + default_detect = self.cpp_compiler.find_library(libname, self.environment, []) + if default_detect is not None: + if module == 'unit_testing_framework': + emon_args = self.cpp_compiler.find_library('boost_test_exec_monitor') + else: + emon_args = None + args += default_detect + if emon_args is not None: + args += emon_args + elif module in self.lib_modules or module in self.lib_modules_mt: + linkcmd = '-l' + libname + args.append(linkcmd) + # FIXME a hack, but Boost's testing framework has a lot of + # different options and it's hard to determine what to do + # without feedback from actual users. Update this + # as we get more bug reports. + if module == 'unit_testing_framework': + args.append('-lboost_test_exec_monitor') + elif module + '-mt' in self.lib_modules_mt: + linkcmd = '-lboost_' + module + '-mt' + args.append(linkcmd) + if module == 'unit_testing_framework': + args.append('-lboost_test_exec_monitor-mt') + return args + + def get_sources(self): + return [] + + def need_threads(self): + return 'thread' in self.requested_modules + + +class ThreadDependency(Dependency): + def __init__(self, environment, kwargs): + super().__init__('threads', {}) + self.name = 'threads' + self.is_found = True + mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES')) + + def need_threads(self): + return True + + def get_version(self): + return 'unknown' + + +class Python3Dependency(Dependency): + def __init__(self, environment, kwargs): + super().__init__('python3', kwargs) + self.name = 'python3' + self.is_found = False + # We can only be sure that it is Python 3 at this point + self.version = '3' + if DependencyMethods.PKGCONFIG in self.methods: + try: + pkgdep = PkgConfigDependency('python3', environment, kwargs) + if pkgdep.found(): + self.cargs = pkgdep.cargs + self.libs = pkgdep.libs + self.version = pkgdep.get_version() + self.is_found = True + return + except Exception: + pass + if not self.is_found: + if mesonlib.is_windows() and DependencyMethods.SYSCONFIG in self.methods: + self._find_libpy3_windows(environment) + elif mesonlib.is_osx() and DependencyMethods.EXTRAFRAMEWORK in self.methods: + # In OSX the Python 3 framework does not have a version + # number in its name. + fw = ExtraFrameworkDependency('python', False, None, kwargs) + if fw.found(): + self.cargs = fw.get_compile_args() + self.libs = fw.get_link_args() + self.is_found = True + if self.is_found: + mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES')) + else: + mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.red('NO')) + + def _find_libpy3_windows(self, env): + ''' + Find python3 libraries on Windows and also verify that the arch matches + what we are building for. + ''' + pyarch = sysconfig.get_platform() + arch = detect_cpu_family(env.coredata.compilers) + if arch == 'x86': + arch = '32' + elif arch == 'x86_64': + arch = '64' + else: + # We can't cross-compile Python 3 dependencies on Windows yet + mlog.log('Unknown architecture {!r} for'.format(arch), + mlog.bold(self.name)) + self.is_found = False + return + # Pyarch ends in '32' or '64' + if arch != pyarch[-2:]: + mlog.log('Need', mlog.bold(self.name), + 'for {}-bit, but found {}-bit'.format(arch, pyarch[-2:])) + self.is_found = False + return + inc = sysconfig.get_path('include') + platinc = sysconfig.get_path('platinclude') + self.cargs = ['-I' + inc] + if inc != platinc: + self.cargs.append('-I' + platinc) + # Nothing exposes this directly that I coulf find + basedir = sysconfig.get_config_var('base') + vernum = sysconfig.get_config_var('py_version_nodot') + self.libs = ['-L{}/libs'.format(basedir), + '-lpython{}'.format(vernum)] + self.version = sysconfig.get_config_var('py_version_short') + self.is_found = True + + def get_compile_args(self): + return self.cargs + + def get_link_args(self): + return self.libs + + def get_methods(self): + if mesonlib.is_windows(): + return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSCONFIG] + elif mesonlib.is_osx(): + return [DependencyMethods.PKGCONFIG, DependencyMethods.EXTRAFRAMEWORK] + else: + return [DependencyMethods.PKGCONFIG] + + def get_version(self): + return self.version |