files.new_contents: # 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 os, pickle, re, shlex, shutil, subprocess, sys
  from collections import OrderedDict
  
  from . import backends
  from .. import modules
  from .. import environment, mesonlib
  from .. import build
  from .. import mlog
  from .. import dependencies
  from .. import compilers
  from ..compilers import CompilerArgs
  from ..linkers import ArLinker
  from ..mesonlib import File, MesonException, OrderedSet
  from ..mesonlib import get_meson_script, get_compiler_for_source
  from .backends import CleanTrees, InstallData
  from ..build import InvalidArguments
  
  if mesonlib.is_windows():
      quote_func = lambda s: '"{}"'.format(s)
      execute_wrapper = 'cmd /c'
      rmfile_prefix = 'del /f /s /q {} &&'
  else:
      quote_func = shlex.quote
      execute_wrapper = ''
      rmfile_prefix = 'rm -f {} &&'
  
  def ninja_quote(text):
      for char in ('$', ' ', ':'):
          text = text.replace(char, '$' + char)
      if '\n' in text:
          raise MesonException('Ninja does not support newlines in rules. '
                               'Please report this error with a test case to the Meson bug tracker.')
      return text
  
  
  class NinjaBuildElement:
      def __init__(self, all_outputs, outfilenames, rule, infilenames):
          if isinstance(outfilenames, str):
              self.outfilenames = [outfilenames]
          else:
              self.outfilenames = outfilenames
          assert(isinstance(rule, str))
          self.rule = rule
          if isinstance(infilenames, str):
              self.infilenames = [infilenames]
          else:
              self.infilenames = infilenames
          self.deps = set()
          self.orderdeps = set()
          self.elems = []
          self.all_outputs = all_outputs
  
      def add_dep(self, dep):
          if isinstance(dep, list):
              self.deps.update(dep)
          else:
              self.deps.add(dep)
  
      def add_orderdep(self, dep):
          if isinstance(dep, list):
              self.orderdeps.update(dep)
          else:
              self.orderdeps.add(dep)
  
      def add_item(self, name, elems):
          if isinstance(elems, str):
              elems = [elems]
          self.elems.append((name, elems))
  
      def write(self, outfile):
          self.check_outputs()
          line = 'build %s: %s %s' % (
              ' '.join([ninja_quote(i) for i in self.outfilenames]),
              self.rule,
              ' '.join([ninja_quote(i) for i in self.infilenames]))
          if len(self.deps) > 0:
              line += ' | ' + ' '.join([ninja_quote(x) for x in self.deps])
          if len(self.orderdeps) > 0:
              line += ' || ' + ' '.join([ninja_quote(x) for x in self.orderdeps])
          line += '\n'
          # This is the only way I could find to make this work on all
          # platforms including Windows command shell. Slash is a dir separator
          # on Windows, too, so all characters are unambiguous and, more importantly,
          # do not require quoting.
          line = line.replace('\\', '/')
          outfile.write(line)
  
          # All the entries that should remain unquoted
          raw_names = {'DEPFILE', 'DESC', 'pool', 'description'}
  
          for e in self.elems:
              (name, elems) = e
              should_quote = name not in raw_names
              line = ' %s = ' % name
              noq_templ = "%s"
              newelems = []
              for i in elems:
                  if not should_quote or i == '&&': # Hackety hack hack
                      quoter = ninja_quote
                  else:
                      quoter = lambda x: ninja_quote(quote_func(x))
                  i = i.replace('\\', '\\\\')
                  if quote_func('') == '""':
                      i = i.replace('"', '\\"')
                  newelems.append(quoter(i))
              line += ' '.join(newelems)
              line += '\n'
              outfile.write(line)
          outfile.write('\n')
  
      def check_outputs(self):
          for n in self.outfilenames:
              if n in self.all_outputs:
                  raise MesonException('Multiple producers for Ninja target "%s". Please rename your targets.' % n)
              self.all_outputs[n] = True
  
  class NinjaBackend(backends.Backend):
  
      def __init__(self, build):
          super().__init__(build)
          self.name = 'ninja'
          self.ninja_filename = 'build.ninja'
          self.target_arg_cache = {}
          self.fortran_deps = {}
          self.all_outputs = {}
  
      def detect_vs_dep_prefix(self, tempfilename):
          '''VS writes its dependency in a locale dependent format.
          Detect the search prefix to use.'''
          # Of course there is another program called 'cl' on
          # some platforms. Let's just require that on Windows
          # cl points to msvc.
          if not mesonlib.is_windows() or shutil.which('cl') is None:
              return open(tempfilename, 'a')
          filename = os.path.join(self.environment.get_scratch_dir(),
                                  'incdetect.c')
          with open(filename, 'w') as f:
              f.write('''#include<stdio.h>
  int dummy;
  ''')
  
          # The output of cl dependency information is language
          # and locale dependent. Any attempt at converting it to
          # Python strings leads to failure. We _must_ do this detection
          # in raw byte mode and write the result in raw bytes.
          pc = subprocess.Popen(['cl', '/showIncludes', '/c', 'incdetect.c'],
                                cwd=self.environment.get_scratch_dir(),
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
          (stdo, _) = pc.communicate()
  
          # We want to match 'Note: including file: ' in the line
          # 'Note: including file: d:\MyDir\include\stdio.h', however
          # different locales have different messages with a different
          # number of colons. Match up to the the drive name 'd:\'.
          matchre = re.compile(rb"^(.*\s)[a-zA-Z]:\\.*stdio.h$")
          for line in stdo.split(b'\r\n'):
              match = matchre.match(line)
              if match:
                  with open(tempfilename, 'ab') as binfile:
                      binfile.write(b'msvc_deps_prefix = ' + match.group(1) + b'\n')
                  return open(tempfilename, 'a')
          raise MesonException('Could not determine vs dep dependency prefix string.')
  
      def generate(self, interp):
          self.interpreter = interp
          outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename)
          tempfilename = outfilename + '~'
          with open(tempfilename, 'w') as outfile:
              outfile.write('# This is the build file for project "%s"\n' %
                            self.build.get_project())
              outfile.write('# It is autogenerated by the Meson build system.\n')
              outfile.write('# Do not edit by hand.\n\n')
              outfile.write('ninja_required_version = 1.5.1\n\n')
          with self.detect_vs_dep_prefix(tempfilename) as outfile:
              self.generate_rules(outfile)
              self.generate_phony(outfile)
              outfile.write('# Build rules for targets\n\n')
              for t in self.build.get_targets().values():
                  self.generate_target(t, outfile)
              outfile.write('# Test rules\n\n')
              self.generate_tests(outfile)
              outfile.write('# Install rules\n\n')
              self.generate_install(outfile)
              self.generate_dist(outfile)
              if 'b_coverage' in self.environment.coredata.base_options and \
                      self.environment.coredata.base_options['b_coverage'].value:
                  outfile.write('# Coverage rules\n\n')
                  self.generate_coverage_rules(outfile)
              outfile.write('# Suffix\n\n')
              self.generate_utils(outfile)
              self.generate_ending(outfile)
          # Only ovewrite the old build file after the new one has been
          # fully created.
          os.replace(tempfilename, outfilename)
          self.generate_compdb()
  
      # http://clang.llvm.org/docs/JSONCompilationDatabase.html
      def generate_compdb(self):
          ninja_exe = environment.detect_ninja()
          native_compilers = ['%s_COMPILER' % i for i in self.build.compilers]
          cross_compilers = ['%s_CROSS_COMPILER' % i for i in self.build.cross_compilers]
          ninja_compdb = [ninja_exe, '-t', 'compdb'] + native_compilers + cross_compilers
          builddir = self.environment.get_build_dir()
          try:
              jsondb = subprocess.check_output(ninja_compdb, cwd=builddir)
              with open(os.path.join(builddir, 'compile_commands.json'), 'wb') as f:
                  f.write(jsondb)
          except Exception:
              mlog.warning('Could not create compilation database.')
  
      # Get all generated headers. Any source file might need them so
      # we need to add an order dependency to them.
      def get_generated_headers(self, target):
          header_deps = []
          # XXX: Why don't we add deps to CustomTarget headers here?
          for genlist in target.get_generated_sources():
              if isinstance(genlist, build.CustomTarget):
                  continue
              for src in genlist.get_outputs():
                  if self.environment.is_header(src):
                      header_deps.append(self.get_target_generated_dir(target, genlist, src))
          if 'vala' in target.compilers and not isinstance(target, build.Executable):
              vala_header = File.from_built_file(self.get_target_dir(target), target.vala_header)
              header_deps.append(vala_header)
          # Recurse and find generated headers
          for dep in target.link_targets:
              if isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
                  header_deps += self.get_generated_headers(dep)
          return header_deps
  
      def get_target_generated_sources(self, target):
          """
          Returns a dictionary with the keys being the path to the file
          (relative to the build directory) of that type and the value
          being the GeneratorList or CustomTarget that generated it.
          """
          srcs = OrderedDict()
          for gensrc in target.get_generated_sources():
              for s in gensrc.get_outputs():
                  f = self.get_target_generated_dir(target, gensrc, s)
                  srcs[f] = s
          return srcs
  
      def get_target_sources(self, target):
          srcs = OrderedDict()
          for s in target.get_sources():
              # BuildTarget sources are always mesonlib.File files which are
              # either in the source root, or generated with configure_file and
              # in the build root
              if not isinstance(s, File):
                  raise InvalidArguments('All sources in target {!r} must be of type mesonlib.File'.format(s))
              f = s.rel_to_builddir(self.build_to_src)
              srcs[f] = s
          return srcs
  
      # Languages that can mix with C or C++ but don't support unity builds yet
      # because the syntax we use for unity builds is specific to C/++/ObjC/++.
      # Assembly files cannot be unitified and neither can LLVM IR files
      langs_cant_unity = ('d', 'fortran')
  
      def get_target_source_can_unity(self, target, source):
          if isinstance(source, File):
              source = source.fname
          if self.environment.is_llvm_ir(source) or \
             self.environment.is_assembly(source):
              return False
          suffix = os.path.splitext(source)[1][1:]
          for lang in self.langs_cant_unity:
              if lang not in target.compilers:
                  continue
              if suffix in target.compilers[lang].file_suffixes:
                  return False
          return True
  
      def generate_target(self, target, outfile):
          if isinstance(target, build.CustomTarget):
              self.generate_custom_target(target, outfile)
          if isinstance(target, build.RunTarget):
              self.generate_run_target(target, outfile)
          name = target.get_id()
          if name in self.processed_targets:
              return
          self.processed_targets[name] = True
          # Generate rules for all dependency targets
          self.process_target_dependencies(target, outfile)
          # If target uses a language that cannot link to C objects,
          # just generate for that language and return.
          if isinstance(target, build.Jar):
              self.generate_jar_target(target, outfile)
              return
          if 'rust' in target.compilers:
              self.generate_rust_target(target, outfile)
              return
          if 'cs' in target.compilers:
              self.generate_cs_target(target, outfile)
              return
          if 'swift' in target.compilers:
              self.generate_swift_target(target, outfile)
              return
  
          # Now we handle the following languages:
          # ObjC++, ObjC, C++, C, D, Fortran, Vala
  
          # target_sources:
          #   Pre-existing target C/C++ sources to be built; dict of full path to
          #   source relative to build root and the original File object.
          # generated_sources:
          #   GeneratedList and CustomTarget sources to be built; dict of the full
          #   path to source relative to build root and the generating target/list
          # vala_generated_sources:
          #   Array of sources generated by valac that have to be compiled
          if 'vala' in target.compilers:
              # Sources consumed by valac are filtered out. These only contain
              # C/C++ sources, objects, generated libs, and unknown sources now.
              target_sources, generated_sources, \
                  vala_generated_sources = self.generate_vala_compile(target, outfile)
          else:
              target_sources = self.get_target_sources(target)
              generated_sources = self.get_target_generated_sources(target)
              vala_generated_sources = []
          self.scan_fortran_module_outputs(target)
          # Generate rules for GeneratedLists
          self.generate_generator_list_rules(target, outfile)
  
          # Generate rules for building the remaining source files in this target
          outname = self.get_target_filename(target)
          obj_list = []
          use_pch = self.environment.coredata.base_options.get('b_pch', False)
          is_unity = self.is_unity(target)
          if use_pch and target.has_pch():
              pch_objects = self.generate_pch(target, outfile)
          else:
              pch_objects = []
          header_deps = []
          unity_src = []
          unity_deps = [] # Generated sources that must be built before compiling a Unity target.
          header_deps += self.get_generated_headers(target)
  
          if is_unity:
              # Warn about incompatible sources if a unity build is enabled
              langs = set(target.compilers.keys())
              langs_cant = langs.intersection(self.langs_cant_unity)
              if langs_cant:
                  langs_are = langs = ', '.join(langs_cant).upper()
                  langs_are += ' are' if len(langs_cant) > 1 else ' is'
                  msg = '{} not supported in Unity builds yet, so {} ' \
                        'sources in the {!r} target will be compiled normally' \
                        ''.format(langs_are, langs, target.name)
                  mlog.log(mlog.red('FIXME'), msg)
  
          # Get a list of all generated headers that will be needed while building
          # this target's sources (generated sources and pre-existing sources).
          # This will be set as dependencies of all the target's sources. At the
          # same time, also deal with generated sources that need to be compiled.
          generated_source_files = []
          for rel_src, gensrc in generated_sources.items():
              dirpart, fnamepart = os.path.split(rel_src)
              raw_src = File(True, dirpart, fnamepart)
              if self.environment.is_source(rel_src) and not self.environment.is_header(rel_src):
                  if is_unity and self.get_target_source_can_unity(target, rel_src):
                      unity_deps.append(raw_src)
                      abs_src = os.path.join(self.environment.get_build_dir(), rel_src)
                      unity_src.append(abs_src)
                  else:
                      generated_source_files.append(raw_src)
              elif self.environment.is_object(rel_src):
                  obj_list.append(rel_src)
              elif self.environment.is_library(rel_src):
                  pass
              else:
                  # Assume anything not specifically a source file is a header. This is because
                  # people generate files with weird suffixes
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/backend/ninjabackend.py
files.old_contents: # 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 os, pickle, re, shlex, shutil, subprocess, sys
  from collections import OrderedDict
  
  from . import backends
  from .. import modules
  from .. import environment, mesonlib
  from .. import build
  from .. import mlog
  from .. import dependencies
  from .. import compilers
  from ..compilers import CompilerArgs
  from ..linkers import ArLinker
  from ..mesonlib import File, MesonException, OrderedSet
  from ..mesonlib import get_meson_script, get_compiler_for_source
  from .backends import CleanTrees, InstallData
  from ..build import InvalidArguments
  
  if mesonlib.is_windows():
      quote_func = lambda s: '"{}"'.format(s)
      execute_wrapper = 'cmd /c'
      rmfile_prefix = 'del /f /s /q {} &&'
  else:
      quote_func = shlex.quote
      execute_wrapper = ''
      rmfile_prefix = 'rm -f {} &&'
  
  def ninja_quote(text):
      for char in ('$', ' ', ':'):
          text = text.replace(char, '$' + char)
      if '\n' in text:
          raise MesonException('Ninja does not support newlines in rules. '
                               'Please report this error with a test case to the Meson bug tracker.')
      return text
  
  
  class NinjaBuildElement:
      def __init__(self, all_outputs, outfilenames, rule, infilenames):
          if isinstance(outfilenames, str):
              self.outfilenames = [outfilenames]
          else:
              self.outfilenames = outfilenames
          assert(isinstance(rule, str))
          self.rule = rule
          if isinstance(infilenames, str):
              self.infilenames = [infilenames]
          else:
              self.infilenames = infilenames
          self.deps = set()
          self.orderdeps = set()
          self.elems = []
          self.all_outputs = all_outputs
  
      def add_dep(self, dep):
          if isinstance(dep, list):
              self.deps.update(dep)
          else:
              self.deps.add(dep)
  
      def add_orderdep(self, dep):
          if isinstance(dep, list):
              self.orderdeps.update(dep)
          else:
              self.orderdeps.add(dep)
  
      def add_item(self, name, elems):
          if isinstance(elems, str):
              elems = [elems]
          self.elems.append((name, elems))
  
      def write(self, outfile):
          self.check_outputs()
          line = 'build %s: %s %s' % (
              ' '.join([ninja_quote(i) for i in self.outfilenames]),
              self.rule,
              ' '.join([ninja_quote(i) for i in self.infilenames]))
          if len(self.deps) > 0:
              line += ' | ' + ' '.join([ninja_quote(x) for x in self.deps])
          if len(self.orderdeps) > 0:
              line += ' || ' + ' '.join([ninja_quote(x) for x in self.orderdeps])
          line += '\n'
          # This is the only way I could find to make this work on all
          # platforms including Windows command shell. Slash is a dir separator
          # on Windows, too, so all characters are unambiguous and, more importantly,
          # do not require quoting.
          line = line.replace('\\', '/')
          outfile.write(line)
  
          # All the entries that should remain unquoted
          raw_names = {'DEPFILE', 'DESC', 'pool', 'description'}
  
          for e in self.elems:
              (name, elems) = e
              should_quote = name not in raw_names
              line = ' %s = ' % name
              noq_templ = "%s"
              newelems = []
              for i in elems:
                  if not should_quote or i == '&&': # Hackety hack hack
                      quoter = ninja_quote
                  else:
                      quoter = lambda x: ninja_quote(quote_func(x))
                  i = i.replace('\\', '\\\\')
                  if quote_func('') == '""':
                      i = i.replace('"', '\\"')
                  newelems.append(quoter(i))
              line += ' '.join(newelems)
              line += '\n'
              outfile.write(line)
          outfile.write('\n')
  
      def check_outputs(self):
          for n in self.outfilenames:
              if n in self.all_outputs:
                  raise MesonException('Multiple producers for Ninja target "%s". Please rename your targets.' % n)
              self.all_outputs[n] = True
  
  class NinjaBackend(backends.Backend):
  
      def __init__(self, build):
          super().__init__(build)
          self.name = 'ninja'
          self.ninja_filename = 'build.ninja'
          self.target_arg_cache = {}
          self.fortran_deps = {}
          self.all_outputs = {}
  
      def detect_vs_dep_prefix(self, tempfilename):
          '''VS writes its dependency in a locale dependent format.
          Detect the search prefix to use.'''
          # Of course there is another program called 'cl' on
          # some platforms. Let's just require that on Windows
          # cl points to msvc.
          if not mesonlib.is_windows() or shutil.which('cl') is None:
              return open(tempfilename, 'a')
          filename = os.path.join(self.environment.get_scratch_dir(),
                                  'incdetect.c')
          with open(filename, 'w') as f:
              f.write('''#include<stdio.h>
  int dummy;
  ''')
  
          # The output of cl dependency information is language
          # and locale dependent. Any attempt at converting it to
          # Python strings leads to failure. We _must_ do this detection
          # in raw byte mode and write the result in raw bytes.
          pc = subprocess.Popen(['cl', '/showIncludes', '/c', 'incdetect.c'],
                                cwd=self.environment.get_scratch_dir(),
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
          (stdo, _) = pc.communicate()
  
          # We want to match 'Note: including file: ' in the line
          # 'Note: including file: d:\MyDir\include\stdio.h', however
          # different locales have different messages with a different
          # number of colons. Match up to the the drive name 'd:\'.
          matchre = re.compile(rb"^(.*\s)[a-zA-Z]:\\.*stdio.h$")
          for line in stdo.split(b'\r\n'):
              match = matchre.match(line)
              if match:
                  with open(tempfilename, 'ab') as binfile:
                      binfile.write(b'msvc_deps_prefix = ' + match.group(1) + b'\n')
                  return open(tempfilename, 'a')
          raise MesonException('Could not determine vs dep dependency prefix string.')
  
      def generate(self, interp):
          self.interpreter = interp
          outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename)
          tempfilename = outfilename + '~'
          with open(tempfilename, 'w') as outfile:
              outfile.write('# This is the build file for project "%s"\n' %
                            self.build.get_project())
              outfile.write('# It is autogenerated by the Meson build system.\n')
              outfile.write('# Do not edit by hand.\n\n')
              outfile.write('ninja_required_version = 1.5.1\n\n')
          with self.detect_vs_dep_prefix(tempfilename) as outfile:
              self.generate_rules(outfile)
              self.generate_phony(outfile)
              outfile.write('# Build rules for targets\n\n')
              for t in self.build.get_targets().values():
                  self.generate_target(t, outfile)
              outfile.write('# Test rules\n\n')
              self.generate_tests(outfile)
              outfile.write('# Install rules\n\n')
              self.generate_install(outfile)
              self.generate_dist(outfile)
              if 'b_coverage' in self.environment.coredata.base_options and \
                      self.environment.coredata.base_options['b_coverage'].value:
                  outfile.write('# Coverage rules\n\n')
                  self.generate_coverage_rules(outfile)
              outfile.write('# Suffix\n\n')
              self.generate_utils(outfile)
              self.generate_ending(outfile)
          # Only ovewrite the old build file after the new one has been
          # fully created.
          os.replace(tempfilename, outfilename)
          self.generate_compdb()
  
      # http://clang.llvm.org/docs/JSONCompilationDatabase.html
      def generate_compdb(self):
          ninja_exe = environment.detect_ninja()
          native_compilers = ['%s_COMPILER' % i for i in self.build.compilers]
          cross_compilers = ['%s_CROSS_COMPILER' % i for i in self.build.cross_compilers]
          ninja_compdb = [ninja_exe, '-t', 'compdb'] + native_compilers + cross_compilers
          builddir = self.environment.get_build_dir()
          try:
              jsondb = subprocess.check_output(ninja_compdb, cwd=builddir)
              with open(os.path.join(builddir, 'compile_commands.json'), 'wb') as f:
                  f.write(jsondb)
          except Exception:
              mlog.warning('Could not create compilation database.')
  
      # Get all generated headers. Any source file might need them so
      # we need to add an order dependency to them.
      def get_generated_headers(self, target):
          header_deps = []
          # XXX: Why don't we add deps to CustomTarget headers here?
          for genlist in target.get_generated_sources():
              if isinstance(genlist, build.CustomTarget):
                  continue
              for src in genlist.get_outputs():
                  if self.environment.is_header(src):
                      header_deps.append(self.get_target_generated_dir(target, genlist, src))
          if 'vala' in target.compilers and not isinstance(target, build.Executable):
              vala_header = File.from_built_file(self.get_target_dir(target), target.vala_header)
              header_deps.append(vala_header)
          # Recurse and find generated headers
          for dep in target.link_targets:
              if isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
                  header_deps += self.get_generated_headers(dep)
          return header_deps
  
      def get_target_generated_sources(self, target):
          """
          Returns a dictionary with the keys being the path to the file
          (relative to the build directory) of that type and the value
          being the GeneratorList or CustomTarget that generated it.
          """
          srcs = OrderedDict()
          for gensrc in target.get_generated_sources():
              for s in gensrc.get_outputs():
                  f = self.get_target_generated_dir(target, gensrc, s)
                  srcs[f] = s
          return srcs
  
      def get_target_sources(self, target):
          srcs = OrderedDict()
          for s in target.get_sources():
              # BuildTarget sources are always mesonlib.File files which are
              # either in the source root, or generated with configure_file and
              # in the build root
              if not isinstance(s, File):
                  raise InvalidArguments('All sources in target {!r} must be of type mesonlib.File'.format(s))
              f = s.rel_to_builddir(self.build_to_src)
              srcs[f] = s
          return srcs
  
      # Languages that can mix with C or C++ but don't support unity builds yet
      # because the syntax we use for unity builds is specific to C/++/ObjC/++.
      # Assembly files cannot be unitified and neither can LLVM IR files
      langs_cant_unity = ('d', 'fortran')
  
      def get_target_source_can_unity(self, target, source):
          if isinstance(source, File):
              source = source.fname
          if self.environment.is_llvm_ir(source) or \
             self.environment.is_assembly(source):
              return False
          suffix = os.path.splitext(source)[1][1:]
          for lang in self.langs_cant_unity:
              if lang not in target.compilers:
                  continue
              if suffix in target.compilers[lang].file_suffixes:
                  return False
          return True
  
      def generate_target(self, target, outfile):
          if isinstance(target, build.CustomTarget):
              self.generate_custom_target(target, outfile)
          if isinstance(target, build.RunTarget):
              self.generate_run_target(target, outfile)
          name = target.get_id()
          if name in self.processed_targets:
              return
          self.processed_targets[name] = True
          # Generate rules for all dependency targets
          self.process_target_dependencies(target, outfile)
          # If target uses a language that cannot link to C objects,
          # just generate for that language and return.
          if isinstance(target, build.Jar):
              self.generate_jar_target(target, outfile)
              return
          if 'rust' in target.compilers:
              self.generate_rust_target(target, outfile)
              return
          if 'cs' in target.compilers:
              self.generate_cs_target(target, outfile)
              return
          if 'swift' in target.compilers:
              self.generate_swift_target(target, outfile)
              return
  
          # Now we handle the following languages:
          # ObjC++, ObjC, C++, C, D, Fortran, Vala
  
          # target_sources:
          #   Pre-existing target C/C++ sources to be built; dict of full path to
          #   source relative to build root and the original File object.
          # generated_sources:
          #   GeneratedList and CustomTarget sources to be built; dict of the full
          #   path to source relative to build root and the generating target/list
          # vala_generated_sources:
          #   Array of sources generated by valac that have to be compiled
          if 'vala' in target.compilers:
              # Sources consumed by valac are filtered out. These only contain
              # C/C++ sources, objects, generated libs, and unknown sources now.
              target_sources, generated_sources, \
                  vala_generated_sources = self.generate_vala_compile(target, outfile)
          else:
              target_sources = self.get_target_sources(target)
              generated_sources = self.get_target_generated_sources(target)
              vala_generated_sources = []
          self.scan_fortran_module_outputs(target)
          # Generate rules for GeneratedLists
          self.generate_generator_list_rules(target, outfile)
  
          # Generate rules for building the remaining source files in this target
          outname = self.get_target_filename(target)
          obj_list = []
          use_pch = self.environment.coredata.base_options.get('b_pch', False)
          is_unity = self.is_unity(target)
          if use_pch and target.has_pch():
              pch_objects = self.generate_pch(target, outfile)
          else:
              pch_objects = []
          header_deps = []
          unity_src = []
          unity_deps = [] # Generated sources that must be built before compiling a Unity target.
          header_deps += self.get_generated_headers(target)
  
          if is_unity:
              # Warn about incompatible sources if a unity build is enabled
              langs = set(target.compilers.keys())
              langs_cant = langs.intersection(self.langs_cant_unity)
              if langs_cant:
                  langs_are = langs = ', '.join(langs_cant).upper()
                  langs_are += ' are' if len(langs_cant) > 1 else ' is'
                  msg = '{} not supported in Unity builds yet, so {} ' \
                        'sources in the {!r} target will be compiled normally' \
                        ''.format(langs_are, langs, target.name)
                  mlog.log(mlog.red('FIXME'), msg)
  
          # Get a list of all generated headers that will be needed while building
          # this target's sources (generated sources and pre-existing sources).
          # This will be set as dependencies of all the target's sources. At the
          # same time, also deal with generated sources that need to be compiled.
          generated_source_files = []
          for rel_src, gensrc in generated_sources.items():
              dirpart, fnamepart = os.path.split(rel_src)
              raw_src = File(True, dirpart, fnamepart)
              if self.environment.is_source(rel_src) and not self.environment.is_header(rel_src):
                  if is_unity and self.get_target_source_can_unity(target, rel_src):
                      unity_deps.append(raw_src)
                      abs_src = os.path.join(self.environment.get_build_dir(), rel_src)
                      unity_src.append(abs_src)
                  else:
                      generated_source_files.append(raw_src)
              elif self.environment.is_object(rel_src):
                  obj_list.append(rel_src)
              elif self.environment.is_library(rel_src):
                  pass
              else:
                  # Assume anything not specifically a source file is a header. This is because
                  # people generate files with weird suffixes
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/backend/ninjabackend.py
files.new_contents: # 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 subprocess, os.path, tempfile
  
  from .. import mlog
  from .. import coredata
  from ..mesonlib import EnvironmentException, version_compare, Popen_safe
  
  from .compilers import (
      GCC_MINGW,
      get_largefile_args,
      gnu_winlibs,
      msvc_buildtype_args,
      msvc_buildtype_linker_args,
      msvc_winlibs,
      ClangCompiler,
      Compiler,
      CompilerArgs,
      CrossNoRunException,
      GnuCompiler,
      IntelCompiler,
      RunResult,
  )
  
  
  class CCompiler(Compiler):
      def __init__(self, exelist, version, is_cross, exe_wrapper=None):
          # If a child ObjC or CPP class has already set it, don't set it ourselves
          if not hasattr(self, 'language'):
              self.language = 'c'
          super().__init__(exelist, version)
          self.id = 'unknown'
          self.is_cross = is_cross
          self.can_compile_suffixes.add('h')
          if isinstance(exe_wrapper, str):
              self.exe_wrapper = [exe_wrapper]
          else:
              self.exe_wrapper = exe_wrapper
  
      def needs_static_linker(self):
          return True # When compiling static libraries, so yes.
  
      def get_always_args(self):
          '''
          Args that are always-on for all C compilers other than MSVC
          '''
          return ['-pipe'] + get_largefile_args(self)
  
      def get_linker_debug_crt_args(self):
          """
          Arguments needed to select a debug crt for the linker
          This is only needed for MSVC
          """
          return []
  
      def get_no_stdinc_args(self):
          return ['-nostdinc']
  
      def get_no_stdlib_link_args(self):
          return ['-nostdlib']
  
      def get_warn_args(self, level):
          return self.warn_args[level]
  
      def get_no_warn_args(self):
          # Almost every compiler uses this for disabling warnings
          return ['-w']
  
      def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
          return []
  
      def split_shlib_to_parts(self, fname):
          return None, fname
  
      # The default behavior is this, override in MSVC
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
          return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath)
  
      def get_dependency_gen_args(self, outtarget, outfile):
          return ['-MMD', '-MQ', outtarget, '-MF', outfile]
  
      def depfile_for_object(self, objfile):
          return objfile + '.' + self.get_depfile_suffix()
  
      def get_depfile_suffix(self):
          return 'd'
  
      def get_exelist(self):
          return self.exelist[:]
  
      def get_linker_exelist(self):
          return self.exelist[:]
  
      def get_preprocess_only_args(self):
          return ['-E', '-P']
  
      def get_compile_only_args(self):
          return ['-c']
  
      def get_no_optimization_args(self):
          return ['-O0']
  
      def get_compiler_check_args(self):
          '''
          Get arguments useful for compiler checks such as being permissive in
          the code quality and not doing any optimization.
          '''
          return self.get_no_optimization_args()
  
      def get_output_args(self, target):
          return ['-o', target]
  
      def get_linker_output_args(self, outputname):
          return ['-o', outputname]
  
      def get_coverage_args(self):
          return ['--coverage']
  
      def get_coverage_link_args(self):
          return ['--coverage']
  
      def get_werror_args(self):
          return ['-Werror']
  
      def get_std_exe_link_args(self):
          return []
  
      def get_include_args(self, path, is_system):
          if path == '':
              path = '.'
          if is_system:
              return ['-isystem', path]
          return ['-I' + path]
  
      def get_std_shared_lib_link_args(self):
          return ['-shared']
  
      def get_library_dirs(self):
          stdo = Popen_safe(self.exelist + ['--print-search-dirs'])[1]
          for line in stdo.split('\n'):
              if line.startswith('libraries:'):
                  libstr = line.split('=', 1)[1]
                  return libstr.split(':')
          return []
  
      def get_pic_args(self):
          return ['-fPIC']
  
      def name_string(self):
          return ' '.join(self.exelist)
  
      def get_pch_use_args(self, pch_dir, header):
          return ['-include', os.path.split(header)[-1]]
  
      def get_pch_name(self, header_name):
          return os.path.split(header_name)[-1] + '.' + self.get_pch_suffix()
  
      def get_linker_search_args(self, dirname):
          return ['-L' + dirname]
  
      def gen_import_library_args(self, implibname):
          """
          The name of the outputted import library
  
          This implementation is used only on Windows by compilers that use GNU ld
          """
          return ['-Wl,--out-implib=' + implibname]
  
      def sanity_check_impl(self, work_dir, environment, sname, code):
          mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist))
          mlog.debug('Is cross compiler: %s.' % str(self.is_cross))
  
          extra_flags = []
          source_name = os.path.join(work_dir, sname)
          binname = sname.rsplit('.', 1)[0]
          if self.is_cross:
              binname += '_cross'
              if self.exe_wrapper is None:
                  # Linking cross built apps is painful. You can't really
                  # tell if you should use -nostdlib or not and for example
                  # on OSX the compiler binary is the same but you need
                  # a ton of compiler flags to differentiate between
                  # arm and x86_64. So just compile.
                  extra_flags += self.get_cross_extra_flags(environment, link=False)
                  extra_flags += self.get_compile_only_args()
              else:
                  extra_flags += self.get_cross_extra_flags(environment, link=True)
          # Is a valid executable output for all toolchains and platforms
          binname += '.exe'
          # Write binary check source
          binary_name = os.path.join(work_dir, binname)
          with open(source_name, 'w') as ofile:
              ofile.write(code)
          # Compile sanity check
          cmdlist = self.exelist + extra_flags + [source_name] + self.get_output_args(binary_name)
          pc, stdo, stde = Popen_safe(cmdlist, cwd=work_dir)
          mlog.debug('Sanity check compiler command line:', ' '.join(cmdlist))
          mlog.debug('Sanity check compile stdout:')
          mlog.debug(stdo)
          mlog.debug('-----\nSanity check compile stderr:')
          mlog.debug(stde)
          mlog.debug('-----')
          if pc.returncode != 0:
              raise EnvironmentException('Compiler {0} can not compile programs.'.format(self.name_string()))
          # Run sanity check
          if self.is_cross:
              if self.exe_wrapper is None:
                  # Can't check if the binaries run so we have to assume they do
                  return
              cmdlist = self.exe_wrapper + [binary_name]
          else:
              cmdlist = [binary_name]
          mlog.debug('Running test binary command: ' + ' '.join(cmdlist))
          pe = subprocess.Popen(cmdlist)
          pe.wait()
          if pe.returncode != 0:
              raise EnvironmentException('Executables created by {0} compiler {1} are not runnable.'.format(self.language, self.name_string()))
  
      def sanity_check(self, work_dir, environment):
          code = 'int main(int argc, char **argv) { int class=0; return class; }\n'
          return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code)
  
      def has_header(self, hname, prefix, env, extra_args=None, dependencies=None):
          fargs = {'prefix': prefix, 'header': hname}
          code = '''{prefix}
          #ifdef __has_include
           #if !__has_include("{header}")
            #error "Header '{header}' could not be found"
           #endif
          #else
           #include <{header}>
          #endif'''
          return self.compiles(code.format(**fargs), env, extra_args,
                               dependencies, 'preprocess')
  
      def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None):
          fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol}
          t = '''{prefix}
          #include <{header}>
          int main () {{
              /* If it's not defined as a macro, try to use as a symbol */
              #ifndef {symbol}
                  {symbol};
              #endif
          }}'''
          return self.compiles(t.format(**fargs), env, extra_args, dependencies)
  
      def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'):
          if extra_args is None:
              extra_args = []
          elif isinstance(extra_args, str):
              extra_args = [extra_args]
          if dependencies is None:
              dependencies = []
          elif not isinstance(dependencies, list):
              dependencies = [dependencies]
          # Collect compiler arguments
          args = CompilerArgs(self)
          for d in dependencies:
              # Add compile flags needed by dependencies
              args += d.get_compile_args()
              if mode == 'link':
                  # Add link flags needed to find dependencies
                  args += d.get_link_args()
          # Select a CRT if needed since we're linking
          if mode == 'link':
              args += self.get_linker_debug_crt_args()
          # Read c_args/cpp_args/etc from the cross-info file (if needed)
          args += self.get_cross_extra_flags(env, link=(mode == 'link'))
          if not self.is_cross:
              if mode == 'preprocess':
                  # Add CPPFLAGS from the env.
                  args += env.coredata.external_preprocess_args[self.language]
              elif mode == 'compile':
                  # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS from the env
                  args += env.coredata.external_args[self.language]
              elif mode == 'link':
                  # Add LDFLAGS from the env
                  args += env.coredata.external_link_args[self.language]
          args += self.get_compiler_check_args()
          # extra_args must override all other arguments, so we add them last
          args += extra_args
          return args
  
      def compiles(self, code, env, extra_args=None, dependencies=None, mode='compile'):
          args = self._get_compiler_check_args(env, extra_args, dependencies, mode)
          # We only want to compile; not link
          with self.compile(code, args.to_native(), mode) as p:
              return p.returncode == 0
  
      def _links_wrapper(self, code, env, extra_args, dependencies):
          "Shares common code between self.links and self.run"
          args = self._get_compiler_check_args(env, extra_args, dependencies, mode='link')
          return self.compile(code, args)
  
      def links(self, code, env, extra_args=None, dependencies=None):
          with self._links_wrapper(code, env, extra_args, dependencies) as p:
              return p.returncode == 0
  
      def run(self, code, env, extra_args=None, dependencies=None):
          if self.is_cross and self.exe_wrapper is None:
              raise CrossNoRunException('Can not run test applications in this cross environment.')
          with self._links_wrapper(code, env, extra_args, dependencies) as p:
              if p.returncode != 0:
                  mlog.debug('Could not compile test file %s: %d\n' % (
                      p.input_name,
                      p.returncode))
                  return RunResult(False)
              if self.is_cross:
                  cmdlist = self.exe_wrapper + [p.output_name]
              else:
                  cmdlist = p.output_name
              try:
                  pe, so, se = Popen_safe(cmdlist)
              except Exception as e:
                  mlog.debug('Could not run: %s (error: %s)\n' % (cmdlist, e))
                  return RunResult(False)
  
          mlog.debug('Program stdout:\n')
          mlog.debug(so)
          mlog.debug('Program stderr:\n')
          mlog.debug(se)
          return RunResult(True, pe.returncode, so, se)
  
      def _compile_int(self, expression, prefix, env, extra_args, dependencies):
          fargs = {'prefix': prefix, 'expression': expression}
          t = '''#include <stdio.h>
          {prefix}
          int main() {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}'''
          return self.compiles(t.format(**fargs), env, extra_args, dependencies)
  
      def cross_compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies):
          if isinstance(guess, int):
              if self._compile_int('%s == %d' % (expression, guess), prefix, env, extra_args, dependencies):
                  return guess
  
          cur = low
          while low < high:
              cur = int((low + high) / 2)
              if cur == low:
                  break
  
              if self._compile_int('%s >= %d' % (expression, cur), prefix, env, extra_args, dependencies):
                  low = cur
              else:
                  high = cur
  
          if self._compile_int('%s == %d' % (expression, cur), prefix, env, extra_args, dependencies):
              return cur
          raise EnvironmentException('Cross-compile check overflowed')
  
      def compute_int(self, expression, low, high, guess, prefix, env, extra_args=None, dependencies=None):
          if extra_args is None:
              extra_args = []
          if self.is_cross:
              return self.cross_compute_int(expression, low, high, guess, prefix, env, extra_args, dependencies)
          fargs = {'prefix': prefix, 'expression': expression}
          t = '''#include<stdio.h>
          {prefix}
          int main(int argc, char **argv) {{
              printf("%ld\\n", (long)({expression}));
              return 0;
          }};'''
          res = self.run(t.format(**fargs), env, extra_args, dependencies)
          if not res.compiled:
              return -1
          if res.returncode != 0:
              raise EnvironmentException('Could not run compute_int test binary.')
          return int(res.stdout)
  
      def cross_sizeof(self, typename, prefix, env, extra_args=None, dependencies=None):
          if extra_args is None:
              extra_args = []
          fargs = {'prefix': prefix, 'type': typename}
          t = '''#include <stdio.h>
          {prefix}
          int main(int argc, char **argv) {{
              {type} something;
          }}'''
          if not self.compiles(t.format(**fargs), env, extra_args, dependencies):
              return -1
          return self.cross_compute_int('sizeof(%s)' % typename, 1, 128, None, prefix, env, extra_args, dependencies)
  
      def sizeof(self, typename, prefix, env, extra_args=None, dependencies=None):
          if extra_args is None:
              extra_args = []
          fargs = {'prefix': prefix, 'type': typename}
          if self.is_cross:
              return self.cross_sizeof(typename, prefix, env, extra_args, dependencies)
          t = '''#include<stdio.h>
          {prefix}
          int main(int argc, char **argv) {{
              printf("%ld\\n", (long)(sizeof({type})));
              return 0;
          }};'''
          res = self.run(t.format(**fargs), env, extra_args, dependencies)
          if not res.compiled:
              return -1
          if res.returncode != 0:
              raise EnvironmentException('Could not run sizeof test binary.')
          return int(res.stdout)
  
      def cross_alignment(self, typename, prefix, env, extra_args=None, dependencies=None):
          if extra_args is None:
              extra_args = []
          fargs = {'prefix': prefix, 'type': typename}
          t = '''#include <stdio.h>
          {prefix}
          int main(int argc, char **argv) {{
              {type} something;
          }}'''
          if not self.compiles(t.format(**fargs), env, extra_args, dependencies):
              return -1
          t = '''#include <stddef.h>
          {prefix}
          struct tmp {{
              char c;
              {type} target;
          }};'''
          return self.cross_compute_int('offsetof(struct tmp, target)', 1, 1024, None, t.format(**fargs), env, extra_args, dependencies)
  
      def alignment
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/compilers/c.py
files.old_contents: # 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 subprocess, os.path, tempfile
  
  from .. import mlog
  from .. import coredata
  from ..mesonlib import EnvironmentException, version_compare, Popen_safe
  
  from .compilers import (
      GCC_MINGW,
      get_largefile_args,
      gnu_winlibs,
      msvc_buildtype_args,
      msvc_buildtype_linker_args,
      msvc_winlibs,
      ClangCompiler,
      Compiler,
      CompilerArgs,
      CrossNoRunException,
      GnuCompiler,
      IntelCompiler,
      RunResult,
  )
  
  
  class CCompiler(Compiler):
      def __init__(self, exelist, version, is_cross, exe_wrapper=None):
          # If a child ObjC or CPP class has already set it, don't set it ourselves
          if not hasattr(self, 'language'):
              self.language = 'c'
          super().__init__(exelist, version)
          self.id = 'unknown'
          self.is_cross = is_cross
          self.can_compile_suffixes.add('h')
          if isinstance(exe_wrapper, str):
              self.exe_wrapper = [exe_wrapper]
          else:
              self.exe_wrapper = exe_wrapper
  
      def needs_static_linker(self):
          return True # When compiling static libraries, so yes.
  
      def get_always_args(self):
          '''
          Args that are always-on for all C compilers other than MSVC
          '''
          return ['-pipe'] + get_largefile_args(self)
  
      def get_linker_debug_crt_args(self):
          """
          Arguments needed to select a debug crt for the linker
          This is only needed for MSVC
          """
          return []
  
      def get_no_stdinc_args(self):
          return ['-nostdinc']
  
      def get_no_stdlib_link_args(self):
          return ['-nostdlib']
  
      def get_warn_args(self, level):
          return self.warn_args[level]
  
      def get_no_warn_args(self):
          # Almost every compiler uses this for disabling warnings
          return ['-w']
  
      def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
          return []
  
      def split_shlib_to_parts(self, fname):
          return None, fname
  
      # The default behavior is this, override in MSVC
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
          return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath)
  
      def get_dependency_gen_args(self, outtarget, outfile):
          return ['-MMD', '-MQ', outtarget, '-MF', outfile]
  
      def depfile_for_object(self, objfile):
          return objfile + '.' + self.get_depfile_suffix()
  
      def get_depfile_suffix(self):
          return 'd'
  
      def get_exelist(self):
          return self.exelist[:]
  
      def get_linker_exelist(self):
          return self.exelist[:]
  
      def get_preprocess_only_args(self):
          return ['-E', '-P']
  
      def get_compile_only_args(self):
          return ['-c']
  
      def get_no_optimization_args(self):
          return ['-O0']
  
      def get_compiler_check_args(self):
          '''
          Get arguments useful for compiler checks such as being permissive in
          the code quality and not doing any optimization.
          '''
          return self.get_no_optimization_args()
  
      def get_output_args(self, target):
          return ['-o', target]
  
      def get_linker_output_args(self, outputname):
          return ['-o', outputname]
  
      def get_coverage_args(self):
          return ['--coverage']
  
      def get_coverage_link_args(self):
          return ['--coverage']
  
      def get_werror_args(self):
          return ['-Werror']
  
      def get_std_exe_link_args(self):
          return []
  
      def get_include_args(self, path, is_system):
          if path == '':
              path = '.'
          if is_system:
              return ['-isystem', path]
          return ['-I' + path]
  
      def get_std_shared_lib_link_args(self):
          return ['-shared']
  
      def get_library_dirs(self):
          stdo = Popen_safe(self.exelist + ['--print-search-dirs'])[1]
          for line in stdo.split('\n'):
              if line.startswith('libraries:'):
                  libstr = line.split('=', 1)[1]
                  return libstr.split(':')
          return []
  
      def get_pic_args(self):
          return ['-fPIC']
  
      def name_string(self):
          return ' '.join(self.exelist)
  
      def get_pch_use_args(self, pch_dir, header):
          return ['-include', os.path.split(header)[-1]]
  
      def get_pch_name(self, header_name):
          return os.path.split(header_name)[-1] + '.' + self.get_pch_suffix()
  
      def get_linker_search_args(self, dirname):
          return ['-L' + dirname]
  
      def gen_import_library_args(self, implibname):
          """
          The name of the outputted import library
  
          This implementation is used only on Windows by compilers that use GNU ld
          """
          return ['-Wl,--out-implib=' + implibname]
  
      def sanity_check_impl(self, work_dir, environment, sname, code):
          mlog.debug('Sanity testing ' + self.language + ' compiler:', ' '.join(self.exelist))
          mlog.debug('Is cross compiler: %s.' % str(self.is_cross))
  
          extra_flags = []
          source_name = os.path.join(work_dir, sname)
          binname = sname.rsplit('.', 1)[0]
          if self.is_cross:
              binname += '_cross'
              if self.exe_wrapper is None:
                  # Linking cross built apps is painful. You can't really
                  # tell if you should use -nostdlib or not and for example
                  # on OSX the compiler binary is the same but you need
                  # a ton of compiler flags to differentiate between
                  # arm and x86_64. So just compile.
                  extra_flags += self.get_cross_extra_flags(environment, link=False)
                  extra_flags += self.get_compile_only_args()
              else:
                  extra_flags += self.get_cross_extra_flags(environment, link=True)
          # Is a valid executable output for all toolchains and platforms
          binname += '.exe'
          # Write binary check source
          binary_name = os.path.join(work_dir, binname)
          with open(source_name, 'w') as ofile:
              ofile.write(code)
          # Compile sanity check
          cmdlist = self.exelist + extra_flags + [source_name] + self.get_output_args(binary_name)
          pc, stdo, stde = Popen_safe(cmdlist, cwd=work_dir)
          mlog.debug('Sanity check compiler command line:', ' '.join(cmdlist))
          mlog.debug('Sanity check compile stdout:')
          mlog.debug(stdo)
          mlog.debug('-----\nSanity check compile stderr:')
          mlog.debug(stde)
          mlog.debug('-----')
          if pc.returncode != 0:
              raise EnvironmentException('Compiler {0} can not compile programs.'.format(self.name_string()))
          # Run sanity check
          if self.is_cross:
              if self.exe_wrapper is None:
                  # Can't check if the binaries run so we have to assume they do
                  return
              cmdlist = self.exe_wrapper + [binary_name]
          else:
              cmdlist = [binary_name]
          mlog.debug('Running test binary command: ' + ' '.join(cmdlist))
          pe = subprocess.Popen(cmdlist)
          pe.wait()
          if pe.returncode != 0:
              raise EnvironmentException('Executables created by {0} compiler {1} are not runnable.'.format(self.language, self.name_string()))
  
      def sanity_check(self, work_dir, environment):
          code = 'int main(int argc, char **argv) { int class=0; return class; }\n'
          return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code)
  
      def has_header(self, hname, prefix, env, extra_args=None, dependencies=None):
          fargs = {'prefix': prefix, 'header': hname}
          code = '''{prefix}
          #ifdef __has_include
           #if !__has_include("{header}")
            #error "Header '{header}' could not be found"
           #endif
          #else
           #include <{header}>
          #endif'''
          return self.compiles(code.format(**fargs), env, extra_args,
                               dependencies, 'preprocess')
  
      def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None):
          fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol}
          t = '''{prefix}
          #include <{header}>
          int main () {{
              /* If it's not defined as a macro, try to use as a symbol */
              #ifndef {symbol}
                  {symbol};
              #endif
          }}'''
          return self.compiles(t.format(**fargs), env, extra_args, dependencies)
  
      def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'):
          if extra_args is None:
              extra_args = []
          elif isinstance(extra_args, str):
              extra_args = [extra_args]
          if dependencies is None:
              dependencies = []
          elif not isinstance(dependencies, list):
              dependencies = [dependencies]
          # Collect compiler arguments
          args = CompilerArgs(self)
          for d in dependencies:
              # Add compile flags needed by dependencies
              args += d.get_compile_args()
              if mode == 'link':
                  # Add link flags needed to find dependencies
                  args += d.get_link_args()
          # Select a CRT if needed since we're linking
          if mode == 'link':
              args += self.get_linker_debug_crt_args()
          # Read c_args/cpp_args/etc from the cross-info file (if needed)
          args += self.get_cross_extra_flags(env, link=(mode == 'link'))
          if not self.is_cross:
              if mode == 'preprocess':
                  # Add CPPFLAGS from the env.
                  args += env.coredata.external_preprocess_args[self.language]
              elif mode == 'compile':
                  # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS from the env
                  args += env.coredata.external_args[self.language]
              elif mode == 'link':
                  # Add LDFLAGS from the env
                  args += env.coredata.external_link_args[self.language]
          args += self.get_compiler_check_args()
          # extra_args must override all other arguments, so we add them last
          args += extra_args
          return args
  
      def compiles(self, code, env, extra_args=None, dependencies=None, mode='compile'):
          args = self._get_compiler_check_args(env, extra_args, dependencies, mode)
          # We only want to compile; not link
          with self.compile(code, args.to_native(), mode) as p:
              return p.returncode == 0
  
      def _links_wrapper(self, code, env, extra_args, dependencies):
          "Shares common code between self.links and self.run"
          args = self._get_compiler_check_args(env, extra_args, dependencies, mode='link')
          return self.compile(code, args)
  
      def links(self, code, env, extra_args=None, dependencies=None):
          with self._links_wrapper(code, env, extra_args, dependencies) as p:
              return p.returncode == 0
  
      def run(self, code, env, extra_args=None, dependencies=None):
          if self.is_cross and self.exe_wrapper is None:
              raise CrossNoRunException('Can not run test applications in this cross environment.')
          with self._links_wrapper(code, env, extra_args, dependencies) as p:
              if p.returncode != 0:
                  mlog.debug('Could not compile test file %s: %d\n' % (
                      p.input_name,
                      p.returncode))
                  return RunResult(False)
              if self.is_cross:
                  cmdlist = self.exe_wrapper + [p.output_name]
              else:
                  cmdlist = p.output_name
              try:
                  pe, so, se = Popen_safe(cmdlist)
              except Exception as e:
                  mlog.debug('Could not run: %s (error: %s)\n' % (cmdlist, e))
                  return RunResult(False)
  
          mlog.debug('Program stdout:\n')
          mlog.debug(so)
          mlog.debug('Program stderr:\n')
          mlog.debug(se)
          return RunResult(True, pe.returncode, so, se)
  
      def _compile_int(self, expression, prefix, env, extra_args, dependencies):
          fargs = {'prefix': prefix, 'expression': expression}
          t = '''#include <stdio.h>
          {prefix}
          int main() {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}'''
          return self.compiles(t.format(**fargs), env, extra_args, dependencies)
  
      def cross_compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies):
          if isinstance(guess, int):
              if self._compile_int('%s == %d' % (expression, guess), prefix, env, extra_args, dependencies):
                  return guess
  
          cur = low
          while low < high:
              cur = int((low + high) / 2)
              if cur == low:
                  break
  
              if self._compile_int('%s >= %d' % (expression, cur), prefix, env, extra_args, dependencies):
                  low = cur
              else:
                  high = cur
  
          if self._compile_int('%s == %d' % (expression, cur), prefix, env, extra_args, dependencies):
              return cur
          raise EnvironmentException('Cross-compile check overflowed')
  
      def compute_int(self, expression, low, high, guess, prefix, env, extra_args=None, dependencies=None):
          if extra_args is None:
              extra_args = []
          if self.is_cross:
              return self.cross_compute_int(expression, low, high, guess, prefix, env, extra_args, dependencies)
          fargs = {'prefix': prefix, 'expression': expression}
          t = '''#include<stdio.h>
          {prefix}
          int main(int argc, char **argv) {{
              printf("%ld\\n", (long)({expression}));
              return 0;
          }};'''
          res = self.run(t.format(**fargs), env, extra_args, dependencies)
          if not res.compiled:
              return -1
          if res.returncode != 0:
              raise EnvironmentException('Could not run compute_int test binary.')
          return int(res.stdout)
  
      def cross_sizeof(self, typename, prefix, env, extra_args=None, dependencies=None):
          if extra_args is None:
              extra_args = []
          fargs = {'prefix': prefix, 'type': typename}
          t = '''#include <stdio.h>
          {prefix}
          int main(int argc, char **argv) {{
              {type} something;
          }}'''
          if not self.compiles(t.format(**fargs), env, extra_args, dependencies):
              return -1
          return self.cross_compute_int('sizeof(%s)' % typename, 1, 128, None, prefix, env, extra_args, dependencies)
  
      def sizeof(self, typename, prefix, env, extra_args=None, dependencies=None):
          if extra_args is None:
              extra_args = []
          fargs = {'prefix': prefix, 'type': typename}
          if self.is_cross:
              return self.cross_sizeof(typename, prefix, env, extra_args, dependencies)
          t = '''#include<stdio.h>
          {prefix}
          int main(int argc, char **argv) {{
              printf("%ld\\n", (long)(sizeof({type})));
              return 0;
          }};'''
          res = self.run(t.format(**fargs), env, extra_args, dependencies)
          if not res.compiled:
              return -1
          if res.returncode != 0:
              raise EnvironmentException('Could not run sizeof test binary.')
          return int(res.stdout)
  
      def cross_alignment(self, typename, prefix, env, extra_args=None, dependencies=None):
          if extra_args is None:
              extra_args = []
          fargs = {'prefix': prefix, 'type': typename}
          t = '''#include <stdio.h>
          {prefix}
          int main(int argc, char **argv) {{
              {type} something;
          }}'''
          if not self.compiles(t.format(**fargs), env, extra_args, dependencies):
              return -1
          t = '''#include <stddef.h>
          {prefix}
          struct tmp {{
              char c;
              {type} target;
          }};'''
          return self.cross_compute_int('offsetof(struct tmp, target)', 1, 1024, None, t.format(**fargs), env, extra_args, dependencies)
  
      def alignment(self, typename,
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/compilers/c.py
files.new_contents: # 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
  
  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'),
      'cs': ('cs',),
      'swift': ('swift',),
      'java': ('java',),
  }
  cpp_suffixes = lang_suffixes['cpp'] + ('h',)
  c_suffixes = lang_suffixes['c'] + ('h',)
  # 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()
  clike_langs = ('objcpp', 'objc', 'd', 'cpp', 'c', 'fortran',)
  clike_suffixes = ()
  for _l in clike_langs:
      clike_suffixes += lang_suffixes[_l]
  clike_suffixes += ('h', 'll', 's')
  
  # 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
      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']}
  
  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': [],
                                   }
  
  msvc_buildtype_linker_args = {'plain': [],
                                'debug': [],
                                'debugoptimized': [],
                                'release': [],
                                'minsize': ['/INCREMENTAL:NO'],
                                }
  
  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', 'comdlg32.lib', 'advapi32.lib']
  
  gnu_color_args = {'auto': ['-fdiagnostics-color=auto'],
                    'always': ['-fdiagnostics-color=always'],
                    'never': ['-fdiagnostics-color=never'],
                    }
  
  clang_color_args = {'auto': ['-Xclang', '-fcolor-diagnostics'],
                      'always': ['-Xclang', '-fcolor-diagnostics'],
                      'never': ['-Xclang', '-fno-color-diagnostics'],
                      }
  
  base_options = {'b_pch': coredata.UserBooleanOption('b_pch', 'Use precompiled headers', True),
                  'b_lto': coredata.UserBooleanOption('b_lto', 'Use link time optimization', False),
                  'b_sanitize': coredata.UserComboOption('b_sanitize',
                                                         'Code sanitizer to use',
                                                         ['none', 'address', 'thread', 'undefined', 'memory'],
                                                         'none'),
                  'b_lundef': coredata.UserBooleanOption('b_lundef', 'Use -Wl,--no-undefined when linking', True),
                  'b_asneeded': coredata.UserBooleanOption('b_asneeded', 'Use -Wl,--as-needed when linking', True),
                  'b_pgo': coredata.UserComboOption('b_pgo', 'Use profile guide optimization',
                                                    ['off', 'generate', 'use'],
                                                    'off'),
                  'b_coverage': coredata.UserBooleanOption('b_coverage',
                                                           'Enable coverage tracking.',
                                                           False),
                  'b_colorout': coredata.UserComboOption('b_colorout', 'Use colored output',
                                                         ['auto', 'always', 'never'],
                                                         'always'),
                  'b_ndebug': coredata.UserBooleanOption('b_ndebug',
                                                         'Disable asserts',
                                                         False),
                  'b_staticpic': coredata.UserBooleanOption('b_staticpic',
                                                            'Build static libraries as position independent',
                                                            True),
                  }
  
  def sanitizer_compile_args(value):
      if value == 'none':
          return []
      args = ['-fsanitize=' + value]
      if value == 'address':
          args.append('-fno-omit-frame-pointer')
      return args
  
  def sanitizer_link_args(value):
      if value == 'none':
          return []
      args = ['-fsanitize=' + value]
      return args
  
  def get_base_compile_args(options, compiler):
      args = []
      # FIXME, gcc/clang specific.
      try:
          if options['b_lto'].value:
              args.append('-flto')
      except KeyError:
          pass
      try:
          args += compiler.get_colorout_args(options['b_colorout'].value)
      except KeyError:
          pass
      try:
          args += sanitizer_compile_args(options['b_sanitize'].value)
      except KeyError:
          pass
      try:
          pgo_val = options['b_pgo'].value
          if pgo_val == 'generate':
              args.append('-fprofile-generate')
          elif pgo_val == 'use':
              args.append('-fprofile-use')
      except KeyError:
          pass
      try:
          if options['b_coverage'].value:
              args += compiler.get_coverage_args()
      except KeyError:
          pass
      try:
          if options['b_ndebug'].value:
              args += ['-DNDEBUG']
      except KeyError:
          pass
      return args
  
  def get_base_link_args(options, linker, is_shared_module):
      args = []
      # FIXME, gcc/clang specific.
      try:
          if options['b_lto'].value:
              args.append('-flto')
      except KeyError:
          pass
      try:
          args += sanitizer_link_args(options['b_sanitize'].value)
      except KeyError:
          pass
      try:
          pgo_val = options['b_pgo'].value
          if pgo_val == 'generate':
              args.append('-fprofile-generate')
          elif pgo_val == 'use':
              args.append('-fprofile-use')
      except KeyError:
          pass
      try:
          if not is_shared_module and 'b_lundef' in linker.base_options and options['b_lundef'].value:
              args.append('-Wl,--no-undefined')
      except KeyError:
          pass
      try:
          if 'b_asneeded' in linker.base_options and options['b_asneeded'].value:
              args.append('-Wl,--as-needed')
      except KeyError:
          pass
      try:
          if options['b_coverage'].value:
              args += linker.get_coverage_link_args()
      except KeyError:
          pass
      return args
  
  class CrossNoRunException(MesonException):
      pass
  
  class RunResult:
      def __init__(self, compiled, returncode=999, stdout='UNDEFINED', stderr='UNDEFINED'):
          self.compiled = compiled
          self.returncode = returncode
          self.stdout = stdout
          self.stderr = stderr
  
  class CompilerArgs(list):
      '''
      Class derived from list() that manages a list of compiler arguments. Should
      be used while constructing compiler arguments from various sources. Can be
      operated with ordinary lists, so this does not need to be used everywhere.
  
      All arguments must be inserted and stored in GCC-style (-lfoo, -Idir, etc)
      and can converted to the native type of each compiler by using the
      .to_native() method to which you must pass an instance of the compiler or
      the compiler class.
  
      New arguments added to this class (either with .append(), .extend(), or +=)
      are added in a way that ensures that they override previous arguments.
      For example:
  
      >>> a = ['-Lfoo', '-lbar']
      >>> a += ['-Lpho', '-lbaz']
      >>> print(a)
      ['-Lpho', '-Lfoo', '-lbar', '-lbaz']
  
      Arguments will also be de-duped if they can be de-duped safely.
  
      Note that because of all this, this class is not commutative and does not
      preserve the order of arguments if it is safe to not. For example:
      >>> ['-Ifoo', '-Ibar'] + ['-Ifez', '-Ibaz', '-Werror']
      ['-Ifez', '-Ibaz', '-Ifoo', '-Ibar', '-Werror']
      >>> ['-Ifez', '-Ibaz', '-Werror'] + ['-Ifoo', '-Ibar']
      ['-Ifoo', '-Ibar', '-Ifez', '-Ibaz', '-Werror']
  
      '''
      # NOTE: currently this class is only for C-like compilers, but it can be
      # extended to other languages easily. Just move the following to the
      # compiler class and initialize when self.compiler is set.
  
      # Arg prefixes that override by prepending instead of appending
      prepend_prefixes = ('-I', '-L')
      # Arg prefixes and args that must be de-duped by returning 2
      dedup2_prefixes = ('-I', '-L', '-D', '-U')
      dedup2_suffixes = ()
      dedup2_args = ()
      # Arg prefixes and args that must be de-duped by returning 1
      dedup1_prefixes = ('-l',)
      dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a')
      # Match a .so of the form path/to/libfoo.so.0.1.0
      # Only UNIX shared libraries require this. Others have a fixed extension.
      dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
      dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread')
      compiler = None
  
      def _check_args(self, args):
          cargs = []
          if len(args) > 2:
              raise TypeError("CompilerArgs() only accepts at most 2 arguments: "
                              "The compiler, and optionally an initial list")
          elif not args:
              return cargs
          elif len(args) == 1:
              if isinstance(args[0], (Compiler, StaticLinker)):
                  self.compiler = args[0]
              else:
                  raise TypeError("you must pass a Compiler instance as one of "
                                  "the arguments")
          elif len(args) == 2:
              if isinstance(args[0], (Compiler, StaticLinker)):
                  self.compiler = args[0]
                  cargs = args[1]
              elif isinstance(args[1], (Compiler, StaticLinker)):
                  cargs = args[0]
                  self.compiler = args[1]
              else:
                  raise TypeError("you must pass a Compiler instance as one of "
                                  "the two arguments")
          else:
              raise AssertionError('Not reached')
          return cargs
  
      def __init__(self, *args):
          super().__init__(self._check_args(args))
  
      @classmethod
      def _can_dedup(cls, arg):
          '''
          Returns whether the argument can be safely de-duped. This is dependent
          on three things:
  
          a) Whether an argument can be 'overriden' by a later argument.  For
            
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/compilers/compilers.py
files.old_contents: # 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
  
  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'),
      'cs': ('cs',),
      'swift': ('swift',),
      'java': ('java',),
  }
  cpp_suffixes = lang_suffixes['cpp'] + ('h',)
  c_suffixes = lang_suffixes['c'] + ('h',)
  # 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()
  clike_langs = ('objcpp', 'objc', 'd', 'cpp', 'c', 'fortran',)
  clike_suffixes = ()
  for _l in clike_langs:
      clike_suffixes += lang_suffixes[_l]
  clike_suffixes += ('h', 'll', 's')
  
  # 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
      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']}
  
  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': [],
                                   }
  
  msvc_buildtype_linker_args = {'plain': [],
                                'debug': [],
                                'debugoptimized': [],
                                'release': [],
                                'minsize': ['/INCREMENTAL:NO'],
                                }
  
  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', 'comdlg32.lib', 'advapi32.lib']
  
  gnu_color_args = {'auto': ['-fdiagnostics-color=auto'],
                    'always': ['-fdiagnostics-color=always'],
                    'never': ['-fdiagnostics-color=never'],
                    }
  
  clang_color_args = {'auto': ['-Xclang', '-fcolor-diagnostics'],
                      'always': ['-Xclang', '-fcolor-diagnostics'],
                      'never': ['-Xclang', '-fno-color-diagnostics'],
                      }
  
  base_options = {'b_pch': coredata.UserBooleanOption('b_pch', 'Use precompiled headers', True),
                  'b_lto': coredata.UserBooleanOption('b_lto', 'Use link time optimization', False),
                  'b_sanitize': coredata.UserComboOption('b_sanitize',
                                                         'Code sanitizer to use',
                                                         ['none', 'address', 'thread', 'undefined', 'memory'],
                                                         'none'),
                  'b_lundef': coredata.UserBooleanOption('b_lundef', 'Use -Wl,--no-undefined when linking', True),
                  'b_asneeded': coredata.UserBooleanOption('b_asneeded', 'Use -Wl,--as-needed when linking', True),
                  'b_pgo': coredata.UserComboOption('b_pgo', 'Use profile guide optimization',
                                                    ['off', 'generate', 'use'],
                                                    'off'),
                  'b_coverage': coredata.UserBooleanOption('b_coverage',
                                                           'Enable coverage tracking.',
                                                           False),
                  'b_colorout': coredata.UserComboOption('b_colorout', 'Use colored output',
                                                         ['auto', 'always', 'never'],
                                                         'always'),
                  'b_ndebug': coredata.UserBooleanOption('b_ndebug',
                                                         'Disable asserts',
                                                         False),
                  'b_staticpic': coredata.UserBooleanOption('b_staticpic',
                                                            'Build static libraries as position independent',
                                                            True),
                  }
  
  def sanitizer_compile_args(value):
      if value == 'none':
          return []
      args = ['-fsanitize=' + value]
      if value == 'address':
          args.append('-fno-omit-frame-pointer')
      return args
  
  def sanitizer_link_args(value):
      if value == 'none':
          return []
      args = ['-fsanitize=' + value]
      return args
  
  def get_base_compile_args(options, compiler):
      args = []
      # FIXME, gcc/clang specific.
      try:
          if options['b_lto'].value:
              args.append('-flto')
      except KeyError:
          pass
      try:
          args += compiler.get_colorout_args(options['b_colorout'].value)
      except KeyError:
          pass
      try:
          args += sanitizer_compile_args(options['b_sanitize'].value)
      except KeyError:
          pass
      try:
          pgo_val = options['b_pgo'].value
          if pgo_val == 'generate':
              args.append('-fprofile-generate')
          elif pgo_val == 'use':
              args.append('-fprofile-use')
      except KeyError:
          pass
      try:
          if options['b_coverage'].value:
              args += compiler.get_coverage_args()
      except KeyError:
          pass
      try:
          if options['b_ndebug'].value:
              args += ['-DNDEBUG']
      except KeyError:
          pass
      return args
  
  def get_base_link_args(options, linker, is_shared_module):
      args = []
      # FIXME, gcc/clang specific.
      try:
          if options['b_lto'].value:
              args.append('-flto')
      except KeyError:
          pass
      try:
          args += sanitizer_link_args(options['b_sanitize'].value)
      except KeyError:
          pass
      try:
          pgo_val = options['b_pgo'].value
          if pgo_val == 'generate':
              args.append('-fprofile-generate')
          elif pgo_val == 'use':
              args.append('-fprofile-use')
      except KeyError:
          pass
      try:
          if not is_shared_module and 'b_lundef' in linker.base_options and options['b_lundef'].value:
              args.append('-Wl,--no-undefined')
      except KeyError:
          pass
      try:
          if 'b_asneeded' in linker.base_options and options['b_asneeded'].value:
              args.append('-Wl,--as-needed')
      except KeyError:
          pass
      try:
          if options['b_coverage'].value:
              args += linker.get_coverage_link_args()
      except KeyError:
          pass
      return args
  
  class CrossNoRunException(MesonException):
      pass
  
  class RunResult:
      def __init__(self, compiled, returncode=999, stdout='UNDEFINED', stderr='UNDEFINED'):
          self.compiled = compiled
          self.returncode = returncode
          self.stdout = stdout
          self.stderr = stderr
  
  class CompilerArgs(list):
      '''
      Class derived from list() that manages a list of compiler arguments. Should
      be used while constructing compiler arguments from various sources. Can be
      operated with ordinary lists, so this does not need to be used everywhere.
  
      All arguments must be inserted and stored in GCC-style (-lfoo, -Idir, etc)
      and can converted to the native type of each compiler by using the
      .to_native() method to which you must pass an instance of the compiler or
      the compiler class.
  
      New arguments added to this class (either with .append(), .extend(), or +=)
      are added in a way that ensures that they override previous arguments.
      For example:
  
      >>> a = ['-Lfoo', '-lbar']
      >>> a += ['-Lpho', '-lbaz']
      >>> print(a)
      ['-Lpho', '-Lfoo', '-lbar', '-lbaz']
  
      Arguments will also be de-duped if they can be de-duped safely.
  
      Note that because of all this, this class is not commutative and does not
      preserve the order of arguments if it is safe to not. For example:
      >>> ['-Ifoo', '-Ibar'] + ['-Ifez', '-Ibaz', '-Werror']
      ['-Ifez', '-Ibaz', '-Ifoo', '-Ibar', '-Werror']
      >>> ['-Ifez', '-Ibaz', '-Werror'] + ['-Ifoo', '-Ibar']
      ['-Ifoo', '-Ibar', '-Ifez', '-Ibaz', '-Werror']
  
      '''
      # NOTE: currently this class is only for C-like compilers, but it can be
      # extended to other languages easily. Just move the following to the
      # compiler class and initialize when self.compiler is set.
  
      # Arg prefixes that override by prepending instead of appending
      prepend_prefixes = ('-I', '-L')
      # Arg prefixes and args that must be de-duped by returning 2
      dedup2_prefixes = ('-I', '-L', '-D', '-U')
      dedup2_suffixes = ()
      dedup2_args = ()
      # Arg prefixes and args that must be de-duped by returning 1
      dedup1_prefixes = ('-l',)
      dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a')
      # Match a .so of the form path/to/libfoo.so.0.1.0
      # Only UNIX shared libraries require this. Others have a fixed extension.
      dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
      dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread')
      compiler = None
  
      def _check_args(self, args):
          cargs = []
          if len(args) > 2:
              raise TypeError("CompilerArgs() only accepts at most 2 arguments: "
                              "The compiler, and optionally an initial list")
          elif not args:
              return cargs
          elif len(args) == 1:
              if isinstance(args[0], (Compiler, StaticLinker)):
                  self.compiler = args[0]
              else:
                  raise TypeError("you must pass a Compiler instance as one of "
                                  "the arguments")
          elif len(args) == 2:
              if isinstance(args[0], (Compiler, StaticLinker)):
                  self.compiler = args[0]
                  cargs = args[1]
              elif isinstance(args[1], (Compiler, StaticLinker)):
                  cargs = args[0]
                  self.compiler = args[1]
              else:
                  raise TypeError("you must pass a Compiler instance as one of "
                                  "the two arguments")
          else:
              raise AssertionError('Not reached')
          return cargs
  
      def __init__(self, *args):
          super().__init__(self._check_args(args))
  
      @classmethod
      def _can_dedup(cls, arg):
          '''
          Returns whether the argument can be safely de-duped. This is dependent
          on three things:
  
          a) Whether an argument can be 'overriden' by a later argument.  For
            
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/compilers/compilers.py
files.new_contents: # 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.
  
  from .. import coredata
  from ..mesonlib import version_compare
  
  from .c import CCompiler, VisualStudioCCompiler
  from .compilers import (
      GCC_MINGW,
      gnu_winlibs,
      msvc_winlibs,
      ClangCompiler,
      GnuCompiler,
      IntelCompiler,
  )
  
  class CPPCompiler(CCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrap):
          # If a child ObjCPP class has already set it, don't set it ourselves
          if not hasattr(self, 'language'):
              self.language = 'cpp'
          CCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
  
      def get_display_language(self):
          return 'C++'
  
      def get_no_stdinc_args(self):
          return ['-nostdinc++']
  
      def sanity_check(self, work_dir, environment):
          code = 'class breakCCompiler;int main(int argc, char **argv) { return 0; }\n'
          return self.sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code)
  
      def get_compiler_check_args(self):
          # -fpermissive allows non-conforming code to compile which is necessary
          # for many C++ checks. Particularly, the has_header_symbol check is
          # too strict without this and always fails.
          return super().get_compiler_check_args() + ['-fpermissive']
  
      def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None):
          # Check if it's a C-like symbol
          if super().has_header_symbol(hname, symbol, prefix, env, extra_args, dependencies):
              return True
          # Check if it's a class or a template
          if extra_args is None:
              extra_args = []
          fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol}
          t = '''{prefix}
          #include <{header}>
          using {symbol};
          int main () {{ return 0; }}'''
          return self.compiles(t.format(**fargs), env, extra_args, dependencies)
  
  
  class ClangCPPCompiler(ClangCompiler, CPPCompiler):
      def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None):
          CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
          ClangCompiler.__init__(self, cltype)
          default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
  
      def get_options(self):
          return {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
                                                      ['none', 'c++03', 'c++11', 'c++14', 'c++1z',
                                                       'gnu++11', 'gnu++14', 'gnu++1z'],
                                                      'none')}
  
      def get_option_compile_args(self, options):
          args = []
          std = options['cpp_std']
          if std.value != 'none':
              args.append('-std=' + std.value)
          return args
  
      def get_option_link_args(self, options):
          return []
  
  
  class GnuCPPCompiler(GnuCompiler, CPPCompiler):
      def __init__(self, exelist, version, gcc_type, is_cross, exe_wrap, defines):
          CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
          GnuCompiler.__init__(self, gcc_type, defines)
          default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
  
      def get_options(self):
          opts = {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
                                                      ['none', 'c++03', 'c++11', 'c++14', 'c++1z',
                                                       'gnu++03', 'gnu++11', 'gnu++14', 'gnu++1z'],
                                                      'none'),
                  'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl',
                                                             'STL debug mode',
                                                             False)}
          if self.gcc_type == GCC_MINGW:
              opts.update({
                  'cpp_winlibs': coredata.UserStringArrayOption('cpp_winlibs', 'Standard Win libraries to link against',
                                                                gnu_winlibs), })
          return opts
  
      def get_option_compile_args(self, options):
          args = []
          std = options['cpp_std']
          if std.value != 'none':
              args.append('-std=' + std.value)
          if options['cpp_debugstl'].value:
              args.append('-D_GLIBCXX_DEBUG=1')
          return args
  
      def get_option_link_args(self, options):
          if self.gcc_type == GCC_MINGW:
              return options['cpp_winlibs'].value[:]
          return []
  
  
  class IntelCPPCompiler(IntelCompiler, CPPCompiler):
      def __init__(self, exelist, version, icc_type, is_cross, exe_wrap):
          CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
          IntelCompiler.__init__(self, icc_type)
          self.lang_header = 'c++-header'
          default_warn_args = ['-Wall', '-w3', '-diag-disable:remark',
                               '-Wpch-messages', '-Wnon-virtual-dtor']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
  
      def get_options(self):
          c_stds = []
          g_stds = ['gnu++98']
          if version_compare(self.version, '>=15.0.0'):
              c_stds += ['c++11', 'c++14']
              g_stds += ['gnu++11']
          if version_compare(self.version, '>=16.0.0'):
              c_stds += ['c++17']
          if version_compare(self.version, '>=17.0.0'):
              g_stds += ['gnu++14']
          opts = {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
                                                      ['none'] + c_stds + g_stds,
                                                      'none'),
                  'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl',
                                                             'STL debug mode',
                                                             False)}
          return opts
  
      def get_option_compile_args(self, options):
          args = []
          std = options['cpp_std']
          if std.value != 'none':
              args.append('-std=' + std.value)
          if options['cpp_debugstl'].value:
              args.append('-D_GLIBCXX_DEBUG=1')
          return args
  
      def get_option_link_args(self, options):
          return []
  
      def has_multi_arguments(self, args, env):
          return super().has_multi_arguments(args + ['-diag-error', '10006'], env)
  
  
  class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrap):
          self.language = 'cpp'
          CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
          VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
          self.base_options = ['b_pch'] # FIXME add lto, pgo and the like
  
      def get_options(self):
          return {'cpp_eh': coredata.UserComboOption('cpp_eh',
                                                     'C++ exception handling type.',
                                                     ['none', 'a', 's', 'sc'],
                                                     'sc'),
                  'cpp_winlibs': coredata.UserStringArrayOption('cpp_winlibs',
                                                                'Windows libs to link against.',
                                                                msvc_winlibs)
                  }
  
      def get_option_compile_args(self, options):
          args = []
          std = options['cpp_eh']
          if std.value != 'none':
              args.append('/EH' + std.value)
          return args
  
      def get_option_link_args(self, options):
          return options['cpp_winlibs'].value[:]
  
      def get_compiler_check_args(self):
          # Visual Studio C++ compiler doesn't support -fpermissive,
          # so just use the plain C args.
          return super(VisualStudioCCompiler, self).get_compiler_check_args()
  
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/compilers/cpp.py
files.old_contents: # 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.
  
  from .. import coredata
  from ..mesonlib import version_compare
  
  from .c import CCompiler, VisualStudioCCompiler
  from .compilers import (
      GCC_MINGW,
      gnu_winlibs,
      msvc_winlibs,
      ClangCompiler,
      GnuCompiler,
      IntelCompiler,
  )
  
  class CPPCompiler(CCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrap):
          # If a child ObjCPP class has already set it, don't set it ourselves
          if not hasattr(self, 'language'):
              self.language = 'cpp'
          CCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
  
      def get_no_stdinc_args(self):
          return ['-nostdinc++']
  
      def sanity_check(self, work_dir, environment):
          code = 'class breakCCompiler;int main(int argc, char **argv) { return 0; }\n'
          return self.sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code)
  
      def get_compiler_check_args(self):
          # -fpermissive allows non-conforming code to compile which is necessary
          # for many C++ checks. Particularly, the has_header_symbol check is
          # too strict without this and always fails.
          return super().get_compiler_check_args() + ['-fpermissive']
  
      def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None):
          # Check if it's a C-like symbol
          if super().has_header_symbol(hname, symbol, prefix, env, extra_args, dependencies):
              return True
          # Check if it's a class or a template
          if extra_args is None:
              extra_args = []
          fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol}
          t = '''{prefix}
          #include <{header}>
          using {symbol};
          int main () {{ return 0; }}'''
          return self.compiles(t.format(**fargs), env, extra_args, dependencies)
  
  
  class ClangCPPCompiler(ClangCompiler, CPPCompiler):
      def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None):
          CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
          ClangCompiler.__init__(self, cltype)
          default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
  
      def get_options(self):
          return {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
                                                      ['none', 'c++03', 'c++11', 'c++14', 'c++1z',
                                                       'gnu++11', 'gnu++14', 'gnu++1z'],
                                                      'none')}
  
      def get_option_compile_args(self, options):
          args = []
          std = options['cpp_std']
          if std.value != 'none':
              args.append('-std=' + std.value)
          return args
  
      def get_option_link_args(self, options):
          return []
  
  
  class GnuCPPCompiler(GnuCompiler, CPPCompiler):
      def __init__(self, exelist, version, gcc_type, is_cross, exe_wrap, defines):
          CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
          GnuCompiler.__init__(self, gcc_type, defines)
          default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
  
      def get_options(self):
          opts = {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
                                                      ['none', 'c++03', 'c++11', 'c++14', 'c++1z',
                                                       'gnu++03', 'gnu++11', 'gnu++14', 'gnu++1z'],
                                                      'none'),
                  'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl',
                                                             'STL debug mode',
                                                             False)}
          if self.gcc_type == GCC_MINGW:
              opts.update({
                  'cpp_winlibs': coredata.UserStringArrayOption('cpp_winlibs', 'Standard Win libraries to link against',
                                                                gnu_winlibs), })
          return opts
  
      def get_option_compile_args(self, options):
          args = []
          std = options['cpp_std']
          if std.value != 'none':
              args.append('-std=' + std.value)
          if options['cpp_debugstl'].value:
              args.append('-D_GLIBCXX_DEBUG=1')
          return args
  
      def get_option_link_args(self, options):
          if self.gcc_type == GCC_MINGW:
              return options['cpp_winlibs'].value[:]
          return []
  
  
  class IntelCPPCompiler(IntelCompiler, CPPCompiler):
      def __init__(self, exelist, version, icc_type, is_cross, exe_wrap):
          CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
          IntelCompiler.__init__(self, icc_type)
          self.lang_header = 'c++-header'
          default_warn_args = ['-Wall', '-w3', '-diag-disable:remark',
                               '-Wpch-messages', '-Wnon-virtual-dtor']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
  
      def get_options(self):
          c_stds = []
          g_stds = ['gnu++98']
          if version_compare(self.version, '>=15.0.0'):
              c_stds += ['c++11', 'c++14']
              g_stds += ['gnu++11']
          if version_compare(self.version, '>=16.0.0'):
              c_stds += ['c++17']
          if version_compare(self.version, '>=17.0.0'):
              g_stds += ['gnu++14']
          opts = {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
                                                      ['none'] + c_stds + g_stds,
                                                      'none'),
                  'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl',
                                                             'STL debug mode',
                                                             False)}
          return opts
  
      def get_option_compile_args(self, options):
          args = []
          std = options['cpp_std']
          if std.value != 'none':
              args.append('-std=' + std.value)
          if options['cpp_debugstl'].value:
              args.append('-D_GLIBCXX_DEBUG=1')
          return args
  
      def get_option_link_args(self, options):
          return []
  
      def has_multi_arguments(self, args, env):
          return super().has_multi_arguments(args + ['-diag-error', '10006'], env)
  
  
  class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrap):
          self.language = 'cpp'
          CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
          VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
          self.base_options = ['b_pch'] # FIXME add lto, pgo and the like
  
      def get_options(self):
          return {'cpp_eh': coredata.UserComboOption('cpp_eh',
                                                     'C++ exception handling type.',
                                                     ['none', 'a', 's', 'sc'],
                                                     'sc'),
                  'cpp_winlibs': coredata.UserStringArrayOption('cpp_winlibs',
                                                                'Windows libs to link against.',
                                                                msvc_winlibs)
                  }
  
      def get_option_compile_args(self, options):
          args = []
          std = options['cpp_eh']
          if std.value != 'none':
              args.append('/EH' + std.value)
          return args
  
      def get_option_link_args(self, options):
          return options['cpp_winlibs'].value[:]
  
      def get_compiler_check_args(self):
          # Visual Studio C++ compiler doesn't support -fpermissive,
          # so just use the plain C args.
          return super(VisualStudioCCompiler, self).get_compiler_check_args()
  
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/compilers/cpp.py
files.new_contents: # 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 os.path, subprocess
  
  from ..mesonlib import EnvironmentException
  
  from .compilers import Compiler, mono_buildtype_args
  
  class MonoCompiler(Compiler):
      def __init__(self, exelist, version):
          self.language = 'cs'
          super().__init__(exelist, version)
          self.id = 'mono'
          self.monorunner = 'mono'
  
      def get_display_language(self):
          return 'C#'
  
      def get_output_args(self, fname):
          return ['-out:' + fname]
  
      def get_link_args(self, fname):
          return ['-r:' + fname]
  
      def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
          return []
  
      def get_werror_args(self):
          return ['-warnaserror']
  
      def split_shlib_to_parts(self, fname):
          return None, fname
  
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
          return []
  
      def get_dependency_gen_args(self, outtarget, outfile):
          return []
  
      def get_linker_exelist(self):
          return self.exelist[:]
  
      def get_compile_only_args(self):
          return []
  
      def get_linker_output_args(self, outputname):
          return []
  
      def get_coverage_args(self):
          return []
  
      def get_coverage_link_args(self):
          return []
  
      def get_std_exe_link_args(self):
          return []
  
      def get_include_args(self, path):
          return []
  
      def get_pic_args(self):
          return []
  
      def name_string(self):
          return ' '.join(self.exelist)
  
      def get_pch_use_args(self, pch_dir, header):
          return []
  
      def get_pch_name(self, header_name):
          return ''
  
      def sanity_check(self, work_dir, environment):
          src = 'sanity.cs'
          obj = 'sanity.exe'
          source_name = os.path.join(work_dir, src)
          with open(source_name, 'w') as ofile:
              ofile.write('''public class Sanity {
      static public void Main () {
      }
  }
  ''')
          pc = subprocess.Popen(self.exelist + [src], cwd=work_dir)
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('Mono compiler %s can not compile programs.' % self.name_string())
          cmdlist = [self.monorunner, obj]
          pe = subprocess.Popen(cmdlist, cwd=work_dir)
          pe.wait()
          if pe.returncode != 0:
              raise EnvironmentException('Executables created by Mono compiler %s are not runnable.' % self.name_string())
  
      def needs_static_linker(self):
          return False
  
      def get_buildtype_args(self, buildtype):
          return mono_buildtype_args[buildtype]
  
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/compilers/cs.py
files.old_contents: # 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 os.path, subprocess
  
  from ..mesonlib import EnvironmentException
  
  from .compilers import Compiler, mono_buildtype_args
  
  class MonoCompiler(Compiler):
      def __init__(self, exelist, version):
          self.language = 'cs'
          super().__init__(exelist, version)
          self.id = 'mono'
          self.monorunner = 'mono'
  
      def get_output_args(self, fname):
          return ['-out:' + fname]
  
      def get_link_args(self, fname):
          return ['-r:' + fname]
  
      def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
          return []
  
      def get_werror_args(self):
          return ['-warnaserror']
  
      def split_shlib_to_parts(self, fname):
          return None, fname
  
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
          return []
  
      def get_dependency_gen_args(self, outtarget, outfile):
          return []
  
      def get_linker_exelist(self):
          return self.exelist[:]
  
      def get_compile_only_args(self):
          return []
  
      def get_linker_output_args(self, outputname):
          return []
  
      def get_coverage_args(self):
          return []
  
      def get_coverage_link_args(self):
          return []
  
      def get_std_exe_link_args(self):
          return []
  
      def get_include_args(self, path):
          return []
  
      def get_pic_args(self):
          return []
  
      def name_string(self):
          return ' '.join(self.exelist)
  
      def get_pch_use_args(self, pch_dir, header):
          return []
  
      def get_pch_name(self, header_name):
          return ''
  
      def sanity_check(self, work_dir, environment):
          src = 'sanity.cs'
          obj = 'sanity.exe'
          source_name = os.path.join(work_dir, src)
          with open(source_name, 'w') as ofile:
              ofile.write('''public class Sanity {
      static public void Main () {
      }
  }
  ''')
          pc = subprocess.Popen(self.exelist + [src], cwd=work_dir)
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('Mono compiler %s can not compile programs.' % self.name_string())
          cmdlist = [self.monorunner, obj]
          pe = subprocess.Popen(cmdlist, cwd=work_dir)
          pe.wait()
          if pe.returncode != 0:
              raise EnvironmentException('Executables created by Mono compiler %s are not runnable.' % self.name_string())
  
      def needs_static_linker(self):
          return False
  
      def get_buildtype_args(self, buildtype):
          return mono_buildtype_args[buildtype]
  
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/compilers/cs.py
files.new_contents: # 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 os.path, subprocess
  
  from ..mesonlib import EnvironmentException
  
  from .c import CCompiler
  from .compilers import ClangCompiler, GnuCompiler
  
  class ObjCCompiler(CCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrap):
          self.language = 'objc'
          CCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
  
      def get_display_language(self):
          return 'Objective-C'
  
      def sanity_check(self, work_dir, environment):
          # TODO try to use sanity_check_impl instead of duplicated code
          source_name = os.path.join(work_dir, 'sanitycheckobjc.m')
          binary_name = os.path.join(work_dir, 'sanitycheckobjc')
          extra_flags = self.get_cross_extra_flags(environment, link=False)
          if self.is_cross:
              extra_flags += self.get_compile_only_args()
          with open(source_name, 'w') as ofile:
              ofile.write('#import<stdio.h>\n'
                          'int main(int argc, char **argv) { return 0; }\n')
          pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('ObjC compiler %s can not compile programs.' % self.name_string())
          if self.is_cross:
              # Can't check if the binaries run so we have to assume they do
              return
          pe = subprocess.Popen(binary_name)
          pe.wait()
          if pe.returncode != 0:
              raise EnvironmentException('Executables created by ObjC compiler %s are not runnable.' % self.name_string())
  
  
  class GnuObjCCompiler(GnuCompiler, ObjCCompiler):
      def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None):
          ObjCCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
          GnuCompiler.__init__(self, gcc_type, defines)
          default_warn_args = ['-Wall', '-Winvalid-pch']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
  
  
  class ClangObjCCompiler(ClangCompiler, GnuObjCCompiler):
      def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None):
          GnuObjCCompiler.__init__(self, exelist, version, cltype, is_cross, exe_wrapper)
          ClangCompiler.__init__(self, cltype)
          self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage']
  
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/compilers/objc.py
files.old_contents: # 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 os.path, subprocess
  
  from ..mesonlib import EnvironmentException
  
  from .c import CCompiler
  from .compilers import ClangCompiler, GnuCompiler
  
  class ObjCCompiler(CCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrap):
          self.language = 'objc'
          CCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
  
      def sanity_check(self, work_dir, environment):
          # TODO try to use sanity_check_impl instead of duplicated code
          source_name = os.path.join(work_dir, 'sanitycheckobjc.m')
          binary_name = os.path.join(work_dir, 'sanitycheckobjc')
          extra_flags = self.get_cross_extra_flags(environment, link=False)
          if self.is_cross:
              extra_flags += self.get_compile_only_args()
          with open(source_name, 'w') as ofile:
              ofile.write('#import<stdio.h>\n'
                          'int main(int argc, char **argv) { return 0; }\n')
          pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('ObjC compiler %s can not compile programs.' % self.name_string())
          if self.is_cross:
              # Can't check if the binaries run so we have to assume they do
              return
          pe = subprocess.Popen(binary_name)
          pe.wait()
          if pe.returncode != 0:
              raise EnvironmentException('Executables created by ObjC compiler %s are not runnable.' % self.name_string())
  
  
  class GnuObjCCompiler(GnuCompiler, ObjCCompiler):
      def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None):
          ObjCCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
          GnuCompiler.__init__(self, gcc_type, defines)
          default_warn_args = ['-Wall', '-Winvalid-pch']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
  
  
  class ClangObjCCompiler(ClangCompiler, GnuObjCCompiler):
      def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None):
          GnuObjCCompiler.__init__(self, exelist, version, cltype, is_cross, exe_wrapper)
          ClangCompiler.__init__(self, cltype)
          self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage']
  
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/compilers/objc.py
files.new_contents: # 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 os.path, subprocess
  
  from ..mesonlib import EnvironmentException
  
  from .cpp import CPPCompiler
  from .compilers import ClangCompiler, GnuCompiler
  
  class ObjCPPCompiler(CPPCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrap):
          self.language = 'objcpp'
          CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
  
      def get_display_language(self):
          return 'Objective-C++'
  
      def sanity_check(self, work_dir, environment):
          # TODO try to use sanity_check_impl instead of duplicated code
          source_name = os.path.join(work_dir, 'sanitycheckobjcpp.mm')
          binary_name = os.path.join(work_dir, 'sanitycheckobjcpp')
          extra_flags = self.get_cross_extra_flags(environment, link=False)
          if self.is_cross:
              extra_flags += self.get_compile_only_args()
          with open(source_name, 'w') as ofile:
              ofile.write('#import<stdio.h>\n'
                          'class MyClass;'
                          'int main(int argc, char **argv) { return 0; }\n')
          pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('ObjC++ compiler %s can not compile programs.' % self.name_string())
          if self.is_cross:
              # Can't check if the binaries run so we have to assume they do
              return
          pe = subprocess.Popen(binary_name)
          pe.wait()
          if pe.returncode != 0:
              raise EnvironmentException('Executables created by ObjC++ compiler %s are not runnable.' % self.name_string())
  
  
  class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler):
      def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None):
          ObjCPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
          GnuCompiler.__init__(self, gcc_type, defines)
          default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
  
  
  class ClangObjCPPCompiler(ClangCompiler, GnuObjCPPCompiler):
      def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None):
          GnuObjCPPCompiler.__init__(self, exelist, version, cltype, is_cross, exe_wrapper)
          ClangCompiler.__init__(self, cltype)
          self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage']
  
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/compilers/objcpp.py
files.old_contents: # 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 os.path, subprocess
  
  from ..mesonlib import EnvironmentException
  
  from .cpp import CPPCompiler
  from .compilers import ClangCompiler, GnuCompiler
  
  class ObjCPPCompiler(CPPCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrap):
          self.language = 'objcpp'
          CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
  
      def sanity_check(self, work_dir, environment):
          # TODO try to use sanity_check_impl instead of duplicated code
          source_name = os.path.join(work_dir, 'sanitycheckobjcpp.mm')
          binary_name = os.path.join(work_dir, 'sanitycheckobjcpp')
          extra_flags = self.get_cross_extra_flags(environment, link=False)
          if self.is_cross:
              extra_flags += self.get_compile_only_args()
          with open(source_name, 'w') as ofile:
              ofile.write('#import<stdio.h>\n'
                          'class MyClass;'
                          'int main(int argc, char **argv) { return 0; }\n')
          pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('ObjC++ compiler %s can not compile programs.' % self.name_string())
          if self.is_cross:
              # Can't check if the binaries run so we have to assume they do
              return
          pe = subprocess.Popen(binary_name)
          pe.wait()
          if pe.returncode != 0:
              raise EnvironmentException('Executables created by ObjC++ compiler %s are not runnable.' % self.name_string())
  
  
  class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler):
      def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None):
          ObjCPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
          GnuCompiler.__init__(self, gcc_type, defines)
          default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
  
  
  class ClangObjCPPCompiler(ClangCompiler, GnuObjCPPCompiler):
      def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None):
          GnuObjCPPCompiler.__init__(self, exelist, version, cltype, is_cross, exe_wrapper)
          ClangCompiler.__init__(self, cltype)
          self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage']
  
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/compilers/objcpp.py
files.new_contents: # 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.
  
  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, get_meson_script
  from .dependencies import ExternalProgram
  from .dependencies import InternalDependency, Dependency, DependencyException
  from .interpreterbase import InterpreterBase
  from .interpreterbase import check_stringlist, noPosargs, noKwargs, stringArgs
  from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode
  from .interpreterbase import InterpreterObject, MutableInterpreterObject
  from .modules import ModuleReturnValue
  
  import os, sys, shutil, uuid
  import re
  from collections import namedtuple
  
  import importlib
  
  run_depr_printed = False
  
  def stringifyUserArguments(args):
      if isinstance(args, list):
          return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args])
      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 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,
                               })
  
      def returncode_method(self, args, kwargs):
          return self.res.returncode
  
      def compiled_method(self, args, kwargs):
          return self.res.compiled
  
      def stdout_method(self, args, kwargs):
          return self.res.stdout
  
      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):
          super().__init__()
          if not isinstance(cmd, ExternalProgram):
              raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
          pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir)
          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):
          command_array = cmd.get_command() + args
          env = {'MESON_SOURCE_ROOT': source_dir,
                 'MESON_BUILD_ROOT': build_dir,
                 'MESON_SUBDIR': subdir,
                 'MESONINTROSPECT': 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)
          mlog.debug('Running command:', ' '.join(command_array))
          try:
              return Popen_safe(command_array, env=child_env, cwd=cwd)
          except FileNotFoundError:
              raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array))
  
      def returncode_method(self, args, kwargs):
          return self.returncode
  
      def stdout_method(self, args, kwargs):
          return self.stdout
  
      def stderr_method(self, args, kwargs):
          return self.stderr
  
  class ConfigureFileHolder(InterpreterObject):
  
      def __init__(self, subdir, sourcename, targetname, configuration_data):
          InterpreterObject.__init__(self)
          self.held_object = build.ConfigureFile(subdir, sourcename, targetname, configuration_data)
  
  
  class EnvironmentVariablesHolder(MutableInterpreterObject):
      def __init__(self):
          super().__init__()
          self.held_object = 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)
  
      @stringArgs
      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))
  
      def set_method(self, args, kwargs):
          self.add_var(self.held_object.set, args, kwargs)
  
      def append_method(self, args, kwargs):
          self.add_var(self.held_object.append, args, kwargs)
  
      def prepend_method(self, args, kwargs):
          self.add_var(self.held_object.prepend, args, kwargs)
  
  
  class ConfigurationDataHolder(MutableInterpreterObject):
      def __init__(self):
          super().__init__()
          self.used = False # These objects become immutable after use in configure_file.
          self.held_object = build.ConfigurationData()
          self.methods.update({'set': self.set_method,
                               'set10': self.set10_method,
                               'set_quoted': self.set_quoted_method,
                               'has': self.has_method,
                               'get': self.get_method,
                               })
  
      def is_used(self):
          return self.used
  
      def mark_used(self):
          self.used = True
  
      def validate_args(self, args, kwargs):
          if len(args) != 2:
              raise InterpreterException("Configuration set requires 2 arguments.")
          if self.used:
              raise InterpreterException("Can not set values on configuration object that has been used.")
          name = args[0]
          val = args[1]
          desc = kwargs.get('description', None)
          if not isinstance(name, str):
              raise InterpreterException("First argument to set must be a string.")
          if desc is not None and not isinstance(desc, str):
              raise InterpreterException('Description must be a string.')
  
          return name, val, desc
  
      def set_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          self.held_object.values[name] = (val, desc)
  
      def set_quoted_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          if not isinstance(val, str):
              raise InterpreterException("Second argument to set_quoted must be a string.")
          escaped_val = '\\"'.join(val.split('"'))
          self.held_object.values[name] = ('"' + escaped_val + '"', desc)
  
      def set10_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          if val:
              self.held_object.values[name] = (1, desc)
          else:
              self.held_object.values[name] = (0, desc)
  
      def has_method(self, args, kwargs):
          return args[0] in self.held_object.values
  
      def get_method(self, args, kwargs):
          if len(args) < 1 or len(args) > 2:
              raise InterpreterException('Get method takes one or two arguments.')
          name = args[0]
          if name in self.held_object:
              return self.held_object.get(name)[0]
          if len(args) > 1:
              return args[1]
          raise InterpreterException('Entry %s not in configuration data.' % name)
  
      def get(self, name):
          return self.held_object.values[name]     # (val, desc)
  
      def keys(self):
          return self.held_object.values.keys()
  
  # Interpreter objects can not be pickled so we must have
  # these wrappers.
  
  class DependencyHolder(InterpreterObject):
      def __init__(self, dep):
          InterpreterObject.__init__(self)
          self.held_object = dep
          self.methods.update({'found': self.found_method,
                               'type_name': self.type_name_method,
                               'version': self.version_method,
                               'get_pkgconfig_variable': self.pkgconfig_method,
                               })
  
      def type_name_method(self, args, kwargs):
          return self.held_object.type_name
  
      def found_method(self, args, kwargs):
          if self.held_object.type_name == 'internal':
              return True
          return self.held_object.found()
  
      def version_method(self, args, kwargs):
          return self.held_object.get_version()
  
      def pkgconfig_method(self, args, kwargs):
          if not isinstance(args, list):
              args = [args]
          if len(args) != 1:
              raise InterpreterException('get_pkgconfig_variable takes exactly one argument.')
          varname = args[0]
          if not isinstance(varname, str):
              raise InterpreterException('Variable name must be a string.')
          return self.held_object.get_pkgconfig_variable(varname)
  
  class InternalDependencyHolder(InterpreterObject):
      def __init__(self, dep):
          InterpreterObject.__init__(self)
          self.held_object = dep
          self.methods.update({'found': self.found_method,
                               'version': self.version_method,
                               })
  
      def found_method(self, args, kwargs):
          return True
  
      def version_method(self, args, kwargs):
          return self.held_object.get_version()
  
  class ExternalProgramHolder(InterpreterObject):
      def __init__(self, ep):
          InterpreterObject.__init__(self)
          self.held_object = ep
          self.methods.update({'found': self.found_method,
                               'path': self.path_method})
  
      def found_method(self, args, kwargs):
          return self.found()
  
      def path_method(self, args, kwargs):
          return self.held_object.get_path()
  
      def found(self):
          return self.held_object.found()
  
      def get_command(self):
          return self.held_object.get_command()
  
      def get_name(self):
          return self.held_object.get_name()
  
  class ExternalLibraryHolder(InterpreterObject):
      def __init__(self, el):
          InterpreterObject.__init__(self)
          self.held_object = el
          self.methods.update({'found': self.found_method})
  
      def found(self):
          return self.held_object.found()
  
      def found_method(self, args, kwargs):
          return self.found()
  
      def get_name(self):
          return self.held_object.name
  
      def get_compile_args(self):
          return self.held_object.get_compile_args()
  
      def get_link_args(self):
          return self.held_object.get_link_args()
  
      def get_exe_args(self):
          return self.held_object.get_exe_args()
  
  class GeneratorHolder(InterpreterObject):
      def __init__(self, interpreter, args, kwargs):
          super().__init__()
          self.interpreter = interpreter
          self.held_object = build.Generator(args, kwargs)
          self.methods.update({'process': self.process_method})
  
      def process_method(self, args, kwargs):
          extras = mesonlib.stringlistify(kwargs.get('extra_args', []))
          gl = self.held_object.process_files('Generator', args, self.interpreter, extra_args=extras)
          return GeneratedListHolder(gl)
  
  
  class GeneratedListHolder(InterpreterObject):
      def __init__(self, arg1, extra_args=[]):
          super().__init__()
          if isinstance(arg1, GeneratorHolder):
              self.held_object = build.GeneratedList(arg1.held_object, extra_args)
          else:
              self.held_object = arg1
  
      def __repr__(self):
          r = '<{}: {!r}>'
          return r.format(self.__class__.__name__, self.held_object.get_outputs())
  
      def add_file(self, a):
          self.held_object.add_file(a)
  
  class BuildMachine(InterpreterObject):
      def __init__(self, compilers):
          self.compilers = compilers
          InterpreterObject.__init__(self)
          self.held_object = environment.MachineInfo(environment.detect_system(),
                                                     environment.detect_cpu_family(self.compilers),
                                                     environment.detect_cpu(self.compilers),
                                                     sys.byteorder)
          self.methods.update({'system': self.system_method,
                               'cpu_family': self.cpu_family_method,
                               'cpu': self.cpu_method,
                               'endian': self.endian_method,
                               })
  
      def cpu_family_method(self, args, kwargs):
          return self.held_object.cpu_family
  
      def cpu_method(self, args, kwargs):
          return self.held_object.cpu
  
      def system_method(self, args, kwargs):
          return self.held_object.system
  
      def endian_method(self, args, kwargs):
          return self.held_object.endian
  
  # This class will provide both host_machine and
  # target_machine
  class CrossMachineInfo(InterpreterObject):
      def __init__(self, cross_info):
          InterpreterObject.__init__(self)
          minimum_cross_info = {'cpu', 'cpu_family', 'endian', 'system'}
          if set(cross_info) < minimum_cross_info:
              raise InterpreterException(
                  'Machine info is currently {}\n'.format(cross_info) +
                  'but is missing {}.'.format(minimum_cross_info - set(cross_info)))
          self.info = cross_info
          self.held_object = environment.MachineInfo(cross_info['system'],
                                                     cross_info['cpu_family'],
                                                     cross_info['cpu'],
                                                     cross_info['endian'])
          self.methods.update({'system': self.system_method,
                               'cpu': self.cpu_method,
                               'cpu_family': self.cpu_family_method,
                               'endian': self.endian_method,
                               })
  
      def cpu_family_method(self, args, kwargs):
          return self.held_object.cpu_family
  
      def cpu_method(self, args, kwargs):
          return self.held_object.cpu
  
      def system_method(self, args, kwargs):
          return self.held_object.system
  
      def endian_method(self, args, kwargs):
          return self.held_object.endian
  
  class IncludeDirsHolder(InterpreterObject):
      def __init__(self, idobj):
          super().__init__()
          self.held_object = idobj
  
  class Headers(InterpreterObject):
  
      def __init__(self, sources, kwargs):
          InterpreterObject.__init__(self)
          self.sources = sources
          self.install_subdir = kwargs.get('subdir', '')
          self.custom_install_dir = kwargs.get('install_dir', None)
          if self.custom_install_dir is not None:
              if not isinstance(self.custom_install_dir, str):
                  raise InterpreterException('Custom_install_dir must be a string.')
  
      def set_install_subdir(self, subdir):
          self.install_subdir = subdir
  
      def get_install_subdir(self):
          return self.install_subdir
  
      def get_sources(self):
          return self.sources
  
      def get_custom_install_dir(self):
          return self.custom_install_dir
  
  class DataHolder(InterpreterObject):
      def __init__(self, data):
          super().__init__()
          self.held_object = data
  
      def get_source_subdir(self):
          return self.held_object.source_subdir
  
      def get_sources(self):
          return self.held_object.sources
  
      def get_install_dir(self):
          return self.held_object.install_dir
  
  class InstallDir(InterpreterObject):
      def __init__(self, src_subdir, inst_subdir, install_dir, install_mode):
          InterpreterObject.__init__(self)
          self.source_subdir = src_subdir
          self.installable_subdir = inst_subdir
          self.install_dir = install_dir
          self.install_mode = install_mode
  
  class Man(InterpreterObject):
  
      def __init__(self, source_subdir, sources, kwargs):
          InterpreterObject.__init__(self)
          self.source_subdir = source_subdir
          self.sources = sources
          self.validate_sources()
          if len(kwargs) > 1:
              raise InvalidArguments('Man function takes at most one keyword arguments.')
          self.custom_install_dir = kwargs.get('install_dir', None)
          if self.custom_install_dir is not None and not isinstance(self.custom_install_dir, str):
              raise InterpreterException('Custom_install_dir must be a string.')
  
      def validate_sources(self):
          for s in self.sources:
              try:
                  num = int(s.split('.')[-1])
              except (IndexError, ValueError):
                  num = 0
              if num < 1 or num > 8:
                  raise InvalidArguments('Man file must have a file extension of a number between 1 and 8')
  
      def get_custom_install_dir(self):
          return self.custom_install_dir
  
      def get_sources(self):
          return self.sources
  
      def get_source_subdir(self):
          return self.source_subdir
  
  class GeneratedObjectsHolder(InterpreterObject):
      def __init__(self, held_object):
          super
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/interpreter.py
files.old_contents: # 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.
  
  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, get_meson_script
  from .dependencies import ExternalProgram
  from .dependencies import InternalDependency, Dependency, DependencyException
  from .interpreterbase import InterpreterBase
  from .interpreterbase import check_stringlist, noPosargs, noKwargs, stringArgs
  from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode
  from .interpreterbase import InterpreterObject, MutableInterpreterObject
  from .modules import ModuleReturnValue
  
  import os, sys, shutil, uuid
  import re
  from collections import namedtuple
  
  import importlib
  
  run_depr_printed = False
  
  def stringifyUserArguments(args):
      if isinstance(args, list):
          return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args])
      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 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,
                               })
  
      def returncode_method(self, args, kwargs):
          return self.res.returncode
  
      def compiled_method(self, args, kwargs):
          return self.res.compiled
  
      def stdout_method(self, args, kwargs):
          return self.res.stdout
  
      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):
          super().__init__()
          if not isinstance(cmd, ExternalProgram):
              raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
          pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir)
          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):
          command_array = cmd.get_command() + args
          env = {'MESON_SOURCE_ROOT': source_dir,
                 'MESON_BUILD_ROOT': build_dir,
                 'MESON_SUBDIR': subdir,
                 'MESONINTROSPECT': 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)
          mlog.debug('Running command:', ' '.join(command_array))
          try:
              return Popen_safe(command_array, env=child_env, cwd=cwd)
          except FileNotFoundError:
              raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array))
  
      def returncode_method(self, args, kwargs):
          return self.returncode
  
      def stdout_method(self, args, kwargs):
          return self.stdout
  
      def stderr_method(self, args, kwargs):
          return self.stderr
  
  class ConfigureFileHolder(InterpreterObject):
  
      def __init__(self, subdir, sourcename, targetname, configuration_data):
          InterpreterObject.__init__(self)
          self.held_object = build.ConfigureFile(subdir, sourcename, targetname, configuration_data)
  
  
  class EnvironmentVariablesHolder(MutableInterpreterObject):
      def __init__(self):
          super().__init__()
          self.held_object = 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)
  
      @stringArgs
      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))
  
      def set_method(self, args, kwargs):
          self.add_var(self.held_object.set, args, kwargs)
  
      def append_method(self, args, kwargs):
          self.add_var(self.held_object.append, args, kwargs)
  
      def prepend_method(self, args, kwargs):
          self.add_var(self.held_object.prepend, args, kwargs)
  
  
  class ConfigurationDataHolder(MutableInterpreterObject):
      def __init__(self):
          super().__init__()
          self.used = False # These objects become immutable after use in configure_file.
          self.held_object = build.ConfigurationData()
          self.methods.update({'set': self.set_method,
                               'set10': self.set10_method,
                               'set_quoted': self.set_quoted_method,
                               'has': self.has_method,
                               'get': self.get_method,
                               })
  
      def is_used(self):
          return self.used
  
      def mark_used(self):
          self.used = True
  
      def validate_args(self, args, kwargs):
          if len(args) != 2:
              raise InterpreterException("Configuration set requires 2 arguments.")
          if self.used:
              raise InterpreterException("Can not set values on configuration object that has been used.")
          name = args[0]
          val = args[1]
          desc = kwargs.get('description', None)
          if not isinstance(name, str):
              raise InterpreterException("First argument to set must be a string.")
          if desc is not None and not isinstance(desc, str):
              raise InterpreterException('Description must be a string.')
  
          return name, val, desc
  
      def set_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          self.held_object.values[name] = (val, desc)
  
      def set_quoted_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          if not isinstance(val, str):
              raise InterpreterException("Second argument to set_quoted must be a string.")
          escaped_val = '\\"'.join(val.split('"'))
          self.held_object.values[name] = ('"' + escaped_val + '"', desc)
  
      def set10_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          if val:
              self.held_object.values[name] = (1, desc)
          else:
              self.held_object.values[name] = (0, desc)
  
      def has_method(self, args, kwargs):
          return args[0] in self.held_object.values
  
      def get_method(self, args, kwargs):
          if len(args) < 1 or len(args) > 2:
              raise InterpreterException('Get method takes one or two arguments.')
          name = args[0]
          if name in self.held_object:
              return self.held_object.get(name)[0]
          if len(args) > 1:
              return args[1]
          raise InterpreterException('Entry %s not in configuration data.' % name)
  
      def get(self, name):
          return self.held_object.values[name]     # (val, desc)
  
      def keys(self):
          return self.held_object.values.keys()
  
  # Interpreter objects can not be pickled so we must have
  # these wrappers.
  
  class DependencyHolder(InterpreterObject):
      def __init__(self, dep):
          InterpreterObject.__init__(self)
          self.held_object = dep
          self.methods.update({'found': self.found_method,
                               'type_name': self.type_name_method,
                               'version': self.version_method,
                               'get_pkgconfig_variable': self.pkgconfig_method,
                               })
  
      def type_name_method(self, args, kwargs):
          return self.held_object.type_name
  
      def found_method(self, args, kwargs):
          if self.held_object.type_name == 'internal':
              return True
          return self.held_object.found()
  
      def version_method(self, args, kwargs):
          return self.held_object.get_version()
  
      def pkgconfig_method(self, args, kwargs):
          if not isinstance(args, list):
              args = [args]
          if len(args) != 1:
              raise InterpreterException('get_pkgconfig_variable takes exactly one argument.')
          varname = args[0]
          if not isinstance(varname, str):
              raise InterpreterException('Variable name must be a string.')
          return self.held_object.get_pkgconfig_variable(varname)
  
  class InternalDependencyHolder(InterpreterObject):
      def __init__(self, dep):
          InterpreterObject.__init__(self)
          self.held_object = dep
          self.methods.update({'found': self.found_method,
                               'version': self.version_method,
                               })
  
      def found_method(self, args, kwargs):
          return True
  
      def version_method(self, args, kwargs):
          return self.held_object.get_version()
  
  class ExternalProgramHolder(InterpreterObject):
      def __init__(self, ep):
          InterpreterObject.__init__(self)
          self.held_object = ep
          self.methods.update({'found': self.found_method,
                               'path': self.path_method})
  
      def found_method(self, args, kwargs):
          return self.found()
  
      def path_method(self, args, kwargs):
          return self.held_object.get_path()
  
      def found(self):
          return self.held_object.found()
  
      def get_command(self):
          return self.held_object.get_command()
  
      def get_name(self):
          return self.held_object.get_name()
  
  class ExternalLibraryHolder(InterpreterObject):
      def __init__(self, el):
          InterpreterObject.__init__(self)
          self.held_object = el
          self.methods.update({'found': self.found_method})
  
      def found(self):
          return self.held_object.found()
  
      def found_method(self, args, kwargs):
          return self.found()
  
      def get_name(self):
          return self.held_object.name
  
      def get_compile_args(self):
          return self.held_object.get_compile_args()
  
      def get_link_args(self):
          return self.held_object.get_link_args()
  
      def get_exe_args(self):
          return self.held_object.get_exe_args()
  
  class GeneratorHolder(InterpreterObject):
      def __init__(self, interpreter, args, kwargs):
          super().__init__()
          self.interpreter = interpreter
          self.held_object = build.Generator(args, kwargs)
          self.methods.update({'process': self.process_method})
  
      def process_method(self, args, kwargs):
          extras = mesonlib.stringlistify(kwargs.get('extra_args', []))
          gl = self.held_object.process_files('Generator', args, self.interpreter, extra_args=extras)
          return GeneratedListHolder(gl)
  
  
  class GeneratedListHolder(InterpreterObject):
      def __init__(self, arg1, extra_args=[]):
          super().__init__()
          if isinstance(arg1, GeneratorHolder):
              self.held_object = build.GeneratedList(arg1.held_object, extra_args)
          else:
              self.held_object = arg1
  
      def __repr__(self):
          r = '<{}: {!r}>'
          return r.format(self.__class__.__name__, self.held_object.get_outputs())
  
      def add_file(self, a):
          self.held_object.add_file(a)
  
  class BuildMachine(InterpreterObject):
      def __init__(self, compilers):
          self.compilers = compilers
          InterpreterObject.__init__(self)
          self.held_object = environment.MachineInfo(environment.detect_system(),
                                                     environment.detect_cpu_family(self.compilers),
                                                     environment.detect_cpu(self.compilers),
                                                     sys.byteorder)
          self.methods.update({'system': self.system_method,
                               'cpu_family': self.cpu_family_method,
                               'cpu': self.cpu_method,
                               'endian': self.endian_method,
                               })
  
      def cpu_family_method(self, args, kwargs):
          return self.held_object.cpu_family
  
      def cpu_method(self, args, kwargs):
          return self.held_object.cpu
  
      def system_method(self, args, kwargs):
          return self.held_object.system
  
      def endian_method(self, args, kwargs):
          return self.held_object.endian
  
  # This class will provide both host_machine and
  # target_machine
  class CrossMachineInfo(InterpreterObject):
      def __init__(self, cross_info):
          InterpreterObject.__init__(self)
          minimum_cross_info = {'cpu', 'cpu_family', 'endian', 'system'}
          if set(cross_info) < minimum_cross_info:
              raise InterpreterException(
                  'Machine info is currently {}\n'.format(cross_info) +
                  'but is missing {}.'.format(minimum_cross_info - set(cross_info)))
          self.info = cross_info
          self.held_object = environment.MachineInfo(cross_info['system'],
                                                     cross_info['cpu_family'],
                                                     cross_info['cpu'],
                                                     cross_info['endian'])
          self.methods.update({'system': self.system_method,
                               'cpu': self.cpu_method,
                               'cpu_family': self.cpu_family_method,
                               'endian': self.endian_method,
                               })
  
      def cpu_family_method(self, args, kwargs):
          return self.held_object.cpu_family
  
      def cpu_method(self, args, kwargs):
          return self.held_object.cpu
  
      def system_method(self, args, kwargs):
          return self.held_object.system
  
      def endian_method(self, args, kwargs):
          return self.held_object.endian
  
  class IncludeDirsHolder(InterpreterObject):
      def __init__(self, idobj):
          super().__init__()
          self.held_object = idobj
  
  class Headers(InterpreterObject):
  
      def __init__(self, sources, kwargs):
          InterpreterObject.__init__(self)
          self.sources = sources
          self.install_subdir = kwargs.get('subdir', '')
          self.custom_install_dir = kwargs.get('install_dir', None)
          if self.custom_install_dir is not None:
              if not isinstance(self.custom_install_dir, str):
                  raise InterpreterException('Custom_install_dir must be a string.')
  
      def set_install_subdir(self, subdir):
          self.install_subdir = subdir
  
      def get_install_subdir(self):
          return self.install_subdir
  
      def get_sources(self):
          return self.sources
  
      def get_custom_install_dir(self):
          return self.custom_install_dir
  
  class DataHolder(InterpreterObject):
      def __init__(self, data):
          super().__init__()
          self.held_object = data
  
      def get_source_subdir(self):
          return self.held_object.source_subdir
  
      def get_sources(self):
          return self.held_object.sources
  
      def get_install_dir(self):
          return self.held_object.install_dir
  
  class InstallDir(InterpreterObject):
      def __init__(self, src_subdir, inst_subdir, install_dir, install_mode):
          InterpreterObject.__init__(self)
          self.source_subdir = src_subdir
          self.installable_subdir = inst_subdir
          self.install_dir = install_dir
          self.install_mode = install_mode
  
  class Man(InterpreterObject):
  
      def __init__(self, source_subdir, sources, kwargs):
          InterpreterObject.__init__(self)
          self.source_subdir = source_subdir
          self.sources = sources
          self.validate_sources()
          if len(kwargs) > 1:
              raise InvalidArguments('Man function takes at most one keyword arguments.')
          self.custom_install_dir = kwargs.get('install_dir', None)
          if self.custom_install_dir is not None and not isinstance(self.custom_install_dir, str):
              raise InterpreterException('Custom_install_dir must be a string.')
  
      def validate_sources(self):
          for s in self.sources:
              try:
                  num = int(s.split('.')[-1])
              except (IndexError, ValueError):
                  num = 0
              if num < 1 or num > 8:
                  raise InvalidArguments('Man file must have a file extension of a number between 1 and 8')
  
      def get_custom_install_dir(self):
          return self.custom_install_dir
  
      def get_sources(self):
          return self.sources
  
      def get_source_subdir(self):
          return self.source_subdir
  
  class GeneratedObjectsHolder(InterpreterObject):
      def __init__(self, held_object):
          super
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/interpreter.py