# 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 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(.+)', ['/LIBPATH:$PATH0']), ('-static', []), ('-shared', ['/DLL']), # TODO(pcloudy): Make "whole archive" a feature in CROSSTOOL # /WHOLEARCHIVE is supported in Visual Stuido 2015 update 2 (('-whole-archive', '(.+)'), ['/WHOLEARCHIVE:$PATH0']), ('-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) # Preprocessing arguments for linking whole archive libraries parser.WholeArchivePreprocess() # Find the output file name. name = '' for arg in parser.options: if '/OUT:' in arg: name = arg[5:] 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 .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']: 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') return self.RunBinary(tool, default_args + parser.options, parser.target_arch, parser) def main(argv): return MsvcLinker().Run(argv[1:]) if __name__ == '__main__': sys.exit(main(sys.argv[1:])) # need to skip the first argument