15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2011 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# TODO(slightlyoff): move to using shared version of this script.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)'''This script makes it easy to combine libs and object files to a new lib,
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)optionally removing some of the object files in the input libs by regular
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)expression matching.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)For usage information, run the script with a --help argument.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)'''
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import optparse
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import subprocess
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def Shell(*args):
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  '''Runs the program and args in args, returns the output from the program.'''
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process = subprocess.Popen(args,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             stdin = None,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             stdout = subprocess.PIPE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             stderr = subprocess.STDOUT)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output = process.stdout.readlines()
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process.wait()
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retcode = process.returncode
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if retcode != 0:
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise RuntimeError('%s exited with status %d' % (args[0], retcode))
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return output
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CollectRemovals(remove_re, inputs):
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  '''Returns a list of all object files in inputs that match remove_re.'''
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  removals = []
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for input in inputs:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output = Shell('lib.exe', '/list', input)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in output:
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      line = line.rstrip()
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if remove_re.search(line):
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        removals.append(line)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return removals
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CombineLibraries(output, remove_re, inputs):
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  '''Combines all the libraries and objects in inputs, while removing any
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  object files that match remove_re.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  '''
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  removals = []
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if remove_re:
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    removals = CollectRemovals(remove_re, inputs)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print removals
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args = ['lib.exe', '/out:%s' % output]
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args += ['/remove:%s' % obj for obj in removals]
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args += inputs
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shell(*args)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)USAGE = '''usage: %prog [options] <lib or obj>+
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Combines input libraries or objects into an output library, while removing
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)any object file (in the input libraries) that matches a given regular
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)expression.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)'''
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetOptionParser():
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser = optparse.OptionParser(USAGE)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('-o', '--output', dest = 'output',
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    help = 'write to this output library')
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('-r', '--remove', dest = 'remove',
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    help = 'object files matching this regexp will be removed '
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            'from the output library')
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return parser
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def Main():
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  '''Main function for this script'''
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser = GetOptionParser()
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (opt, args) = parser.parse_args()
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output = opt.output
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remove = opt.remove
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not output:
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser.error('You must specify an output file')
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not args:
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser.error('You must specify at least one object or library')
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output = output.strip()
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remove = remove.strip()
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if remove:
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      remove_re = re.compile(opt.remove)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    except:
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parser.error('%s is not a valid regular expression' % opt.remove)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remove_re = None
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if sys.platform != 'win32' and sys.platform != 'cygwin':
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser.error('this script only works on Windows for now')
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # If this is set, we can't capture lib.exe's output.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if 'VS_UNICODE_OUTPUT' in os.environ:
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    del os.environ['VS_UNICODE_OUTPUT']
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CombineLibraries(output, remove_re, args)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sys.exit(Main())
117