forked from kovidgoyal/calibre
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparallel_build.py
97 lines (83 loc) · 2.93 KB
/
parallel_build.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env python2
# vim:fileencoding=utf-8
from __future__ import absolute_import, division, print_function, unicode_literals
__license__ = 'GPL v3'
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
import subprocess, os
from multiprocessing.dummy import Pool
from functools import partial
from contextlib import closing
from setup import iswindows
from polyglot.builtins import unicode_type
if iswindows:
from ctypes import windll, Structure, POINTER, c_size_t
from ctypes.wintypes import WORD, DWORD, LPVOID
class SYSTEM_INFO(Structure):
_fields_ = [
("wProcessorArchitecture", WORD),
("wReserved", WORD),
("dwPageSize", DWORD),
("lpMinimumApplicationAddress", LPVOID),
("lpMaximumApplicationAddress", LPVOID),
("dwActiveProcessorMask", c_size_t),
("dwNumberOfProcessors", DWORD),
("dwProcessorType", DWORD),
("dwAllocationGranularity", DWORD),
("wProcessorLevel", WORD),
("wProcessorRevision", WORD)]
gsi = windll.kernel32.GetSystemInfo
gsi.argtypes = [POINTER(SYSTEM_INFO)]
gsi.restype = None
si = SYSTEM_INFO()
gsi(si)
cpu_count = si.dwNumberOfProcessors
else:
from multiprocessing import cpu_count
try:
cpu_count = cpu_count()
except NotImplementedError:
cpu_count = 1
cpu_count = min(16, max(1, cpu_count))
def run_worker(job, decorate=True):
cmd, human_text = job
human_text = human_text or ' '.join(cmd)
cwd = None
if cmd[0].lower().endswith('cl.exe'):
cwd = os.environ.get('COMPILER_CWD')
try:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=cwd)
except Exception as err:
return False, human_text, unicode_type(err)
stdout, stderr = p.communicate()
if stdout:
stdout = stdout.decode('utf-8')
if stderr:
stderr = stderr.decode('utf-8')
if decorate:
stdout = human_text + '\n' + (stdout or '')
ok = p.returncode == 0
return ok, stdout, (stderr or '')
def create_job(cmd, human_text=None):
return (cmd, human_text)
def parallel_build(jobs, log, verbose=True):
p = Pool(cpu_count)
with closing(p):
for ok, stdout, stderr in p.imap(run_worker, jobs):
if verbose or not ok:
log(stdout)
if stderr:
log(stderr)
if not ok:
return False
return True
def parallel_check_output(jobs, log):
p = Pool(cpu_count)
with closing(p):
for ok, stdout, stderr in p.imap(
partial(run_worker, decorate=False), ((j, '') for j in jobs)):
if not ok:
log(stdout)
if stderr:
log(stderr)
raise SystemExit(1)
yield stdout