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, subprocess
  from collections import OrderedDict
  import itertools
  from pathlib import PurePath
  
  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_compiler_for_source, has_path_sep
  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, is_build_line=False):
      if is_build_line:
          qcs = ('$', ' ', ':')
      else:
          qcs = ('$', ' ')
      for char in qcs:
          text = text.replace(char, '$' + char)
      if '\n' in text:
          errmsg = '''Ninja does not support newlines in rules. The content was:
  
  %s
  
  Please report this error with a test case to the Meson bug tracker.''' % text
          raise MesonException(errmsg)
      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, True) for i in self.outfilenames]),
                                      self.rule,
                                      ' '.join([ninja_quote(i, True) for i in self.infilenames]))
          if len(self.deps) > 0:
              line += ' | ' + ' '.join([ninja_quote(x, True) for x in self.deps])
          if len(self.orderdeps) > 0:
              line += ' || ' + ' '.join([ninja_quote(x, True) 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, unless explicitely specified, which is necessary for
          # the csc compiler.
          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
              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 create_target_alias(self, to_target, outfile):
          # We need to use aliases for targets that might be used as directory
          # names to workaround a Ninja bug that breaks `ninja -t clean`.
          # This is used for 'reserved' targets such as 'test', 'install',
          # 'benchmark', etc, and also for RunTargets.
          # https://github.com/mesonbuild/meson/issues/1644
          if not to_target.startswith('meson-'):
              m = 'Invalid usage of create_target_alias with {!r}'
              raise AssertionError(m.format(to_target))
          from_target = to_target[len('meson-'):]
          elem = NinjaBuildElement(self.all_outputs, from_target, 'phony', to_target)
          elem.write(outfile)
  
      def detect_vs_dep_prefix(self, tempfilename):
          '''VS writes its dependency in a locale dependent format.
          Detect the search prefix to use.'''
          for compiler in self.build.compilers.values():
              # Have to detect the dependency format
              if compiler.id == 'msvc':
                  break
          else:
              # None of our compilers are MSVC, we're done.
              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
          self.ninja_command = environment.detect_ninja(log=True)
          if self.ninja_command is None:
              raise MesonException('Could not detect Ninja v1.5 or newer')
          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 overwrite 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):
          pch_compilers = ['%s_PCH' % i for i in self.build.compilers]
          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 = [self.ninja_command, '-t', 'compdb'] + pch_compilers + 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, build.CustomTargetIndex)):
                  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 itertools.chain(target.link_targets, target.link_whole_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 (.inc, .fh) that they then include
                  # in their source files.
                  header_deps.append(raw_src)
          # These are the generated source files that need to be built for use by
          # this target. We create the Ninja build file elements for this here
          # because we need `header_deps` to be fully generated in the above loop.
          for src in generated_source_files:
              if self.environment.is_llvm_ir(src):
                  o = self.generate_llvm_ir_compile(target, outfile, src)
              else:
                  o = self.generate_single_compile(target, outfile, src, True,
                                                   header_deps=header_deps)
              obj_list.append(o)
  
          # Generate compilation targets for C sources generated from Vala
          # sources. This can be extended to other $LANG->C compilers later if
          # necessary. This needs to be separate for at least Vala
          vala_generated_source_files = []
          for src in vala_generated_sources:
              dirpart, fnamepart = os.path.split(src)
              raw_src = File(True, dirpart, fnamepart)
              if is_unity:
                 
  
  [... 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, subprocess
  from collections import OrderedDict
  import itertools
  from pathlib import PurePath
  
  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_compiler_for_source, has_path_sep
  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, is_build_line=False):
      if is_build_line:
          qcs = ('$', ' ', ':')
      else:
          qcs = ('$', ' ')
      for char in qcs:
          text = text.replace(char, '$' + char)
      if '\n' in text:
          errmsg = '''Ninja does not support newlines in rules. The content was:
  
  %s
  
  Please report this error with a test case to the Meson bug tracker.''' % text
          raise MesonException(errmsg)
      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, True) for i in self.outfilenames]),
                                      self.rule,
                                      ' '.join([ninja_quote(i, True) for i in self.infilenames]))
          if len(self.deps) > 0:
              line += ' | ' + ' '.join([ninja_quote(x, True) for x in self.deps])
          if len(self.orderdeps) > 0:
              line += ' || ' + ' '.join([ninja_quote(x, True) 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, unless explicitely specified, which is necessary for
          # the csc compiler.
          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
              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 create_target_alias(self, to_target, outfile):
          # We need to use aliases for targets that might be used as directory
          # names to workaround a Ninja bug that breaks `ninja -t clean`.
          # This is used for 'reserved' targets such as 'test', 'install',
          # 'benchmark', etc, and also for RunTargets.
          # https://github.com/mesonbuild/meson/issues/1644
          if not to_target.startswith('meson-'):
              m = 'Invalid usage of create_target_alias with {!r}'
              raise AssertionError(m.format(to_target))
          from_target = to_target[len('meson-'):]
          elem = NinjaBuildElement(self.all_outputs, from_target, 'phony', to_target)
          elem.write(outfile)
  
      def detect_vs_dep_prefix(self, tempfilename):
          '''VS writes its dependency in a locale dependent format.
          Detect the search prefix to use.'''
          for compiler in self.build.compilers.values():
              # Have to detect the dependency format
              if compiler.id == 'msvc':
                  break
          else:
              # None of our compilers are MSVC, we're done.
              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
          self.ninja_command = environment.detect_ninja(log=True)
          if self.ninja_command is None:
              raise MesonException('Could not detect Ninja v1.5 or newer')
          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 overwrite 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):
          pch_compilers = ['%s_PCH' % i for i in self.build.compilers]
          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 = [self.ninja_command, '-t', 'compdb'] + pch_compilers + 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, build.CustomTargetIndex)):
                  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 itertools.chain(target.link_targets, target.link_whole_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 (.inc, .fh) that they then include
                  # in their source files.
                  header_deps.append(raw_src)
          # These are the generated source files that need to be built for use by
          # this target. We create the Ninja build file elements for this here
          # because we need `header_deps` to be fully generated in the above loop.
          for src in generated_source_files:
              if self.environment.is_llvm_ir(src):
                  o = self.generate_llvm_ir_compile(target, outfile, src)
              else:
                  o = self.generate_single_compile(target, outfile, src, True,
                                                   header_deps=header_deps)
              obj_list.append(o)
  
          # Generate compilation targets for C sources generated from Vala
          # sources. This can be extended to other $LANG->C compilers later if
          # necessary. This needs to be separate for at least Vala
          vala_generated_source_files = []
          for src in vala_generated_sources:
              dirpart, fnamepart = os.path.split(src)
              raw_src = File(True, dirpart, fnamepart)
              if is_unity:
                 
  
  [... 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 . import compilers
  from ..mesonlib import (
      EnvironmentException, version_compare, Popen_safe, listify,
      for_windows, for_darwin, for_cygwin, for_haiku,
  )
  
  from .compilers import (
      GCC_MINGW,
      get_largefile_args,
      gnu_winlibs,
      msvc_buildtype_args,
      msvc_buildtype_linker_args,
      msvc_winlibs,
      vs32_instruction_set_args,
      vs64_instruction_set_args,
      ClangCompiler,
      Compiler,
      CompilerArgs,
      CrossNoRunException,
      GnuCompiler,
      ElbrusCompiler,
      IntelCompiler,
      RunResult,
  )
  
  
  class CCompiler(Compiler):
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs):
          # 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, **kwargs)
          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, version, 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, build_rpath, install_rpath):
          if self.id == 'clang' and self.clang_type == compilers.CLANG_OSX:
              return self.build_osx_rpath_args(build_dir, rpath_paths, build_rpath)
          return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
  
      def get_dependency_gen_args(self, outtarget, outfile):
          return ['-MD', '-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):
          env = os.environ.copy()
          env['LC_ALL'] = 'C'
          stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=env)[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.basename(header)]
  
      def get_pch_name(self, header_name):
          return os.path.basename(header_name) + '.' + self.get_pch_suffix()
  
      def get_linker_search_args(self, dirname):
          return ['-L' + dirname]
  
      def get_default_include_dirs(self):
          return []
  
      def gen_export_dynamic_link_args(self, env):
          if for_windows(env.is_cross_build(), env) or for_cygwin(env.is_cross_build(), env):
              return ['-Wl,--export-all-symbols']
          elif for_darwin(env.is_cross_build(), env):
              return []
          else:
              return ['-Wl,-export-dynamic']
  
      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 d.need_threads():
                  args += self.thread_flags(env)
              if mode == 'link':
                  # Add link flags needed to find dependencies
                  args += d.get_link_args()
                  if d.need_threads():
                      args += self.thread_link_flags(env)
          # 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', want_output=False):
          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, want_output=False):
          "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, want_output=want_output)
  
      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, True) 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):
          # Try user's guess first
          if isinstance(guess, int):
              if self._compile_int('%s == %d' % (expression, guess), prefix, env, extra_args, dependencies):
                  return guess
  
          # If no bounds are given, compute them in the limit of int32
          maxint = 0x7fffffff
          minint = -0x80000000
          if not isinstance(low, int) or not isinstance(high, int):
              if self._compile_int('%s >= 0' % (expression), prefix, env, extra_args, dependencies):
                  low = cur = 0
                  while self._compile_int('%s > %d' % (expression, cur), prefix, env, extra_args, dependencies):
                      low = cur + 1
                      if low > maxint:
                          raise EnvironmentException('Cross-compile check overflowed')
                      cur = cur * 2 + 1
                      if cur > maxint:
                          cur = maxint
                  high = cur
              else:
                  low = cur = -1
                  while self._compile_int('%s < %d' % (expression, cur), prefix, env, extra_args, dependencies):
                      high = cur - 1
                      if high < minint:
                          raise EnvironmentException('Cross-compile check overflowed')
                      cur = cur * 2
                      if cur < minint:
                          cur = minint
                  low = cur
          else:
              # Sanity check limits given by user
              if high < low:
                  raise EnvironmentException('high limit smaller than low limit')
              condition = '%s <= %d && %s >= %d' % (expression, high, expression, low)
              if not self._compile_int(condition, prefix, env, extra_args, dependencies):
                  raise EnvironmentException('Value out of given range')
  
          # Binary search
          while low != high:
              cur = low + int((high - low) / 2)
              if self._compile_int('%s <= %d' % (expression, cur), prefix, env, extra_args, dependencies):
                  high = cur
              else:
                  low = cur + 1
  
          return low
  
      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, None, None, 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_com
  
  [... 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 . import compilers
  from ..mesonlib import (
      EnvironmentException, version_compare, Popen_safe, listify,
      for_windows, for_darwin, for_cygwin, for_haiku,
  )
  
  from .compilers import (
      GCC_MINGW,
      get_largefile_args,
      gnu_winlibs,
      msvc_buildtype_args,
      msvc_buildtype_linker_args,
      msvc_winlibs,
      vs32_instruction_set_args,
      vs64_instruction_set_args,
      ClangCompiler,
      Compiler,
      CompilerArgs,
      CrossNoRunException,
      GnuCompiler,
      ElbrusCompiler,
      IntelCompiler,
      RunResult,
  )
  
  
  class CCompiler(Compiler):
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs):
          # 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, **kwargs)
          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, build_rpath, install_rpath):
          if self.id == 'clang' and self.clang_type == compilers.CLANG_OSX:
              return self.build_osx_rpath_args(build_dir, rpath_paths, build_rpath)
          return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
  
      def get_dependency_gen_args(self, outtarget, outfile):
          return ['-MD', '-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):
          env = os.environ.copy()
          env['LC_ALL'] = 'C'
          stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=env)[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.basename(header)]
  
      def get_pch_name(self, header_name):
          return os.path.basename(header_name) + '.' + self.get_pch_suffix()
  
      def get_linker_search_args(self, dirname):
          return ['-L' + dirname]
  
      def get_default_include_dirs(self):
          return []
  
      def gen_export_dynamic_link_args(self, env):
          if for_windows(env.is_cross_build(), env) or for_cygwin(env.is_cross_build(), env):
              return ['-Wl,--export-all-symbols']
          elif for_darwin(env.is_cross_build(), env):
              return []
          else:
              return ['-Wl,-export-dynamic']
  
      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 d.need_threads():
                  args += self.thread_flags(env)
              if mode == 'link':
                  # Add link flags needed to find dependencies
                  args += d.get_link_args()
                  if d.need_threads():
                      args += self.thread_link_flags(env)
          # 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', want_output=False):
          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, want_output=False):
          "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, want_output=want_output)
  
      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, True) 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):
          # Try user's guess first
          if isinstance(guess, int):
              if self._compile_int('%s == %d' % (expression, guess), prefix, env, extra_args, dependencies):
                  return guess
  
          # If no bounds are given, compute them in the limit of int32
          maxint = 0x7fffffff
          minint = -0x80000000
          if not isinstance(low, int) or not isinstance(high, int):
              if self._compile_int('%s >= 0' % (expression), prefix, env, extra_args, dependencies):
                  low = cur = 0
                  while self._compile_int('%s > %d' % (expression, cur), prefix, env, extra_args, dependencies):
                      low = cur + 1
                      if low > maxint:
                          raise EnvironmentException('Cross-compile check overflowed')
                      cur = cur * 2 + 1
                      if cur > maxint:
                          cur = maxint
                  high = cur
              else:
                  low = cur = -1
                  while self._compile_int('%s < %d' % (expression, cur), prefix, env, extra_args, dependencies):
                      high = cur - 1
                      if high < minint:
                          raise EnvironmentException('Cross-compile check overflowed')
                      cur = cur * 2
                      if cur < minint:
                          cur = minint
                  low = cur
          else:
              # Sanity check limits given by user
              if high < low:
                  raise EnvironmentException('high limit smaller than low limit')
              condition = '%s <= %d && %s >= %d' % (expression, high, expression, low)
              if not self._compile_int(condition, prefix, env, extra_args, dependencies):
                  raise EnvironmentException('Value out of given range')
  
          # Binary search
          while low != high:
              cur = low + int((high - low) / 2)
              if self._compile_int('%s <= %d' % (expression, cur), prefix, env, extra_args, dependencies):
                  high = cur
              else:
                  low = cur + 1
  
          return low
  
      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, None, None, 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
  
  [... 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
  import subprocess
  
  from ..linkers import StaticLinker
  from .. import coredata
  from .. import mlog
  from .. import mesonlib
  from ..mesonlib import EnvironmentException, MesonException, version_compare, Popen_safe
  
  """This file contains the data files of all compilers Meson knows
  about. To support a new compiler, add its information below.
  Also add corresponding autodetection code in environment.py."""
  
  header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di')
  obj_suffixes = ('o', 'obj', 'res')
  lib_suffixes = ('a', 'lib', 'dll', 'dylib', 'so')
  # Mapping of language to suffixes of files that should always be in that language
  # This means we can't include .h headers here since they could be C, C++, ObjC, etc.
  lang_suffixes = {
      'c': ('c',),
      'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx'),
      # f90, f95, f03, f08 are for free-form fortran ('f90' recommended)
      # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended)
      'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp'),
      'd': ('d', 'di'),
      'objc': ('m',),
      'objcpp': ('mm',),
      'rust': ('rs',),
      'vala': ('vala', 'vapi', 'gs'),
      'cs': ('cs',),
      'swift': ('swift',),
      'java': ('java',),
  }
  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 = ('d', 'objcpp', 'cpp', 'objc', 'c', 'fortran',)
  clike_suffixes = ()
  for _l in clike_langs:
      clike_suffixes += lang_suffixes[_l]
  clike_suffixes += ('h', 'll', 's')
  
  soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
  
  # All these are only for C-like languages; see `clike_langs` above.
  
  def sort_clike(lang):
      '''
      Sorting function to sort the list of languages according to
      reversed(compilers.clike_langs) and append the unknown langs in the end.
      The purpose is to prefer C over C++ for files that can be compiled by
      both such as assembly, C, etc. Also applies to ObjC, ObjC++, etc.
      '''
      if lang not in clike_langs:
          return 1
      return -clike_langs.index(lang)
  
  def is_header(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1]
      return suffix in header_suffixes
  
  def is_source(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1].lower()
      return suffix in clike_suffixes
  
  def is_assembly(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      return fname.split('.')[-1].lower() == 's'
  
  def is_llvm_ir(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      return fname.split('.')[-1] == 'll'
  
  def is_object(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1]
      return suffix in obj_suffixes
  
  def is_library(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
  
      if soregex.match(fname):
          return True
  
      suffix = fname.split('.')[-1]
      return suffix in lib_suffixes
  
  gnulike_buildtype_args = {'plain': [],
                            # -O0 is passed for improved debugging information with gcc
                            # See https://github.com/mesonbuild/meson/pull/509
                            'debug': ['-O0', '-g'],
                            'debugoptimized': ['-O2', '-g'],
                            'release': ['-O3'],
                            'minsize': ['-Os', '-g']}
  
  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': [],
                                # The otherwise implicit REF and ICF linker
                                # optimisations are disabled by /DEBUG.
                                # REF implies ICF.
                                'release': ['/OPT:REF'],
                                'minsize': ['/INCREMENTAL:NO', '/OPT:REF'],
                                }
  
  java_buildtype_args = {'plain': [],
                         'debug': ['-g'],
                         'debugoptimized': ['-g'],
                         'release': [],
                         'minsize': [],
                         }
  
  rust_buildtype_args = {'plain': [],
                         'debug': ['-C', 'debuginfo=2'],
                         'debugoptimized': ['-C', 'debuginfo=2', '-C', 'opt-level=2'],
                         'release': ['-C', 'opt-level=3'],
                         'minsize': [], # In a future release: ['-C', 'opt-level=s'],
                         }
  
  d_gdc_buildtype_args = {'plain': [],
                          'debug': ['-g', '-O0'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O3', '-frelease'],
                          'minsize': [],
                          }
  
  d_ldc_buildtype_args = {'plain': [],
                          'debug': ['-g', '-O0'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O3', '-release'],
                          'minsize': [],
                          }
  
  d_dmd_buildtype_args = {'plain': [],
                          'debug': ['-g'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O', '-release'],
                          'minsize': [],
                          }
  
  mono_buildtype_args = {'plain': [],
                         'debug': ['-debug'],
                         'debugoptimized': ['-debug', '-optimize+'],
                         'release': ['-optimize+'],
                         'minsize': [],
                         }
  
  swift_buildtype_args = {'plain': [],
                          'debug': ['-g'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O'],
                          'minsize': [],
                          }
  
  gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32',
                 '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32']
  
  msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib',
                  'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib',
                  'uuid.lib', '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', 'address,undefined'],
                                                         '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 guided 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.UserComboOption('b_ndebug', 'Disable asserts',
                                                       ['true', 'false', 'if-release'], 'false'),
                  'b_staticpic': coredata.UserBooleanOption('b_staticpic',
                                                            'Build static libraries as position independent',
                                                            True),
                  }
  
  gnulike_instruction_set_args = {'mmx': ['-mmmx'],
                                  'sse': ['-msse'],
                                  'sse2': ['-msse2'],
                                  'sse3': ['-msse3'],
                                  'ssse3': ['-mssse3'],
                                  'sse41': ['-msse4.1'],
                                  'sse42': ['-msse4.2'],
                                  'avx': ['-mavx'],
                                  'avx2': ['-mavx2'],
                                  'neon': ['-mfpu=neon'],
                                  }
  
  vs32_instruction_set_args = {'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX
                               'sse': ['/arch:SSE'],
                               'sse2': ['/arch:SSE2'],
                               'sse3': ['/arch:AVX'], # VS leaped from SSE2 directly to AVX.
                               'sse41': ['/arch:AVX'],
                               'sse42': ['/arch:AVX'],
                               'avx': ['/arch:AVX'],
                               'avx2': ['/arch:AVX2'],
                               'neon': None,
                               }
  
  # The 64 bit compiler defaults to /arch:avx.
  vs64_instruction_set_args = {'mmx': ['/arch:AVX'],
                               'sse': ['/arch:AVX'],
                               'sse2': ['/arch:AVX'],
                               'sse3': ['/arch:AVX'],
                               'ssse3': ['/arch:AVX'],
                               'sse41': ['/arch:AVX'],
                               'sse42': ['/arch:AVX'],
                               'avx': ['/arch:AVX'],
                               'avx2': ['/arch:AVX2'],
                               'neon': None,
                               }
  
  
  def sanitizer_compile_args(value):
      if value == 'none':
          return []
      args = ['-fsanitize=' + value]
      if 'address' in value: # For -fsanitize=address,undefined
          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 == 'true' or
                  (options['b_ndebug'].value == 'if-release' and
                   options['buildtype'].value == 'release')):
              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(linker.get_asneeded_args())
      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 'overridden' 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
  import subprocess
  
  from ..linkers import StaticLinker
  from .. import coredata
  from .. import mlog
  from .. import mesonlib
  from ..mesonlib import EnvironmentException, MesonException, version_compare, Popen_safe
  
  """This file contains the data files of all compilers Meson knows
  about. To support a new compiler, add its information below.
  Also add corresponding autodetection code in environment.py."""
  
  header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di')
  obj_suffixes = ('o', 'obj', 'res')
  lib_suffixes = ('a', 'lib', 'dll', 'dylib', 'so')
  # Mapping of language to suffixes of files that should always be in that language
  # This means we can't include .h headers here since they could be C, C++, ObjC, etc.
  lang_suffixes = {
      'c': ('c',),
      'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx'),
      # f90, f95, f03, f08 are for free-form fortran ('f90' recommended)
      # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended)
      'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp'),
      'd': ('d', 'di'),
      'objc': ('m',),
      'objcpp': ('mm',),
      'rust': ('rs',),
      'vala': ('vala', 'vapi', 'gs'),
      'cs': ('cs',),
      'swift': ('swift',),
      'java': ('java',),
  }
  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 = ('d', 'objcpp', 'cpp', 'objc', 'c', 'fortran',)
  clike_suffixes = ()
  for _l in clike_langs:
      clike_suffixes += lang_suffixes[_l]
  clike_suffixes += ('h', 'll', 's')
  
  soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
  
  # All these are only for C-like languages; see `clike_langs` above.
  
  def sort_clike(lang):
      '''
      Sorting function to sort the list of languages according to
      reversed(compilers.clike_langs) and append the unknown langs in the end.
      The purpose is to prefer C over C++ for files that can be compiled by
      both such as assembly, C, etc. Also applies to ObjC, ObjC++, etc.
      '''
      if lang not in clike_langs:
          return 1
      return -clike_langs.index(lang)
  
  def is_header(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1]
      return suffix in header_suffixes
  
  def is_source(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1].lower()
      return suffix in clike_suffixes
  
  def is_assembly(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      return fname.split('.')[-1].lower() == 's'
  
  def is_llvm_ir(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      return fname.split('.')[-1] == 'll'
  
  def is_object(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
      suffix = fname.split('.')[-1]
      return suffix in obj_suffixes
  
  def is_library(fname):
      if hasattr(fname, 'fname'):
          fname = fname.fname
  
      if soregex.match(fname):
          return True
  
      suffix = fname.split('.')[-1]
      return suffix in lib_suffixes
  
  gnulike_buildtype_args = {'plain': [],
                            # -O0 is passed for improved debugging information with gcc
                            # See https://github.com/mesonbuild/meson/pull/509
                            'debug': ['-O0', '-g'],
                            'debugoptimized': ['-O2', '-g'],
                            'release': ['-O3'],
                            'minsize': ['-Os', '-g']}
  
  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': [],
                                # The otherwise implicit REF and ICF linker
                                # optimisations are disabled by /DEBUG.
                                # REF implies ICF.
                                'release': ['/OPT:REF'],
                                'minsize': ['/INCREMENTAL:NO', '/OPT:REF'],
                                }
  
  java_buildtype_args = {'plain': [],
                         'debug': ['-g'],
                         'debugoptimized': ['-g'],
                         'release': [],
                         'minsize': [],
                         }
  
  rust_buildtype_args = {'plain': [],
                         'debug': ['-C', 'debuginfo=2'],
                         'debugoptimized': ['-C', 'debuginfo=2', '-C', 'opt-level=2'],
                         'release': ['-C', 'opt-level=3'],
                         'minsize': [], # In a future release: ['-C', 'opt-level=s'],
                         }
  
  d_gdc_buildtype_args = {'plain': [],
                          'debug': ['-g', '-O0'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O3', '-frelease'],
                          'minsize': [],
                          }
  
  d_ldc_buildtype_args = {'plain': [],
                          'debug': ['-g', '-O0'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O3', '-release'],
                          'minsize': [],
                          }
  
  d_dmd_buildtype_args = {'plain': [],
                          'debug': ['-g'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O', '-release'],
                          'minsize': [],
                          }
  
  mono_buildtype_args = {'plain': [],
                         'debug': ['-debug'],
                         'debugoptimized': ['-debug', '-optimize+'],
                         'release': ['-optimize+'],
                         'minsize': [],
                         }
  
  swift_buildtype_args = {'plain': [],
                          'debug': ['-g'],
                          'debugoptimized': ['-g', '-O'],
                          'release': ['-O'],
                          'minsize': [],
                          }
  
  gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32',
                 '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32']
  
  msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib',
                  'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib',
                  'uuid.lib', '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', 'address,undefined'],
                                                         '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 guided 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.UserComboOption('b_ndebug', 'Disable asserts',
                                                       ['true', 'false', 'if-release'], 'false'),
                  'b_staticpic': coredata.UserBooleanOption('b_staticpic',
                                                            'Build static libraries as position independent',
                                                            True),
                  }
  
  gnulike_instruction_set_args = {'mmx': ['-mmmx'],
                                  'sse': ['-msse'],
                                  'sse2': ['-msse2'],
                                  'sse3': ['-msse3'],
                                  'ssse3': ['-mssse3'],
                                  'sse41': ['-msse4.1'],
                                  'sse42': ['-msse4.2'],
                                  'avx': ['-mavx'],
                                  'avx2': ['-mavx2'],
                                  'neon': ['-mfpu=neon'],
                                  }
  
  vs32_instruction_set_args = {'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX
                               'sse': ['/arch:SSE'],
                               'sse2': ['/arch:SSE2'],
                               'sse3': ['/arch:AVX'], # VS leaped from SSE2 directly to AVX.
                               'sse41': ['/arch:AVX'],
                               'sse42': ['/arch:AVX'],
                               'avx': ['/arch:AVX'],
                               'avx2': ['/arch:AVX2'],
                               'neon': None,
                               }
  
  # The 64 bit compiler defaults to /arch:avx.
  vs64_instruction_set_args = {'mmx': ['/arch:AVX'],
                               'sse': ['/arch:AVX'],
                               'sse2': ['/arch:AVX'],
                               'sse3': ['/arch:AVX'],
                               'ssse3': ['/arch:AVX'],
                               'sse41': ['/arch:AVX'],
                               'sse42': ['/arch:AVX'],
                               'avx': ['/arch:AVX'],
                               'avx2': ['/arch:AVX2'],
                               'neon': None,
                               }
  
  
  def sanitizer_compile_args(value):
      if value == 'none':
          return []
      args = ['-fsanitize=' + value]
      if 'address' in value: # For -fsanitize=address,undefined
          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 == 'true' or
                  (options['b_ndebug'].value == 'if-release' and
                   options['buildtype'].value == 'release')):
              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(linker.get_asneeded_args())
      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 'overridden' 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.
  
  import os.path, subprocess
  
  from ..mesonlib import EnvironmentException
  from ..mesonlib import is_windows
  
  from .compilers import Compiler, mono_buildtype_args
  
  class CsCompiler(Compiler):
      def __init__(self, exelist, version, id, runner=None):
          self.language = 'cs'
          super().__init__(exelist, version)
          self.id = id
          self.runner = runner
  
      def get_display_language(self):
          return 'C sharp'
  
      def get_always_args(self):
          return ['/nologo']
  
      def get_linker_always_args(self):
          return ['/nologo']
  
      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, version, 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, build_rpath, 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 + self.get_always_args() + [src], cwd=work_dir)
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('Mono compiler %s can not compile programs.' % self.name_string())
          if self.runner:
              cmdlist = [self.runner, obj]
          else:
              cmdlist = [os.path.join(work_dir, 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]
  
  
  class MonoCompiler(CsCompiler):
      def __init__(self, exelist, version):
          super().__init__(exelist, version, 'mono',
                           'mono')
  
  
  class VisualStudioCsCompiler(CsCompiler):
      def __init__(self, exelist, version):
          super().__init__(exelist, version, 'csc')
  
      def get_buildtype_args(self, buildtype):
          res = mono_buildtype_args[buildtype]
          if not is_windows():
              tmp = []
              for flag in res:
                  if flag == '-debug':
                      flag = '-debug:portable'
                  tmp.append(flag)
              res = tmp
          return res
  
  
  [... 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 ..mesonlib import is_windows
  
  from .compilers import Compiler, mono_buildtype_args
  
  class CsCompiler(Compiler):
      def __init__(self, exelist, version, id, runner=None):
          self.language = 'cs'
          super().__init__(exelist, version)
          self.id = id
          self.runner = runner
  
      def get_display_language(self):
          return 'C sharp'
  
      def get_always_args(self):
          return ['/nologo']
  
      def get_linker_always_args(self):
          return ['/nologo']
  
      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, build_rpath, 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 + self.get_always_args() + [src], cwd=work_dir)
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('Mono compiler %s can not compile programs.' % self.name_string())
          if self.runner:
              cmdlist = [self.runner, obj]
          else:
              cmdlist = [os.path.join(work_dir, 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]
  
  
  class MonoCompiler(CsCompiler):
      def __init__(self, exelist, version):
          super().__init__(exelist, version, 'mono',
                           'mono')
  
  
  class VisualStudioCsCompiler(CsCompiler):
      def __init__(self, exelist, version):
          super().__init__(exelist, version, 'csc')
  
      def get_buildtype_args(self, buildtype):
          res = mono_buildtype_args[buildtype]
          if not is_windows():
              tmp = []
              for flag in res:
                  if flag == '-debug':
                      flag = '-debug:portable'
                  tmp.append(flag)
              res = tmp
          return res
  
  
  [... 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, version_compare
  
  from .compilers import (
      GCC_STANDARD,
      d_dmd_buildtype_args,
      d_gdc_buildtype_args,
      d_ldc_buildtype_args,
      get_gcc_soname_args,
      gnu_color_args,
      Compiler,
      CompilerArgs,
  )
  
  d_feature_args = {'gcc':  {'unittest': '-funittest',
                             'version': '-fversion',
                             'import_dir': '-J'
                             },
                    'llvm': {'unittest': '-unittest',
                             'version': '-d-version',
                             'import_dir': '-J'
                             },
                    'dmd':  {'unittest': '-unittest',
                             'version': '-version',
                             'import_dir': '-J'
                             }
                    }
  
  class DCompiler(Compiler):
      def __init__(self, exelist, version, is_cross, **kwargs):
          self.language = 'd'
          super().__init__(exelist, version, **kwargs)
          self.id = 'unknown'
          self.is_cross = is_cross
  
      def sanity_check(self, work_dir, environment):
          source_name = os.path.join(work_dir, 'sanity.d')
          output_name = os.path.join(work_dir, 'dtest')
          with open(source_name, 'w') as ofile:
              ofile.write('''void main() {
  }
  ''')
          pc = subprocess.Popen(self.exelist + self.get_output_args(output_name) + [source_name], cwd=work_dir)
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('D compiler %s can not compile programs.' % self.name_string())
          if subprocess.call(output_name) != 0:
              raise EnvironmentException('Executables created by D compiler %s are not runnable.' % self.name_string())
  
      def needs_static_linker(self):
          return True
  
      def name_string(self):
          return ' '.join(self.exelist)
  
      def get_linker_exelist(self):
          return self.exelist[:]
  
      def get_preprocess_only_args(self):
          return ['-E']
  
      def get_compile_only_args(self):
          return ['-c']
  
      def depfile_for_object(self, objfile):
          return objfile + '.' + self.get_depfile_suffix()
  
      def get_depfile_suffix(self):
          return 'deps'
  
      def get_pic_args(self):
          return ['-fPIC']
  
      def get_std_shared_lib_link_args(self):
          return ['-shared']
  
      def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, version, is_shared_module):
          # FIXME: Make this work for Windows, MacOS and cross-compiling
          return get_gcc_soname_args(GCC_STANDARD, prefix, shlib_name, suffix, path, soversion, version, is_shared_module)
  
      def get_feature_args(self, kwargs, build_to_src):
          res = []
          if 'unittest' in kwargs:
              unittest = kwargs.pop('unittest')
              unittest_arg = d_feature_args[self.id]['unittest']
              if not unittest_arg:
                  raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string())
              if unittest:
                  res.append(unittest_arg)
  
          if 'versions' in kwargs:
              versions = kwargs.pop('versions')
              if not isinstance(versions, list):
                  versions = [versions]
  
              version_arg = d_feature_args[self.id]['version']
              if not version_arg:
                  raise EnvironmentException('D compiler %s does not support the "feature versions" feature.' % self.name_string())
              for v in versions:
                  res.append('{0}={1}'.format(version_arg, v))
  
          if 'import_dirs' in kwargs:
              import_dirs = kwargs.pop('import_dirs')
              if not isinstance(import_dirs, list):
                  import_dirs = [import_dirs]
  
              import_dir_arg = d_feature_args[self.id]['import_dir']
              if not import_dir_arg:
                  raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string())
              for idir_obj in import_dirs:
                  basedir = idir_obj.get_curdir()
                  for idir in idir_obj.get_incdirs():
                      # Avoid superfluous '/.' at the end of paths when d is '.'
                      if idir not in ('', '.'):
                          expdir = os.path.join(basedir, idir)
                      else:
                          expdir = basedir
                      srctreedir = os.path.join(build_to_src, expdir)
                      res.append('{0}{1}'.format(import_dir_arg, srctreedir))
  
          if kwargs:
              raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys()))
  
          return res
  
      def get_buildtype_linker_args(self, buildtype):
          return []
  
      def get_std_exe_link_args(self):
          return []
  
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
          # This method is to be used by LDC and DMD.
          # GDC can deal with the verbatim flags.
          if not rpath_paths and not install_rpath:
              return []
          paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths])
          if build_rpath != '':
              paths += ':' + build_rpath
          if len(paths) < len(install_rpath):
              padding = 'X' * (len(install_rpath) - len(paths))
              if not paths:
                  paths = padding
              else:
                  paths = paths + ':' + padding
          return ['-L-rpath={}'.format(paths)]
  
      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()
  
          if mode == 'compile':
              # Add DFLAGS 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]
          # 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)
  
          with self.compile(code, args, mode) as p:
              return p.returncode == 0
  
      def has_multi_arguments(self, args, env):
          return self.compiles('int i;\n', env, extra_args=args)
  
      @classmethod
      def translate_args_to_nongnu(cls, args):
          dcargs = []
          # Translate common arguments to flags the LDC/DMD compilers
          # can understand.
          # The flags might have been added by pkg-config files,
          # and are therefore out of the user's control.
          for arg in args:
              if arg == '-pthread':
                  continue
              if arg.startswith('-Wl,'):
                  linkargs = arg[arg.index(',') + 1:].split(',')
                  for la in linkargs:
                      dcargs.append('-L' + la.strip())
                  continue
              elif arg.startswith('-l'):
                  # translate library link flag
                  dcargs.append('-L' + arg)
                  continue
              elif arg.startswith('-L/') or arg.startswith('-L./'):
                  # we need to handle cases where -L is set by e.g. a pkg-config
                  # setting to select a linker search path. We can however not
                  # unconditionally prefix '-L' with '-L' because the user might
                  # have set this flag too to do what it is intended to for this
                  # compiler (pass flag through to the linker)
                  # Hence, we guess here whether the flag was intended to pass
                  # a linker search path.
                  dcargs.append('-L' + arg)
                  continue
              dcargs.append(arg)
  
          return dcargs
  
  
  class GnuDCompiler(DCompiler):
      def __init__(self, exelist, version, is_cross, **kwargs):
          DCompiler.__init__(self, exelist, version, is_cross, **kwargs)
          self.id = 'gcc'
          default_warn_args = ['-Wall', '-Wdeprecated']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
          self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic']
  
          self._has_color_support = version_compare(self.version, '>=4.9')
          # dependencies were implemented before, but broken - support was fixed in GCC 7.1+
          # (and some backported versions)
          self._has_deps_support = version_compare(self.version, '>=7.1')
  
      def get_colorout_args(self, colortype):
          if self._has_color_support:
              return gnu_color_args[colortype][:]
          return []
  
      def get_dependency_gen_args(self, outtarget, outfile):
          if not self._has_deps_support:
              return []
          return ['-MD', '-MQ', outtarget, '-MF', outfile]
  
      def get_output_args(self, target):
          return ['-o', target]
  
      def get_linker_output_args(self, target):
          return ['-o', target]
  
      def get_include_args(self, path, is_system):
          return ['-I' + path]
  
      def get_warn_args(self, level):
          return self.warn_args[level]
  
      def get_werror_args(self):
          return ['-Werror']
  
      def get_linker_search_args(self, dirname):
          return ['-L' + dirname]
  
      def get_buildtype_args(self, buildtype):
          return d_gdc_buildtype_args[buildtype]
  
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
          return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
  
  
  class LLVMDCompiler(DCompiler):
      def __init__(self, exelist, version, is_cross, **kwargs):
          DCompiler.__init__(self, exelist, version, is_cross, **kwargs)
          self.id = 'llvm'
          self.base_options = ['b_coverage', 'b_colorout']
  
      def get_colorout_args(self, colortype):
          if colortype == 'always':
              return ['-enable-color']
          return []
  
      def get_dependency_gen_args(self, outtarget, outfile):
          # LDC using the -deps flag returns a non-Makefile dependency-info file, which
          # the backends can not use. So we disable this feature for now.
          return []
  
      def get_output_args(self, target):
          return ['-of', target]
  
      def get_linker_output_args(self, target):
          return ['-of', target]
  
      def get_include_args(self, path, is_system):
          return ['-I' + path]
  
      def get_warn_args(self, level):
          if level == '2' or level == '3':
              return ['-wi', '-dw']
          else:
              return ['-wi']
  
      def get_werror_args(self):
          return ['-w']
  
      def get_coverage_args(self):
          return ['-cov']
  
      def get_buildtype_args(self, buildtype):
          return d_ldc_buildtype_args[buildtype]
  
      def get_pic_args(self):
          return ['-relocation-model=pic']
  
      def get_linker_search_args(self, dirname):
          # -L is recognized as "add this to the search path" by the linker,
          # while the compiler recognizes it as "pass to linker". So, the first
          # -L is for the compiler, telling it to pass the second -L to the linker.
          return ['-L-L' + dirname]
  
      @classmethod
      def unix_args_to_native(cls, args):
          return cls.translate_args_to_nongnu(args)
  
  
  class DmdDCompiler(DCompiler):
      def __init__(self, exelist, version, is_cross, **kwargs):
          DCompiler.__init__(self, exelist, version, is_cross, **kwargs)
          self.id = 'dmd'
          self.base_options = ['b_coverage', 'b_colorout']
  
      def get_colorout_args(self, colortype):
          if colortype == 'always':
              return ['-color=on']
          return []
  
      def get_dependency_gen_args(self, outtarget, outfile):
          # LDC using the -deps flag returns a non-Makefile dependency-info file, which
          # the backends can not use. So we disable this feature for now.
          return []
  
      def get_output_args(self, target):
          return ['-of' + target]
  
      def get_werror_args(self):
          return ['-w']
  
      def get_linker_output_args(self, target):
          return ['-of' + target]
  
      def get_include_args(self, path, is_system):
          return ['-I' + path]
  
      def get_warn_args(self, level):
          return ['-wi']
  
      def get_coverage_args(self):
          return ['-cov']
  
      def get_linker_search_args(self, dirname):
          # -L is recognized as "add this to the search path" by the linker,
          # while the compiler recognizes it as "pass to linker". So, the first
          # -L is for the compiler, telling it to pass the second -L to the linker.
          return ['-L-L' + dirname]
  
      def get_buildtype_args(self, buildtype):
          return d_dmd_buildtype_args[buildtype]
  
      def get_std_shared_lib_link_args(self):
          return ['-shared', '-defaultlib=libphobos2.so']
  
      @classmethod
      def unix_args_to_native(cls, args):
          return cls.translate_args_to_nongnu(args)
  
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/compilers/d.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, version_compare
  
  from .compilers import (
      GCC_STANDARD,
      d_dmd_buildtype_args,
      d_gdc_buildtype_args,
      d_ldc_buildtype_args,
      get_gcc_soname_args,
      gnu_color_args,
      Compiler,
      CompilerArgs,
  )
  
  d_feature_args = {'gcc':  {'unittest': '-funittest',
                             'version': '-fversion',
                             'import_dir': '-J'
                             },
                    'llvm': {'unittest': '-unittest',
                             'version': '-d-version',
                             'import_dir': '-J'
                             },
                    'dmd':  {'unittest': '-unittest',
                             'version': '-version',
                             'import_dir': '-J'
                             }
                    }
  
  class DCompiler(Compiler):
      def __init__(self, exelist, version, is_cross, **kwargs):
          self.language = 'd'
          super().__init__(exelist, version, **kwargs)
          self.id = 'unknown'
          self.is_cross = is_cross
  
      def sanity_check(self, work_dir, environment):
          source_name = os.path.join(work_dir, 'sanity.d')
          output_name = os.path.join(work_dir, 'dtest')
          with open(source_name, 'w') as ofile:
              ofile.write('''void main() {
  }
  ''')
          pc = subprocess.Popen(self.exelist + self.get_output_args(output_name) + [source_name], cwd=work_dir)
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('D compiler %s can not compile programs.' % self.name_string())
          if subprocess.call(output_name) != 0:
              raise EnvironmentException('Executables created by D compiler %s are not runnable.' % self.name_string())
  
      def needs_static_linker(self):
          return True
  
      def name_string(self):
          return ' '.join(self.exelist)
  
      def get_linker_exelist(self):
          return self.exelist[:]
  
      def get_preprocess_only_args(self):
          return ['-E']
  
      def get_compile_only_args(self):
          return ['-c']
  
      def depfile_for_object(self, objfile):
          return objfile + '.' + self.get_depfile_suffix()
  
      def get_depfile_suffix(self):
          return 'deps'
  
      def get_pic_args(self):
          return ['-fPIC']
  
      def get_std_shared_lib_link_args(self):
          return ['-shared']
  
      def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
          # FIXME: Make this work for Windows, MacOS and cross-compiling
          return get_gcc_soname_args(GCC_STANDARD, prefix, shlib_name, suffix, path, soversion, is_shared_module)
  
      def get_feature_args(self, kwargs, build_to_src):
          res = []
          if 'unittest' in kwargs:
              unittest = kwargs.pop('unittest')
              unittest_arg = d_feature_args[self.id]['unittest']
              if not unittest_arg:
                  raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string())
              if unittest:
                  res.append(unittest_arg)
  
          if 'versions' in kwargs:
              versions = kwargs.pop('versions')
              if not isinstance(versions, list):
                  versions = [versions]
  
              version_arg = d_feature_args[self.id]['version']
              if not version_arg:
                  raise EnvironmentException('D compiler %s does not support the "feature versions" feature.' % self.name_string())
              for v in versions:
                  res.append('{0}={1}'.format(version_arg, v))
  
          if 'import_dirs' in kwargs:
              import_dirs = kwargs.pop('import_dirs')
              if not isinstance(import_dirs, list):
                  import_dirs = [import_dirs]
  
              import_dir_arg = d_feature_args[self.id]['import_dir']
              if not import_dir_arg:
                  raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string())
              for idir_obj in import_dirs:
                  basedir = idir_obj.get_curdir()
                  for idir in idir_obj.get_incdirs():
                      # Avoid superfluous '/.' at the end of paths when d is '.'
                      if idir not in ('', '.'):
                          expdir = os.path.join(basedir, idir)
                      else:
                          expdir = basedir
                      srctreedir = os.path.join(build_to_src, expdir)
                      res.append('{0}{1}'.format(import_dir_arg, srctreedir))
  
          if kwargs:
              raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys()))
  
          return res
  
      def get_buildtype_linker_args(self, buildtype):
          return []
  
      def get_std_exe_link_args(self):
          return []
  
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
          # This method is to be used by LDC and DMD.
          # GDC can deal with the verbatim flags.
          if not rpath_paths and not install_rpath:
              return []
          paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths])
          if build_rpath != '':
              paths += ':' + build_rpath
          if len(paths) < len(install_rpath):
              padding = 'X' * (len(install_rpath) - len(paths))
              if not paths:
                  paths = padding
              else:
                  paths = paths + ':' + padding
          return ['-L-rpath={}'.format(paths)]
  
      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()
  
          if mode == 'compile':
              # Add DFLAGS 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]
          # 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)
  
          with self.compile(code, args, mode) as p:
              return p.returncode == 0
  
      def has_multi_arguments(self, args, env):
          return self.compiles('int i;\n', env, extra_args=args)
  
      @classmethod
      def translate_args_to_nongnu(cls, args):
          dcargs = []
          # Translate common arguments to flags the LDC/DMD compilers
          # can understand.
          # The flags might have been added by pkg-config files,
          # and are therefore out of the user's control.
          for arg in args:
              if arg == '-pthread':
                  continue
              if arg.startswith('-Wl,'):
                  linkargs = arg[arg.index(',') + 1:].split(',')
                  for la in linkargs:
                      dcargs.append('-L' + la.strip())
                  continue
              elif arg.startswith('-l'):
                  # translate library link flag
                  dcargs.append('-L' + arg)
                  continue
              elif arg.startswith('-L/') or arg.startswith('-L./'):
                  # we need to handle cases where -L is set by e.g. a pkg-config
                  # setting to select a linker search path. We can however not
                  # unconditionally prefix '-L' with '-L' because the user might
                  # have set this flag too to do what it is intended to for this
                  # compiler (pass flag through to the linker)
                  # Hence, we guess here whether the flag was intended to pass
                  # a linker search path.
                  dcargs.append('-L' + arg)
                  continue
              dcargs.append(arg)
  
          return dcargs
  
  
  class GnuDCompiler(DCompiler):
      def __init__(self, exelist, version, is_cross, **kwargs):
          DCompiler.__init__(self, exelist, version, is_cross, **kwargs)
          self.id = 'gcc'
          default_warn_args = ['-Wall', '-Wdeprecated']
          self.warn_args = {'1': default_warn_args,
                            '2': default_warn_args + ['-Wextra'],
                            '3': default_warn_args + ['-Wextra', '-Wpedantic']}
          self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic']
  
          self._has_color_support = version_compare(self.version, '>=4.9')
          # dependencies were implemented before, but broken - support was fixed in GCC 7.1+
          # (and some backported versions)
          self._has_deps_support = version_compare(self.version, '>=7.1')
  
      def get_colorout_args(self, colortype):
          if self._has_color_support:
              return gnu_color_args[colortype][:]
          return []
  
      def get_dependency_gen_args(self, outtarget, outfile):
          if not self._has_deps_support:
              return []
          return ['-MD', '-MQ', outtarget, '-MF', outfile]
  
      def get_output_args(self, target):
          return ['-o', target]
  
      def get_linker_output_args(self, target):
          return ['-o', target]
  
      def get_include_args(self, path, is_system):
          return ['-I' + path]
  
      def get_warn_args(self, level):
          return self.warn_args[level]
  
      def get_werror_args(self):
          return ['-Werror']
  
      def get_linker_search_args(self, dirname):
          return ['-L' + dirname]
  
      def get_buildtype_args(self, buildtype):
          return d_gdc_buildtype_args[buildtype]
  
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
          return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
  
  
  class LLVMDCompiler(DCompiler):
      def __init__(self, exelist, version, is_cross, **kwargs):
          DCompiler.__init__(self, exelist, version, is_cross, **kwargs)
          self.id = 'llvm'
          self.base_options = ['b_coverage', 'b_colorout']
  
      def get_colorout_args(self, colortype):
          if colortype == 'always':
              return ['-enable-color']
          return []
  
      def get_dependency_gen_args(self, outtarget, outfile):
          # LDC using the -deps flag returns a non-Makefile dependency-info file, which
          # the backends can not use. So we disable this feature for now.
          return []
  
      def get_output_args(self, target):
          return ['-of', target]
  
      def get_linker_output_args(self, target):
          return ['-of', target]
  
      def get_include_args(self, path, is_system):
          return ['-I' + path]
  
      def get_warn_args(self, level):
          if level == '2' or level == '3':
              return ['-wi', '-dw']
          else:
              return ['-wi']
  
      def get_werror_args(self):
          return ['-w']
  
      def get_coverage_args(self):
          return ['-cov']
  
      def get_buildtype_args(self, buildtype):
          return d_ldc_buildtype_args[buildtype]
  
      def get_pic_args(self):
          return ['-relocation-model=pic']
  
      def get_linker_search_args(self, dirname):
          # -L is recognized as "add this to the search path" by the linker,
          # while the compiler recognizes it as "pass to linker". So, the first
          # -L is for the compiler, telling it to pass the second -L to the linker.
          return ['-L-L' + dirname]
  
      @classmethod
      def unix_args_to_native(cls, args):
          return cls.translate_args_to_nongnu(args)
  
  
  class DmdDCompiler(DCompiler):
      def __init__(self, exelist, version, is_cross, **kwargs):
          DCompiler.__init__(self, exelist, version, is_cross, **kwargs)
          self.id = 'dmd'
          self.base_options = ['b_coverage', 'b_colorout']
  
      def get_colorout_args(self, colortype):
          if colortype == 'always':
              return ['-color=on']
          return []
  
      def get_dependency_gen_args(self, outtarget, outfile):
          # LDC using the -deps flag returns a non-Makefile dependency-info file, which
          # the backends can not use. So we disable this feature for now.
          return []
  
      def get_output_args(self, target):
          return ['-of' + target]
  
      def get_werror_args(self):
          return ['-w']
  
      def get_linker_output_args(self, target):
          return ['-of' + target]
  
      def get_include_args(self, path, is_system):
          return ['-I' + path]
  
      def get_warn_args(self, level):
          return ['-wi']
  
      def get_coverage_args(self):
          return ['-cov']
  
      def get_linker_search_args(self, dirname):
          # -L is recognized as "add this to the search path" by the linker,
          # while the compiler recognizes it as "pass to linker". So, the first
          # -L is for the compiler, telling it to pass the second -L to the linker.
          return ['-L-L' + dirname]
  
      def get_buildtype_args(self, buildtype):
          return d_dmd_buildtype_args[buildtype]
  
      def get_std_shared_lib_link_args(self):
          return ['-shared', '-defaultlib=libphobos2.so']
  
      @classmethod
      def unix_args_to_native(cls, args):
          return cls.translate_args_to_nongnu(args)
  
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/compilers/d.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, is_osx
  
  from .compilers import (
      GCC_CYGWIN,
      GCC_MINGW,
      GCC_OSX,
      GCC_STANDARD,
      ICC_STANDARD,
      apple_buildtype_linker_args,
      get_gcc_soname_args,
      gnulike_buildtype_args,
      gnulike_buildtype_linker_args,
      Compiler,
      ElbrusCompiler,
      IntelCompiler,
  )
  
  class FortranCompiler(Compiler):
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs):
          self.language = 'fortran'
          super().__init__(exelist, version, **kwargs)
          self.is_cross = is_cross
          self.exe_wrapper = exe_wrapper
          # Not really correct but I don't have Fortran compilers to test with. Sorry.
          self.gcc_type = GCC_STANDARD
          self.id = "IMPLEMENTATION CLASSES MUST SET THIS"
  
      def name_string(self):
          return ' '.join(self.exelist)
  
      def get_pic_args(self):
          if self.gcc_type in (GCC_CYGWIN, GCC_MINGW, GCC_OSX):
              return [] # On Window and OS X, pic is always on.
          return ['-fPIC']
  
      def get_std_shared_lib_link_args(self):
          return ['-shared']
  
      def needs_static_linker(self):
          return True
  
      def sanity_check(self, work_dir, environment):
          source_name = os.path.join(work_dir, 'sanitycheckf.f90')
          binary_name = os.path.join(work_dir, 'sanitycheckf')
          with open(source_name, 'w') as ofile:
              ofile.write('''program prog
       print *, "Fortran compilation is working."
  end program prog
  ''')
          extra_flags = self.get_cross_extra_flags(environment, link=True)
          pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string())
          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]
          pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
          pe.wait()
          if pe.returncode != 0:
              raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string())
  
      def get_std_warn_args(self, level):
          return FortranCompiler.std_warn_args
  
      def get_buildtype_args(self, buildtype):
          return gnulike_buildtype_args[buildtype]
  
      def get_buildtype_linker_args(self, buildtype):
          if is_osx():
              return apple_buildtype_linker_args[buildtype]
          return gnulike_buildtype_linker_args[buildtype]
  
      def split_shlib_to_parts(self, fname):
          return os.path.dirname(fname), fname
  
      def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, version, is_shared_module):
          return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, version, is_shared_module)
  
      def get_dependency_gen_args(self, outtarget, outfile):
          # Disabled until this is fixed:
          # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62162
          # return ['-cpp', '-MD', '-MQ', outtarget]
          return []
  
      def get_output_args(self, target):
          return ['-o', target]
  
      def get_preprocess_only_args(self):
          return ['-E']
  
      def get_compile_only_args(self):
          return ['-c']
  
      def get_linker_exelist(self):
          return self.exelist[:]
  
      def get_linker_output_args(self, outputname):
          return ['-o', outputname]
  
      def get_include_args(self, path, is_system):
          return ['-I' + path]
  
      def get_module_incdir_args(self):
          return ('-I', )
  
      def get_module_outdir_args(self, path):
          return ['-J' + path]
  
      def depfile_for_object(self, objfile):
          return objfile + '.' + self.get_depfile_suffix()
  
      def get_depfile_suffix(self):
          return 'd'
  
      def get_std_exe_link_args(self):
          return []
  
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
          return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
  
      def module_name_to_filename(self, module_name):
          return module_name.lower() + '.mod'
  
      def get_warn_args(self, level):
          return ['-Wall']
  
      def get_no_warn_args(self):
          return ['-w']
  
  
  class GnuFortranCompiler(FortranCompiler):
      def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwargs)
          self.gcc_type = gcc_type
          self.defines = defines or {}
          self.id = 'gcc'
  
      def has_builtin_define(self, define):
          return define in self.defines
  
      def get_builtin_define(self, define):
          if define in self.defines:
              return self.defines[define]
  
      def get_always_args(self):
          return ['-pipe']
  
      def get_coverage_args(self):
          return ['--coverage']
  
      def get_coverage_link_args(self):
          return ['--coverage']
  
      def gen_import_library_args(self, implibname):
          """
          The name of the outputted import library
  
          Used only on Windows
          """
          return ['-Wl,--out-implib=' + implibname]
  
  
  class ElbrusFortranCompiler(GnuFortranCompiler, ElbrusCompiler):
      def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs):
          GnuFortranCompiler.__init__(self, exelist, version, gcc_type, is_cross, exe_wrapper, defines, **kwargs)
          ElbrusCompiler.__init__(self, gcc_type, defines)
  
  
  class G95FortranCompiler(FortranCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'g95'
  
      def get_module_outdir_args(self, path):
          return ['-fmod=' + path]
  
      def get_always_args(self):
          return ['-pipe']
  
      def get_no_warn_args(self):
          # FIXME: Confirm that there's no compiler option to disable all warnings
          return []
  
      def gen_import_library_args(self, implibname):
          """
          The name of the outputted import library
  
          Used only on Windows
          """
          return ['-Wl,--out-implib=' + implibname]
  
  
  class SunFortranCompiler(FortranCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'sun'
  
      def get_dependency_gen_args(self, outtarget, outfile):
          return ['-fpp']
  
      def get_always_args(self):
          return []
  
      def get_warn_args(self, level):
          return []
  
      def get_module_incdir_args(self):
          return ('-M', )
  
      def get_module_outdir_args(self, path):
          return ['-moddir=' + path]
  
  
  class IntelFortranCompiler(IntelCompiler, FortranCompiler):
      std_warn_args = ['-warn', 'all']
  
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          self.file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp')
          FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags)
          # FIXME: Add support for OS X and Windows in detect_fortran_compiler so
          # we are sent the type of compiler
          IntelCompiler.__init__(self, ICC_STANDARD)
          self.id = 'intel'
  
      def get_module_outdir_args(self, path):
          return ['-module', path]
  
      def get_warn_args(self, level):
          return IntelFortranCompiler.std_warn_args
  
  
  class PathScaleFortranCompiler(FortranCompiler):
      std_warn_args = ['-fullwarn']
  
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'pathscale'
  
      def get_module_outdir_args(self, path):
          return ['-module', path]
  
      def get_std_warn_args(self, level):
          return PathScaleFortranCompiler.std_warn_args
  
  class PGIFortranCompiler(FortranCompiler):
      std_warn_args = ['-Minform=inform']
  
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'pgi'
  
      def get_module_incdir_args(self):
          return ('-module', )
  
      def get_module_outdir_args(self, path):
          return ['-module', path]
  
      def get_warn_args(self, level):
          return PGIFortranCompiler.std_warn_args
  
      def get_no_warn_args(self):
          return ['-silent']
  
  
  class Open64FortranCompiler(FortranCompiler):
      std_warn_args = ['-fullwarn']
  
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'open64'
  
      def get_module_outdir_args(self, path):
          return ['-module', path]
  
      def get_warn_args(self, level):
          return Open64FortranCompiler.std_warn_args
  
  
  class NAGFortranCompiler(FortranCompiler):
      std_warn_args = []
  
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'nagfor'
  
      def get_module_outdir_args(self, path):
          return ['-mdir', path]
  
      def get_warn_args(self, level):
          return NAGFortranCompiler.std_warn_args
  
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/compilers/fortran.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, is_osx
  
  from .compilers import (
      GCC_CYGWIN,
      GCC_MINGW,
      GCC_OSX,
      GCC_STANDARD,
      ICC_STANDARD,
      apple_buildtype_linker_args,
      get_gcc_soname_args,
      gnulike_buildtype_args,
      gnulike_buildtype_linker_args,
      Compiler,
      ElbrusCompiler,
      IntelCompiler,
  )
  
  class FortranCompiler(Compiler):
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs):
          self.language = 'fortran'
          super().__init__(exelist, version, **kwargs)
          self.is_cross = is_cross
          self.exe_wrapper = exe_wrapper
          # Not really correct but I don't have Fortran compilers to test with. Sorry.
          self.gcc_type = GCC_STANDARD
          self.id = "IMPLEMENTATION CLASSES MUST SET THIS"
  
      def name_string(self):
          return ' '.join(self.exelist)
  
      def get_pic_args(self):
          if self.gcc_type in (GCC_CYGWIN, GCC_MINGW, GCC_OSX):
              return [] # On Window and OS X, pic is always on.
          return ['-fPIC']
  
      def get_std_shared_lib_link_args(self):
          return ['-shared']
  
      def needs_static_linker(self):
          return True
  
      def sanity_check(self, work_dir, environment):
          source_name = os.path.join(work_dir, 'sanitycheckf.f90')
          binary_name = os.path.join(work_dir, 'sanitycheckf')
          with open(source_name, 'w') as ofile:
              ofile.write('''program prog
       print *, "Fortran compilation is working."
  end program prog
  ''')
          extra_flags = self.get_cross_extra_flags(environment, link=True)
          pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string())
          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]
          pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
          pe.wait()
          if pe.returncode != 0:
              raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string())
  
      def get_std_warn_args(self, level):
          return FortranCompiler.std_warn_args
  
      def get_buildtype_args(self, buildtype):
          return gnulike_buildtype_args[buildtype]
  
      def get_buildtype_linker_args(self, buildtype):
          if is_osx():
              return apple_buildtype_linker_args[buildtype]
          return gnulike_buildtype_linker_args[buildtype]
  
      def split_shlib_to_parts(self, fname):
          return os.path.dirname(fname), fname
  
      def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
          return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module)
  
      def get_dependency_gen_args(self, outtarget, outfile):
          # Disabled until this is fixed:
          # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62162
          # return ['-cpp', '-MD', '-MQ', outtarget]
          return []
  
      def get_output_args(self, target):
          return ['-o', target]
  
      def get_preprocess_only_args(self):
          return ['-E']
  
      def get_compile_only_args(self):
          return ['-c']
  
      def get_linker_exelist(self):
          return self.exelist[:]
  
      def get_linker_output_args(self, outputname):
          return ['-o', outputname]
  
      def get_include_args(self, path, is_system):
          return ['-I' + path]
  
      def get_module_incdir_args(self):
          return ('-I', )
  
      def get_module_outdir_args(self, path):
          return ['-J' + path]
  
      def depfile_for_object(self, objfile):
          return objfile + '.' + self.get_depfile_suffix()
  
      def get_depfile_suffix(self):
          return 'd'
  
      def get_std_exe_link_args(self):
          return []
  
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
          return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
  
      def module_name_to_filename(self, module_name):
          return module_name.lower() + '.mod'
  
      def get_warn_args(self, level):
          return ['-Wall']
  
      def get_no_warn_args(self):
          return ['-w']
  
  
  class GnuFortranCompiler(FortranCompiler):
      def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwargs)
          self.gcc_type = gcc_type
          self.defines = defines or {}
          self.id = 'gcc'
  
      def has_builtin_define(self, define):
          return define in self.defines
  
      def get_builtin_define(self, define):
          if define in self.defines:
              return self.defines[define]
  
      def get_always_args(self):
          return ['-pipe']
  
      def get_coverage_args(self):
          return ['--coverage']
  
      def get_coverage_link_args(self):
          return ['--coverage']
  
      def gen_import_library_args(self, implibname):
          """
          The name of the outputted import library
  
          Used only on Windows
          """
          return ['-Wl,--out-implib=' + implibname]
  
  
  class ElbrusFortranCompiler(GnuFortranCompiler, ElbrusCompiler):
      def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs):
          GnuFortranCompiler.__init__(self, exelist, version, gcc_type, is_cross, exe_wrapper, defines, **kwargs)
          ElbrusCompiler.__init__(self, gcc_type, defines)
  
  
  class G95FortranCompiler(FortranCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'g95'
  
      def get_module_outdir_args(self, path):
          return ['-fmod=' + path]
  
      def get_always_args(self):
          return ['-pipe']
  
      def get_no_warn_args(self):
          # FIXME: Confirm that there's no compiler option to disable all warnings
          return []
  
      def gen_import_library_args(self, implibname):
          """
          The name of the outputted import library
  
          Used only on Windows
          """
          return ['-Wl,--out-implib=' + implibname]
  
  
  class SunFortranCompiler(FortranCompiler):
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'sun'
  
      def get_dependency_gen_args(self, outtarget, outfile):
          return ['-fpp']
  
      def get_always_args(self):
          return []
  
      def get_warn_args(self, level):
          return []
  
      def get_module_incdir_args(self):
          return ('-M', )
  
      def get_module_outdir_args(self, path):
          return ['-moddir=' + path]
  
  
  class IntelFortranCompiler(IntelCompiler, FortranCompiler):
      std_warn_args = ['-warn', 'all']
  
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          self.file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp')
          FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags)
          # FIXME: Add support for OS X and Windows in detect_fortran_compiler so
          # we are sent the type of compiler
          IntelCompiler.__init__(self, ICC_STANDARD)
          self.id = 'intel'
  
      def get_module_outdir_args(self, path):
          return ['-module', path]
  
      def get_warn_args(self, level):
          return IntelFortranCompiler.std_warn_args
  
  
  class PathScaleFortranCompiler(FortranCompiler):
      std_warn_args = ['-fullwarn']
  
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'pathscale'
  
      def get_module_outdir_args(self, path):
          return ['-module', path]
  
      def get_std_warn_args(self, level):
          return PathScaleFortranCompiler.std_warn_args
  
  class PGIFortranCompiler(FortranCompiler):
      std_warn_args = ['-Minform=inform']
  
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'pgi'
  
      def get_module_incdir_args(self):
          return ('-module', )
  
      def get_module_outdir_args(self, path):
          return ['-module', path]
  
      def get_warn_args(self, level):
          return PGIFortranCompiler.std_warn_args
  
      def get_no_warn_args(self):
          return ['-silent']
  
  
  class Open64FortranCompiler(FortranCompiler):
      std_warn_args = ['-fullwarn']
  
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'open64'
  
      def get_module_outdir_args(self, path):
          return ['-module', path]
  
      def get_warn_args(self, level):
          return Open64FortranCompiler.std_warn_args
  
  
  class NAGFortranCompiler(FortranCompiler):
      std_warn_args = []
  
      def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
          super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
          self.id = 'nagfor'
  
      def get_module_outdir_args(self, path):
          return ['-mdir', path]
  
      def get_warn_args(self, level):
          return NAGFortranCompiler.std_warn_args
  
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/compilers/fortran.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, shutil, subprocess
  
  from ..mesonlib import EnvironmentException
  
  from .compilers import Compiler, java_buildtype_args
  
  class JavaCompiler(Compiler):
      def __init__(self, exelist, version):
          self.language = 'java'
          super().__init__(exelist, version)
          self.id = 'unknown'
          self.javarunner = 'java'
  
      def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, version, is_shared_module):
          return []
  
      def get_werror_args(self):
          return ['-Werror']
  
      def split_shlib_to_parts(self, fname):
          return None, fname
  
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, 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_output_args(self, subdir):
          if subdir == '':
              subdir = './'
          return ['-d', subdir, '-s', subdir]
  
      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 get_buildtype_args(self, buildtype):
          return java_buildtype_args[buildtype]
  
      def sanity_check(self, work_dir, environment):
          src = 'SanityCheck.java'
          obj = 'SanityCheck'
          source_name = os.path.join(work_dir, src)
          with open(source_name, 'w') as ofile:
              ofile.write('''class SanityCheck {
    public static void main(String[] args) {
      int i;
    }
  }
  ''')
          pc = subprocess.Popen(self.exelist + [src], cwd=work_dir)
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('Java compiler %s can not compile programs.' % self.name_string())
          runner = shutil.which(self.javarunner)
          if runner:
              cmdlist = [runner, obj]
              pe = subprocess.Popen(cmdlist, cwd=work_dir)
              pe.wait()
              if pe.returncode != 0:
                  raise EnvironmentException('Executables created by Java compiler %s are not runnable.' % self.name_string())
          else:
              m = "Java Virtual Machine wasn't found, but it's needed by Meson. " \
                  "Please install a JRE.\nIf you have specific needs where this " \
                  "requirement doesn't make sense, please open a bug at " \
                  "https://github.com/mesonbuild/meson/issues/new and tell us " \
                  "all about it."
              raise EnvironmentException(m)
  
      def needs_static_linker(self):
          return False
  
  
  [... the rest is omitted ...]
files.new_path: mesonbuild/compilers/java.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, shutil, subprocess
  
  from ..mesonlib import EnvironmentException
  
  from .compilers import Compiler, java_buildtype_args
  
  class JavaCompiler(Compiler):
      def __init__(self, exelist, version):
          self.language = 'java'
          super().__init__(exelist, version)
          self.id = 'unknown'
          self.javarunner = 'java'
  
      def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
          return []
  
      def get_werror_args(self):
          return ['-Werror']
  
      def split_shlib_to_parts(self, fname):
          return None, fname
  
      def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, 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_output_args(self, subdir):
          if subdir == '':
              subdir = './'
          return ['-d', subdir, '-s', subdir]
  
      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 get_buildtype_args(self, buildtype):
          return java_buildtype_args[buildtype]
  
      def sanity_check(self, work_dir, environment):
          src = 'SanityCheck.java'
          obj = 'SanityCheck'
          source_name = os.path.join(work_dir, src)
          with open(source_name, 'w') as ofile:
              ofile.write('''class SanityCheck {
    public static void main(String[] args) {
      int i;
    }
  }
  ''')
          pc = subprocess.Popen(self.exelist + [src], cwd=work_dir)
          pc.wait()
          if pc.returncode != 0:
              raise EnvironmentException('Java compiler %s can not compile programs.' % self.name_string())
          runner = shutil.which(self.javarunner)
          if runner:
              cmdlist = [runner, obj]
              pe = subprocess.Popen(cmdlist, cwd=work_dir)
              pe.wait()
              if pe.returncode != 0:
                  raise EnvironmentException('Executables created by Java compiler %s are not runnable.' % self.name_string())
          else:
              m = "Java Virtual Machine wasn't found, but it's needed by Meson. " \
                  "Please install a JRE.\nIf you have specific needs where this " \
                  "requirement doesn't make sense, please open a bug at " \
                  "https://github.com/mesonbuild/meson/issues/new and tell us " \
                  "all about it."
              raise EnvironmentException(m)
  
      def needs_static_linker(self):
          return False
  
  
  [... the rest is omitted ...]
files.old_path: mesonbuild/compilers/java.py