files.new_contents: # 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 external dependencies.
  # Custom logic for several other packages are in separate files.
  
  import os
  import sys
  import stat
  import shlex
  import shutil
  from enum import Enum
  
  from .. import mlog
  from .. import mesonlib
  from ..mesonlib import (
      MesonException, Popen_safe, version_compare_many, version_compare, listify
  )
  
  
  # These must be defined in this file to avoid cyclical references.
  packages = {}
  _packages_accept_language = set()
  
  
  class DependencyException(MesonException):
      '''Exceptions raised while trying to find dependencies'''
  
  
  class DependencyMethods(Enum):
      # Auto means to use whatever dependency checking mechanisms in whatever order meson thinks is best.
      AUTO = 'auto'
      PKGCONFIG = 'pkg-config'
      QMAKE = 'qmake'
      # Just specify the standard link arguments, assuming the operating system provides the library.
      SYSTEM = 'system'
      # Detect using sdl2-config
      SDLCONFIG = 'sdlconfig'
      # Detect using pcap-config
      PCAPCONFIG = 'pcap-config'
      # Detect using cups-config
      CUPSCONFIG = 'cups-config'
      # Detect using libwmf-config
      LIBWMFCONFIG = 'libwmf-config'
      # This is only supported on OSX - search the frameworks directory by name.
      EXTRAFRAMEWORK = 'extraframework'
      # Detect using the sysconfig module.
      SYSCONFIG = 'sysconfig'
      # Specify using a "program"-config style tool
      CONFIG_TOOL = 'config-tool'
  
  
  class Dependency:
      def __init__(self, type_name, kwargs):
          self.name = "null"
          self.version = 'none'
          self.language = None # None means C-like
          self.is_found = False
          self.type_name = type_name
          self.compile_args = []
          self.link_args = []
          self.sources = []
          method = kwargs.get('method', 'auto')
          if method not in [e.value for e in DependencyMethods]:
              raise DependencyException('method {!r} is invalid'.format(method))
          method = DependencyMethods(method)
  
          # Set the detection method. If the method is set to auto, use any available method.
          # If method is set to a specific string, allow only that detection method.
          if method == DependencyMethods.AUTO:
              self.methods = self.get_methods()
          elif method in self.get_methods():
              self.methods = [method]
          else:
              raise DependencyException(
                  'Unsupported detection method: {}, allowed methods are {}'.format(
                      method.value,
                      mlog.format_list([x.value for x in [DependencyMethods.AUTO] + self.get_methods()])))
  
      def __repr__(self):
          s = '<{0} {1}: {2}>'
          return s.format(self.__class__.__name__, self.name, self.is_found)
  
      def get_compile_args(self):
          return self.compile_args
  
      def get_link_args(self):
          return self.link_args
  
      def found(self):
          return self.is_found
  
      def get_sources(self):
          """Source files that need to be added to the target.
          As an example, gtest-all.cc when using GTest."""
          return self.sources
  
      def get_methods(self):
          return [DependencyMethods.AUTO]
  
      def get_name(self):
          return self.name
  
      def get_version(self):
          return self.version
  
      def get_exe_args(self, compiler):
          return []
  
      def need_threads(self):
          return False
  
      def get_pkgconfig_variable(self, variable_name):
          raise NotImplementedError('{!r} is not a pkgconfig dependency'.format(self.name))
  
  
  class InternalDependency(Dependency):
      def __init__(self, version, incdirs, compile_args, link_args, libraries, sources, ext_deps):
          super().__init__('internal', {})
          self.version = version
          self.is_found = True
          self.include_directories = incdirs
          self.compile_args = compile_args
          self.link_args = link_args
          self.libraries = libraries
          self.sources = sources
          self.ext_deps = ext_deps
  
  
  class ExternalDependency(Dependency):
      def __init__(self, type_name, environment, language, kwargs):
          super().__init__(type_name, kwargs)
          self.env = environment
          self.name = type_name # default
          self.is_found = False
          self.language = language
          if language and language not in self.env.coredata.compilers:
              m = self.name.capitalize() + ' requires a {} compiler'
              raise DependencyException(m.format(language.capitalize()))
          self.version_reqs = kwargs.get('version', None)
          self.required = kwargs.get('required', True)
          self.silent = kwargs.get('silent', False)
          self.static = kwargs.get('static', False)
          if not isinstance(self.static, bool):
              raise DependencyException('Static keyword must be boolean')
          # Is this dependency for cross-compilation?
          if 'native' in kwargs and self.env.is_cross_build():
              self.want_cross = not kwargs['native']
          else:
              self.want_cross = self.env.is_cross_build()
          # Set the compiler that will be used by this dependency
          # This is only used for configuration checks
          if self.want_cross:
              compilers = self.env.coredata.cross_compilers
          else:
              compilers = self.env.coredata.compilers
          self.compiler = compilers.get(self.language or 'c', None)
  
      def get_compiler(self):
          return self.compiler
  
  
  class ConfigToolDependency(ExternalDependency):
  
      """Class representing dependencies found using a config tool."""
  
      tools = None
      tool_name = None
  
      def __init__(self, name, environment, language, kwargs):
          super().__init__('config-tool', environment, language, kwargs)
          self.name = name
          self.tools = listify(kwargs.get('tools', self.tools))
  
          req_version = kwargs.get('version', None)
          tool, version = self.find_config(req_version)
          self.config = tool
          self.is_found = self.report_config(version, req_version)
          if not self.is_found:
              self.config = None
              return
          self.version = version
  
      def find_config(self, versions=None):
          """Helper method that searchs for config tool binaries in PATH and
          returns the one that best matches the given version requirements.
          """
          if not isinstance(versions, list) and versions is not None:
              versions = listify(versions)
  
          best_match = (None, None)
          for tool in self.tools:
              try:
                  p, out = Popen_safe([tool, '--version'])[:2]
              except (FileNotFoundError, PermissionError):
                  continue
              if p.returncode != 0:
                  continue
  
              out = out.strip()
              # Some tools, like pcap-config don't supply a version, but also
              # dont fail with --version, in that case just assume that there is
              # only one verison and return it.
              if not out:
                  return (tool, 'none')
              if versions:
                  is_found = version_compare_many(out, versions)[0]
                  # This allows returning a found version without a config tool,
                  # which is useful to inform the user that you found version x,
                  # but y was required.
                  if not is_found:
                      tool = None
              if best_match[1]:
                  if version_compare(out, '> {}'.format(best_match[1])):
                      best_match = (tool, out)
              else:
                  best_match = (tool, out)
  
          return best_match
  
      def report_config(self, version, req_version):
          """Helper method to print messages about the tool."""
          if self.config is None:
              if version is not None:
                  mlog.log('found {} {!r} but need:'.format(self.tool_name, version),
                           req_version)
              else:
                  mlog.log("No {} found; can't detect dependency".format(self.tool_name))
              mlog.log('Dependency {} found:'.format(self.name), mlog.red('NO'))
              if self.required:
                  raise DependencyException('Dependency {} not found'.format(self.name))
              return False
          mlog.log('Found {}:'.format
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/dependencies/base.py
files.old_contents: # 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 external dependencies.
  # Custom logic for several other packages are in separate files.
  
  import os
  import sys
  import stat
  import shlex
  import shutil
  from enum import Enum
  
  from .. import mlog
  from .. import mesonlib
  from ..mesonlib import MesonException, Popen_safe, version_compare_many, listify
  
  
  # These must be defined in this file to avoid cyclical references.
  packages = {}
  _packages_accept_language = set()
  
  
  class DependencyException(MesonException):
      '''Exceptions raised while trying to find dependencies'''
  
  
  class DependencyMethods(Enum):
      # Auto means to use whatever dependency checking mechanisms in whatever order meson thinks is best.
      AUTO = 'auto'
      PKGCONFIG = 'pkg-config'
      QMAKE = 'qmake'
      # Just specify the standard link arguments, assuming the operating system provides the library.
      SYSTEM = 'system'
      # Detect using sdl2-config
      SDLCONFIG = 'sdlconfig'
      # Detect using pcap-config
      PCAPCONFIG = 'pcap-config'
      # Detect using cups-config
      CUPSCONFIG = 'cups-config'
      # Detect using libwmf-config
      LIBWMFCONFIG = 'libwmf-config'
      # This is only supported on OSX - search the frameworks directory by name.
      EXTRAFRAMEWORK = 'extraframework'
      # Detect using the sysconfig module.
      SYSCONFIG = 'sysconfig'
  
  
  class Dependency:
      def __init__(self, type_name, kwargs):
          self.name = "null"
          self.version = 'none'
          self.language = None # None means C-like
          self.is_found = False
          self.type_name = type_name
          self.compile_args = []
          self.link_args = []
          self.sources = []
          method = kwargs.get('method', 'auto')
          if method not in [e.value for e in DependencyMethods]:
              raise DependencyException('method {!r} is invalid'.format(method))
          method = DependencyMethods(method)
  
          # Set the detection method. If the method is set to auto, use any available method.
          # If method is set to a specific string, allow only that detection method.
          if method == DependencyMethods.AUTO:
              self.methods = self.get_methods()
          elif method in self.get_methods():
              self.methods = [method]
          else:
              raise DependencyException(
                  'Unsupported detection method: {}, allowed methods are {}'.format(
                      method.value,
                      mlog.format_list([x.value for x in [DependencyMethods.AUTO] + self.get_methods()])))
  
      def __repr__(self):
          s = '<{0} {1}: {2}>'
          return s.format(self.__class__.__name__, self.name, self.is_found)
  
      def get_compile_args(self):
          return self.compile_args
  
      def get_link_args(self):
          return self.link_args
  
      def found(self):
          return self.is_found
  
      def get_sources(self):
          """Source files that need to be added to the target.
          As an example, gtest-all.cc when using GTest."""
          return self.sources
  
      def get_methods(self):
          return [DependencyMethods.AUTO]
  
      def get_name(self):
          return self.name
  
      def get_version(self):
          return self.version
  
      def get_exe_args(self, compiler):
          return []
  
      def need_threads(self):
          return False
  
      def get_pkgconfig_variable(self, variable_name):
          raise NotImplementedError('{!r} is not a pkgconfig dependency'.format(self.name))
  
  
  class InternalDependency(Dependency):
      def __init__(self, version, incdirs, compile_args, link_args, libraries, sources, ext_deps):
          super().__init__('internal', {})
          self.version = version
          self.is_found = True
          self.include_directories = incdirs
          self.compile_args = compile_args
          self.link_args = link_args
          self.libraries = libraries
          self.sources = sources
          self.ext_deps = ext_deps
  
  
  class ExternalDependency(Dependency):
      def __init__(self, type_name, environment, language, kwargs):
          super().__init__(type_name, kwargs)
          self.env = environment
          self.name = type_name # default
          self.is_found = False
          self.language = language
          if language and language not in self.env.coredata.compilers:
              m = self.name.capitalize() + ' requires a {} compiler'
              raise DependencyException(m.format(language.capitalize()))
          self.version_reqs = kwargs.get('version', None)
          self.required = kwargs.get('required', True)
          self.silent = kwargs.get('silent', False)
          self.static = kwargs.get('static', False)
          if not isinstance(self.static, bool):
              raise DependencyException('Static keyword must be boolean')
          # Is this dependency for cross-compilation?
          if 'native' in kwargs and self.env.is_cross_build():
              self.want_cross = not kwargs['native']
          else:
              self.want_cross = self.env.is_cross_build()
          # Set the compiler that will be used by this dependency
          # This is only used for configuration checks
          if self.want_cross:
              compilers = self.env.coredata.cross_compilers
          else:
              compilers = self.env.coredata.compilers
          self.compiler = compilers.get(self.language or 'c', None)
  
      def get_compiler(self):
          return self.compiler
  
  
  class PkgConfigDependency(ExternalDependency):
      # The class's copy of the pkg-config path. Avoids having to search for it
      # multiple times in the same Meson invocation.
      class_pkgbin = None
  
      def __init__(self, name, environment, kwargs):
          super().__init__('pkgconfig', environment, None, kwargs)
          self.name = name
          self.is_libtool = False
          # Store a copy of the pkg-config path on the object itself so it is
          # stored in the pickled coredata and recovered.
          self.pkgbin = None
  
          # When finding dependencies for cross-compiling, we don't care about
          # the 'native' pkg-config
          if self.want_cross:
              if 'pkgconfig' not in environment.cross_info.config['binaries']:
                  if self.required:
                      raise DependencyException('Pkg-config binary missing from cross file')
              else:
                  pkgname = environment.cross_info.config['binaries']['pkgconfig']
                  potential_pkgbin = ExternalProgram(pkgname, silent=True)
                  if potential_pkgbin.found():
                      # FIXME, we should store all pkg-configs in ExternalPrograms.
                      # However that is too destabilizing a change to do just before release.
                      self.pkgbin = potential_pkgbin.get_command()[0]
                      PkgConfigDependency.class_pkgbin = self.pkgbin
                  else:
                      mlog.debug('Cross pkg-config %s not found.' % potential_pkgbin.name)
          # Only search for the native pkg-config the first time and
          # store the result in the class definition
          elif PkgConfigDependency.class_pkgbin is None:
              self.pkgbin = self.check_pkgconfig()
              PkgConfigDependency.class_pkgbin = self.pkgbin
          else:
              self.pkgbin = PkgConfigDependency.class_pkgbin
  
          if not self.pkgbin:
              if self.required:
                  raise DependencyException('Pkg-config not found.')
              return
          if self.want_cross:
              self.type_string = 'Cross'
          else:
              self.type_string = 'Native'
  
          mlog.debug('Determining dependency {!r} with pkg-config executable '
                     '{!r}'.format(name, self.pkgbin))
          ret, self.version = self._call_pkgbin(['--modversion', name])
          if ret != 0:
              if self.required:
                  raise DependencyException('{} dependency {!r} not found'
                                            ''.format(self.type_string, name))
              return
          found_msg = [self.type_string + ' dependency', mlog.bold(name), 'found:']
          if self.version_reqs is None:
              self.is_found = True
          else:
              if not isinstance(self.version_reqs, (str, list)):
                  raise DependencyException('Version argument
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/dependencies/base.py