# @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.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()

