# Copyright 2013-2019 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.

from pathlib import Path
import functools
import re
import sysconfig
import typing as T

from .. import mesonlib
from .. import mlog
from ..environment import detect_cpu_family
from .base import DependencyException, DependencyMethods
from .base import BuiltinDependency, SystemDependency
from .cmake import CMakeDependency
from .configtool import ConfigToolDependency
from .factory import DependencyFactory, factory_methods
from .pkgconfig import PkgConfigDependency

if T.TYPE_CHECKING:
    from ..environment import Environment, MachineChoice
    from .factory import DependencyGenerator


@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE})
def netcdf_factory(env: 'Environment',
                   for_machine: 'MachineChoice',
                   kwargs: T.Dict[str, T.Any],
                   methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
    language = kwargs.get('language', 'c')
    if language not in ('c', 'cpp', 'fortran'):
        raise DependencyException(f'Language {language} is not supported with NetCDF.')

    candidates: T.List['DependencyGenerator'] = []

    if DependencyMethods.PKGCONFIG in methods:
        if language == 'fortran':
            pkg = 'netcdf-fortran'
        else:
            pkg = 'netcdf'

        candidates.append(functools.partial(PkgConfigDependency, pkg, env, kwargs, language=language))

    if DependencyMethods.CMAKE in methods:
        candidates.append(functools.partial(CMakeDependency, 'NetCDF', env, kwargs, language=language))

    return candidates


class DlBuiltinDependency(BuiltinDependency):
    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, env, kwargs)
        self.feature_since = ('0.62.0', "consider checking for `dlopen` with and without `find_library('dl')`")

        if self.clib_compiler.has_function('dlopen', '#include <dlfcn.h>', env)[0]:
            self.is_found = True


class DlSystemDependency(SystemDependency):
    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, env, kwargs)
        self.feature_since = ('0.62.0', "consider checking for `dlopen` with and without `find_library('dl')`")

        h = self.clib_compiler.has_header('dlfcn.h', '', env)
        self.link_args = self.clib_compiler.find_library('dl', env, [], self.libtype)

        if h[0] and self.link_args:
            self.is_found = True


class OpenMPDependency(SystemDependency):
    # Map date of specification release (which is the macro value) to a version.
    VERSIONS = {
        '201811': '5.0',
        '201611': '5.0-revision1',  # This is supported by ICC 19.x
        '201511': '4.5',
        '201307': '4.0',
        '201107': '3.1',
        '200805': '3.0',
        '200505': '2.5',
        '200203': '2.0',
        '199810': '1.0',
    }

    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
        language = kwargs.get('language')
        super().__init__('openmp', environment, kwargs, language=language)
        self.is_found = False
        if self.clib_compiler.get_id() == 'nagfor':
            # No macro defined for OpenMP, but OpenMP 3.1 is supported.
            self.version = '3.1'
            self.is_found = True
            self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
            return
        if self.clib_compiler.get_id() == 'pgi':
            # through at least PGI 19.4, there is no macro defined for OpenMP, but OpenMP 3.1 is supported.
            self.version = '3.1'
            self.is_found = True
            self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
            return
        try:
            openmp_date = self.clib_compiler.get_define(
                '_OPENMP', '', self.env, self.clib_compiler.openmp_flags(), [self], disable_cache=True)[0]
        except mesonlib.EnvironmentException as e:
            mlog.debug('OpenMP support not available in the compiler')
            mlog.debug(e)
            openmp_date = None

        if openmp_date:
            try:
                self.version = self.VERSIONS[openmp_date]
            except KeyError:
                mlog.debug(f'Could not find an OpenMP version matching {openmp_date}')
                if openmp_date == '_OPENMP':
                    mlog.debug('This can be caused by flags such as gcc\'s `-fdirectives-only`, which affect preprocessor behavior.')
                return
            # Flang has omp_lib.h
            header_names = ('omp.h', 'omp_lib.h')
            for name in header_names:
                if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]:
                    self.is_found = True
                    self.compile_args = self.clib_compiler.openmp_flags()
                    self.link_args = self.clib_compiler.openmp_link_flags()
                    break
            if not self.is_found:
                mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.')


class ThreadDependency(SystemDependency):
    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
        super().__init__(name, environment, kwargs)
        self.is_found = True
        # Happens if you are using a language with threads
        # concept without C, such as plain Cuda.
        if self.clib_compiler is None:
            self.compile_args = []
            self.link_args = []
        else:
            self.compile_args = self.clib_compiler.thread_flags(environment)
            self.link_args = self.clib_compiler.thread_link_flags(environment)


class BlocksDependency(SystemDependency):
    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
        super().__init__('blocks', environment, kwargs)
        self.name = 'blocks'
        self.is_found = False

        if self.env.machines[self.for_machine].is_darwin():
            self.compile_args = []
            self.link_args = []
        else:
            self.compile_args = ['-fblocks']
            self.link_args = ['-lBlocksRuntime']

            if not self.clib_compiler.has_header('Block.h', '', environment, disable_cache=True) or \
               not self.clib_compiler.find_library('BlocksRuntime', environment, []):
                mlog.log(mlog.red('ERROR:'), 'BlocksRuntime not found.')
                return

        source = '''
            int main(int argc, char **argv)
            {
                int (^callback)(void) = ^ int (void) { return 0; };
                return callback();
            }'''

        with self.clib_compiler.compile(source, extra_args=self.compile_args + self.link_args) as p:
            if p.returncode != 0:
                mlog.log(mlog.red('ERROR:'), 'Compiler does not support blocks extension.')
                return

            self.is_found = True


class Python3DependencySystem(SystemDependency):
    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
        super().__init__(name, environment, kwargs)

        if not environment.machines.matches_build_machine(self.for_machine):
            return
        if not environment.machines[self.for_machine].is_windows():
            return

        self.name = 'python3'
        self.static = kwargs.get('static', False)
        # We can only be sure that it is Python 3 at this point
        self.version = '3'
        self._find_libpy3_windows(environment)

    @staticmethod
    def get_windows_python_arch() -> T.Optional[str]:
        pyplat = sysconfig.get_platform()
        if pyplat == 'mingw':
            pycc = sysconfig.get_config_var('CC')
            if pycc.startswith('x86_64'):
                return '64'
            elif pycc.startswith(('i686', 'i386')):
                return '32'
            else:
                mlog.log(f'MinGW Python built with unknown CC {pycc!r}, please file a bug')
                return None
        elif pyplat == 'win32':
            return '32'
        elif pyplat in ('win64', 'win-amd64'):
            return '64'
        mlog.log(f'Unknown Windows Python platform {pyplat!r}')
        return None

    def get_windows_link_args(self) -> T.Optional[T.List[str]]:
        pyplat = sysconfig.get_platform()
        if pyplat.startswith('win'):
            vernum = sysconfig.get_config_var('py_version_nodot')
            if self.static:
                libpath = Path('libs') / f'libpython{vernum}.a'
            else:
                comp = self.get_compiler()
                if comp.id == "gcc":
                    libpath = Path(f'python{vernum}.dll')
                else:
                    libpath = Path('libs') / f'python{vernum}.lib'
            lib = Path(sysconfig.get_config_var('base')) / libpath
        elif pyplat == 'mingw':
            if self.static:
                libname = sysconfig.get_config_var('LIBRARY')
            else:
                libname = sysconfig.get_config_var('LDLIBRARY')
            lib = Path(sysconfig.get_config_var('LIBDIR')) / libname
        if not lib.exists():
            mlog.log('Could not find Python3 library {!r}'.format(str(lib)))
            return None
        return [str(lib)]

    def _find_libpy3_windows(self, env: 'Environment') -> None:
        '''
        Find python3 libraries on Windows and also verify that the arch matches
        what we are building for.
        '''
        pyarch = self.get_windows_python_arch()
        if pyarch is None:
            self.is_found = False
            return
        arch = detect_cpu_family(env.coredata.compilers.host)
        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(f'Unknown architecture {arch!r} for',
                     mlog.bold(self.name))
            self.is_found = False
            return
        # Pyarch ends in '32' or '64'
        if arch != pyarch:
            mlog.log('Need', mlog.bold(self.name), 'for {}-bit, but '
                     'found {}-bit'.format(arch, pyarch))
            self.is_found = False
            return
        # This can fail if the library is not found
        largs = self.get_windows_link_args()
        if largs is None:
            self.is_found = False
            return
        self.link_args = largs
        # Compile args
        inc = sysconfig.get_path('include')
        platinc = sysconfig.get_path('platinclude')
        self.compile_args = ['-I' + inc]
        if inc != platinc:
            self.compile_args.append('-I' + platinc)
        self.version = sysconfig.get_config_var('py_version')
        self.is_found = True

    def log_tried(self) -> str:
        return 'sysconfig'

class PcapDependencyConfigTool(ConfigToolDependency):

    tools = ['pcap-config']
    tool_name = 'pcap-config'

    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, environment, kwargs)
        if not self.is_found:
            return
        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
        self.link_args = self.get_config_value(['--libs'], 'link_args')
        self.version = self.get_pcap_lib_version()

    def get_pcap_lib_version(self) -> T.Optional[str]:
        # Since we seem to need to run a program to discover the pcap version,
        # we can't do that when cross-compiling
        # FIXME: this should be handled if we have an exe_wrapper
        if not self.env.machines.matches_build_machine(self.for_machine):
            return None

        v = self.clib_compiler.get_return_value('pcap_lib_version', 'string',
                                                '#include <pcap.h>', self.env, [], [self])
        v = re.sub(r'libpcap version ', '', str(v))
        v = re.sub(r' -- Apple version.*$', '', v)
        return v


class CupsDependencyConfigTool(ConfigToolDependency):

    tools = ['cups-config']
    tool_name = 'cups-config'

    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, environment, kwargs)
        if not self.is_found:
            return
        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
        self.link_args = self.get_config_value(['--ldflags', '--libs'], 'link_args')


class LibWmfDependencyConfigTool(ConfigToolDependency):

    tools = ['libwmf-config']
    tool_name = 'libwmf-config'

    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, environment, kwargs)
        if not self.is_found:
            return
        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
        self.link_args = self.get_config_value(['--libs'], 'link_args')


class LibGCryptDependencyConfigTool(ConfigToolDependency):

    tools = ['libgcrypt-config']
    tool_name = 'libgcrypt-config'

    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, environment, kwargs)
        if not self.is_found:
            return
        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
        self.link_args = self.get_config_value(['--libs'], 'link_args')
        self.version = self.get_config_value(['--version'], 'version')[0]


class GpgmeDependencyConfigTool(ConfigToolDependency):

    tools = ['gpgme-config']
    tool_name = 'gpg-config'

    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, environment, kwargs)
        if not self.is_found:
            return
        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
        self.link_args = self.get_config_value(['--libs'], 'link_args')
        self.version = self.get_config_value(['--version'], 'version')[0]


class ShadercDependency(SystemDependency):

    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__('shaderc', environment, kwargs)

        static_lib = 'shaderc_combined'
        shared_lib = 'shaderc_shared'

        libs = [shared_lib, static_lib]
        if self.static:
            libs.reverse()

        cc = self.get_compiler()

        for lib in libs:
            self.link_args = cc.find_library(lib, environment, [])
            if self.link_args is not None:
                self.is_found = True

                if self.static and lib != static_lib:
                    mlog.warning(f'Static library {static_lib!r} not found for dependency '
                                 f'{self.name!r}, may not be statically linked')

                break

    def log_tried(self) -> str:
        return 'system'


class CursesConfigToolDependency(ConfigToolDependency):

    """Use the curses config tools."""

    tool = 'curses-config'
    # ncurses5.4-config is for macOS Catalina
    tools = ['ncursesw6-config', 'ncursesw5-config', 'ncurses6-config', 'ncurses5-config', 'ncurses5.4-config']

    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None):
        super().__init__(name, env, kwargs, language)
        if not self.is_found:
            return
        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
        self.link_args = self.get_config_value(['--libs'], 'link_args')


class CursesSystemDependency(SystemDependency):

    """Curses dependency the hard way.

    This replaces hand rolled find_library() and has_header() calls. We
    provide this for portability reasons, there are a large number of curses
    implementations, and the differences between them can be very annoying.
    """

    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, env, kwargs)

        candidates = [
            ('pdcurses', ['pdcurses/curses.h']),
            ('ncursesw',  ['ncursesw/ncurses.h', 'ncurses.h']),
            ('ncurses',  ['ncurses/ncurses.h', 'ncurses/curses.h', 'ncurses.h']),
            ('curses',  ['curses.h']),
        ]

        # Not sure how else to elegently break out of both loops
        for lib, headers in candidates:
            l = self.clib_compiler.find_library(lib, env, [])
            if l:
                for header in headers:
                    h = self.clib_compiler.has_header(header, '', env)
                    if h[0]:
                        self.is_found = True
                        self.link_args = l
                        # Not sure how to find version for non-ncurses curses
                        # implementations. The one in illumos/OpenIndiana
                        # doesn't seem to have a version defined in the header.
                        if lib.startswith('ncurses'):
                            v, _ = self.clib_compiler.get_define('NCURSES_VERSION', f'#include <{header}>', env, [], [self])
                            self.version = v.strip('"')
                        if lib.startswith('pdcurses'):
                            v_major, _ = self.clib_compiler.get_define('PDC_VER_MAJOR', f'#include <{header}>', env, [], [self])
                            v_minor, _ = self.clib_compiler.get_define('PDC_VER_MINOR', f'#include <{header}>', env, [], [self])
                            self.version = f'{v_major}.{v_minor}'

                        # Check the version if possible, emit a warning if we can't
                        req = kwargs.get('version')
                        if req:
                            if self.version:
                                self.is_found = mesonlib.version_compare(self.version, req)
                            else:
                                mlog.warning('Cannot determine version of curses to compare against.')

                        if self.is_found:
                            mlog.debug('Curses library:', l)
                            mlog.debug('Curses header:', header)
                            break
            if self.is_found:
                break


class IconvBuiltinDependency(BuiltinDependency):
    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, env, kwargs)
        self.feature_since = ('0.60.0', "consider checking for `iconv_open` with and without `find_library('iconv')`")
        code = '''#include <iconv.h>\n\nint main() {\n    iconv_open("","");\n}''' # [ignore encoding] this is C, not python, Mr. Lint

        if self.clib_compiler.links(code, env)[0]:
            self.is_found = True


class IconvSystemDependency(SystemDependency):
    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, env, kwargs)
        self.feature_since = ('0.60.0', "consider checking for `iconv_open` with and without find_library('iconv')")

        h = self.clib_compiler.has_header('iconv.h', '', env)
        self.link_args = self.clib_compiler.find_library('iconv', env, [], self.libtype)

        if h[0] and self.link_args:
            self.is_found = True


class IntlBuiltinDependency(BuiltinDependency):
    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, env, kwargs)
        self.feature_since = ('0.59.0', "consider checking for `ngettext` with and without `find_library('intl')`")
        code = '''#include <libintl.h>\n\nint main() {\n    gettext("Hello world");\n}'''

        if self.clib_compiler.links(code, env)[0]:
            self.is_found = True


class IntlSystemDependency(SystemDependency):
    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, env, kwargs)
        self.feature_since = ('0.59.0', "consider checking for `ngettext` with and without `find_library('intl')`")

        h = self.clib_compiler.has_header('libintl.h', '', env)
        self.link_args = self.clib_compiler.find_library('intl', env, [], self.libtype)

        if h[0] and self.link_args:
            self.is_found = True

            if self.static:
                if not self._add_sub_dependency(iconv_factory(env, self.for_machine, {'static': True})):
                    self.is_found = False
                    return


class OpensslSystemDependency(SystemDependency):
    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, env, kwargs)

        dependency_kwargs = {
            'method': 'system',
            'static': self.static,
        }
        if not self.clib_compiler.has_header('openssl/ssl.h', '', env)[0]:
            return

        # openssl >= 3 only
        self.version = self.clib_compiler.get_define('OPENSSL_VERSION_STR', '#include <openssl/opensslv.h>', env, [], [self])[0]
        # openssl < 3 only
        if not self.version:
            version_hex = self.clib_compiler.get_define('OPENSSL_VERSION_NUMBER', '#include <openssl/opensslv.h>', env, [], [self])[0]
            if not version_hex:
                return
            version_hex = version_hex.rstrip('L')
            version_ints = [((int(version_hex.rstrip('L'), 16) >> 4 + i) & 0xFF) for i in (24, 16, 8, 0)]
            # since this is openssl, the format is 1.2.3a in four parts
            self.version = '.'.join(str(i) for i in version_ints[:3]) + chr(ord('a') + version_ints[3] - 1)

        if name == 'openssl':
            if self._add_sub_dependency(libssl_factory(env, self.for_machine, dependency_kwargs)) and \
                    self._add_sub_dependency(libcrypto_factory(env, self.for_machine, dependency_kwargs)):
                self.is_found = True
            return
        else:
            self.link_args = self.clib_compiler.find_library(name.lstrip('lib'), env, [], self.libtype)
            if not self.link_args:
                return

        if not self.static:
            self.is_found = True
        else:
            if name == 'libssl':
                if self._add_sub_dependency(libcrypto_factory(env, self.for_machine, dependency_kwargs)):
                    self.is_found = True
            elif name == 'libcrypto':
                use_threads = self.clib_compiler.has_header_symbol('openssl/opensslconf.h', 'OPENSSL_THREADS', '', env, dependencies=[self])[0]
                if not use_threads or self._add_sub_dependency(threads_factory(env, self.for_machine, {})):
                    self.is_found = True
                # only relevant on platforms where it is distributed with the libc, in which case it always succeeds
                sublib = self.clib_compiler.find_library('dl', env, [], self.libtype)
                if sublib:
                    self.link_args.extend(sublib)


@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.SYSTEM})
def curses_factory(env: 'Environment',
                   for_machine: 'MachineChoice',
                   kwargs: T.Dict[str, T.Any],
                   methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
    candidates: T.List['DependencyGenerator'] = []

    if DependencyMethods.PKGCONFIG in methods:
        pkgconfig_files = ['pdcurses', 'ncursesw', 'ncurses', 'curses']
        for pkg in pkgconfig_files:
            candidates.append(functools.partial(PkgConfigDependency, pkg, env, kwargs))

    # There are path handling problems with these methods on msys, and they
    # don't apply to windows otherwise (cygwin is handled separately from
    # windows)
    if not env.machines[for_machine].is_windows():
        if DependencyMethods.CONFIG_TOOL in methods:
            candidates.append(functools.partial(CursesConfigToolDependency, 'curses', env, kwargs))

        if DependencyMethods.SYSTEM in methods:
            candidates.append(functools.partial(CursesSystemDependency, 'curses', env, kwargs))

    return candidates


@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM})
def shaderc_factory(env: 'Environment',
                    for_machine: 'MachineChoice',
                    kwargs: T.Dict[str, T.Any],
                    methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
    """Custom DependencyFactory for ShaderC.

    ShaderC's odd you get three different libraries from the same build
    thing are just easier to represent as a separate function than
    twisting DependencyFactory even more.
    """
    candidates: T.List['DependencyGenerator'] = []

    if DependencyMethods.PKGCONFIG in methods:
        # ShaderC packages their shared and static libs together
        # and provides different pkg-config files for each one. We
        # smooth over this difference by handling the static
        # keyword before handing off to the pkg-config handler.
        shared_libs = ['shaderc']
        static_libs = ['shaderc_combined', 'shaderc_static']

        if kwargs.get('static', False):
            c = [functools.partial(PkgConfigDependency, name, env, kwargs)
                 for name in static_libs + shared_libs]
        else:
            c = [functools.partial(PkgConfigDependency, name, env, kwargs)
                 for name in shared_libs + static_libs]
        candidates.extend(c)

    if DependencyMethods.SYSTEM in methods:
        candidates.append(functools.partial(ShadercDependency, env, kwargs))

    return candidates


cups_factory = DependencyFactory(
    'cups',
    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK, DependencyMethods.CMAKE],
    configtool_class=CupsDependencyConfigTool,
    cmake_name='Cups',
)

dl_factory = DependencyFactory(
    'dl',
    [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM],
    builtin_class=DlBuiltinDependency,
    system_class=DlSystemDependency,
)

gpgme_factory = DependencyFactory(
    'gpgme',
    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
    configtool_class=GpgmeDependencyConfigTool,
)

libgcrypt_factory = DependencyFactory(
    'libgcrypt',
    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
    configtool_class=LibGCryptDependencyConfigTool,
)

libwmf_factory = DependencyFactory(
    'libwmf',
    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
    configtool_class=LibWmfDependencyConfigTool,
)

pcap_factory = DependencyFactory(
    'pcap',
    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
    configtool_class=PcapDependencyConfigTool,
    pkgconfig_name='libpcap',
)

python3_factory = DependencyFactory(
    'python3',
    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.EXTRAFRAMEWORK],
    system_class=Python3DependencySystem,
    # There is no version number in the macOS version number
    framework_name='Python',
    # There is a python in /System/Library/Frameworks, but that's python 2.x,
    # Python 3 will always be in /Library
    extra_kwargs={'paths': ['/Library/Frameworks']},
)

threads_factory = DependencyFactory(
    'threads',
    [DependencyMethods.SYSTEM, DependencyMethods.CMAKE],
    cmake_name='Threads',
    system_class=ThreadDependency,
)

iconv_factory = DependencyFactory(
    'iconv',
    [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM],
    builtin_class=IconvBuiltinDependency,
    system_class=IconvSystemDependency,
)

intl_factory = DependencyFactory(
    'intl',
    [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM],
    builtin_class=IntlBuiltinDependency,
    system_class=IntlSystemDependency,
)

openssl_factory = DependencyFactory(
    'openssl',
    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE],
    system_class=OpensslSystemDependency,
    cmake_class=lambda name, env, kwargs: CMakeDependency('OpenSSL', env, dict(kwargs, modules=['OpenSSL::Crypto', 'OpenSSL::SSL'])),
)

libcrypto_factory = DependencyFactory(
    'libcrypto',
    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE],
    system_class=OpensslSystemDependency,
    cmake_class=lambda name, env, kwargs: CMakeDependency('OpenSSL', env, dict(kwargs, modules=['OpenSSL::Crypto'])),
)

libssl_factory = DependencyFactory(
    'libssl',
    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE],
    system_class=OpensslSystemDependency,
    cmake_class=lambda name, env, kwargs: CMakeDependency('OpenSSL', env, dict(kwargs, modules=['OpenSSL::SSL'])),
)
