]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Makefiles/NmakeSubdirs.py
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(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
))
54 return p
.returncode
, stdout
56 class TaskUnit(object):
57 def __init__(self
, func
, args
, kwargs
):
62 def __eq__(self
, other
):
63 return id(self
).__eq
__(id(other
))
66 return self
.func(*self
.args
, **self
.kwargs
)
69 para
= list(self
.args
)
70 para
.extend("{0}={1}".format(k
, v
)for k
, v
in self
.kwargs
.items())
72 return "{0}({1})".format(self
.func
.__name
__, ",".join(para
))
74 class ThreadControl(object):
76 def __init__(self
, maxthread
):
77 self
._processNum
= maxthread
80 self
.pendingLock
= threading
.Lock()
81 self
.runningLock
= threading
.Lock()
83 self
.errorLock
= threading
.Lock()
84 self
.errorMsg
= "errorMsg"
86 def addTask(self
, func
, *args
, **kwargs
):
87 self
.pending
.append(TaskUnit(func
, args
, kwargs
))
89 def waitComplete(self
):
92 def startSchedule(self
):
93 self
._schedule
= threading
.Thread(target
=self
.Schedule
)
94 self
._schedule
.start()
97 for i
in range(self
._processNum
):
98 task
= threading
.Thread(target
=self
.startTask
)
100 self
.running
.append(task
)
102 self
.runningLock
.acquire(True)
103 for thread
in self
.running
:
105 self
.runningLock
.release()
107 while len(self
.running
) > 0:
110 print("subprocess not exit successfully")
117 self
.pendingLock
.acquire(True)
118 if len(self
.pending
) == 0:
119 self
.pendingLock
.release()
121 task
= self
.pending
.pop(0)
122 self
.pendingLock
.release()
125 except RuntimeError as e
:
127 self
.errorLock
.acquire(True)
129 self
.errorMsg
= str(e
)
131 self
.errorLock
.release()
134 self
.runningLock
.acquire(True)
135 self
.running
.remove(threading
.currentThread())
136 self
.runningLock
.release()
139 curdir
= os
.path
.abspath(os
.curdir
)
140 if len(args
.subdirs
) == 1:
144 for dir in args
.subdirs
:
145 RunCommand(os
.path
.join(curdir
, dir), "nmake", args
.target
, stdout
=sys
.stdout
, stderr
=subprocess
.STDOUT
)
149 controller
= ThreadControl(args
.jobs
)
150 for dir in args
.subdirs
:
151 controller
.addTask(RunCommand
, os
.path
.join(curdir
, dir), "nmake", args
.target
)
152 controller
.startSchedule()
153 controller
.waitComplete()
157 if __name__
== "__main__":
158 parser
= argparse
.ArgumentParser(prog
=__prog__
, description
=__description__
+ __copyright__
, conflict_handler
='resolve')
160 parser
.add_argument("target", help="the target for nmake")
161 parser
.add_argument("subdirs", nargs
="+", help="the relative dir path of makefile")
162 parser
.add_argument("--jobs", type=int, dest
="jobs", default
=cpu_count
, help="thread number")
163 parser
.add_argument('--version', action
='version', version
=__version__
)
164 args
= parser
.parse_args()