]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Makefiles/NmakeSubdirs.py
abcbea89a46c91a720282579b74624bd6561c9a8
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 # This program and the accompanying materials
8 # are licensed and made available under the terms and conditions of the BSD License
9 # which accompanies this distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 from __future__
import print_function
26 import multiprocessing
29 __prog__
= 'NmakeSubdirs'
30 __version__
= '%s Version %s' % (__prog__
, '0.10 ')
31 __copyright__
= 'Copyright (c) 2018, Intel Corporation. All rights reserved.'
32 __description__
= 'Replace for NmakeSubdirs.bat in windows ,support parallel build for nmake.\n'
34 cpu_count
= multiprocessing
.cpu_count()
35 output_lock
= threading
.Lock()
36 def RunCommand(WorkDir
=None, *Args
, **kwargs
):
39 if "stderr" not in kwargs
:
40 kwargs
["stderr"] = subprocess
.STDOUT
41 if "stdout" not in kwargs
:
42 kwargs
["stdout"] = subprocess
.PIPE
43 p
= subprocess
.Popen(Args
, cwd
=WorkDir
, stderr
=kwargs
["stderr"], stdout
=kwargs
["stdout"])
44 stdout
, stderr
= p
.communicate()
46 if stdout
is not None:
47 message
= stdout
.decode(encoding
='utf-8', errors
='ignore') #for compatibility in python 2 and 3
50 raise RuntimeError("Error while execute command \'{0}\' in direcotry {1}\n{2}".format(" ".join(Args
), WorkDir
, message
))
52 output_lock
.acquire(True)
53 print("execute command \"{0}\" in directory {1}".format(" ".join(Args
), WorkDir
))
57 return p
.returncode
, stdout
59 class TaskUnit(object):
60 def __init__(self
, func
, args
, kwargs
):
65 def __eq__(self
, other
):
66 return id(self
).__eq
__(id(other
))
69 return self
.func(*self
.args
, **self
.kwargs
)
72 para
= list(self
.args
)
73 para
.extend("{0}={1}".format(k
, v
)for k
, v
in self
.kwargs
.items())
75 return "{0}({1})".format(self
.func
.__name
__, ",".join(para
))
77 class ThreadControl(object):
79 def __init__(self
, maxthread
):
80 self
._processNum
= maxthread
83 self
.pendingLock
= threading
.Lock()
84 self
.runningLock
= threading
.Lock()
86 self
.errorLock
= threading
.Lock()
87 self
.errorMsg
= "errorMsg"
89 def addTask(self
, func
, *args
, **kwargs
):
90 self
.pending
.append(TaskUnit(func
, args
, kwargs
))
92 def waitComplete(self
):
95 def startSchedule(self
):
96 self
._schedule
= threading
.Thread(target
=self
.Schedule
)
97 self
._schedule
.start()
100 for i
in range(self
._processNum
):
101 task
= threading
.Thread(target
=self
.startTask
)
103 self
.running
.append(task
)
105 self
.runningLock
.acquire(True)
106 for thread
in self
.running
:
108 self
.runningLock
.release()
110 while len(self
.running
) > 0:
113 print("subprocess not exit sucessfully")
120 self
.pendingLock
.acquire(True)
121 if len(self
.pending
) == 0:
122 self
.pendingLock
.release()
124 task
= self
.pending
.pop(0)
125 self
.pendingLock
.release()
128 except RuntimeError as e
:
130 self
.errorLock
.acquire(True)
132 self
.errorMsg
= str(e
)
134 self
.errorLock
.release()
137 self
.runningLock
.acquire(True)
138 self
.running
.remove(threading
.currentThread())
139 self
.runningLock
.release()
142 curdir
= os
.path
.abspath(os
.curdir
)
143 if len(args
.subdirs
) == 1:
147 for dir in args
.subdirs
:
148 RunCommand(os
.path
.join(curdir
, dir), "nmake", args
.target
, stdout
=sys
.stdout
, stderr
=subprocess
.STDOUT
)
152 controller
= ThreadControl(args
.jobs
)
153 for dir in args
.subdirs
:
154 controller
.addTask(RunCommand
, os
.path
.join(curdir
, dir), "nmake", args
.target
)
155 controller
.startSchedule()
156 controller
.waitComplete()
160 if __name__
== "__main__":
161 parser
= argparse
.ArgumentParser(prog
=__prog__
, description
=__description__
+ __copyright__
, conflict_handler
='resolve')
163 parser
.add_argument("target", help="the target for nmake")
164 parser
.add_argument("subdirs", nargs
="+", help="the relative dir path of makefile")
165 parser
.add_argument("--jobs", type=int, dest
="jobs", default
=cpu_count
, help="thread number")
166 parser
.add_argument('--version', action
='version', version
=__version__
)
167 args
= parser
.parse_args()