#!/usr/bin/env python
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# TODO(slightlyoff): move to using shared version of this script.
'''This script makes it easy to combine libs and object files to a new lib,
optionally removing some of the object files in the input libs by regular
expression matching.
For usage information, run the script with a --help argument.
'''
import optparse
import os
import re
import subprocess
import sys


def Shell(*args):
  '''Runs the program and args in args, returns the output from the program.'''
  process = subprocess.Popen(
      args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  output = process.stdout.readlines()
  process.wait()
  retcode = process.returncode
  if retcode != 0:
    raise RuntimeError('%s exited with status %d' % (args[0], retcode))
  return output


def CollectRemovals(remove_re, inputs):
  '''Returns a list of all object files in inputs that match remove_re.'''
  removals = []
  for input in inputs:
    output = Shell('lib.exe', '/list', input)

    for line in output:
      line = line.rstrip()
      if remove_re.search(line):
        removals.append(line)

  return removals


def CombineLibraries(output, remove_re, inputs):
  '''Combines all the libraries and objects in inputs, while removing any
  object files that match remove_re.
  '''
  removals = []
  if remove_re:
    removals = CollectRemovals(remove_re, inputs)

  if len(removals) > 0:
    print 'Removals: ', removals

  args = ['lib.exe', '/out:%s' % output]
  args += ['/remove:%s' % obj for obj in removals]
  args += inputs
  Shell(*args)


USAGE = '''usage: %prog [options] <lib or obj>+

Combines input libraries or objects into an output library, while removing
any object file (in the input libraries) that matches a given regular
expression.
'''


def GetOptionParser():
  parser = optparse.OptionParser(USAGE)
  parser.add_option(
      '-o', '--output', dest='output', help='write to this output library')
  parser.add_option(
      '-r',
      '--remove',
      dest='remove',
      help='object files matching this regexp will be removed '
      'from the output library')
  return parser


def Main():
  '''Main function for this script'''
  parser = GetOptionParser()
  (opt, args) = parser.parse_args()
  output = opt.output
  remove = opt.remove
  if not output:
    parser.error('You must specify an output file')

  if not args:
    parser.error('You must specify at least one object or library')

  output = output.strip()
  if remove:
    remove = remove.strip()

  if remove:
    try:
      remove_re = re.compile(opt.remove)
    except:
      parser.error('%s is not a valid regular expression' % opt.remove)
  else:
    remove_re = None

  if sys.platform != 'win32' and sys.platform != 'cygwin':
    parser.error('this script only works on Windows for now')

  # If this is set, we can't capture lib.exe's output.
  if 'VS_UNICODE_OUTPUT' in os.environ:
    del os.environ['VS_UNICODE_OUTPUT']

  CombineLibraries(output, remove_re, args)
  return 0


if __name__ == '__main__':
  sys.exit(Main())
