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