# @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>
#
#  SPDX-License-Identifier: BSD-2-Clause-Patent
#

#
# 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(errors='ignore') #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))
    try:
        print(message)
    except:
        pass
    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 successfully")
            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.current_thread())
        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()

