]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/Makefiles/NmakeSubdirs.py
edksetup.bat stuck on unicode locale Windows
[mirror_edk2.git] / BaseTools / Source / C / Makefiles / NmakeSubdirs.py
CommitLineData
4c0d19e5
DG
1# @file NmakeSubdirs.py\r
2# This script support parallel build for nmake in windows environment.\r
3# It supports Python2.x and Python3.x both.\r
4#\r
5# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
6#\r
2e351cbe 7# SPDX-License-Identifier: BSD-2-Clause-Patent\r
4c0d19e5
DG
8#\r
9\r
10#\r
11# Import Modules\r
12#\r
13\r
14from __future__ import print_function\r
15import argparse\r
16import threading\r
17import time\r
18import os\r
19import subprocess\r
20import multiprocessing\r
21import copy\r
22import sys\r
23__prog__ = 'NmakeSubdirs'\r
24__version__ = '%s Version %s' % (__prog__, '0.10 ')\r
25__copyright__ = 'Copyright (c) 2018, Intel Corporation. All rights reserved.'\r
26__description__ = 'Replace for NmakeSubdirs.bat in windows ,support parallel build for nmake.\n'\r
27\r
28cpu_count = multiprocessing.cpu_count()\r
29output_lock = threading.Lock()\r
30def RunCommand(WorkDir=None, *Args, **kwargs):\r
31 if WorkDir is None:\r
32 WorkDir = os.curdir\r
33 if "stderr" not in kwargs:\r
34 kwargs["stderr"] = subprocess.STDOUT\r
35 if "stdout" not in kwargs:\r
36 kwargs["stdout"] = subprocess.PIPE\r
37 p = subprocess.Popen(Args, cwd=WorkDir, stderr=kwargs["stderr"], stdout=kwargs["stdout"])\r
38 stdout, stderr = p.communicate()\r
39 message = ""\r
40 if stdout is not None:\r
caa91749 41 message = stdout.decode(errors='ignore') #for compatibility in python 2 and 3\r
4c0d19e5
DG
42\r
43 if p.returncode != 0:\r
44 raise RuntimeError("Error while execute command \'{0}\' in direcotry {1}\n{2}".format(" ".join(Args), WorkDir, message))\r
45\r
46 output_lock.acquire(True)\r
47 print("execute command \"{0}\" in directory {1}".format(" ".join(Args), WorkDir))\r
48 print(message)\r
49 output_lock.release()\r
50\r
51 return p.returncode, stdout\r
52\r
53class TaskUnit(object):\r
54 def __init__(self, func, args, kwargs):\r
55 self.func = func\r
56 self.args = args\r
57 self.kwargs = kwargs\r
58\r
59 def __eq__(self, other):\r
60 return id(self).__eq__(id(other))\r
61\r
62 def run(self):\r
63 return self.func(*self.args, **self.kwargs)\r
64\r
65 def __str__(self):\r
66 para = list(self.args)\r
67 para.extend("{0}={1}".format(k, v)for k, v in self.kwargs.items())\r
68\r
69 return "{0}({1})".format(self.func.__name__, ",".join(para))\r
70\r
71class ThreadControl(object):\r
72\r
73 def __init__(self, maxthread):\r
74 self._processNum = maxthread\r
75 self.pending = []\r
76 self.running = []\r
77 self.pendingLock = threading.Lock()\r
78 self.runningLock = threading.Lock()\r
79 self.error = False\r
80 self.errorLock = threading.Lock()\r
81 self.errorMsg = "errorMsg"\r
82\r
83 def addTask(self, func, *args, **kwargs):\r
84 self.pending.append(TaskUnit(func, args, kwargs))\r
85\r
86 def waitComplete(self):\r
87 self._schedule.join()\r
88\r
89 def startSchedule(self):\r
90 self._schedule = threading.Thread(target=self.Schedule)\r
91 self._schedule.start()\r
92\r
93 def Schedule(self):\r
94 for i in range(self._processNum):\r
95 task = threading.Thread(target=self.startTask)\r
96 task.daemon = False\r
97 self.running.append(task)\r
98\r
99 self.runningLock.acquire(True)\r
100 for thread in self.running:\r
101 thread.start()\r
102 self.runningLock.release()\r
103\r
104 while len(self.running) > 0:\r
105 time.sleep(0.1)\r
106 if self.error:\r
2d53d54a 107 print("subprocess not exit successfully")\r
4c0d19e5
DG
108 print(self.errorMsg)\r
109\r
110 def startTask(self):\r
111 while True:\r
112 if self.error:\r
113 break\r
114 self.pendingLock.acquire(True)\r
115 if len(self.pending) == 0:\r
116 self.pendingLock.release()\r
117 break\r
118 task = self.pending.pop(0)\r
119 self.pendingLock.release()\r
120 try:\r
121 task.run()\r
122 except RuntimeError as e:\r
123 if self.error: break\r
124 self.errorLock.acquire(True)\r
125 self.error = True\r
126 self.errorMsg = str(e)\r
127 time.sleep(0.1)\r
128 self.errorLock.release()\r
129 break\r
130\r
131 self.runningLock.acquire(True)\r
132 self.running.remove(threading.currentThread())\r
133 self.runningLock.release()\r
134\r
135def Run():\r
136 curdir = os.path.abspath(os.curdir)\r
137 if len(args.subdirs) == 1:\r
138 args.jobs = 1\r
139 if args.jobs == 1:\r
140 try:\r
141 for dir in args.subdirs:\r
142 RunCommand(os.path.join(curdir, dir), "nmake", args.target, stdout=sys.stdout, stderr=subprocess.STDOUT)\r
143 except RuntimeError:\r
144 exit(1)\r
145 else:\r
146 controller = ThreadControl(args.jobs)\r
147 for dir in args.subdirs:\r
148 controller.addTask(RunCommand, os.path.join(curdir, dir), "nmake", args.target)\r
149 controller.startSchedule()\r
150 controller.waitComplete()\r
151 if controller.error:\r
152 exit(1)\r
153\r
154if __name__ == "__main__":\r
155 parser = argparse.ArgumentParser(prog=__prog__, description=__description__ + __copyright__, conflict_handler='resolve')\r
156\r
157 parser.add_argument("target", help="the target for nmake")\r
158 parser.add_argument("subdirs", nargs="+", help="the relative dir path of makefile")\r
159 parser.add_argument("--jobs", type=int, dest="jobs", default=cpu_count, help="thread number")\r
160 parser.add_argument('--version', action='version', version=__version__)\r
161 args = parser.parse_args()\r
162 Run()\r
163\r