]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Makefiles/NmakeSubdirs.py
356f5aca638eebf1366fb9279da478d053b48daa
1 # @file NmakeSubdirs.py
2 # This script support parallel build for nmake in windows environment.
3 # It supports Python2.x and Python3.x both.
5 # Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
7 # SPDX-License-Identifier: BSD-2-Clause-Patent
14 from __future__
import print_function
20 import multiprocessing
23 __prog__
= 'NmakeSubdirs'
24 __version__
= '%s Version %s' % (__prog__
, '0.10 ')
25 __copyright__
= 'Copyright (c) 2018, Intel Corporation. All rights reserved.'
26 __description__
= 'Replace for NmakeSubdirs.bat in windows ,support parallel build for nmake.\n'
28 cpu_count
= multiprocessing
.cpu_count()
29 output_lock
= threading
.Lock()
30 def RunCommand(WorkDir
=None, *Args
, **kwargs
):
33 if "stderr" not in kwargs
:
34 kwargs
["stderr"] = subprocess
.STDOUT
35 if "stdout" not in kwargs
:
36 kwargs
["stdout"] = subprocess
.PIPE
37 p
= subprocess
.Popen(Args
, cwd
=WorkDir
, stderr
=kwargs
["stderr"], stdout
=kwargs
["stdout"])
38 stdout
, stderr
= p
.communicate()
40 if stdout
is not None:
41 message
= stdout
.decode(encoding
='utf-8', errors
='ignore') #for compatibility in python 2 and 3
44 raise RuntimeError("Error while execute command \'{0}\' in direcotry {1}\n{2}".format(" ".join(Args
), WorkDir
, message
))
46 output_lock
.acquire(True)
47 print("execute command \"{0}\" in directory {1}".format(" ".join(Args
), WorkDir
))
51 return p
.returncode
, stdout
53 class TaskUnit(object):
54 def __init__(self
, func
, args
, kwargs
):
59 def __eq__(self
, other
):
60 return id(self
).__eq
__(id(other
))
63 return self
.func(*self
.args
, **self
.kwargs
)
66 para
= list(self
.args
)
67 para
.extend("{0}={1}".format(k
, v
)for k
, v
in self
.kwargs
.items())
69 return "{0}({1})".format(self
.func
.__name
__, ",".join(para
))
71 class ThreadControl(object):
73 def __init__(self
, maxthread
):
74 self
._processNum
= maxthread
77 self
.pendingLock
= threading
.Lock()
78 self
.runningLock
= threading
.Lock()
80 self
.errorLock
= threading
.Lock()
81 self
.errorMsg
= "errorMsg"
83 def addTask(self
, func
, *args
, **kwargs
):
84 self
.pending
.append(TaskUnit(func
, args
, kwargs
))
86 def waitComplete(self
):
89 def startSchedule(self
):
90 self
._schedule
= threading
.Thread(target
=self
.Schedule
)
91 self
._schedule
.start()
94 for i
in range(self
._processNum
):
95 task
= threading
.Thread(target
=self
.startTask
)
97 self
.running
.append(task
)
99 self
.runningLock
.acquire(True)
100 for thread
in self
.running
:
102 self
.runningLock
.release()
104 while len(self
.running
) > 0:
107 print("subprocess not exit successfully")
114 self
.pendingLock
.acquire(True)
115 if len(self
.pending
) == 0:
116 self
.pendingLock
.release()
118 task
= self
.pending
.pop(0)
119 self
.pendingLock
.release()
122 except RuntimeError as e
:
124 self
.errorLock
.acquire(True)
126 self
.errorMsg
= str(e
)
128 self
.errorLock
.release()
131 self
.runningLock
.acquire(True)
132 self
.running
.remove(threading
.currentThread())
133 self
.runningLock
.release()
136 curdir
= os
.path
.abspath(os
.curdir
)
137 if len(args
.subdirs
) == 1:
141 for dir in args
.subdirs
:
142 RunCommand(os
.path
.join(curdir
, dir), "nmake", args
.target
, stdout
=sys
.stdout
, stderr
=subprocess
.STDOUT
)
146 controller
= ThreadControl(args
.jobs
)
147 for dir in args
.subdirs
:
148 controller
.addTask(RunCommand
, os
.path
.join(curdir
, dir), "nmake", args
.target
)
149 controller
.startSchedule()
150 controller
.waitComplete()
154 if __name__
== "__main__":
155 parser
= argparse
.ArgumentParser(prog
=__prog__
, description
=__description__
+ __copyright__
, conflict_handler
='resolve')
157 parser
.add_argument("target", help="the target for nmake")
158 parser
.add_argument("subdirs", nargs
="+", help="the relative dir path of makefile")
159 parser
.add_argument("--jobs", type=int, dest
="jobs", default
=cpu_count
, help="thread number")
160 parser
.add_argument('--version', action
='version', version
=__version__
)
161 args
= parser
.parse_args()