# pylint: disable=g-bad-file-header
# Copyright 2016 The Bazel Authors. All rights reserved.
#
# 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.
"""Wrapper script for executing the Microsoft Linker."""

import os
import shutil
import sys
import msvc_tools

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))

sys.path.append(SCRIPT_DIR)

LINKPATTERNS = [
    ('-m(32|64)', ['$TARGET_ARCH']),
    ('-Xcompilation-mode=(dbg|fastbuild|opt)', ['$COMPILATION_MODE']),
    (('rcs.*', '(.+)'), ['/OUT:$PATH0']),
    (('-o', '(.+)'), ['/OUT:$PATH0']),
    ('-B(.+)', []),
    ('-lpthread', []),
    ('-l(.+)', ['lib$0.so']),
    ('-L(.+)', ['/LIBPATH:$PATH0']),
    ('-static', []),
    ('-shared', []),
    ('-whole-archive', []),
    ('-no-whole-archive', []),
    ('-rdynamic', []),
    (r'-Wl,(.+)\.lib', ['$0.lib']),
    ('-Wl,@(.+)', ['$LOAD_PARAMS0']),
    ('@(.+)', ['$LOAD_PARAMS0']),
    ('-Wl,-rpath(.+)', []),
    ('-Wl,-S', []),  # Debug symbols are in pdb files.
    ('-Wl,/SUBSYSTEM:(WINDOWS|CONSOLE)', ['/SUBSYSTEM:$0']),
]


class MsvcLinker(msvc_tools.WindowsRunner):
  """Driver for the Microsoft linker."""

  def Run(self, argv):
    """Runs the linker using the passed clang/gcc style argument list.

    Args:
      argv: List of arguments

    Returns:
      The return code of the link.

    Raises:
      ValueError: if target architecture or compile mode isn't specified
    """
    # For now assume we are building a library.
    tool = 'lib'
    default_args = ['/nologo']

    # Build argument list.
    parser = msvc_tools.ArgParser(self, argv, LINKPATTERNS)

    # Find the output file name.
    name = ''
    self.output_dll_file = None
    for arg in parser.options:
      if '/OUT:' in arg:
        name = arg[5:]
        # if output file ends with .so.exe, we generate dll library.
        if name.endswith('.so.exe'):
          default_args.append('/DLL')
          self.output_dll_file = os.path.normpath(name[0:-7])
        break
    if not name:
      raise msvc_tools.Error('No output file name specified!')
    # Check if the library is empty, which is what happens when we create header
    # or intermediate link-only libraries.
    if (len(parser.options) == 2 and parser.options[0].startswith('/OUT') and
        parser.options[1].startswith('/M')):
      # Just "touch" the library to create the file.
      with open(name, 'w'):
        os.utime(name, None)
    else:
      # If the output name ends in .so, .lo, or .a, it is a library, otherwise
      # we need to use link to create an executable.
      if os.path.splitext(name)[1] not in ['.a', '.lo', '.so']:
        tool = 'link'

        if not parser.target_arch:
          raise ValueError('Must specify target architecture (-m32 or -m64)')

        # Append explicit machine type.
        if parser.target_arch == 'x64':
          default_args.append('/MACHINE:X64')
        else:
          default_args.append('/MACHINE:X86')

        # Args for buildng a console application. These must appear here since
        # blaze will not properly pass them to the linker.
        # /SUBSYSTEM:CONSOLE: Build a console application.
        default_args += ['/SUBSYSTEM:CONSOLE']
        # If there is no .o on the command line, then we need to add the
        # run-time library for the target. Without this the linker gives a
        # LNK4001 error and cannot find an entry point.
        for arg in parser.options:
          if arg.endswith('.o'):
            break
        else:
          if not parser.compilation_mode:
            raise ValueError('Must specify compilation mode '
                             '(-Xcompilation-mode={dbg,fastbuild,opt})')

          if parser.compilation_mode == 'dbg':
            default_args.insert(0, 'libcmtd.lib')
          else:
            default_args.insert(0, 'libcmt.lib')

      ret_code = self.RunBinary(tool, default_args + parser.options,
                                parser.target_arch, parser)
      if not ret_code and self.output_dll_file:
        shutil.copyfile(self.output_dll_file + '.so.exe',
                        self.output_dll_file + '.dll')
      return ret_code


def main(argv):
  return MsvcLinker().Run(argv[1:])


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))  # need to skip the first argument
