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

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
binji 2012/10/03 22:52:13 add license header
Sam Clegg 2012/10/04 22:57:57 Done.
2 import os
3 import Queue
4 import shlex
5 import subprocess
6 import sys
7 import threading
8 import multiprocessing
9 import time
binji 2012/10/03 22:52:13 sort imports alphabetically
Sam Clegg 2012/10/04 22:57:57 Done.
10
11 """Python wrapper around gcc to make it behave a little
12 more like cl.exe WRT to parallel building.
13 """
14
15 verbose = int(os.environ.get('NACL_GCC_VERBOSE', '0'))
16 show_commands = int(os.environ.get('NACL_GCC_SHOW_COMMANDS', '0'))
17 cores = int(os.environ.get('NACL_GCC_CORES', '0'))
18 stop_on_error = False
19
20 def RunGCC(cmd, basename):
21 cmdstring = subprocess.list2cmdline(cmd)
22 if show_commands:
binji 2012/10/03 22:52:13 nit: move down to use of logmsg
Sam Clegg 2012/10/04 22:57:57 Done.
23 logmsg = cmdstring
24 else:
25 logmsg = basename
26 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
27 stdout, stderr = p.communicate()
28 p.wait()
29 stdout = logmsg + '\n' + stdout
30 return (p.returncode, stdout, stderr)
31
32
33 def BuildSerial(base_cmd, outpath, files):
binji 2012/10/03 22:52:13 Is this necessary? Why not always use BuildParalle
Sam Clegg 2012/10/04 22:57:57 Just here for debugging. This code path is not us
binji 2012/10/04 23:27:31 Looks like it will still run if cores==1... but it
34 final_result = 0
35
36 for filename in files:
37 cmd, basename = MakeCommand(base_cmd, outpath, filename)
38 rtn, stdout, stderr = RunGCC(cmd, basename)
39 sys.stderr.write(stdout)
40 sys.stderr.write(stderr)
41 if rtn:
42 final_result = rtn
43 if stop_on_error:
44 break
45
46 return final_result
47
48
49 q = Queue.Queue()
binji 2012/10/03 22:52:13 IMO, it is nicer to make these local to BuildParal
Sam Clegg 2012/10/04 22:57:57 Done.
50 outq = Queue.Queue()
51
52
53 def Worker():
54 while not q.empty():
binji 2012/10/03 22:52:13 and Worker.running?
Sam Clegg 2012/10/04 22:57:57 Done.
55 item = q.get(False)
56 if not item:
57 break
58 results = RunGCC(item[0], item[1])
59 outq.put(results)
60
61
62 def MakeCommand(base_cmd, outpath, filename):
63 basename = os.path.basename(filename)
64 out = os.path.join(outpath, os.path.splitext(basename)[0] + '.obj')
binji 2012/10/03 22:52:13 use .o instead of .obj?
Sam Clegg 2012/10/04 22:57:57 Unfortunately we can't in this case as we need the
binji 2012/10/04 23:27:31 ok, comment would be nice. :)
65 return (base_cmd + ['-c', filename, '-o', out], basename)
66
67
68 def BuildParallel(base_cmd, outpath, files):
69 pool = []
70
71 for filename in files:
72 cmd, basename = MakeCommand(base_cmd, outpath, filename)
73 q.put((cmd, basename))
74
75 Worker.running = True
76 for i in xrange(cores):
77 t = threading.Thread(target=Worker)
78 t.start()
79
80 results = 0
81 Trace("waiting for %d results" % len(files))
82 final_result = 0
83 while results < len(files):
84 results += 1
85 rtn, stdout, stderr = outq.get()
86 sys.stderr.write(stdout)
binji 2012/10/03 22:52:13 why write stdout from compiler to stderr?
Sam Clegg 2012/10/04 22:57:57 Good question. Visual studio doesn't display stdo
binji 2012/10/04 23:27:31 OK, might add a comment then.
Sam Clegg 2012/10/05 21:11:19 Done.
87 sys.stderr.write(stderr)
88 if rtn:
89 final_result = rtn
90 if stop_on_error:
91 # stop all workers
92 Worker.running = False
93 break
94
95 return final_result
96
97
98 def Log(msg):
99 sys.stderr.write(str(msg) + '\n')
100 sys.stderr.flush()
101
102
103 def Trace(msg):
104 if verbose:
105 Log(msg)
106
107
108 def main(args):
109 global cores
110 if args[0][0] == '@':
111 rspfile = args[0][1:]
112 args = shlex.split(open(rspfile).read())
113
114 # find the last occurance of '--' in the argument
binji 2012/10/03 22:52:13 nit: s/occurance/occurrence/
Sam Clegg 2012/10/04 22:57:57 Done.
115 # list an use that to signify the start of the
binji 2012/10/03 22:52:13 s/an/and/
Sam Clegg 2012/10/04 22:57:57 Done.
116 # list of sources
117 index = list(reversed(args)).index('--')
118 index = len(args) - index
119 base_cmd = args[:index-1]
120 files = args[index:]
121
122 # remove -o <path> from base_cmd
123 index = base_cmd.index('-o')
124 outpath = base_cmd[index+1]
125 del base_cmd[index+1]
126 del base_cmd[index]
127
128 if not cores:
129 cores = multiprocessing.cpu_count()
130
131 cores = min(cores, len(files))
132
133 Trace("compiling %d sources using %d threads" % (len(files), cores))
134
135 if cores == 1:
136 rtn = BuildSerial(base_cmd, outpath, files)
137 else:
138 rtn = BuildParallel(base_cmd, outpath, files)
139
140 Trace("done build of %d sources" % (len(files)))
binji 2012/10/03 22:52:13 what about when the build fails?
Sam Clegg 2012/10/04 22:57:57 Well spotted. Amazingly (you are not going to bel
binji 2012/10/04 23:27:31 Haha, I actually meant the Trace is displaying tha
Sam Clegg 2012/10/05 21:11:19 Done.
141
142
143 if __name__ == '__main__':
144 main(sys.argv[1:])
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698