## @file\r
# Windows makefile for C tools build.\r
#\r
-# Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
# This program and the accompanying materials\r
# are licensed and made available under the terms and conditions of the BSD License\r
# which accompanies this distribution. The full text of the license may be found at\r
\r
LIBRARIES = Common\r
APPLICATIONS = \\r
- BootSectImage \\r
+ VfrCompile \\r
BrotliCompress \\r
EfiLdrImage \\r
EfiRom \\r
Split \\r
TianoCompress \\r
VolInfo \\r
- VfrCompile \\r
+ BootSectImage \\r
DevicePath\r
\r
all: libs apps install\r
@echo # Build libraries\r
@echo ######################\r
@if not exist $(LIB_PATH) mkdir $(LIB_PATH)\r
- @Makefiles\NmakeSubdirs.bat all $**\r
+ @$(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py all $**\r
\r
apps: $(APPLICATIONS)\r
@echo.\r
@echo # Build executables\r
@echo ######################\r
@if not exist $(BIN_PATH) mkdir $(BIN_PATH)\r
- @Makefiles\NmakeSubdirs.bat all $**\r
+ @$(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py all $**\r
\r
install: $(LIB_PATH) $(BIN_PATH)\r
@echo.\r
\r
.PHONY: clean\r
clean:\r
- @Makefiles\NmakeSubdirs.bat clean $(LIBRARIES) $(APPLICATIONS)\r
+ @$(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py clean $(LIBRARIES) $(APPLICATIONS)\r
\r
.PHONY: cleanall\r
cleanall:\r
- @Makefiles\NmakeSubdirs.bat cleanall $(LIBRARIES) $(APPLICATIONS)\r
+ @$(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py cleanall $(LIBRARIES) $(APPLICATIONS)\r
\r
!INCLUDE Makefiles\ms.rule\r
\r
--- /dev/null
+# @file NmakeSubdirs.py\r
+# This script support parallel build for nmake in windows environment.\r
+# It supports Python2.x and Python3.x both.\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+#\r
+# Import Modules\r
+#\r
+\r
+from __future__ import print_function\r
+import argparse\r
+import threading\r
+import time\r
+import os\r
+import subprocess\r
+import multiprocessing\r
+import copy\r
+import sys\r
+__prog__ = 'NmakeSubdirs'\r
+__version__ = '%s Version %s' % (__prog__, '0.10 ')\r
+__copyright__ = 'Copyright (c) 2018, Intel Corporation. All rights reserved.'\r
+__description__ = 'Replace for NmakeSubdirs.bat in windows ,support parallel build for nmake.\n'\r
+\r
+cpu_count = multiprocessing.cpu_count()\r
+output_lock = threading.Lock()\r
+def RunCommand(WorkDir=None, *Args, **kwargs):\r
+ if WorkDir is None:\r
+ WorkDir = os.curdir\r
+ if "stderr" not in kwargs:\r
+ kwargs["stderr"] = subprocess.STDOUT\r
+ if "stdout" not in kwargs:\r
+ kwargs["stdout"] = subprocess.PIPE\r
+ p = subprocess.Popen(Args, cwd=WorkDir, stderr=kwargs["stderr"], stdout=kwargs["stdout"])\r
+ stdout, stderr = p.communicate()\r
+ message = ""\r
+ if stdout is not None:\r
+ message = stdout.decode() #for compatibility in python 2 and 3\r
+\r
+ if p.returncode != 0:\r
+ raise RuntimeError("Error while execute command \'{0}\' in direcotry {1}\n{2}".format(" ".join(Args), WorkDir, message))\r
+\r
+ output_lock.acquire(True)\r
+ print("execute command \"{0}\" in directory {1}".format(" ".join(Args), WorkDir))\r
+ print(message)\r
+ output_lock.release()\r
+\r
+ return p.returncode, stdout\r
+\r
+class TaskUnit(object):\r
+ def __init__(self, func, args, kwargs):\r
+ self.func = func\r
+ self.args = args\r
+ self.kwargs = kwargs\r
+\r
+ def __eq__(self, other):\r
+ return id(self).__eq__(id(other))\r
+\r
+ def run(self):\r
+ return self.func(*self.args, **self.kwargs)\r
+\r
+ def __str__(self):\r
+ para = list(self.args)\r
+ para.extend("{0}={1}".format(k, v)for k, v in self.kwargs.items())\r
+\r
+ return "{0}({1})".format(self.func.__name__, ",".join(para))\r
+\r
+class ThreadControl(object):\r
+\r
+ def __init__(self, maxthread):\r
+ self._processNum = maxthread\r
+ self.pending = []\r
+ self.running = []\r
+ self.pendingLock = threading.Lock()\r
+ self.runningLock = threading.Lock()\r
+ self.error = False\r
+ self.errorLock = threading.Lock()\r
+ self.errorMsg = "errorMsg"\r
+\r
+ def addTask(self, func, *args, **kwargs):\r
+ self.pending.append(TaskUnit(func, args, kwargs))\r
+\r
+ def waitComplete(self):\r
+ self._schedule.join()\r
+\r
+ def startSchedule(self):\r
+ self._schedule = threading.Thread(target=self.Schedule)\r
+ self._schedule.start()\r
+\r
+ def Schedule(self):\r
+ for i in range(self._processNum):\r
+ task = threading.Thread(target=self.startTask)\r
+ task.daemon = False\r
+ self.running.append(task)\r
+\r
+ self.runningLock.acquire(True)\r
+ for thread in self.running:\r
+ thread.start()\r
+ self.runningLock.release()\r
+\r
+ while len(self.running) > 0:\r
+ time.sleep(0.1)\r
+ if self.error:\r
+ print("subprocess not exit sucessfully")\r
+ print(self.errorMsg)\r
+\r
+ def startTask(self):\r
+ while True:\r
+ if self.error:\r
+ break\r
+ self.pendingLock.acquire(True)\r
+ if len(self.pending) == 0:\r
+ self.pendingLock.release()\r
+ break\r
+ task = self.pending.pop(0)\r
+ self.pendingLock.release()\r
+ try:\r
+ task.run()\r
+ except RuntimeError as e:\r
+ if self.error: break\r
+ self.errorLock.acquire(True)\r
+ self.error = True\r
+ self.errorMsg = str(e)\r
+ time.sleep(0.1)\r
+ self.errorLock.release()\r
+ break\r
+\r
+ self.runningLock.acquire(True)\r
+ self.running.remove(threading.currentThread())\r
+ self.runningLock.release()\r
+\r
+def Run():\r
+ curdir = os.path.abspath(os.curdir)\r
+ if len(args.subdirs) == 1:\r
+ args.jobs = 1\r
+ if args.jobs == 1:\r
+ try:\r
+ for dir in args.subdirs:\r
+ RunCommand(os.path.join(curdir, dir), "nmake", args.target, stdout=sys.stdout, stderr=subprocess.STDOUT)\r
+ except RuntimeError:\r
+ exit(1)\r
+ else:\r
+ controller = ThreadControl(args.jobs)\r
+ for dir in args.subdirs:\r
+ controller.addTask(RunCommand, os.path.join(curdir, dir), "nmake", args.target)\r
+ controller.startSchedule()\r
+ controller.waitComplete()\r
+ if controller.error:\r
+ exit(1)\r
+\r
+if __name__ == "__main__":\r
+ parser = argparse.ArgumentParser(prog=__prog__, description=__description__ + __copyright__, conflict_handler='resolve')\r
+\r
+ parser.add_argument("target", help="the target for nmake")\r
+ parser.add_argument("subdirs", nargs="+", help="the relative dir path of makefile")\r
+ parser.add_argument("--jobs", type=int, dest="jobs", default=cpu_count, help="thread number")\r
+ parser.add_argument('--version', action='version', version=__version__)\r
+ args = parser.parse_args()\r
+ Run()\r
+\r