Jaben:
  NmakeSubdirs.bat will be removed once NmakeSubdirs.py is stable. Now, bat is 
kept for a while.

Thanks
Liming
> -----Original Message-----
> From: Carsey, Jaben
> Sent: Wednesday, August 29, 2018 12:10 AM
> To: Gao, Liming <liming....@intel.com>
> Cc: edk2-devel@lists.01.org; Guo, Dongao <dongao....@intel.com>
> Subject: Re: [edk2] [Patch] BaseTools: Support multi thread build Basetool on 
> Windows
> 
> This looks like a great change.  Why not delete the bat file?
> 
> Reviewed-by Jaben Carsey: <jaben.caspr...@intel.com>
> 
> Jaben
> 
> > On Aug 28, 2018, at 8:28 AM, Liming Gao <liming....@intel.com> wrote:
> >
> > From: Dongao Guo <dongao....@intel.com>
> >
> > Add NmakeSubdirs.py to replace NmakeSubdirs.bat in VS Makefile. This script 
> > will
> > invoke nmake in multi thread mode. It can save more than half time of 
> > BaseTools
> > C clean build.
> > GCC make supports multiple thread in make phase. So, GNNmakefile doesn't 
> > need apply
> > this script.
> >
> > single task or job=1:
> >    just single thread and invoke subprocess,subprocess will use
> >    system.stdout to print output.
> > multi task:
> >    thread number is logic cpu count.All subprocess output will pass to
> >    python script by PIPE and then script print it to system.stdout.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Dongao Guo<dongao....@intel.com>
> > Reviewed-by: Liming Gao <liming....@intel.com>
> > Test-by: Liming Gao <liming....@intel.com>
> > ---
> > BaseTools/Makefile                           |  12 +-
> > BaseTools/Source/C/Makefile                  |  14 +--
> > BaseTools/Source/C/Makefiles/NmakeSubdirs.py | 169 
> > +++++++++++++++++++++++++++
> > 3 files changed, 182 insertions(+), 13 deletions(-)
> > create mode 100644 BaseTools/Source/C/Makefiles/NmakeSubdirs.py
> >
> > diff --git a/BaseTools/Makefile b/BaseTools/Makefile
> > index 3736d85..b98cd85 100644
> > --- a/BaseTools/Makefile
> > +++ b/BaseTools/Makefile
> > @@ -1,7 +1,7 @@
> > ## @file
> > # Windows makefile for Base Tools project build.
> > #
> > -# Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
> > +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
> > # This program and the accompanying materials
> > # are licensed and made available under the terms and conditions of the BSD 
> > License
> > # which accompanies this distribution.  The full text of the license may be 
> > found at
> > @@ -20,19 +20,19 @@ SUBDIRS = $(BASE_TOOLS_PATH)\Source\C 
> > $(BASE_TOOLS_PATH)\Source\Python
> > all: c python
> >
> > c :
> > -  @$(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.bat all 
> > $(BASE_TOOLS_PATH)\Source\C
> > +  @$(PYTHON_HOME)\python.exe 
> > $(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.py  all
> $(BASE_TOOLS_PATH)\Source\C
> >
> > python:
> > -  @$(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.bat all 
> > $(BASE_TOOLS_PATH)\Source\Python
> > +  @$(PYTHON_HOME)\python.exe 
> > $(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.py  all
> $(BASE_TOOLS_PATH)\Source\Python
> >
> > subdirs: $(SUBDIRS)
> > -  @$(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.bat all $**
> > +  @$(PYTHON_HOME)\python.exe 
> > $(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.py  all $**
> >
> > .PHONY: clean
> > clean:
> > -  @$(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.bat clean $(SUBDIRS)
> > +  $(PYTHON_HOME)\python.exe 
> > $(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.py clean $(SUBDIRS)
> >
> > .PHONY: cleanall
> > cleanall:
> > -  @$(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.bat cleanall 
> > $(SUBDIRS)
> > +  $(PYTHON_HOME)\python.exe 
> > $(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.py  cleanall $(SUBDIRS)
> >
> > diff --git a/BaseTools/Source/C/Makefile b/BaseTools/Source/C/Makefile
> > index 5428180..1246d23 100644
> > --- a/BaseTools/Source/C/Makefile
> > +++ b/BaseTools/Source/C/Makefile
> > @@ -1,7 +1,7 @@
> > ## @file
> > # Windows makefile for C tools build.
> > #
> > -# Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
> > +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
> > # This program and the accompanying materials
> > # are licensed and made available under the terms and conditions of the BSD 
> > License
> > # which accompanies this distribution.  The full text of the license may be 
> > found at
> > @@ -16,7 +16,7 @@ HOST_ARCH = IA32
> >
> > LIBRARIES = Common
> > APPLICATIONS = \
> > -  BootSectImage \
> > +  VfrCompile \
> >   BrotliCompress \
> >   EfiLdrImage \
> >   EfiRom \
> > @@ -32,7 +32,7 @@ APPLICATIONS = \
> >   Split \
> >   TianoCompress \
> >   VolInfo \
> > -  VfrCompile \
> > +  BootSectImage \
> >   DevicePath
> >
> > all: libs apps install
> > @@ -43,7 +43,7 @@ libs: $(LIBRARIES)
> >    @echo # Build libraries
> >    @echo ######################
> >    @if not exist $(LIB_PATH) mkdir $(LIB_PATH)
> > -    @Makefiles\NmakeSubdirs.bat all $**
> > +    @$(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py all $**
> >
> > apps: $(APPLICATIONS)
> >    @echo.
> > @@ -51,7 +51,7 @@ apps: $(APPLICATIONS)
> >    @echo # Build executables
> >    @echo ######################
> >    @if not exist $(BIN_PATH) mkdir $(BIN_PATH)
> > -    @Makefiles\NmakeSubdirs.bat all $**
> > +    @$(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py all $**
> >
> > install: $(LIB_PATH) $(BIN_PATH)
> >    @echo.
> > @@ -65,11 +65,11 @@ install: $(LIB_PATH) $(BIN_PATH)
> >
> > .PHONY: clean
> > clean:
> > -  @Makefiles\NmakeSubdirs.bat clean $(LIBRARIES) $(APPLICATIONS)
> > +  @$(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py clean $(LIBRARIES) 
> > $(APPLICATIONS)
> >
> > .PHONY: cleanall
> > cleanall:
> > -  @Makefiles\NmakeSubdirs.bat cleanall $(LIBRARIES) $(APPLICATIONS)
> > +  @$(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py cleanall 
> > $(LIBRARIES) $(APPLICATIONS)
> >
> > !INCLUDE Makefiles\ms.rule
> >
> > diff --git a/BaseTools/Source/C/Makefiles/NmakeSubdirs.py 
> > b/BaseTools/Source/C/Makefiles/NmakeSubdirs.py
> > new file mode 100644
> > index 0000000..29bb5df
> > --- /dev/null
> > +++ b/BaseTools/Source/C/Makefiles/NmakeSubdirs.py
> > @@ -0,0 +1,169 @@
> > +# @file NmakeSubdirs.py
> > +# This script support parallel build for nmake in windows environment.
> > +# It supports Python2.x and Python3.x both.
> > +#
> > +#  Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
> > +#
> > +#  This program and the accompanying materials
> > +#  are licensed and made available under the terms and conditions of the 
> > BSD License
> > +#  which accompanies this distribution.  The full text of the license may 
> > be found at
> > +#  http://opensource.org/licenses/bsd-license.php
> > +#
> > +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> > +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
> > IMPLIED.
> > +#
> > +
> > +#
> > +# Import Modules
> > +#
> > +
> > +from __future__ import print_function
> > +import argparse
> > +import threading
> > +import time
> > +import os
> > +import subprocess
> > +import multiprocessing
> > +import copy
> > +import sys
> > +__prog__        = 'NmakeSubdirs'
> > +__version__     = '%s Version %s' % (__prog__, '0.10 ')
> > +__copyright__   = 'Copyright (c) 2018, Intel Corporation. All rights 
> > reserved.'
> > +__description__ = 'Replace for NmakeSubdirs.bat in windows ,support 
> > parallel build for nmake.\n'
> > +
> > +cpu_count = multiprocessing.cpu_count()
> > +output_lock = threading.Lock()
> > +def RunCommand(WorkDir=None, *Args, **kwargs):
> > +    if WorkDir is None:
> > +        WorkDir = os.curdir
> > +    if "stderr" not in kwargs:
> > +        kwargs["stderr"] = subprocess.STDOUT
> > +    if "stdout" not in kwargs:
> > +        kwargs["stdout"] = subprocess.PIPE
> > +    p = subprocess.Popen(Args, cwd=WorkDir, stderr=kwargs["stderr"], 
> > stdout=kwargs["stdout"])
> > +    stdout, stderr = p.communicate()
> > +    message = ""
> > +    if stdout is not None:
> > +        message = stdout.decode() #for compatibility in python 2 and 3
> > +
> > +    if p.returncode != 0:
> > +        raise RuntimeError("Error while execute command \'{0}\' in 
> > direcotry {1}\n{2}".format(" ".join(Args), WorkDir, message))
> > +
> > +    output_lock.acquire(True)
> > +    print("execute command \"{0}\" in directory {1}".format(" 
> > ".join(Args), WorkDir))
> > +    print(message)
> > +    output_lock.release()
> > +
> > +    return p.returncode, stdout
> > +
> > +class TaskUnit(object):
> > +    def __init__(self, func, args, kwargs):
> > +        self.func = func
> > +        self.args = args
> > +        self.kwargs = kwargs
> > +
> > +    def __eq__(self, other):
> > +        return id(self).__eq__(id(other))
> > +
> > +    def run(self):
> > +        return self.func(*self.args, **self.kwargs)
> > +
> > +    def __str__(self):
> > +        para = list(self.args)
> > +        para.extend("{0}={1}".format(k, v)for k, v in self.kwargs.items())
> > +
> > +        return "{0}({1})".format(self.func.__name__, ",".join(para))
> > +
> > +class ThreadControl(object):
> > +
> > +    def __init__(self, maxthread):
> > +        self._processNum = maxthread
> > +        self.pending = []
> > +        self.running = []
> > +        self.pendingLock = threading.Lock()
> > +        self.runningLock = threading.Lock()
> > +        self.error = False
> > +        self.errorLock = threading.Lock()
> > +        self.errorMsg = "errorMsg"
> > +
> > +    def addTask(self, func, *args, **kwargs):
> > +        self.pending.append(TaskUnit(func, args, kwargs))
> > +
> > +    def waitComplete(self):
> > +        self._schedule.join()
> > +
> > +    def startSchedule(self):
> > +        self._schedule = threading.Thread(target=self.Schedule)
> > +        self._schedule.start()
> > +
> > +    def Schedule(self):
> > +        for i in range(self._processNum):
> > +            task = threading.Thread(target=self.startTask)
> > +            task.daemon = False
> > +            self.running.append(task)
> > +
> > +        self.runningLock.acquire(True)
> > +        for thread in self.running:
> > +            thread.start()
> > +        self.runningLock.release()
> > +
> > +        while len(self.running) > 0:
> > +            time.sleep(0.1)
> > +        if self.error:
> > +            print("subprocess not exit sucessfully")
> > +            print(self.errorMsg)
> > +
> > +    def startTask(self):
> > +        while True:
> > +            if self.error:
> > +                break
> > +            self.pendingLock.acquire(True)
> > +            if len(self.pending) == 0:
> > +                self.pendingLock.release()
> > +                break
> > +            task = self.pending.pop(0)
> > +            self.pendingLock.release()
> > +            try:
> > +                task.run()
> > +            except RuntimeError as e:
> > +                if self.error: break
> > +                self.errorLock.acquire(True)
> > +                self.error = True
> > +                self.errorMsg = str(e)
> > +                time.sleep(0.1)
> > +                self.errorLock.release()
> > +                break
> > +
> > +        self.runningLock.acquire(True)
> > +        self.running.remove(threading.currentThread())
> > +        self.runningLock.release()
> > +
> > +def Run():
> > +    curdir = os.path.abspath(os.curdir)
> > +    if len(args.subdirs) == 1:
> > +        args.jobs = 1
> > +    if args.jobs == 1:
> > +        try:
> > +            for dir in args.subdirs:
> > +                RunCommand(os.path.join(curdir, dir), "nmake", 
> > args.target, stdout=sys.stdout, stderr=subprocess.STDOUT)
> > +        except RuntimeError:
> > +            exit(1)
> > +    else:
> > +        controller = ThreadControl(args.jobs)
> > +        for dir in args.subdirs:
> > +            controller.addTask(RunCommand, os.path.join(curdir, dir), 
> > "nmake", args.target)
> > +        controller.startSchedule()
> > +        controller.waitComplete()
> > +        if controller.error:
> > +            exit(1)
> > +
> > +if __name__ == "__main__":
> > +    parser = argparse.ArgumentParser(prog=__prog__, 
> > description=__description__ + __copyright__, conflict_handler='resolve')
> > +
> > +    parser.add_argument("target", help="the target for nmake")
> > +    parser.add_argument("subdirs", nargs="+", help="the relative dir path 
> > of makefile")
> > +    parser.add_argument("--jobs", type=int, dest="jobs", 
> > default=cpu_count, help="thread number")
> > +    parser.add_argument('--version', action='version', version=__version__)
> > +    args = parser.parse_args()
> > +    Run()
> > +
> > --
> > 2.10.0.windows.1
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to