files: # Copyright 2012-2016 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.
  
  import os, pickle, re
  from .. import build
  from .. import dependencies
  from .. import mesonlib
  from .. import mlog
  from .. import compilers
  import json
  import subprocess
  from ..mesonlib import MesonException, OrderedSet
  from ..mesonlib import classify_unity_sources
  from ..mesonlib import File
  from ..compilers import CompilerArgs
  from collections import OrderedDict
  import shlex
  
  class CleanTrees:
      '''
      Directories outputted by custom targets that have to be manually cleaned
      because on Linux `ninja clean` only deletes empty directories.
      '''
      def __init__(self, build_dir, trees):
          self.build_dir = build_dir
          self.trees = trees
  
  class InstallData:
      def __init__(self, source_dir, build_dir, prefix, strip_bin,
                   install_umask, mesonintrospect):
          self.source_dir = source_dir
          self.build_dir = build_dir
          self.prefix = prefix
          self.strip_bin = strip_bin
          self.install_umask = install_umask
          self.targets = []
          self.headers = []
          self.man = []
          self.data = []
          self.po_package_name = ''
          self.po = []
          self.install_scripts = []
          self.install_subdirs = []
          self.mesonintrospect = mesonintrospect
  
  class TargetInstallData:
      def __init__(self, fname, outdir, aliases, strip, install_name_mappings, install_rpath, install_mode):
          self.fname = fname
          self.outdir = outdir
          self.aliases = aliases
          self.strip = strip
          self.install_name_mappings = install_name_mappings
          self.install_rpath = install_rpath
          self.install_mode = install_mode
  
  class ExecutableSerialisation:
      def __init__(self, name, fname, cmd_args, env, is_cross, exe_wrapper,
                   workdir, extra_paths, capture):
          self.name = name
          self.fname = fname
          self.cmd_args = cmd_args
          self.env = env
          self.is_cross = is_cross
          self.exe_runner = exe_wrapper
          self.workdir = workdir
          self.extra_paths = extra_paths
          self.capture = capture
  
  class TestSerialisation:
      def __init__(self, name, project, suite, fname, is_cross_built, exe_wrapper, is_parallel,
                   cmd_args, env, should_fail, timeout, workdir, extra_paths):
          self.name = name
          self.project_name = project
          self.suite = suite
          self.fname = fname
          self.is_cross_built = is_cross_built
          self.exe_runner = exe_wrapper
          self.is_parallel = is_parallel
          self.cmd_args = cmd_args
          self.env = env
          self.should_fail = should_fail
          self.timeout = timeout
          self.workdir = workdir
          self.extra_paths = extra_paths
  
  class OptionProxy:
      def __init__(self, name, value):
          self.name = name
          self.value = value
  
  class OptionOverrideProxy:
      '''Mimic an option list but transparently override
      selected option values.'''
      def __init__(self, overrides, *options):
          self.overrides = overrides
          self.options = options
  
      def __getitem__(self, option_name):
          for opts in self.options:
              if option_name in opts:
                  return self._get_override(option_name, opts[option_name])
          raise KeyError('Option not found', option_name)
  
      def _get_override(self, option_name, base_opt):
          if option_name in self.overrides:
              return OptionProxy(base_opt.name, base_opt.validate_value(self.overrides[option_name]))
          return base_opt
  
  # This class contains the basic functionality that is needed by all backends.
  # Feel free to move stuff in and out of it as you see fit.
  class Backend:
      def __init__(self, build):
          self.build = build
          self.environment = build.environment
          self.processed_targets = {}
          self.build_to_src = os.path.relpath(self.environment.get_source_dir(),
                                              self.environment.get_build_dir())
  
      def get_target_filename(self, t):
          if isinstance(t, build.CustomTarget):
              if len(t.get_outputs()) != 1:
                  mlog.warning('custom_target {!r} has more than one output! '
                               'Using the first one.'.format(t.name))
              filename = t.get_outputs()[0]
          else:
              assert(isinstance(t, build.BuildTarget))
              filename = t.get_filename()
          return os.path.join(self.get_target_dir(t), filename)
  
      def get_target_filename_abs(self, target):
          return os.path.join(self.environment.get_build_dir(), self.get_target_filename(target))
  
      def get_builtin_options_for_target(self, target):
          return OptionOverrideProxy(target.option_overrides,
                                     self.environment.coredata.builtins)
  
      def get_base_options_for_target(self, target):
          return OptionOverrideProxy(target.option_overrides,
                                     self.environment.coredata.builtins,
                                     self.environment.coredata.base_options)
  
      def get_compiler_options_for_target(self, target):
          return OptionOverrideProxy(target.option_overrides,
                                     # no code depends on builtins for now
                                     self.environment.coredata.compiler_options)
  
      def get_option_for_target(self, option_name, target):
          if option_name in target.option_overrides:
              override = target.option_overrides[option_name]
              return self.environment.coredata.validate_option_value(option_name, override)
          return self.environment.coredata.get_builtin_option(option_name)
  
      def get_target_filename_for_linking(self, target):
          # On some platforms (msvc for instance), the file that is used for
          # dynamic linking is not the same as the dynamic library itself. This
          # file is called an import library, and we want to link against that.
          # On all other platforms, we link to the library directly.
          if isinstance(target, build.SharedLibrary):
              link_lib = target.get_import_filename() or target.get_filename()
              return os.path.join(self.get_target_dir(target), link_lib)
          elif isinstance(target, build.StaticLibrary):
              return os.path.join(self.get_target_dir(target), target.get_filename())
          elif isinstance(target, build.Executable):
              if target.import_filename:
                  return os.path.join(self.get_target_dir(target), target.get_import_filename())
              else:
                  return None
          raise AssertionError('BUG: Tried to link to {!r} which is not linkable'.format(target))
  
      def get_target_dir(self, target):
          if self.environment.coredata.get_builtin_option('layout') == 'mirror':
              dirname = target.get_subdir()
          else:
              dirname = 'meson-out'
          return dirname
  
      def get_target_dir_relative_to(self, t, o):
          '''Get a target dir relative to another target's directory'''
          target_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(t))
          othert_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(o))
          return os.path.relpath(target_dir, othert_dir)
  
      def get_target_source_dir(self, target):
          # if target dir is empty, avoid extraneous trailing / from os.path.join()
          target_dir = self.get_target_dir(target)
          if target_dir:
              return os.path.join(self.build_to_src, target_dir)
          return self.build_to_src
  
      def get_target_private_dir(self, target):
          return os.path.join(self.get_target_dir(target), target.get_id())
  
      def get_target_private_dir_abs(self, target):
          return os.path.join(self.environment.get_build_dir(), self.get_target_private_dir(target))
  
      def get_target_generated_dir(self, target, gensrc, src):
          """
          Takes a BuildTarget, a generator source (CustomTarget or GeneratedList),
          and a generated source filename.
          Returns the full path of the generated source relative to the build root
          """
          # CustomTarget generators output to the build dir of the CustomTarget
          if isinstance(gensrc, (build.CustomTarget, build.CustomTargetIndex)):
              return os.path.join(self.get_target_dir(gensrc), src)
          # GeneratedList generators output to the private build directory of the
          # target that the GeneratedList is used in
          return os.path.join(self.get_target_private_dir(target), src)
  
      def get_unity_source_file(self, target, suffix):
          # There is a potential conflict here, but it is unlikely that
          # anyone both enables unity builds and has a file called foo-unity.cpp.
          osrc = target.name + '-unity.' + suffix
          return mesonlib.File.from_built_file(self.get_target_private_dir(target), osrc)
  
      def generate_unity_files(self, target, unity_src):
          abs_files = []
          result = []
          compsrcs = classify_unity_sources(target.compilers.values(), unity_src)
  
          def init_language_file(suffix):
              unity_src = self.get_unity_source_file(target, suffix)
              outfileabs = unity_src.absolute_path(self.environment.get_source_dir(),
                                                   self.environment.get_build_dir())
              outfileabs_tmp = outfileabs + '.tmp'
              abs_files.append(outfileabs)
              outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp)
              if not os.path.exists(outfileabs_tmp_dir):
                 
  
  [... the rest is omitted ...]
files: mesonbuild/backend/backends.py
files: # Copyright 2012-2016 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.
  
  import os, pickle, re
  from .. import build
  from .. import dependencies
  from .. import mesonlib
  from .. import mlog
  from .. import compilers
  import json
  import subprocess
  from ..mesonlib import MesonException, OrderedSet
  from ..mesonlib import classify_unity_sources
  from ..mesonlib import File
  from ..compilers import CompilerArgs
  from collections import OrderedDict
  import shlex
  
  class CleanTrees:
      '''
      Directories outputted by custom targets that have to be manually cleaned
      because on Linux `ninja clean` only deletes empty directories.
      '''
      def __init__(self, build_dir, trees):
          self.build_dir = build_dir
          self.trees = trees
  
  class InstallData:
      def __init__(self, source_dir, build_dir, prefix, strip_bin,
                   install_umask, mesonintrospect):
          self.source_dir = source_dir
          self.build_dir = build_dir
          self.prefix = prefix
          self.strip_bin = strip_bin
          self.install_umask = install_umask
          self.targets = []
          self.headers = []
          self.man = []
          self.data = []
          self.po_package_name = ''
          self.po = []
          self.install_scripts = []
          self.install_subdirs = []
          self.mesonintrospect = mesonintrospect
  
  class TargetInstallData:
      def __init__(self, fname, outdir, aliases, strip, install_name_mappings, install_rpath, install_mode):
          self.fname = fname
          self.outdir = outdir
          self.aliases = aliases
          self.strip = strip
          self.install_name_mappings = install_name_mappings
          self.install_rpath = install_rpath
          self.install_mode = install_mode
  
  class ExecutableSerialisation:
      def __init__(self, name, fname, cmd_args, env, is_cross, exe_wrapper,
                   workdir, extra_paths, capture):
          self.name = name
          self.fname = fname
          self.cmd_args = cmd_args
          self.env = env
          self.is_cross = is_cross
          self.exe_runner = exe_wrapper
          self.workdir = workdir
          self.extra_paths = extra_paths
          self.capture = capture
  
  class TestSerialisation:
      def __init__(self, name, project, suite, fname, is_cross_built, exe_wrapper, is_parallel,
                   cmd_args, env, should_fail, timeout, workdir, extra_paths):
          self.name = name
          self.project_name = project
          self.suite = suite
          self.fname = fname
          self.is_cross_built = is_cross_built
          self.exe_runner = exe_wrapper
          self.is_parallel = is_parallel
          self.cmd_args = cmd_args
          self.env = env
          self.should_fail = should_fail
          self.timeout = timeout
          self.workdir = workdir
          self.extra_paths = extra_paths
  
  class OptionProxy:
      def __init__(self, name, value):
          self.name = name
          self.value = value
  
  class OptionOverrideProxy:
      '''Mimic an option list but transparently override
      selected option values.'''
      def __init__(self, overrides, *options):
          self.overrides = overrides
          self.options = options
  
      def __getitem__(self, option_name):
          for opts in self.options:
              if option_name in opts:
                  return self._get_override(option_name, opts[option_name])
          raise KeyError('Option not found', option_name)
  
      def _get_override(self, option_name, base_opt):
          if option_name in self.overrides:
              return OptionProxy(base_opt.name, base_opt.validate_value(self.overrides[option_name]))
          return base_opt
  
  # This class contains the basic functionality that is needed by all backends.
  # Feel free to move stuff in and out of it as you see fit.
  class Backend:
      def __init__(self, build):
          self.build = build
          self.environment = build.environment
          self.processed_targets = {}
          self.build_to_src = os.path.relpath(self.environment.get_source_dir(),
                                              self.environment.get_build_dir())
  
      def get_target_filename(self, t):
          if isinstance(t, build.CustomTarget):
              if len(t.get_outputs()) != 1:
                  mlog.warning('custom_target {!r} has more than one output! '
                               'Using the first one.'.format(t.name))
              filename = t.get_outputs()[0]
          else:
              assert(isinstance(t, build.BuildTarget))
              filename = t.get_filename()
          return os.path.join(self.get_target_dir(t), filename)
  
      def get_target_filename_abs(self, target):
          return os.path.join(self.environment.get_build_dir(), self.get_target_filename(target))
  
      def get_builtin_options_for_target(self, target):
          return OptionOverrideProxy(target.option_overrides,
                                     self.environment.coredata.builtins)
  
      def get_base_options_for_target(self, target):
          return OptionOverrideProxy(target.option_overrides,
                                     self.environment.coredata.builtins,
                                     self.environment.coredata.base_options)
  
      def get_compiler_options_for_target(self, target):
          return OptionOverrideProxy(target.option_overrides,
                                     # no code depends on builtins for now
                                     self.environment.coredata.compiler_options)
  
      def get_option_for_target(self, option_name, target):
          if option_name in target.option_overrides:
              override = target.option_overrides[option_name]
              return self.environment.coredata.validate_option_value(option_name, override)
          return self.environment.coredata.get_builtin_option(option_name)
  
      def get_target_filename_for_linking(self, target):
          # On some platforms (msvc for instance), the file that is used for
          # dynamic linking is not the same as the dynamic library itself. This
          # file is called an import library, and we want to link against that.
          # On all other platforms, we link to the library directly.
          if isinstance(target, build.SharedLibrary):
              link_lib = target.get_import_filename() or target.get_filename()
              return os.path.join(self.get_target_dir(target), link_lib)
          elif isinstance(target, build.StaticLibrary):
              return os.path.join(self.get_target_dir(target), target.get_filename())
          elif isinstance(target, build.Executable):
              if target.import_filename:
                  return os.path.join(self.get_target_dir(target), target.get_import_filename())
              else:
                  return None
          raise AssertionError('BUG: Tried to link to {!r} which is not linkable'.format(target))
  
      def get_target_dir(self, target):
          if self.environment.coredata.get_builtin_option('layout') == 'mirror':
              dirname = target.get_subdir()
          else:
              dirname = 'meson-out'
          return dirname
  
      def get_target_dir_relative_to(self, t, o):
          '''Get a target dir relative to another target's directory'''
          target_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(t))
          othert_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(o))
          return os.path.relpath(target_dir, othert_dir)
  
      def get_target_source_dir(self, target):
          # if target dir is empty, avoid extraneous trailing / from os.path.join()
          target_dir = self.get_target_dir(target)
          if target_dir:
              return os.path.join(self.build_to_src, target_dir)
          return self.build_to_src
  
      def get_target_private_dir(self, target):
          return os.path.join(self.get_target_dir(target), target.get_id())
  
      def get_target_private_dir_abs(self, target):
          return os.path.join(self.environment.get_build_dir(), self.get_target_private_dir(target))
  
      def get_target_generated_dir(self, target, gensrc, src):
          """
          Takes a BuildTarget, a generator source (CustomTarget or GeneratedList),
          and a generated source filename.
          Returns the full path of the generated source relative to the build root
          """
          # CustomTarget generators output to the build dir of the CustomTarget
          if isinstance(gensrc, (build.CustomTarget, build.CustomTargetIndex)):
              return os.path.join(self.get_target_dir(gensrc), src)
          # GeneratedList generators output to the private build directory of the
          # target that the GeneratedList is used in
          return os.path.join(self.get_target_private_dir(target), src)
  
      def get_unity_source_file(self, target, suffix):
          # There is a potential conflict here, but it is unlikely that
          # anyone both enables unity builds and has a file called foo-unity.cpp.
          osrc = target.name + '-unity.' + suffix
          return mesonlib.File.from_built_file(self.get_target_private_dir(target), osrc)
  
      def generate_unity_files(self, target, unity_src):
          abs_files = []
          result = []
          compsrcs = classify_unity_sources(target.compilers.values(), unity_src)
  
          def init_language_file(suffix):
              unity_src = self.get_unity_source_file(target, suffix)
              outfileabs = unity_src.absolute_path(self.environment.get_source_dir(),
                                                   self.environment.get_build_dir())
              outfileabs_tmp = outfileabs + '.tmp'
              abs_files.append(outfileabs)
              outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp)
              if not os.path.exists(outfileabs_tmp_dir):
                 
  
  [... the rest is omitted ...]
files: mesonbuild/backend/backends.py
files: # Copyright 2012-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.
  
  import copy, os, re
  from collections import OrderedDict
  import itertools, pathlib
  import pickle
  
  from . import environment
  from . import dependencies
  from . import mlog
  from .mesonlib import File, MesonException, listify, extract_as_list
  from .mesonlib import typeslistify, stringlistify, classify_unity_sources
  from .mesonlib import get_filenames_templates_dict, substitute_values
  from .mesonlib import for_windows, for_darwin, for_cygwin, for_android, has_path_sep
  from .compilers import is_object, clink_langs, sort_clink, lang_suffixes
  from .interpreterbase import FeatureNew, FeatureNewKwargs
  
  pch_kwargs = set(['c_pch', 'cpp_pch'])
  
  lang_arg_kwargs = set([
      'c_args',
      'cpp_args',
      'd_args',
      'd_import_dirs',
      'd_unittest',
      'd_module_versions',
      'fortran_args',
      'java_args',
      'objc_args',
      'objcpp_args',
      'rust_args',
      'vala_args',
      'cs_args',
  ])
  
  vala_kwargs = set(['vala_header', 'vala_gir', 'vala_vapi'])
  rust_kwargs = set(['rust_crate_type'])
  cs_kwargs = set(['resources', 'cs_args'])
  
  buildtarget_kwargs = set([
      'build_by_default',
      'build_rpath',
      'dependencies',
      'extra_files',
      'gui_app',
      'link_with',
      'link_whole',
      'link_args',
      'link_depends',
      'implicit_include_directories',
      'include_directories',
      'install',
      'install_rpath',
      'install_dir',
      'install_mode',
      'name_prefix',
      'name_suffix',
      'native',
      'objects',
      'override_options',
      'sources',
  ])
  
  known_build_target_kwargs = (
      buildtarget_kwargs |
      lang_arg_kwargs |
      pch_kwargs |
      vala_kwargs |
      rust_kwargs |
      cs_kwargs)
  
  known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic'}
  known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs'}
  known_shmod_kwargs = known_build_target_kwargs
  known_stlib_kwargs = known_build_target_kwargs | {'pic'}
  known_jar_kwargs = known_exe_kwargs | {'main_class'}
  
  class InvalidArguments(MesonException):
      pass
  
  class Build:
      """A class that holds the status of one build including
      all dependencies and so on.
      """
  
      def __init__(self, environment):
          self.project_name = 'name of master project'
          self.project_version = None
          self.environment = environment
          self.projects = {}
          self.targets = OrderedDict()
          self.compilers = OrderedDict()
          self.cross_compilers = OrderedDict()
          self.global_args = {}
          self.projects_args = {}
          self.global_link_args = {}
          self.projects_link_args = {}
          self.tests = []
          self.benchmarks = []
          self.headers = []
          self.man = []
          self.data = []
          self.static_linker = None
          self.static_cross_linker = None
          self.subprojects = {}
          self.subproject_dir = ''
          self.install_scripts = []
          self.postconf_scripts = []
          self.install_dirs = []
          self.dep_manifest_name = None
          self.dep_manifest = {}
          self.cross_stdlibs = {}
          self.test_setups = {}
          self.find_overrides = {}
          self.searched_programs = set() # The list of all programs that have been searched for.
  
      def add_compiler(self, compiler):
          if self.static_linker is None and compiler.needs_static_linker():
              self.static_linker = self.environment.detect_static_linker(compiler)
          lang = compiler.get_language()
          if lang not in self.compilers:
              self.compilers[lang] = compiler
  
      def add_cross_compiler(self, compiler):
          if not self.cross_compilers:
              self.static_cross_linker = self.environment.detect_static_linker(compiler)
          lang = compiler.get_language()
          if lang not in self.cross_compilers:
              self.cross_compilers[lang] = compiler
  
      def get_project(self):
          return self.projects['']
  
      def get_subproject_dir(self):
          return self.subproject_dir
  
      def get_targets(self):
          return self.targets
  
      def get_tests(self):
          return self.tests
  
      def get_benchmarks(self):
          return self.benchmarks
  
      def get_headers(self):
          return self.headers
  
      def get_man(self):
          return self.man
  
      def get_data(self):
          return self.data
  
      def get_install_subdirs(self):
          return self.install_dirs
  
      def get_global_args(self, compiler):
          return self.global_args.get(compiler.get_language(), [])
  
      def get_project_args(self, compiler, project):
          args = self.projects_args.get(project)
          if not args:
              return []
          return args.get(compiler.get_language(), [])
  
      def get_global_link_args(self, compiler):
          return self.global_link_args.get(compiler.get_language(), [])
  
      def get_project_link_args(self, compiler, project):
          link_args = self.projects_link_args.get(project)
          if not link_args:
              return []
  
          return link_args.get(compiler.get_language(), [])
  
  class IncludeDirs:
      def __init__(self, curdir, dirs, is_system, extra_build_dirs=None):
          self.curdir = curdir
          self.incdirs = dirs
          self.is_system = is_system
          # Interpreter has validated that all given directories
          # actually exist.
          if extra_build_dirs is None:
              self.extra_build_dirs = []
          else:
              self.extra_build_dirs = extra_build_dirs
  
      def __repr__(self):
          r = '<{} {}/{}>'
          return r.format(self.__class__.__name__, self.curdir, self.incdirs)
  
      def get_curdir(self):
          return self.curdir
  
      def get_incdirs(self):
          return self.incdirs
  
      def get_extra_build_dirs(self):
          return self.extra_build_dirs
  
  class ExtractedObjects:
      '''
      Holds a list of sources for which the objects must be extracted
      '''
      def __init__(self, target, srclist=[], genlist=[], objlist=[], recursive=True):
          self.target = target
          self.recursive = recursive
          self.srclist = srclist
          self.genlist = genlist
          self.objlist = objlist
          if self.target.is_unity:
              self.check_unity_compatible()
  
      def __repr__(self):
          r = '<{0} {1!r}: {2}>'
          return r.format(self.__class__.__name__, self.target.name, self.srclist)
  
      def classify_all_sources(self, sources, generated_sources):
          # Merge sources and generated sources
          sources = list(sources)
          for gensrc in generated_sources:
              for s in gensrc.get_outputs():
                  # We cannot know the path where this source will be generated,
                  # but all we need here is the file extension to determine the
                  # compiler.
                  sources.append(s)
  
          # Filter out headers and all non-source files
          sources = [s for s in sources if environment.is_source(s) and not environment.is_header(s)]
  
          return classify_unity_sources(self.target.compilers.values(), sources)
  
      def check_unity_compatible(self):
          # Figure out if the extracted object list is compatible with a Unity
          # build. When we're doing a Unified build, we go through the sources,
          # and create a single source file from each subset of the sources that
          # can be compiled with a specific compiler. Then we create one object
          # from each unified source file. So for each compiler we can either
          # extra all its sources or none.
          cmpsrcs = self.classify_all_sources(self.target.sources, self.target.generated)
          extracted_cmpsrcs = self.classify_all_sources(self.srclist, self.genlist)
  
          for comp, srcs in extracted_cmpsrcs.items():
              if set(srcs) != set(cmpsrcs[comp]):
                  raise MesonException('Single object files can not be extracted '
                                       'in Unity builds. You can only extract all '
                                       'the object files for each compiler at once.')
  
  class EnvironmentVariables:
      def __init__(self):
          self.envvars = []
  
      def __repr__(self):
          repr_str = "<{0}: {1}>"
          return repr_str.format(self.__class__.__name__, self.envvars)
  
      def get_value(self, values, kwargs):
          separator = kwargs.get('separator', os.pathsep)
  
          value = ''
          for var in values:
              value += separator + var
          return separator, value.strip(separator)
  
      def set(self, env, name, values, kwargs):
          return self.get_value(values, kwargs)[1]
  
      def append(self, env, name, values, kwargs):
          sep, value = self.get_value(values, kwargs)
          if name in env:
             
  
  [... the rest is omitted ...]
files: mesonbuild/build.py
files: # Copyright 2012-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.
  
  import copy, os, re
  from collections import OrderedDict
  import itertools, pathlib
  import pickle
  
  from . import environment
  from . import dependencies
  from . import mlog
  from .mesonlib import File, MesonException, listify, extract_as_list
  from .mesonlib import typeslistify, stringlistify, classify_unity_sources
  from .mesonlib import get_filenames_templates_dict, substitute_values
  from .mesonlib import for_windows, for_darwin, for_cygwin, for_android, has_path_sep
  from .compilers import is_object, clike_langs, sort_clike, lang_suffixes
  from .interpreterbase import FeatureNew, FeatureNewKwargs
  
  pch_kwargs = set(['c_pch', 'cpp_pch'])
  
  lang_arg_kwargs = set([
      'c_args',
      'cpp_args',
      'd_args',
      'd_import_dirs',
      'd_unittest',
      'd_module_versions',
      'fortran_args',
      'java_args',
      'objc_args',
      'objcpp_args',
      'rust_args',
      'vala_args',
      'cs_args',
  ])
  
  vala_kwargs = set(['vala_header', 'vala_gir', 'vala_vapi'])
  rust_kwargs = set(['rust_crate_type'])
  cs_kwargs = set(['resources', 'cs_args'])
  
  buildtarget_kwargs = set([
      'build_by_default',
      'build_rpath',
      'dependencies',
      'extra_files',
      'gui_app',
      'link_with',
      'link_whole',
      'link_args',
      'link_depends',
      'implicit_include_directories',
      'include_directories',
      'install',
      'install_rpath',
      'install_dir',
      'install_mode',
      'name_prefix',
      'name_suffix',
      'native',
      'objects',
      'override_options',
      'sources',
  ])
  
  known_build_target_kwargs = (
      buildtarget_kwargs |
      lang_arg_kwargs |
      pch_kwargs |
      vala_kwargs |
      rust_kwargs |
      cs_kwargs)
  
  known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic'}
  known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs'}
  known_shmod_kwargs = known_build_target_kwargs
  known_stlib_kwargs = known_build_target_kwargs | {'pic'}
  known_jar_kwargs = known_exe_kwargs | {'main_class'}
  
  class InvalidArguments(MesonException):
      pass
  
  class Build:
      """A class that holds the status of one build including
      all dependencies and so on.
      """
  
      def __init__(self, environment):
          self.project_name = 'name of master project'
          self.project_version = None
          self.environment = environment
          self.projects = {}
          self.targets = OrderedDict()
          self.compilers = OrderedDict()
          self.cross_compilers = OrderedDict()
          self.global_args = {}
          self.projects_args = {}
          self.global_link_args = {}
          self.projects_link_args = {}
          self.tests = []
          self.benchmarks = []
          self.headers = []
          self.man = []
          self.data = []
          self.static_linker = None
          self.static_cross_linker = None
          self.subprojects = {}
          self.subproject_dir = ''
          self.install_scripts = []
          self.postconf_scripts = []
          self.install_dirs = []
          self.dep_manifest_name = None
          self.dep_manifest = {}
          self.cross_stdlibs = {}
          self.test_setups = {}
          self.find_overrides = {}
          self.searched_programs = set() # The list of all programs that have been searched for.
  
      def add_compiler(self, compiler):
          if self.static_linker is None and compiler.needs_static_linker():
              self.static_linker = self.environment.detect_static_linker(compiler)
          lang = compiler.get_language()
          if lang not in self.compilers:
              self.compilers[lang] = compiler
  
      def add_cross_compiler(self, compiler):
          if not self.cross_compilers:
              self.static_cross_linker = self.environment.detect_static_linker(compiler)
          lang = compiler.get_language()
          if lang not in self.cross_compilers:
              self.cross_compilers[lang] = compiler
  
      def get_project(self):
          return self.projects['']
  
      def get_subproject_dir(self):
          return self.subproject_dir
  
      def get_targets(self):
          return self.targets
  
      def get_tests(self):
          return self.tests
  
      def get_benchmarks(self):
          return self.benchmarks
  
      def get_headers(self):
          return self.headers
  
      def get_man(self):
          return self.man
  
      def get_data(self):
          return self.data
  
      def get_install_subdirs(self):
          return self.install_dirs
  
      def get_global_args(self, compiler):
          return self.global_args.get(compiler.get_language(), [])
  
      def get_project_args(self, compiler, project):
          args = self.projects_args.get(project)
          if not args:
              return []
          return args.get(compiler.get_language(), [])
  
      def get_global_link_args(self, compiler):
          return self.global_link_args.get(compiler.get_language(), [])
  
      def get_project_link_args(self, compiler, project):
          link_args = self.projects_link_args.get(project)
          if not link_args:
              return []
  
          return link_args.get(compiler.get_language(), [])
  
  class IncludeDirs:
      def __init__(self, curdir, dirs, is_system, extra_build_dirs=None):
          self.curdir = curdir
          self.incdirs = dirs
          self.is_system = is_system
          # Interpreter has validated that all given directories
          # actually exist.
          if extra_build_dirs is None:
              self.extra_build_dirs = []
          else:
              self.extra_build_dirs = extra_build_dirs
  
      def __repr__(self):
          r = '<{} {}/{}>'
          return r.format(self.__class__.__name__, self.curdir, self.incdirs)
  
      def get_curdir(self):
          return self.curdir
  
      def get_incdirs(self):
          return self.incdirs
  
      def get_extra_build_dirs(self):
          return self.extra_build_dirs
  
  class ExtractedObjects:
      '''
      Holds a list of sources for which the objects must be extracted
      '''
      def __init__(self, target, srclist=[], genlist=[], objlist=[], recursive=True):
          self.target = target
          self.recursive = recursive
          self.srclist = srclist
          self.genlist = genlist
          self.objlist = objlist
          if self.target.is_unity:
              self.check_unity_compatible()
  
      def __repr__(self):
          r = '<{0} {1!r}: {2}>'
          return r.format(self.__class__.__name__, self.target.name, self.srclist)
  
      def classify_all_sources(self, sources, generated_sources):
          # Merge sources and generated sources
          sources = list(sources)
          for gensrc in generated_sources:
              for s in gensrc.get_outputs():
                  # We cannot know the path where this source will be generated,
                  # but all we need here is the file extension to determine the
                  # compiler.
                  sources.append(s)
  
          # Filter out headers and all non-source files
          sources = [s for s in sources if environment.is_source(s) and not environment.is_header(s)]
  
          return classify_unity_sources(self.target.compilers.values(), sources)
  
      def check_unity_compatible(self):
          # Figure out if the extracted object list is compatible with a Unity
          # build. When we're doing a Unified build, we go through the sources,
          # and create a single source file from each subset of the sources that
          # can be compiled with a specific compiler. Then we create one object
          # from each unified source file. So for each compiler we can either
          # extra all its sources or none.
          cmpsrcs = self.classify_all_sources(self.target.sources, self.target.generated)
          extracted_cmpsrcs = self.classify_all_sources(self.srclist, self.genlist)
  
          for comp, srcs in extracted_cmpsrcs.items():
              if set(srcs) != set(cmpsrcs[comp]):
                  raise MesonException('Single object files can not be extracted '
                                       'in Unity builds. You can only extract all '
                                       'the object files for each compiler at once.')
  
  class EnvironmentVariables:
      def __init__(self):
          self.envvars = []
  
      def __repr__(self):
          repr_str = "<{0}: {1}>"
          return repr_str.format(self.__class__.__name__, self.envvars)
  
      def get_value(self, values, kwargs):
          separator = kwargs.get('separator', os.pathsep)
  
          value = ''
          for var in values:
              value += separator + var
          return separator, value.strip(separator)
  
      def set(self, env, name, values, kwargs):
          return self.get_value(values, kwargs)[1]
  
      def append(self, env, name, values, kwargs):
          sep, value = self.get_value(values, kwargs)
          if name in env:
             
  
  [... the rest is omitted ...]
files: mesonbuild/build.py
files: # Copyright 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.
  
  # Public symbols for compilers sub-package when using 'from . import compilers'
  __all__ = [
      'CLANG_OSX',
      'CLANG_STANDARD',
      'CLANG_WIN',
      'GCC_CYGWIN',
      'GCC_MINGW',
      'GCC_OSX',
      'GCC_STANDARD',
      'ICC_OSX',
      'ICC_STANDARD',
      'ICC_WIN',
  
      'all_languages',
      'base_options',
      'clib_langs',
      'clink_langs',
      'c_suffixes',
      'cpp_suffixes',
      'get_macos_dylib_install_name',
      'get_base_compile_args',
      'get_base_link_args',
      'is_assembly',
      'is_header',
      'is_library',
      'is_llvm_ir',
      'is_object',
      'is_source',
      'lang_suffixes',
      'sanitizer_compile_args',
      'sort_clink',
  
      'ArmCCompiler',
      'ArmCPPCompiler',
      'CCompiler',
      'ClangCCompiler',
      'ClangCompiler',
      'ClangCPPCompiler',
      'ClangObjCCompiler',
      'ClangObjCPPCompiler',
      'CompilerArgs',
      'CPPCompiler',
      'DCompiler',
      'DmdDCompiler',
      'FortranCompiler',
      'G95FortranCompiler',
      'GnuCCompiler',
      'ElbrusCCompiler',
      'GnuCompiler',
      'GnuCPPCompiler',
      'ElbrusCPPCompiler',
      'GnuDCompiler',
      'GnuFortranCompiler',
      'ElbrusFortranCompiler',
      'GnuObjCCompiler',
      'GnuObjCPPCompiler',
      'IntelCompiler',
      'IntelCCompiler',
      'IntelCPPCompiler',
      'IntelFortranCompiler',
      'JavaCompiler',
      'LLVMDCompiler',
      'MonoCompiler',
      'VisualStudioCsCompiler',
      'NAGFortranCompiler',
      'ObjCCompiler',
      'ObjCPPCompiler',
      'Open64FortranCompiler',
      'PathScaleFortranCompiler',
      'PGIFortranCompiler',
      'RustCompiler',
      'SunFortranCompiler',
      'SwiftCompiler',
      'ValaCompiler',
      'VisualStudioCCompiler',
      'VisualStudioCPPCompiler',
  ]
  
  # Bring symbols from each module into compilers sub-package namespace
  from .compilers import (
      GCC_OSX,
      GCC_MINGW,
      GCC_CYGWIN,
      GCC_STANDARD,
      CLANG_OSX,
      CLANG_WIN,
      CLANG_STANDARD,
      ICC_OSX,
      ICC_WIN,
      ICC_STANDARD,
      all_languages,
      base_options,
      clib_langs,
      clink_langs,
      c_suffixes,
      cpp_suffixes,
      get_macos_dylib_install_name,
      get_base_compile_args,
      get_base_link_args,
      is_header,
      is_source,
      is_assembly,
      is_llvm_ir,
      is_object,
      is_library,
      lang_suffixes,
      sanitizer_compile_args,
      sort_clink,
      ClangCompiler,
      CompilerArgs,
      GnuCompiler,
      IntelCompiler,
  )
  from .c import (
      ArmCCompiler,
      CCompiler,
      ClangCCompiler,
      GnuCCompiler,
      ElbrusCCompiler,
      IntelCCompiler,
      VisualStudioCCompiler,
  )
  from .cpp import (
      ArmCPPCompiler,
      CPPCompiler,
      ClangCPPCompiler,
      GnuCPPCompiler,
      ElbrusCPPCompiler,
      IntelCPPCompiler,
      VisualStudioCPPCompiler,
  )
  from .cs import MonoCompiler, VisualStudioCsCompiler
  from .d import (
      DCompiler,
      DmdDCompiler,
      GnuDCompiler,
      LLVMDCompiler,
  )
  from .fortran import (
      FortranCompiler,
      G95FortranCompiler,
      GnuFortranCompiler,
      ElbrusFortranCompiler,
      IntelFortranCompiler,
      NAGFortranCompiler,
      Open64FortranCompiler,
      PathScaleFortranCompiler,
      PGIFortranCompiler,
      SunFortranCompiler,
  )
  from .java import JavaCompiler
  from .objc import (
      ObjCCompiler,
      ClangObjCCompiler,
      GnuObjCCompiler,
  )
  from .objcpp import (
      ObjCPPCompiler,
      ClangObjCPPCompiler,
      GnuObjCPPCompiler,
  )
  from .rust import RustCompiler
  from .swift import SwiftCompiler
  from .vala import ValaCompiler
  
  
  [... the rest is omitted ...]
files: mesonbuild/compilers/__init__.py
files: # Copyright 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.
  
  # Public symbols for compilers sub-package when using 'from . import compilers'
  __all__ = [
      'CLANG_OSX',
      'CLANG_STANDARD',
      'CLANG_WIN',
      'GCC_CYGWIN',
      'GCC_MINGW',
      'GCC_OSX',
      'GCC_STANDARD',
      'ICC_OSX',
      'ICC_STANDARD',
      'ICC_WIN',
  
      'all_languages',
      'base_options',
      'clib_langs',
      'clike_langs',
      'c_suffixes',
      'cpp_suffixes',
      'get_macos_dylib_install_name',
      'get_base_compile_args',
      'get_base_link_args',
      'is_assembly',
      'is_header',
      'is_library',
      'is_llvm_ir',
      'is_object',
      'is_source',
      'lang_suffixes',
      'sanitizer_compile_args',
      'sort_clike',
  
      'ArmCCompiler',
      'ArmCPPCompiler',
      'CCompiler',
      'ClangCCompiler',
      'ClangCompiler',
      'ClangCPPCompiler',
      'ClangObjCCompiler',
      'ClangObjCPPCompiler',
      'CompilerArgs',
      'CPPCompiler',
      'DCompiler',
      'DmdDCompiler',
      'FortranCompiler',
      'G95FortranCompiler',
      'GnuCCompiler',
      'ElbrusCCompiler',
      'GnuCompiler',
      'GnuCPPCompiler',
      'ElbrusCPPCompiler',
      'GnuDCompiler',
      'GnuFortranCompiler',
      'ElbrusFortranCompiler',
      'GnuObjCCompiler',
      'GnuObjCPPCompiler',
      'IntelCompiler',
      'IntelCCompiler',
      'IntelCPPCompiler',
      'IntelFortranCompiler',
      'JavaCompiler',
      'LLVMDCompiler',
      'MonoCompiler',
      'VisualStudioCsCompiler',
      'NAGFortranCompiler',
      'ObjCCompiler',
      'ObjCPPCompiler',
      'Open64FortranCompiler',
      'PathScaleFortranCompiler',
      'PGIFortranCompiler',
      'RustCompiler',
      'SunFortranCompiler',
      'SwiftCompiler',
      'ValaCompiler',
      'VisualStudioCCompiler',
      'VisualStudioCPPCompiler',
  ]
  
  # Bring symbols from each module into compilers sub-package namespace
  from .compilers import (
      GCC_OSX,
      GCC_MINGW,
      GCC_CYGWIN,
      GCC_STANDARD,
      CLANG_OSX,
      CLANG_WIN,
      CLANG_STANDARD,
      ICC_OSX,
      ICC_WIN,
      ICC_STANDARD,
      all_languages,
      base_options,
      clib_langs,
      clike_langs,
      c_suffixes,
      cpp_suffixes,
      get_macos_dylib_install_name,
      get_base_compile_args,
      get_base_link_args,
      is_header,
      is_source,
      is_assembly,
      is_llvm_ir,
      is_object,
      is_library,
      lang_suffixes,
      sanitizer_compile_args,
      sort_clike,
      ClangCompiler,
      CompilerArgs,
      GnuCompiler,
      IntelCompiler,
  )
  from .c import (
      ArmCCompiler,
      CCompiler,
      ClangCCompiler,
      GnuCCompiler,
      ElbrusCCompiler,
      IntelCCompiler,
      VisualStudioCCompiler,
  )
  from .cpp import (
      ArmCPPCompiler,
      CPPCompiler,
      ClangCPPCompiler,
      GnuCPPCompiler,
      ElbrusCPPCompiler,
      IntelCPPCompiler,
      VisualStudioCPPCompiler,
  )
  from .cs import MonoCompiler, VisualStudioCsCompiler
  from .d import (
      DCompiler,
      DmdDCompiler,
      GnuDCompiler,
      LLVMDCompiler,
  )
  from .fortran import (
      FortranCompiler,
      G95FortranCompiler,
      GnuFortranCompiler,
      ElbrusFortranCompiler,
      IntelFortranCompiler,
      NAGFortranCompiler,
      Open64FortranCompiler,
      PathScaleFortranCompiler,
      PGIFortranCompiler,
      SunFortranCompiler,
  )
  from .java import JavaCompiler
  from .objc import (
      ObjCCompiler,
      ClangObjCCompiler,
      GnuObjCCompiler,
  )
  from .objcpp import (
      ObjCPPCompiler,
      ClangObjCPPCompiler,
      GnuObjCPPCompiler,
  )
  from .rust import RustCompiler
  from .swift import SwiftCompiler
  from .vala import ValaCompiler
  
  
  [... the rest is omitted ...]
files: mesonbuild/compilers/__init__.py
files: # Copyright 2012-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.
  
  import contextlib, os.path, re, tempfile, shlex
  import subprocess
  
  from ..linkers import StaticLinker
  from .. import coredata
  from .. import mlog
  from .. import mesonlib
  from ..mesonlib import EnvironmentException, MesonException, version_compare, Popen_safe
  
  """This file contains the data files of all compilers Meson knows
  about. To support a new compiler, add its information below.
  Also add corresponding autodetection code in environment.py."""
  
  header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di')
  obj_suffixes = ('o', 'obj', 'res')
  lib_suffixes = ('a', 'lib', 'dll', 'dylib', 'so')
  # Mapping of language to suffixes of files that should always be in that language
  # This means we can't include .h headers here since they could be C, C++, ObjC, etc.
  lang_suffixes = {
      'c': ('c',),
      'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx'),
      # f90, f95, f03, f08 are for free-form fortran ('f90' recommended)
      # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended)
      'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp'),
      'd': ('d', 'di'),
      'objc': ('m',),
      'objcpp': ('mm',),
      'rust': ('rs',),
      'vala': ('vala', 'vapi', 'gs'),
      'cs': ('cs',),
      'swift': ('swift',),
      'java': ('java',),
  }
  all_languages = lang_suffixes.keys()
  cpp_suffixes = lang_suffixes['cpp'] + ('h',)
  c_suffixes = lang_suffixes['c'] + ('h',)
  # List of languages that by default consume and output libraries following the
  # C ABI; these can generally be used interchangebly
  clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'fortran',)
  # List of languages that can be linked with C code directly by the linker
  # used in build.py:process_compilers() and build.py:get_dynamic_linker()
  # XXX: Add Rust to this?
  clink_langs = ('d',) + clib_langs
  clink_suffixes = ()
  for _l in clink_langs + ('vala',):
      clink_suffixes += lang_suffixes[_l]
  clink_suffixes += ('h', 'll', 's')
  
  soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
  
  # Environment variables that each lang uses.
  cflags_mapping = {'c': 'CFLAGS',
                    'cpp': 'CXXFLAGS',
                    'objc': 'OBJCFLAGS',
                    'objcpp': 'OBJCXXFLAGS',
                    'fortran': 'FFLAGS',
                    'd': 'DFLAGS',
                    'vala': 'VALAFLAGS',
                    'rust': 'RUSTFLAGS'}
  
  # All these are only for C-linkable languages; see `clink_langs` above.
  
  def sort_clink(lang):
      '''
      Sorting function to sort the list of languages according to
      reversed(compilers.clink_langs) and append the unknown langs in the end.
      The purpose is to prefer C over C++ for files that can be compiled by
      both such as assembly, C, etc. Also applies to ObjC, ObjC++, etc.
      '''
      if lang not in clink_langs:
          return 1
      return -clink_langs.index(lang)
  
  def is_header(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1]
      return suffix in header_suffixes
  
  def is_source(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1].lower()
      return suffix in clink_suffixes
  
  def is_assembly(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      return fname.split('.')[-1].lower() == 's'
  
  def is_llvm_ir(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      return fname.split('.')[-1] == 'll'
  
  def is_object(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1]
      return suffix in obj_suffixes
  
  def is_library(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
  
      if soregex.match(fname):
          return True
  
      suffix = fname.split('.')[-1]
      return suffix in lib_suffixes
  
  gnulike_buildtype_args = {'plain': [],
                            # -O0 is passed for improved debugging information with gcc
                            # See https://github.com/mesonbuild/meson/pull/509
                            'debug': ['-O0', '-g'],
                            'debugoptimized': ['-O2', '-g'],
                            'release': ['-O3'],
                            'minsize': ['-Os', '-g']}
  
  arm_buildtype_args = {'plain': [],
                        'debug': ['-O0', '--debug'],
                        'debugoptimized': ['-O1', '--debug'],
                        'release': ['-O3', '-Otime'],
                        'minsize': ['-O3', '-Ospace'],
                        }
  
  msvc_buildtype_args = {'plain': [],
                         'debug': ["/MDd", "/ZI", "/Ob0", "/Od", "/RTC1"],
                         'debugoptimized': ["/MD", "/Zi", "/O2", "/Ob1"],
                         'release': ["/MD", "/O2", "/Ob2"],
                         'minsize': ["/MD", "/Zi", "/Os", "/Ob1"],
                         }
  
  apple_buildtype_linker_args = {'plain': [],
                                 'debug': [],
                                 'debugoptimized': [],
                                 'release': [],
                                 'minsize': [],
                                 }
  
  gnulike_buildtype_linker_args = {'plain': [],
                                   'debug': [],
                                   'debugoptimized': [],
                                   'release': ['-Wl,-O1'],
                                   'minsize': [],
                                   }
  
  arm_buildtype_linker_args = {'plain': [],
                               'debug': [],
                               'debugoptimized': [],
                               'release': [],
                               'minsize': [],
                               }
  
  msvc_buildtype_linker_args = {'plain': [],
                                'debug': [],
                                'debugoptimized': [],
                                # The otherwise implicit REF and ICF linker
                                # optimisations are disabled by /DEBUG.
                                # REF implies ICF.
                                'release': ['/OPT:REF'],
                                'minsize': ['/INCREMENTAL:NO', '/OPT:REF'],
                                }
  
  java_buildtype_args = {'plain': [],
                         'debug': ['-g'],
                         'debugoptimized': ['-g'],
                         'release': [],
                         'minsize': [],
                         }
  
  rust_buildtype_args = {'plain': [],
                         'debug': ['-C', 'debuginfo=2'],
                         'debugoptimized': ['-C', 'debuginfo=2', '-C', 'opt-level=2'],
                         'release': ['-C', 'opt-level=3'],
                         'minsize': [], # In a future release: ['-C', 'opt-level=s'],
                         }
  
  d_gdc_buildtype_args = {'plain': [],
                          'debug': ['-g', '-O0'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O3', '-frelease'],
                          'minsize': [],
                          }
  
  d_ldc_buildtype_args = {'plain': [],
                          'debug': ['-g', '-O0'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O3', '-release'],
                          'minsize': [],
                          }
  
  d_dmd_buildtype_args = {'plain': [],
                          'debug': ['-g'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O', '-release'],
                          'minsize': [],
                          }
  
  mono_buildtype_args = {'plain': [],
                         'debug': ['-debug'],
                         'debugoptimized': ['-debug', '-optimize+'],
                         'release': ['-optimize+'],
                         'minsize': [],
                         }
  
  swift_buildtype_args = {'plain': [],
                          'debug': ['-g'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O'],
                          'minsize': [],
                          }
  
  gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32',
                 '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32']
  
  msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib',
                  'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib',
                  'uuid.lib', 'comdl
  
  [... the rest is omitted ...]
files: mesonbuild/compilers/compilers.py
files: # Copyright 2012-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.
  
  import contextlib, os.path, re, tempfile, shlex
  import subprocess
  
  from ..linkers import StaticLinker
  from .. import coredata
  from .. import mlog
  from .. import mesonlib
  from ..mesonlib import EnvironmentException, MesonException, version_compare, Popen_safe
  
  """This file contains the data files of all compilers Meson knows
  about. To support a new compiler, add its information below.
  Also add corresponding autodetection code in environment.py."""
  
  header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di')
  obj_suffixes = ('o', 'obj', 'res')
  lib_suffixes = ('a', 'lib', 'dll', 'dylib', 'so')
  # Mapping of language to suffixes of files that should always be in that language
  # This means we can't include .h headers here since they could be C, C++, ObjC, etc.
  lang_suffixes = {
      'c': ('c',),
      'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx'),
      # f90, f95, f03, f08 are for free-form fortran ('f90' recommended)
      # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended)
      'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp'),
      'd': ('d', 'di'),
      'objc': ('m',),
      'objcpp': ('mm',),
      'rust': ('rs',),
      'vala': ('vala', 'vapi', 'gs'),
      'cs': ('cs',),
      'swift': ('swift',),
      'java': ('java',),
  }
  all_languages = lang_suffixes.keys()
  cpp_suffixes = lang_suffixes['cpp'] + ('h',)
  c_suffixes = lang_suffixes['c'] + ('h',)
  # List of languages that by default consume and output libraries following the
  # C ABI; these can generally be used interchangebly
  clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'fortran',)
  # List of languages that can be linked with C code directly by the linker
  # used in build.py:process_compilers() and build.py:get_dynamic_linker()
  # XXX: Add Rust to this?
  clike_langs = ('d',) + clib_langs
  clike_suffixes = ()
  for _l in clike_langs + ('vala',):
      clike_suffixes += lang_suffixes[_l]
  clike_suffixes += ('h', 'll', 's')
  
  soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
  
  # Environment variables that each lang uses.
  cflags_mapping = {'c': 'CFLAGS',
                    'cpp': 'CXXFLAGS',
                    'objc': 'OBJCFLAGS',
                    'objcpp': 'OBJCXXFLAGS',
                    'fortran': 'FFLAGS',
                    'd': 'DFLAGS',
                    'vala': 'VALAFLAGS',
                    'rust': 'RUSTFLAGS'}
  
  # All these are only for C-like languages; see `clike_langs` above.
  
  def sort_clike(lang):
      '''
      Sorting function to sort the list of languages according to
      reversed(compilers.clike_langs) and append the unknown langs in the end.
      The purpose is to prefer C over C++ for files that can be compiled by
      both such as assembly, C, etc. Also applies to ObjC, ObjC++, etc.
      '''
      if lang not in clike_langs:
          return 1
      return -clike_langs.index(lang)
  
  def is_header(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1]
      return suffix in header_suffixes
  
  def is_source(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1].lower()
      return suffix in clike_suffixes
  
  def is_assembly(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      return fname.split('.')[-1].lower() == 's'
  
  def is_llvm_ir(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      return fname.split('.')[-1] == 'll'
  
  def is_object(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1]
      return suffix in obj_suffixes
  
  def is_library(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
  
      if soregex.match(fname):
          return True
  
      suffix = fname.split('.')[-1]
      return suffix in lib_suffixes
  
  gnulike_buildtype_args = {'plain': [],
                            # -O0 is passed for improved debugging information with gcc
                            # See https://github.com/mesonbuild/meson/pull/509
                            'debug': ['-O0', '-g'],
                            'debugoptimized': ['-O2', '-g'],
                            'release': ['-O3'],
                            'minsize': ['-Os', '-g']}
  
  arm_buildtype_args = {'plain': [],
                        'debug': ['-O0', '--debug'],
                        'debugoptimized': ['-O1', '--debug'],
                        'release': ['-O3', '-Otime'],
                        'minsize': ['-O3', '-Ospace'],
                        }
  
  msvc_buildtype_args = {'plain': [],
                         'debug': ["/MDd", "/ZI", "/Ob0", "/Od", "/RTC1"],
                         'debugoptimized': ["/MD", "/Zi", "/O2", "/Ob1"],
                         'release': ["/MD", "/O2", "/Ob2"],
                         'minsize': ["/MD", "/Zi", "/Os", "/Ob1"],
                         }
  
  apple_buildtype_linker_args = {'plain': [],
                                 'debug': [],
                                 'debugoptimized': [],
                                 'release': [],
                                 'minsize': [],
                                 }
  
  gnulike_buildtype_linker_args = {'plain': [],
                                   'debug': [],
                                   'debugoptimized': [],
                                   'release': ['-Wl,-O1'],
                                   'minsize': [],
                                   }
  
  arm_buildtype_linker_args = {'plain': [],
                               'debug': [],
                               'debugoptimized': [],
                               'release': [],
                               'minsize': [],
                               }
  
  msvc_buildtype_linker_args = {'plain': [],
                                'debug': [],
                                'debugoptimized': [],
                                # The otherwise implicit REF and ICF linker
                                # optimisations are disabled by /DEBUG.
                                # REF implies ICF.
                                'release': ['/OPT:REF'],
                                'minsize': ['/INCREMENTAL:NO', '/OPT:REF'],
                                }
  
  java_buildtype_args = {'plain': [],
                         'debug': ['-g'],
                         'debugoptimized': ['-g'],
                         'release': [],
                         'minsize': [],
                         }
  
  rust_buildtype_args = {'plain': [],
                         'debug': ['-C', 'debuginfo=2'],
                         'debugoptimized': ['-C', 'debuginfo=2', '-C', 'opt-level=2'],
                         'release': ['-C', 'opt-level=3'],
                         'minsize': [], # In a future release: ['-C', 'opt-level=s'],
                         }
  
  d_gdc_buildtype_args = {'plain': [],
                          'debug': ['-g', '-O0'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O3', '-frelease'],
                          'minsize': [],
                          }
  
  d_ldc_buildtype_args = {'plain': [],
                          'debug': ['-g', '-O0'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O3', '-release'],
                          'minsize': [],
                          }
  
  d_dmd_buildtype_args = {'plain': [],
                          'debug': ['-g'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O', '-release'],
                          'minsize': [],
                          }
  
  mono_buildtype_args = {'plain': [],
                         'debug': ['-debug'],
                         'debugoptimized': ['-debug', '-optimize+'],
                         'release': ['-optimize+'],
                         'minsize': [],
                         }
  
  swift_buildtype_args = {'plain': [],
                          'debug': ['-g'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O'],
                          'minsize': [],
                          }
  
  gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32',
                 '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32']
  
  msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib',
                  'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib',
                  'uuid.lib', 'comdlg
  
  [... the rest is omitted ...]
files: mesonbuild/compilers/compilers.py
files: # Copyright 2013-2018 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 copy
  import os
  import re
  import stat
  import shlex
  import shutil
  import textwrap
  from enum import Enum
  from pathlib import PurePath
  
  from .. import mlog
  from .. import mesonlib
  from ..compilers import clib_langs
  from ..mesonlib import MesonException, OrderedSet
  from ..mesonlib import 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'
      # 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'
      # For backewards compatibility
      SDLCONFIG = 'sdlconfig'
      CUPSCONFIG = 'cups-config'
      PCAPCONFIG = 'pcap-config'
      LIBWMFCONFIG = 'libwmf-config'
  
  
  class Dependency:
      @classmethod
      def _process_method_kw(cls, kwargs):
          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)
  
          # This sets per-tool config methods which are deprecated to to the new
          # generic CONFIG_TOOL value.
          if method in [DependencyMethods.SDLCONFIG, DependencyMethods.CUPSCONFIG,
                        DependencyMethods.PCAPCONFIG, DependencyMethods.LIBWMFCONFIG]:
              mlog.warning(textwrap.dedent("""\
                  Configuration method {} has been deprecated in favor of
                  'config-tool'. This will be removed in a future version of
                  meson.""".format(method)))
              method = DependencyMethods.CONFIG_TOOL
  
          # 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:
              methods = cls.get_methods()
          elif method in cls.get_methods():
              methods = [method]
          else:
              raise DependencyException(
                  'Unsupported detection method: {}, allowed methods are {}'.format(
                      method.value,
                      mlog.format_list([x.value for x in [DependencyMethods.AUTO] + cls.get_methods()])))
  
          return methods
  
      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 = []
          self.methods = self._process_method_kw(kwargs)
  
      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
  
      @staticmethod
      def get_methods():
          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_openmp(self):
          return False
  
      def need_threads(self):
          return False
  
      def get_pkgconfig_variable(self, variable_name, kwargs):
          raise DependencyException('{!r} is not a pkgconfig dependency'.format(self.name))
  
      def get_configtool_variable(self, variable_name):
          raise DependencyException('{!r} is not a config-tool dependency'.format(self.name))
  
      def get_partial_dependency(self, *, compile_args=False, link_args=False,
                                 links=False, includes=False, sources=False):
          """Create a new dependency that contains part of the parent dependency.
  
          The following options can be inherited:
              links -- all link_with arguemnts
              includes -- all include_directory and -I/-isystem calls
              sources -- any source, header, or generated sources
              compile_args -- any compile args
              link_args -- any link args
  
          Additionally the new dependency will have the version parameter of it's
          parent (if any) and the requested values of any dependencies will be
          added as well.
          """
          RuntimeError('Unreachable code in partial_dependency called')
  
  
  class InternalDependency(Dependency):
      def __init__(self, version, incdirs, compile_args, link_args, libraries, whole_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.whole_libraries = whole_libraries
          self.sources = sources
          self.ext_deps = ext_deps
  
      def get_pkgconfig_variable(self, variable_name, kwargs):
          raise DependencyException('Method "get_pkgconfig_variable()" is '
                                    'invalid for an internal dependency')
  
      def get_configtool_variable(self, variable_name):
          raise DependencyException('Method "get_configtool_variable()" is '
                                    'invalid for an internal dependency')
  
      def get_partial_dependency(self, *, compile_args=False, link_args=False,
                                 links=False, includes=False, sources=False):
          compile_args = self.compile_args.copy() if compile_args else []
          link_args = self.link_args.copy() if link_args else []
          libraries = self.libraries.copy() if links else []
          whole_libraries = self.whole_libraries.copy() if links else []
          sources = self.sources.copy() if sources else []
          includes = self.include_directories.copy() if includes else []
          deps = [d.get_partial_dependency(
              compile_args=compile_args, link_args=link_args, links=links,
              includes=includes, sources=sources) for d in self.ext_deps]
          return InternalDependency(
              self.version, includes, compile_args, link_args, libraries,
              whole_libraries, sources, 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
          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()
          self.clib_compiler = None
          # 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
          # Set the compiler for this dependency if a language is specified,
          # else try to pick something that looks usable.
          if self.language:
              if self.language not in compilers:
                  m = self.name.capitalize() + ' requires a {0} compiler, but ' \
                      '{0} is not in the list of project languages'
                  raise DependencyException(m.format(self.language.capitalize()))
              self.clib_compiler = compilers[self.language]
          else:
              # Try to find a compiler that can find C libraries for
              # running compiler.find_library()
              for lang in clib_langs:
                  self.clib_compiler = compilers.get(lang, None)
                  if self.clib_compiler:
                      break
  
      def get_compiler(self):
          return self.clib_compiler
  
      def get_partial_dependency(self, *, compile_args=False, link_args=False,
                                 links=False, includes=False, sources=False):
          new = copy.copy(self)
          if not compile_args:
              new.compile_args = []
          if not link_args:
              new.link_args = []
          if not sources:
              new.sources = []
  
          return new
  
  
  class NotFoundDependency(Dependency):
      def __init__(self, environment):
          super().__init__('not-found', {})
          self.env = environment
          self.name = 'not-found'
          self.is_found = False
  
  
  class ConfigToolDependency(ExternalDependency):
  
  
  
  [... the rest is omitted ...]
files: mesonbuild/dependencies/base.py
files: # Copyright 2013-2018 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 copy
  import os
  import re
  import stat
  import shlex
  import shutil
  import textwrap
  from enum import Enum
  from pathlib import PurePath
  
  from .. import mlog
  from .. import mesonlib
  from ..compilers import clib_langs, clike_langs
  from ..mesonlib import MesonException, OrderedSet
  from ..mesonlib import 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'
      # 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'
      # For backewards compatibility
      SDLCONFIG = 'sdlconfig'
      CUPSCONFIG = 'cups-config'
      PCAPCONFIG = 'pcap-config'
      LIBWMFCONFIG = 'libwmf-config'
  
  
  class Dependency:
      @classmethod
      def _process_method_kw(cls, kwargs):
          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)
  
          # This sets per-tool config methods which are deprecated to to the new
          # generic CONFIG_TOOL value.
          if method in [DependencyMethods.SDLCONFIG, DependencyMethods.CUPSCONFIG,
                        DependencyMethods.PCAPCONFIG, DependencyMethods.LIBWMFCONFIG]:
              mlog.warning(textwrap.dedent("""\
                  Configuration method {} has been deprecated in favor of
                  'config-tool'. This will be removed in a future version of
                  meson.""".format(method)))
              method = DependencyMethods.CONFIG_TOOL
  
          # 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:
              methods = cls.get_methods()
          elif method in cls.get_methods():
              methods = [method]
          else:
              raise DependencyException(
                  'Unsupported detection method: {}, allowed methods are {}'.format(
                      method.value,
                      mlog.format_list([x.value for x in [DependencyMethods.AUTO] + cls.get_methods()])))
  
          return methods
  
      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 = []
          self.methods = self._process_method_kw(kwargs)
  
      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
  
      @staticmethod
      def get_methods():
          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_openmp(self):
          return False
  
      def need_threads(self):
          return False
  
      def get_pkgconfig_variable(self, variable_name, kwargs):
          raise DependencyException('{!r} is not a pkgconfig dependency'.format(self.name))
  
      def get_configtool_variable(self, variable_name):
          raise DependencyException('{!r} is not a config-tool dependency'.format(self.name))
  
      def get_partial_dependency(self, *, compile_args=False, link_args=False,
                                 links=False, includes=False, sources=False):
          """Create a new dependency that contains part of the parent dependency.
  
          The following options can be inherited:
              links -- all link_with arguemnts
              includes -- all include_directory and -I/-isystem calls
              sources -- any source, header, or generated sources
              compile_args -- any compile args
              link_args -- any link args
  
          Additionally the new dependency will have the version parameter of it's
          parent (if any) and the requested values of any dependencies will be
          added as well.
          """
          RuntimeError('Unreachable code in partial_dependency called')
  
  
  class InternalDependency(Dependency):
      def __init__(self, version, incdirs, compile_args, link_args, libraries, whole_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.whole_libraries = whole_libraries
          self.sources = sources
          self.ext_deps = ext_deps
  
      def get_pkgconfig_variable(self, variable_name, kwargs):
          raise DependencyException('Method "get_pkgconfig_variable()" is '
                                    'invalid for an internal dependency')
  
      def get_configtool_variable(self, variable_name):
          raise DependencyException('Method "get_configtool_variable()" is '
                                    'invalid for an internal dependency')
  
      def get_partial_dependency(self, *, compile_args=False, link_args=False,
                                 links=False, includes=False, sources=False):
          compile_args = self.compile_args.copy() if compile_args else []
          link_args = self.link_args.copy() if link_args else []
          libraries = self.libraries.copy() if links else []
          whole_libraries = self.whole_libraries.copy() if links else []
          sources = self.sources.copy() if sources else []
          includes = self.include_directories.copy() if includes else []
          deps = [d.get_partial_dependency(
              compile_args=compile_args, link_args=link_args, links=links,
              includes=includes, sources=sources) for d in self.ext_deps]
          return InternalDependency(
              self.version, includes, compile_args, link_args, libraries,
              whole_libraries, sources, 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
          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()
          self.clib_compiler = None
          # 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
          # Set the compiler for this dependency if a language is specified,
          # else try to pick something that looks usable.
          if self.language:
              if self.language not in compilers:
                  m = self.name.capitalize() + ' requires a {0} compiler, but ' \
                      '{0} is not in the list of project languages'
                  raise DependencyException(m.format(self.language.capitalize()))
              self.clib_compiler = compilers[self.language]
          else:
              # Try to find a compiler that can find C libraries for
              # running compiler.find_library()
              for lang in clib_langs:
                  self.clib_compiler = compilers.get(lang, None)
                  if self.clib_compiler:
                      break
  
      def get_compiler(self):
          return self.clib_compiler
  
      def get_partial_dependency(self, *, compile_args=False, link_args=False,
                                 links=False, includes=False, sources=False):
          new = copy.copy(self)
          if not compile_args:
              new.compile_args = []
          if not link_args:
              new.link_args = []
          if not sources:
              new.sources = []
  
          return new
  
  
  class NotFoundDependency(Dependency):
      def __init__(self, environment):
          super().__init__('not-found', {})
          self.env = environment
          self.name = 'not-found'
          self.is_found = False
  
  
  class ConfigToolDependency
  
  [... the rest is omitted ...]
files: mesonbuild/dependencies/base.py
files: # 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 os
  import re
  import shlex
  import sysconfig
  
  from pathlib import Path
  
  from .. import mlog
  from .. import mesonlib
  from ..environment import detect_cpu_family
  
  from .base import (
      DependencyException, DependencyMethods, ExternalDependency,
      ExternalProgram, ExtraFrameworkDependency, PkgConfigDependency,
      ConfigToolDependency,
  )
  
  from ..interpreterbase import FeatureNew
  
  class MPIDependency(ExternalDependency):
  
      @FeatureNew('MPI Dependency', '0.42.0')
      def __init__(self, environment, kwargs):
          language = kwargs.get('language', 'c')
          super().__init__('mpi', environment, language, kwargs)
          required = kwargs.pop('required', True)
          kwargs['required'] = False
          kwargs['silent'] = True
          self.is_found = False
  
          # NOTE: Only OpenMPI supplies a pkg-config file at the moment.
          if language == 'c':
              env_vars = ['MPICC']
              pkgconfig_files = ['ompi-c']
              default_wrappers = ['mpicc']
          elif language == 'cpp':
              env_vars = ['MPICXX']
              pkgconfig_files = ['ompi-cxx']
              default_wrappers = ['mpic++', 'mpicxx', 'mpiCC']
          elif language == 'fortran':
              env_vars = ['MPIFC', 'MPIF90', 'MPIF77']
              pkgconfig_files = ['ompi-fort']
              default_wrappers = ['mpifort', 'mpif90', 'mpif77']
          else:
              raise DependencyException('Language {} is not supported with MPI.'.format(language))
  
          for pkg in pkgconfig_files:
              try:
                  pkgdep = PkgConfigDependency(pkg, environment, kwargs, language=self.language)
                  if pkgdep.found():
                      self.compile_args = pkgdep.get_compile_args()
                      self.link_args = pkgdep.get_link_args()
                      self.version = pkgdep.get_version()
                      self.is_found = True
                      self.pcdep = pkgdep
                      break
              except Exception:
                  pass
  
          if not self.is_found:
              # Prefer environment.
              for var in env_vars:
                  if var in os.environ:
                      wrappers = [os.environ[var]]
                      break
              else:
                  # Or search for default wrappers.
                  wrappers = default_wrappers
  
              for prog in wrappers:
                  result = self._try_openmpi_wrapper(prog)
                  if result is not None:
                      self.is_found = True
                      self.version = result[0]
                      self.compile_args = self._filter_compile_args(result[1])
                      self.link_args = self._filter_link_args(result[2])
                      break
                  result = self._try_other_wrapper(prog)
                  if result is not None:
                      self.is_found = True
                      self.version = result[0]
                      self.compile_args = self._filter_compile_args(result[1])
                      self.link_args = self._filter_link_args(result[2])
                      break
  
          if not self.is_found and mesonlib.is_windows():
              result = self._try_msmpi()
              if result is not None:
                  self.is_found = True
                  self.version, self.compile_args, self.link_args = result
  
          if self.is_found:
              mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.green('YES'), self.version)
          else:
              mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.red('NO'))
              if required:
                  raise DependencyException('MPI dependency {!r} not found'.format(self.name))
  
      def _filter_compile_args(self, args):
          """
          MPI wrappers return a bunch of garbage args.
          Drop -O2 and everything that is not needed.
          """
          result = []
          multi_args = ('-I', )
          if self.language == 'fortran':
              fc = self.env.coredata.compilers['fortran']
              multi_args += fc.get_module_incdir_args()
  
          include_next = False
          for f in args:
              if f.startswith(('-D', '-f') + multi_args) or f == '-pthread' \
                      or (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')):
                  result.append(f)
                  if f in multi_args:
                      # Path is a separate argument.
                      include_next = True
              elif include_next:
                  include_next = False
                  result.append(f)
          return result
  
      def _filter_link_args(self, args):
          """
          MPI wrappers return a bunch of garbage args.
          Drop -O2 and everything that is not needed.
          """
          result = []
          include_next = False
          for f in args:
              if f.startswith(('-L', '-l', '-Xlinker')) or f == '-pthread' \
                      or (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')):
                  result.append(f)
                  if f in ('-L', '-Xlinker'):
                      include_next = True
              elif include_next:
                  include_next = False
                  result.append(f)
          return result
  
      def _try_openmpi_wrapper(self, prog):
          prog = ExternalProgram(prog, silent=True)
          if prog.found():
              cmd = prog.get_command() + ['--showme:compile']
              p, o, e = mesonlib.Popen_safe(cmd)
              p.wait()
              if p.returncode != 0:
                  mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
                  mlog.debug(mlog.bold('Standard output\n'), o)
                  mlog.debug(mlog.bold('Standard error\n'), e)
                  return
              cargs = shlex.split(o)
  
              cmd = prog.get_command() + ['--showme:link']
              p, o, e = mesonlib.Popen_safe(cmd)
              p.wait()
              if p.returncode != 0:
                  mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
                  mlog.debug(mlog.bold('Standard output\n'), o)
                  mlog.debug(mlog.bold('Standard error\n'), e)
                  return
              libs = shlex.split(o)
  
              cmd = prog.get_command() + ['--showme:version']
              p, o, e = mesonlib.Popen_safe(cmd)
              p.wait()
              if p.returncode != 0:
                  mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
                  mlog.debug(mlog.bold('Standard output\n'), o)
                  mlog.debug(mlog.bold('Standard error\n'), e)
                  return
              version = re.search('\d+.\d+.\d+', o)
              if version:
                  version = version.group(0)
              else:
                  version = 'none'
  
              return version, cargs, libs
  
      def _try_other_wrapper(self, prog):
          prog = ExternalProgram(prog, silent=True)
          if prog.found():
              cmd = prog.get_command() + ['-show']
              p, o, e = mesonlib.Popen_safe(cmd)
              p.wait()
              if p.returncode != 0:
                  mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
                  mlog.debug(mlog.bold('Standard output\n'), o)
                  mlog.debug(mlog.bold('Standard error\n'), e)
                  return
              args = shlex.split(o)
  
              version = 'none'
  
              return version, args, args
  
      def _try_msmpi(self):
          if self.language == 'cpp':
              # MS-MPI does not support the C++ version of MPI, only the standard C API.
              return
          if 'MSMPI_INC' not in os.environ:
              return
          incdir = os.environ['MSMPI_INC']
          arch = detect_cpu_family(self.env.coredata.compilers)
          if arch == 'x86':
              if 'MSMPI_LIB32' not in os.environ:
                  return
              libdir = os.environ['MSMPI_LIB32']
              post = 'x86'
          elif arch == 'x86_64':
              if 'MSMPI_LIB64' not in os.environ:
                  return
              libdir = os.environ['MSMPI_LIB64']
              post = 'x64'
          else:
              return
          if self.language == 'fortran':
              return ('none',
                      ['-I' + incdir, '-I' + os.path.join(incdir, post)],
                      [os.path.join(libdir, 'msmpi.lib'), os.path.join(libdir, 'msmpifec.lib')])
          else:
              return ('none',
                      ['-I' + incdir, '-I' + os.path.join(incdir, post)],
                      [os.path.join(libdir, 'msmpi.lib')])
  
  
  class OpenMPDependency(ExternalDependency):
      # Map date of specification release (which is the macro value) to a version.
      VERSIONS = {
          '201511': '4.5',
          '201307': '4.0',
          '201107': '3.1',
          '200805': '3.0',
          '200505': '2.5',
          '200203': '2.0',
  
  
  [... the rest is omitted ...]
files: mesonbuild/dependencies/misc.py
files: # 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 os
  import re
  import shlex
  import sysconfig
  
  from pathlib import Path
  
  from .. import mlog
  from .. import mesonlib
  from ..environment import detect_cpu_family
  
  from .base import (
      DependencyException, DependencyMethods, ExternalDependency,
      ExternalProgram, ExtraFrameworkDependency, PkgConfigDependency,
      ConfigToolDependency,
  )
  
  from ..interpreterbase import FeatureNew
  
  class MPIDependency(ExternalDependency):
  
      @FeatureNew('MPI Dependency', '0.42.0')
      def __init__(self, environment, kwargs):
          language = kwargs.get('language', 'c')
          super().__init__('mpi', environment, language, kwargs)
          required = kwargs.pop('required', True)
          kwargs['required'] = False
          kwargs['silent'] = True
          self.is_found = False
  
          # NOTE: Only OpenMPI supplies a pkg-config file at the moment.
          if language == 'c':
              env_vars = ['MPICC']
              pkgconfig_files = ['ompi-c']
              default_wrappers = ['mpicc']
          elif language == 'cpp':
              env_vars = ['MPICXX']
              pkgconfig_files = ['ompi-cxx']
              default_wrappers = ['mpic++', 'mpicxx', 'mpiCC']
          elif language == 'fortran':
              env_vars = ['MPIFC', 'MPIF90', 'MPIF77']
              pkgconfig_files = ['ompi-fort']
              default_wrappers = ['mpifort', 'mpif90', 'mpif77']
          else:
              raise DependencyException('Language {} is not supported with MPI.'.format(language))
  
          for pkg in pkgconfig_files:
              try:
                  pkgdep = PkgConfigDependency(pkg, environment, kwargs, language=self.language)
                  if pkgdep.found():
                      self.compile_args = pkgdep.get_compile_args()
                      self.link_args = pkgdep.get_link_args()
                      self.version = pkgdep.get_version()
                      self.is_found = True
                      self.pcdep = pkgdep
                      break
              except Exception:
                  pass
  
          if not self.is_found:
              # Prefer environment.
              for var in env_vars:
                  if var in os.environ:
                      wrappers = [os.environ[var]]
                      break
              else:
                  # Or search for default wrappers.
                  wrappers = default_wrappers
  
              for prog in wrappers:
                  result = self._try_openmpi_wrapper(prog)
                  if result is not None:
                      self.is_found = True
                      self.version = result[0]
                      self.compile_args = self._filter_compile_args(result[1])
                      self.link_args = self._filter_link_args(result[2])
                      break
                  result = self._try_other_wrapper(prog)
                  if result is not None:
                      self.is_found = True
                      self.version = result[0]
                      self.compile_args = self._filter_compile_args(result[1])
                      self.link_args = self._filter_link_args(result[2])
                      break
  
          if not self.is_found and mesonlib.is_windows():
              result = self._try_msmpi()
              if result is not None:
                  self.is_found = True
                  self.version, self.compile_args, self.link_args = result
  
          if self.is_found:
              mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.green('YES'), self.version)
          else:
              mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.red('NO'))
              if required:
                  raise DependencyException('MPI dependency {!r} not found'.format(self.name))
  
      def _filter_compile_args(self, args):
          """
          MPI wrappers return a bunch of garbage args.
          Drop -O2 and everything that is not needed.
          """
          result = []
          multi_args = ('-I', )
          if self.language == 'fortran':
              fc = self.env.coredata.compilers['fortran']
              multi_args += fc.get_module_incdir_args()
  
          include_next = False
          for f in args:
              if f.startswith(('-D', '-f') + multi_args) or f == '-pthread' \
                      or (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')):
                  result.append(f)
                  if f in multi_args:
                      # Path is a separate argument.
                      include_next = True
              elif include_next:
                  include_next = False
                  result.append(f)
          return result
  
      def _filter_link_args(self, args):
          """
          MPI wrappers return a bunch of garbage args.
          Drop -O2 and everything that is not needed.
          """
          result = []
          include_next = False
          for f in args:
              if f.startswith(('-L', '-l', '-Xlinker')) or f == '-pthread' \
                      or (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')):
                  result.append(f)
                  if f in ('-L', '-Xlinker'):
                      include_next = True
              elif include_next:
                  include_next = False
                  result.append(f)
          return result
  
      def _try_openmpi_wrapper(self, prog):
          prog = ExternalProgram(prog, silent=True)
          if prog.found():
              cmd = prog.get_command() + ['--showme:compile']
              p, o, e = mesonlib.Popen_safe(cmd)
              p.wait()
              if p.returncode != 0:
                  mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
                  mlog.debug(mlog.bold('Standard output\n'), o)
                  mlog.debug(mlog.bold('Standard error\n'), e)
                  return
              cargs = shlex.split(o)
  
              cmd = prog.get_command() + ['--showme:link']
              p, o, e = mesonlib.Popen_safe(cmd)
              p.wait()
              if p.returncode != 0:
                  mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
                  mlog.debug(mlog.bold('Standard output\n'), o)
                  mlog.debug(mlog.bold('Standard error\n'), e)
                  return
              libs = shlex.split(o)
  
              cmd = prog.get_command() + ['--showme:version']
              p, o, e = mesonlib.Popen_safe(cmd)
              p.wait()
              if p.returncode != 0:
                  mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
                  mlog.debug(mlog.bold('Standard output\n'), o)
                  mlog.debug(mlog.bold('Standard error\n'), e)
                  return
              version = re.search('\d+.\d+.\d+', o)
              if version:
                  version = version.group(0)
              else:
                  version = 'none'
  
              return version, cargs, libs
  
      def _try_other_wrapper(self, prog):
          prog = ExternalProgram(prog, silent=True)
          if prog.found():
              cmd = prog.get_command() + ['-show']
              p, o, e = mesonlib.Popen_safe(cmd)
              p.wait()
              if p.returncode != 0:
                  mlog.debug('Command', mlog.bold(cmd), 'failed to run:')
                  mlog.debug(mlog.bold('Standard output\n'), o)
                  mlog.debug(mlog.bold('Standard error\n'), e)
                  return
              args = shlex.split(o)
  
              version = 'none'
  
              return version, args, args
  
      def _try_msmpi(self):
          if self.language == 'cpp':
              # MS-MPI does not support the C++ version of MPI, only the standard C API.
              return
          if 'MSMPI_INC' not in os.environ:
              return
          incdir = os.environ['MSMPI_INC']
          arch = detect_cpu_family(self.env.coredata.compilers)
          if arch == 'x86':
              if 'MSMPI_LIB32' not in os.environ:
                  return
              libdir = os.environ['MSMPI_LIB32']
              post = 'x86'
          elif arch == 'x86_64':
              if 'MSMPI_LIB64' not in os.environ:
                  return
              libdir = os.environ['MSMPI_LIB64']
              post = 'x64'
          else:
              return
          if self.language == 'fortran':
              return ('none',
                      ['-I' + incdir, '-I' + os.path.join(incdir, post)],
                      [os.path.join(libdir, 'msmpi.lib'), os.path.join(libdir, 'msmpifec.lib')])
          else:
              return ('none',
                      ['-I' + incdir, '-I' + os.path.join(incdir, post)],
                      [os.path.join(libdir, 'msmpi.lib')])
  
  
  class OpenMPDependency(ExternalDependency):
      # Map date of specification release (which is the macro value) to a version.
      VERSIONS = {
          '201511': '4.5',
          '201307': '4.0',
          '201107': '3.1',
          '200805': '3.0',
          '200505': '2.5',
          '200203': '2.0',
  
  
  [... the rest is omitted ...]
files: mesonbuild/dependencies/misc.py
files: # Copyright 2012-2018 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.
  
  from . import mparser
  from . import environment
  from . import coredata
  from . import dependencies
  from . import mlog
  from . import build
  from . import optinterpreter
  from . import compilers
  from .wrap import wrap, WrapMode
  from . import mesonlib
  from .mesonlib import FileMode, Popen_safe, listify, extract_as_list, has_path_sep
  from .dependencies import ExternalProgram
  from .dependencies import InternalDependency, Dependency, NotFoundDependency, DependencyException
  from .interpreterbase import InterpreterBase
  from .interpreterbase import check_stringlist, flatten, noPosargs, noKwargs, stringArgs, permittedKwargs, noArgsFlattening
  from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
  from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabler
  from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs
  from .modules import ModuleReturnValue
  
  import os, sys, shutil, uuid
  import re, shlex
  import subprocess
  from collections import namedtuple
  from pathlib import PurePath
  
  import importlib
  
  permitted_method_kwargs = {
      'partial_dependency': {'compile_args', 'link_args', 'links', 'includes',
                             'sources'},
  }
  
  def stringifyUserArguments(args):
      if isinstance(args, list):
          return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args])
      elif isinstance(args, dict):
          return '{%s}' % ', '.join(['%s : %s' % (stringifyUserArguments(k), stringifyUserArguments(v)) for k, v in args.items()])
      elif isinstance(args, int):
          return str(args)
      elif isinstance(args, str):
          return "'%s'" % args
      raise InvalidArguments('Function accepts only strings, integers, lists and lists thereof.')
  
  
  class ObjectHolder:
      def __init__(self, obj):
          self.held_object = obj
  
      def __repr__(self):
          return '<Holder: {!r}>'.format(self.held_object)
  
  class FeatureOptionHolder(InterpreterObject, ObjectHolder):
      def __init__(self, env, option):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, option)
          if option.is_auto():
              self.held_object = env.coredata.builtins['auto_features']
          self.name = option.name
          self.methods.update({'enabled': self.enabled_method,
                               'disabled': self.disabled_method,
                               'auto': self.auto_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def enabled_method(self, args, kwargs):
          return self.held_object.is_enabled()
  
      @noPosargs
      @permittedKwargs({})
      def disabled_method(self, args, kwargs):
          return self.held_object.is_disabled()
  
      @noPosargs
      @permittedKwargs({})
      def auto_method(self, args, kwargs):
          return self.held_object.is_auto()
  
  def extract_required_kwarg(kwargs):
      val = kwargs.get('required', True)
      disabled = False
      required = False
      feature = None
      if isinstance(val, FeatureOptionHolder):
          option = val.held_object
          feature = val.name
          if option.is_disabled():
              disabled = True
          elif option.is_enabled():
              required = True
      elif isinstance(required, bool):
          required = val
      else:
          raise InterpreterException('required keyword argument must be boolean or a feature option')
  
      # Keep boolean value in kwargs to simplify other places where this kwarg is
      # checked.
      kwargs['required'] = required
  
      return disabled, required, feature
  
  class TryRunResultHolder(InterpreterObject):
      def __init__(self, res):
          super().__init__()
          self.res = res
          self.methods.update({'returncode': self.returncode_method,
                               'compiled': self.compiled_method,
                               'stdout': self.stdout_method,
                               'stderr': self.stderr_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def returncode_method(self, args, kwargs):
          return self.res.returncode
  
      @noPosargs
      @permittedKwargs({})
      def compiled_method(self, args, kwargs):
          return self.res.compiled
  
      @noPosargs
      @permittedKwargs({})
      def stdout_method(self, args, kwargs):
          return self.res.stdout
  
      @noPosargs
      @permittedKwargs({})
      def stderr_method(self, args, kwargs):
          return self.res.stderr
  
  class RunProcess(InterpreterObject):
  
      def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False, check=False, capture=True):
          super().__init__()
          if not isinstance(cmd, ExternalProgram):
              raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
          self.capture = capture
          pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check)
          self.returncode = pc.returncode
          self.methods.update({'returncode': self.returncode_method,
                               'stdout': self.stdout_method,
                               'stderr': self.stderr_method,
                               })
  
      def run_command(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check=False):
          command_array = cmd.get_command() + args
          env = {'MESON_SOURCE_ROOT': source_dir,
                 'MESON_BUILD_ROOT': build_dir,
                 'MESON_SUBDIR': subdir,
                 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in mesonintrospect]),
                 }
          if in_builddir:
              cwd = os.path.join(build_dir, subdir)
          else:
              cwd = os.path.join(source_dir, subdir)
          child_env = os.environ.copy()
          child_env.update(env)
          stdout = subprocess.PIPE if self.capture else subprocess.DEVNULL
          mlog.debug('Running command:', ' '.join(command_array))
          try:
              p, o, e = Popen_safe(command_array, stdout=stdout, env=child_env, cwd=cwd)
              if self.capture:
                  mlog.debug('--- stdout ---')
                  mlog.debug(o)
              else:
                  o = ''
                  mlog.debug('--- stdout disabled ---')
              mlog.debug('--- stderr ---')
              mlog.debug(e)
              mlog.debug('')
  
              if check and p.returncode != 0:
                  raise InterpreterException('Command "{}" failed with status {}.'.format(' '.join(command_array), p.returncode))
  
              return p, o, e
          except FileNotFoundError:
              raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array))
  
      @noPosargs
      @permittedKwargs({})
      def returncode_method(self, args, kwargs):
          return self.returncode
  
      @noPosargs
      @permittedKwargs({})
      def stdout_method(self, args, kwargs):
          return self.stdout
  
      @noPosargs
      @permittedKwargs({})
      def stderr_method(self, args, kwargs):
          return self.stderr
  
  class ConfigureFileHolder(InterpreterObject, ObjectHolder):
  
      def __init__(self, subdir, sourcename, targetname, configuration_data):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, build.ConfigureFile(subdir, sourcename,
                                                          targetname, configuration_data))
  
  
  class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder):
      def __init__(self):
          MutableInterpreterObject.__init__(self)
          ObjectHolder.__init__(self, build.EnvironmentVariables())
          self.methods.update({'set': self.set_method,
                               'append': self.append_method,
                               'prepend': self.prepend_method,
                               })
  
      def __repr__(self):
          repr_str = "<{0}: {1}>"
          return repr_str.format(self.__class__.__name__, self.held_object.envvars)
  
      def add_var(self, method, args, kwargs):
          if not isinstance(kwargs.get("separator", ""), str):
              raise InterpreterException("EnvironmentVariablesHolder methods 'separator'"
                                         " argument needs to be a string.")
          if len(args) < 2:
              raise InterpreterException("EnvironmentVariablesHolder methods require at least"
                                         "2 arguments, first is the name of the variable and"
                                         " following one are values")
          self.held_object.envvars.append((method, args[0], args[1:], kwargs))
  
      @stringArgs
      @permittedKwargs({'separator'})
      def set_method(self, args, kwargs):
          self.add_var(self.held_object.set, args, kwargs)
  
      @stringArgs
      @permittedKwargs({'separator'})
      def append_method(self, args, kwargs):
          self.add_var(self.held_object.append, args, kwargs)
  
      @stringArgs
      @permittedKwargs({'separator'})
      def prepend_method(self, args, kwargs):
          self.add_var(self.held_object.prepend, args, kwargs)
  
  
  class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder):
      def __init__(self):
          MutableInterpreterObject.__init__(self)
          self.used = False # These objects become immutable after use in configure_file.
          ObjectHolder.__init__(self, build.ConfigurationData())
          self.methods.update({'set': self.set
  
  [... the rest is omitted ...]
files: mesonbuild/interpreter.py
files: # Copyright 2012-2018 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.
  
  from . import mparser
  from . import environment
  from . import coredata
  from . import dependencies
  from . import mlog
  from . import build
  from . import optinterpreter
  from . import compilers
  from .wrap import wrap, WrapMode
  from . import mesonlib
  from .mesonlib import FileMode, Popen_safe, listify, extract_as_list, has_path_sep
  from .dependencies import ExternalProgram
  from .dependencies import InternalDependency, Dependency, NotFoundDependency, DependencyException
  from .interpreterbase import InterpreterBase
  from .interpreterbase import check_stringlist, flatten, noPosargs, noKwargs, stringArgs, permittedKwargs, noArgsFlattening
  from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
  from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabler
  from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs
  from .modules import ModuleReturnValue
  
  import os, sys, shutil, uuid
  import re, shlex
  import subprocess
  from collections import namedtuple
  from pathlib import PurePath
  
  import importlib
  
  permitted_method_kwargs = {
      'partial_dependency': {'compile_args', 'link_args', 'links', 'includes',
                             'sources'},
  }
  
  def stringifyUserArguments(args):
      if isinstance(args, list):
          return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args])
      elif isinstance(args, dict):
          return '{%s}' % ', '.join(['%s : %s' % (stringifyUserArguments(k), stringifyUserArguments(v)) for k, v in args.items()])
      elif isinstance(args, int):
          return str(args)
      elif isinstance(args, str):
          return "'%s'" % args
      raise InvalidArguments('Function accepts only strings, integers, lists and lists thereof.')
  
  
  class ObjectHolder:
      def __init__(self, obj):
          self.held_object = obj
  
      def __repr__(self):
          return '<Holder: {!r}>'.format(self.held_object)
  
  class FeatureOptionHolder(InterpreterObject, ObjectHolder):
      def __init__(self, env, option):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, option)
          if option.is_auto():
              self.held_object = env.coredata.builtins['auto_features']
          self.name = option.name
          self.methods.update({'enabled': self.enabled_method,
                               'disabled': self.disabled_method,
                               'auto': self.auto_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def enabled_method(self, args, kwargs):
          return self.held_object.is_enabled()
  
      @noPosargs
      @permittedKwargs({})
      def disabled_method(self, args, kwargs):
          return self.held_object.is_disabled()
  
      @noPosargs
      @permittedKwargs({})
      def auto_method(self, args, kwargs):
          return self.held_object.is_auto()
  
  def extract_required_kwarg(kwargs):
      val = kwargs.get('required', True)
      disabled = False
      required = False
      feature = None
      if isinstance(val, FeatureOptionHolder):
          option = val.held_object
          feature = val.name
          if option.is_disabled():
              disabled = True
          elif option.is_enabled():
              required = True
      elif isinstance(required, bool):
          required = val
      else:
          raise InterpreterException('required keyword argument must be boolean or a feature option')
  
      # Keep boolean value in kwargs to simplify other places where this kwarg is
      # checked.
      kwargs['required'] = required
  
      return disabled, required, feature
  
  class TryRunResultHolder(InterpreterObject):
      def __init__(self, res):
          super().__init__()
          self.res = res
          self.methods.update({'returncode': self.returncode_method,
                               'compiled': self.compiled_method,
                               'stdout': self.stdout_method,
                               'stderr': self.stderr_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def returncode_method(self, args, kwargs):
          return self.res.returncode
  
      @noPosargs
      @permittedKwargs({})
      def compiled_method(self, args, kwargs):
          return self.res.compiled
  
      @noPosargs
      @permittedKwargs({})
      def stdout_method(self, args, kwargs):
          return self.res.stdout
  
      @noPosargs
      @permittedKwargs({})
      def stderr_method(self, args, kwargs):
          return self.res.stderr
  
  class RunProcess(InterpreterObject):
  
      def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False, check=False, capture=True):
          super().__init__()
          if not isinstance(cmd, ExternalProgram):
              raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
          self.capture = capture
          pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check)
          self.returncode = pc.returncode
          self.methods.update({'returncode': self.returncode_method,
                               'stdout': self.stdout_method,
                               'stderr': self.stderr_method,
                               })
  
      def run_command(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check=False):
          command_array = cmd.get_command() + args
          env = {'MESON_SOURCE_ROOT': source_dir,
                 'MESON_BUILD_ROOT': build_dir,
                 'MESON_SUBDIR': subdir,
                 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in mesonintrospect]),
                 }
          if in_builddir:
              cwd = os.path.join(build_dir, subdir)
          else:
              cwd = os.path.join(source_dir, subdir)
          child_env = os.environ.copy()
          child_env.update(env)
          stdout = subprocess.PIPE if self.capture else subprocess.DEVNULL
          mlog.debug('Running command:', ' '.join(command_array))
          try:
              p, o, e = Popen_safe(command_array, stdout=stdout, env=child_env, cwd=cwd)
              if self.capture:
                  mlog.debug('--- stdout ---')
                  mlog.debug(o)
              else:
                  o = ''
                  mlog.debug('--- stdout disabled ---')
              mlog.debug('--- stderr ---')
              mlog.debug(e)
              mlog.debug('')
  
              if check and p.returncode != 0:
                  raise InterpreterException('Command "{}" failed with status {}.'.format(' '.join(command_array), p.returncode))
  
              return p, o, e
          except FileNotFoundError:
              raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array))
  
      @noPosargs
      @permittedKwargs({})
      def returncode_method(self, args, kwargs):
          return self.returncode
  
      @noPosargs
      @permittedKwargs({})
      def stdout_method(self, args, kwargs):
          return self.stdout
  
      @noPosargs
      @permittedKwargs({})
      def stderr_method(self, args, kwargs):
          return self.stderr
  
  class ConfigureFileHolder(InterpreterObject, ObjectHolder):
  
      def __init__(self, subdir, sourcename, targetname, configuration_data):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, build.ConfigureFile(subdir, sourcename,
                                                          targetname, configuration_data))
  
  
  class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder):
      def __init__(self):
          MutableInterpreterObject.__init__(self)
          ObjectHolder.__init__(self, build.EnvironmentVariables())
          self.methods.update({'set': self.set_method,
                               'append': self.append_method,
                               'prepend': self.prepend_method,
                               })
  
      def __repr__(self):
          repr_str = "<{0}: {1}>"
          return repr_str.format(self.__class__.__name__, self.held_object.envvars)
  
      def add_var(self, method, args, kwargs):
          if not isinstance(kwargs.get("separator", ""), str):
              raise InterpreterException("EnvironmentVariablesHolder methods 'separator'"
                                         " argument needs to be a string.")
          if len(args) < 2:
              raise InterpreterException("EnvironmentVariablesHolder methods require at least"
                                         "2 arguments, first is the name of the variable and"
                                         " following one are values")
          self.held_object.envvars.append((method, args[0], args[1:], kwargs))
  
      @stringArgs
      @permittedKwargs({'separator'})
      def set_method(self, args, kwargs):
          self.add_var(self.held_object.set, args, kwargs)
  
      @stringArgs
      @permittedKwargs({'separator'})
      def append_method(self, args, kwargs):
          self.add_var(self.held_object.append, args, kwargs)
  
      @stringArgs
      @permittedKwargs({'separator'})
      def prepend_method(self, args, kwargs):
          self.add_var(self.held_object.prepend, args, kwargs)
  
  
  class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder):
      def __init__(self):
          MutableInterpreterObject.__init__(self)
          self.used = False # These objects become immutable after use in configure_file.
          ObjectHolder.__init__(self, build.ConfigurationData())
          self.methods.update({'set': self.set
  
  [... the rest is omitted ...]
files: mesonbuild/interpreter.py