1 #!/usr/bin/env python 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 # TODO(slightlyoff): move to using shared version of this script. 7 8 '''This script makes it easy to combine libs and object files to a new lib, 9 optionally removing some of the object files in the input libs by regular 10 expression matching. 11 For usage information, run the script with a --help argument. 12 ''' 13 import optparse 14 import os 15 import re 16 import subprocess 17 import sys 18 19 20 def Shell(*args): 21 '''Runs the program and args in args, returns the output from the program.''' 22 process = subprocess.Popen(args, 23 stdin = None, 24 stdout = subprocess.PIPE, 25 stderr = subprocess.STDOUT) 26 output = process.stdout.readlines() 27 process.wait() 28 retcode = process.returncode 29 if retcode != 0: 30 raise RuntimeError('%s exited with status %d' % (args[0], retcode)) 31 return output 32 33 34 def CollectRemovals(remove_re, inputs): 35 '''Returns a list of all object files in inputs that match remove_re.''' 36 removals = [] 37 for input in inputs: 38 output = Shell('lib.exe', '/list', input) 39 40 for line in output: 41 line = line.rstrip() 42 if remove_re.search(line): 43 removals.append(line) 44 45 return removals 46 47 48 def CombineLibraries(output, remove_re, inputs): 49 '''Combines all the libraries and objects in inputs, while removing any 50 object files that match remove_re. 51 ''' 52 removals = [] 53 if remove_re: 54 removals = CollectRemovals(remove_re, inputs) 55 56 print removals 57 58 args = ['lib.exe', '/out:%s' % output] 59 args += ['/remove:%s' % obj for obj in removals] 60 args += inputs 61 Shell(*args) 62 63 64 USAGE = '''usage: %prog [options] <lib or obj>+ 65 66 Combines input libraries or objects into an output library, while removing 67 any object file (in the input libraries) that matches a given regular 68 expression. 69 ''' 70 71 def GetOptionParser(): 72 parser = optparse.OptionParser(USAGE) 73 parser.add_option('-o', '--output', dest = 'output', 74 help = 'write to this output library') 75 parser.add_option('-r', '--remove', dest = 'remove', 76 help = 'object files matching this regexp will be removed ' 77 'from the output library') 78 return parser 79 80 81 def Main(): 82 '''Main function for this script''' 83 parser = GetOptionParser() 84 (opt, args) = parser.parse_args() 85 output = opt.output 86 remove = opt.remove 87 if not output: 88 parser.error('You must specify an output file') 89 90 if not args: 91 parser.error('You must specify at least one object or library') 92 93 output = output.strip() 94 remove = remove.strip() 95 96 if remove: 97 try: 98 remove_re = re.compile(opt.remove) 99 except: 100 parser.error('%s is not a valid regular expression' % opt.remove) 101 else: 102 remove_re = None 103 104 if sys.platform != 'win32' and sys.platform != 'cygwin': 105 parser.error('this script only works on Windows for now') 106 107 # If this is set, we can't capture lib.exe's output. 108 if 'VS_UNICODE_OUTPUT' in os.environ: 109 del os.environ['VS_UNICODE_OUTPUT'] 110 111 CombineLibraries(output, remove_re, args) 112 return 0 113 114 115 if __name__ == '__main__': 116 sys.exit(Main()) 117