Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(512)

Side by Side Diff: visual_studio/NativeClientVSAddIn/InstallerResources/NaCl/compiler_wrapper.py

Issue 11044024: Implement multi-core builds in MSVS (Closed) Base URL: http://nativeclient-sdk.googlecode.com/svn/trunk/src
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 stop_on_error = False
22
23
24 def RunGCC(cmd, basename):
25 """Run gcc and return the result along will the stdout/stderr."""
26 cmdstring = subprocess.list2cmdline(cmd)
27 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
28 stdout, stderr = p.communicate()
29 p.wait()
30 if show_commands:
31 logmsg = cmdstring
32 else:
33 logmsg = basename
34 stderr = logmsg + '\n' + stderr
35 return (p.returncode, stdout, stderr)
36
37
38 def BuildSerial(base_cmd, outpath, files):
39 final_result = 0
40
41 for filename in files:
42 cmd, basename = MakeCommand(base_cmd, outpath, filename)
43 rtn, stdout, stderr = RunGCC(cmd, basename)
44 sys.stdout.write(stdout)
45 sys.stdout.flush()
46 sys.stderr.write(stderr)
47 sys.stderr.flush()
48 if rtn:
49 final_result = rtn
50 if stop_on_error:
51 break
52
53 return final_result
54
55
56 def Worker(queue, out_queue):
57 """Entry point got worker threads.
58
59 Each thread will compiler jobs from the queue until
60 there are no jobs left or until the main thread signals
61 for the work to stop.
62 """
63 while not queue.empty() and Worker.running:
64 item = queue.get(False)
65 if not item:
66 break
67 results = RunGCC(item[0], item[1])
68 out_queue.put(results)
69
70
71 def MakeCommand(base_cmd, outpath, filename):
72 """Build the full commandline given that output root
73 and the intput filename.
74
75 If VS passes an existing directory to -o, then we derive the
76 actual object name by combining he directory name with the
77 basename of the source file and andding ".obj"
78 """
79 basename = os.path.basename(filename)
80 out = os.path.join(outpath, os.path.splitext(basename)[0] + '.obj')
81 return (base_cmd + ['-c', filename, '-o', out], basename)
82
83
84 def BuildParallel(cores, base_cmd, outpath, files):
85 Worker.running = True
86 pool = []
87 job_queue = Queue.Queue()
88 out_queue = Queue.Queue()
89
90 for filename in files:
91 cmd, basename = MakeCommand(base_cmd, outpath, filename)
92 job_queue.put((cmd, basename))
93
94 # Create worker thread pool, passing job queue
95 # and output queue to each worker.
96 args = (job_queue, out_queue)
97 for i in xrange(cores):
98 t = threading.Thread(target=Worker, args=args)
99 t.start()
100
101 results = 0
102 Trace("waiting for %d results" % len(files))
103 final_result = 0
104 while results < len(files):
105 results += 1
106 rtn, stdout, stderr = out_queue.get()
107 # stdout seem to be completely ignored by visual studio
108 # but GCC should output all useful information on stderr
109 # anyway.
110 sys.stdout.write(stdout)
111 sys.stdout.flush()
112 sys.stderr.write(stderr)
113 sys.stderr.flush()
114 if rtn:
115 final_result = rtn
116 if stop_on_error:
117 # stop all workers
118 Worker.running = False
119 break
120
121 return final_result
122
123
124 def Log(msg):
125 """Log message to stderr."""
126 # Since Visual Studio basically seems to completely ignore the stdout
127 # of the compiler and only echo stderr we print everythign to stderr.
128 sys.stderr.write(str(msg) + '\n')
129 sys.stderr.flush()
130
131
132 def Trace(msg):
133 if verbose:
134 Log("nacl_compiler:" + str(msg))
135
136
137 def main(args):
138 if args[0][0] == '@':
139 rspfile = args[0][1:]
140 args = shlex.split(open(rspfile).read())
141
142 # find the last occurrence of '--' in the argument
143 # list and use that to signify the start of the
144 # list of sources
145 index = list(reversed(args)).index('--')
146 index = len(args) - index
147 base_cmd = args[:index-1]
148 files = args[index:]
149
150 # remove -o <path> from base_cmd
151 index = base_cmd.index('-o')
152 outpath = base_cmd[index+1]
153 del base_cmd[index+1]
154 del base_cmd[index]
155
156 cores = int(os.environ.get('NACL_GCC_CORES', '0'))
157 if not cores:
158 cores = multiprocessing.cpu_count()
159 cores = min(cores, len(files))
160
161 Trace("compiling %d sources using %d threads" % (len(files), cores))
162 rtn = BuildParallel(cores, base_cmd, outpath, files)
163 Trace("returning %d" % rtn)
164 return rtn
165
166
167 if __name__ == '__main__':
168 sys.exit(main(sys.argv[1:]))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698