Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2012 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 """Python wrapper around gcc to make it behave a little | |
| 7 more like cl.exe WRT to parallel building. | |
| 8 """ | |
| 9 | |
| 10 import multiprocessing | |
| 11 import os | |
| 12 import Queue | |
| 13 import shlex | |
| 14 import subprocess | |
| 15 import sys | |
| 16 import threading | |
| 17 import time | |
| 18 | |
| 19 verbose = int(os.environ.get('NACL_GCC_VERBOSE', '0')) | |
| 20 show_commands = int(os.environ.get('NACL_GCC_SHOW_COMMANDS', '0')) | |
| 21 cores = int(os.environ.get('NACL_GCC_CORES', '0')) | |
| 22 stop_on_error = False | |
| 23 | |
| 24 def RunGCC(cmd, basename): | |
| 25 cmdstring = subprocess.list2cmdline(cmd) | |
| 26 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
| 27 stdout, stderr = p.communicate() | |
| 28 p.wait() | |
| 29 if show_commands: | |
| 30 logmsg = cmdstring | |
| 31 else: | |
| 32 logmsg = basename | |
| 33 stdout = logmsg + '\n' + stdout | |
| 34 return (p.returncode, stdout, stderr) | |
| 35 | |
| 36 | |
| 37 def BuildSerial(base_cmd, outpath, files): | |
| 38 final_result = 0 | |
| 39 | |
| 40 for filename in files: | |
| 41 cmd, basename = MakeCommand(base_cmd, outpath, filename) | |
| 42 rtn, stdout, stderr = RunGCC(cmd, basename) | |
| 43 sys.stderr.write(stdout) | |
| 44 sys.stderr.write(stderr) | |
| 45 if rtn: | |
| 46 final_result = rtn | |
| 47 if stop_on_error: | |
| 48 break | |
| 49 | |
| 50 return final_result | |
| 51 | |
| 52 | |
| 53 | |
| 54 | |
| 55 def Worker(queue, out_queue): | |
| 56 while not queue.empty() and Worker.running: | |
| 57 item = queue.get(False) | |
| 58 if not item: | |
| 59 break | |
| 60 results = RunGCC(item[0], item[1]) | |
| 61 out_queue.put(results) | |
| 62 | |
| 63 | |
| 64 def MakeCommand(base_cmd, outpath, filename): | |
| 65 basename = os.path.basename(filename) | |
| 66 out = os.path.join(outpath, os.path.splitext(basename)[0] + '.obj') | |
| 67 return (base_cmd + ['-c', filename, '-o', out], basename) | |
| 68 | |
| 69 | |
| 70 def BuildParallel(base_cmd, outpath, files): | |
| 71 Worker.running = True | |
| 72 pool = [] | |
| 73 job_queue = Queue.Queue() | |
| 74 out_queue = Queue.Queue() | |
| 75 | |
| 76 for filename in files: | |
| 77 cmd, basename = MakeCommand(base_cmd, outpath, filename) | |
| 78 job_queue.put((cmd, basename)) | |
| 79 | |
| 80 # Create worker thread pool, passing job queue | |
| 81 # and output queue to each worker. | |
| 82 args = (job_queue, out_queue) | |
| 83 for i in xrange(cores): | |
| 84 t = threading.Thread(target=Worker, args=args) | |
| 85 t.start() | |
| 86 | |
| 87 results = 0 | |
| 88 Trace("waiting for %d results" % len(files)) | |
| 89 final_result = 0 | |
| 90 while results < len(files): | |
| 91 results += 1 | |
| 92 rtn, stdout, stderr = out_queue.get() | |
| 93 sys.stderr.write(stdout) | |
| 94 sys.stderr.write(stderr) | |
| 95 if rtn: | |
| 96 final_result = rtn | |
| 97 if stop_on_error: | |
| 98 # stop all workers | |
| 99 Worker.running = False | |
| 100 break | |
| 101 | |
| 102 return final_result | |
| 103 | |
| 104 | |
| 105 def Log(msg): | |
| 106 sys.stderr.write(str(msg) + '\n') | |
| 107 sys.stderr.flush() | |
| 108 | |
| 109 | |
| 110 def Trace(msg): | |
| 111 if verbose: | |
| 112 Log(msg) | |
| 113 | |
| 114 | |
| 115 def main(args): | |
| 116 global cores | |
| 117 if args[0][0] == '@': | |
| 118 rspfile = args[0][1:] | |
| 119 args = shlex.split(open(rspfile).read()) | |
| 120 | |
| 121 # find the last occurrence of '--' in the argument | |
| 122 # list and use that to signify the start of the | |
| 123 # list of sources | |
| 124 index = list(reversed(args)).index('--') | |
| 125 index = len(args) - index | |
| 126 base_cmd = args[:index-1] | |
| 127 files = args[index:] | |
| 128 | |
| 129 # remove -o <path> from base_cmd | |
| 130 index = base_cmd.index('-o') | |
| 131 outpath = base_cmd[index+1] | |
| 132 del base_cmd[index+1] | |
| 133 del base_cmd[index] | |
| 134 | |
| 135 if not cores: | |
| 136 cores = multiprocessing.cpu_count() | |
| 137 | |
| 138 cores = min(cores, len(files)) | |
| 139 | |
| 140 Trace("compiling %d sources using %d threads" % (len(files), cores)) | |
| 141 | |
| 142 if cores == 1: | |
| 143 rtn = BuildSerial(base_cmd, outpath, files) | |
| 144 else: | |
| 145 rtn = BuildParallel(base_cmd, outpath, files) | |
| 146 | |
| 147 Trace("done build of %d sources" % (len(files))) | |
| 148 return rtn | |
| 149 | |
| 150 | |
| 151 if __name__ == '__main__': | |
| 152 main(sys.argv[1:]) | |
|
binji
2012/10/04 23:27:31
sys.exit(...) to send the errorcode (as long as yo
Sam Clegg
2012/10/05 21:11:19
Done.
| |
| OLD | NEW |