mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-24 11:45:27 +01:00
02287fbb4b
Signed-off-by: SergeySlice <sergey.slice@gmail.com>
330 lines
15 KiB
Python
Executable File
330 lines
15 KiB
Python
Executable File
## @file
|
|
# Create makefile for MS nmake and GNU make
|
|
#
|
|
# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
#
|
|
from __future__ import absolute_import
|
|
import multiprocessing as mp
|
|
import threading
|
|
from Common.Misc import PathClass
|
|
from AutoGen.ModuleAutoGen import ModuleAutoGen
|
|
from AutoGen.ModuleAutoGenHelper import WorkSpaceInfo,AutoGenInfo
|
|
import Common.GlobalData as GlobalData
|
|
import Common.EdkLogger as EdkLogger
|
|
import os
|
|
from Common.MultipleWorkspace import MultipleWorkspace as mws
|
|
from AutoGen.AutoGen import AutoGen
|
|
from Workspace.WorkspaceDatabase import BuildDB
|
|
try:
|
|
from queue import Empty
|
|
except:
|
|
from Queue import Empty
|
|
import traceback
|
|
import sys
|
|
from AutoGen.DataPipe import MemoryDataPipe
|
|
import logging
|
|
import time
|
|
|
|
def clearQ(q):
|
|
try:
|
|
while True:
|
|
q.get_nowait()
|
|
except Empty:
|
|
pass
|
|
|
|
class LogAgent(threading.Thread):
|
|
def __init__(self,log_q,log_level,log_file=None):
|
|
super(LogAgent,self).__init__()
|
|
self.log_q = log_q
|
|
self.log_level = log_level
|
|
self.log_file = log_file
|
|
def InitLogger(self):
|
|
# For DEBUG level (All DEBUG_0~9 are applicable)
|
|
self._DebugLogger_agent = logging.getLogger("tool_debug_agent")
|
|
_DebugFormatter = logging.Formatter("[%(asctime)s.%(msecs)d]: %(message)s", datefmt="%H:%M:%S")
|
|
self._DebugLogger_agent.setLevel(self.log_level)
|
|
_DebugChannel = logging.StreamHandler(sys.stdout)
|
|
_DebugChannel.setFormatter(_DebugFormatter)
|
|
self._DebugLogger_agent.addHandler(_DebugChannel)
|
|
|
|
# For VERBOSE, INFO, WARN level
|
|
self._InfoLogger_agent = logging.getLogger("tool_info_agent")
|
|
_InfoFormatter = logging.Formatter("%(message)s")
|
|
self._InfoLogger_agent.setLevel(self.log_level)
|
|
_InfoChannel = logging.StreamHandler(sys.stdout)
|
|
_InfoChannel.setFormatter(_InfoFormatter)
|
|
self._InfoLogger_agent.addHandler(_InfoChannel)
|
|
|
|
# For ERROR level
|
|
self._ErrorLogger_agent = logging.getLogger("tool_error_agent")
|
|
_ErrorFormatter = logging.Formatter("%(message)s")
|
|
self._ErrorLogger_agent.setLevel(self.log_level)
|
|
_ErrorCh = logging.StreamHandler(sys.stderr)
|
|
_ErrorCh.setFormatter(_ErrorFormatter)
|
|
self._ErrorLogger_agent.addHandler(_ErrorCh)
|
|
|
|
if self.log_file:
|
|
if os.path.exists(self.log_file):
|
|
os.remove(self.log_file)
|
|
_Ch = logging.FileHandler(self.log_file)
|
|
_Ch.setFormatter(_DebugFormatter)
|
|
self._DebugLogger_agent.addHandler(_Ch)
|
|
|
|
_Ch= logging.FileHandler(self.log_file)
|
|
_Ch.setFormatter(_InfoFormatter)
|
|
self._InfoLogger_agent.addHandler(_Ch)
|
|
|
|
_Ch = logging.FileHandler(self.log_file)
|
|
_Ch.setFormatter(_ErrorFormatter)
|
|
self._ErrorLogger_agent.addHandler(_Ch)
|
|
|
|
def run(self):
|
|
self.InitLogger()
|
|
while True:
|
|
log_message = self.log_q.get()
|
|
if log_message is None:
|
|
break
|
|
if log_message.name == "tool_error":
|
|
self._ErrorLogger_agent.log(log_message.levelno,log_message.getMessage())
|
|
elif log_message.name == "tool_info":
|
|
self._InfoLogger_agent.log(log_message.levelno,log_message.getMessage())
|
|
elif log_message.name == "tool_debug":
|
|
self._DebugLogger_agent.log(log_message.levelno,log_message.getMessage())
|
|
else:
|
|
self._InfoLogger_agent.log(log_message.levelno,log_message.getMessage())
|
|
|
|
def kill(self):
|
|
self.log_q.put(None)
|
|
class AutoGenManager(threading.Thread):
|
|
def __init__(self,autogen_workers, feedback_q,error_event):
|
|
super(AutoGenManager,self).__init__()
|
|
self.autogen_workers = autogen_workers
|
|
self.feedback_q = feedback_q
|
|
self.Status = True
|
|
self.error_event = error_event
|
|
def run(self):
|
|
try:
|
|
fin_num = 0
|
|
while True:
|
|
badnews = self.feedback_q.get()
|
|
if badnews is None:
|
|
break
|
|
if badnews == "Done":
|
|
fin_num += 1
|
|
elif badnews == "QueueEmpty":
|
|
EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), badnews))
|
|
self.TerminateWorkers()
|
|
else:
|
|
EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), badnews))
|
|
self.Status = False
|
|
self.TerminateWorkers()
|
|
if fin_num == len(self.autogen_workers):
|
|
self.clearQueue()
|
|
for w in self.autogen_workers:
|
|
w.join()
|
|
break
|
|
except Exception:
|
|
return
|
|
|
|
def clearQueue(self):
|
|
taskq = self.autogen_workers[0].module_queue
|
|
logq = self.autogen_workers[0].log_q
|
|
clearQ(taskq)
|
|
clearQ(self.feedback_q)
|
|
clearQ(logq)
|
|
# Copy the cache queue itmes to parent thread before clear
|
|
cacheq = self.autogen_workers[0].cache_q
|
|
try:
|
|
cache_num = 0
|
|
while True:
|
|
item = cacheq.get()
|
|
if item == "CacheDone":
|
|
cache_num += 1
|
|
else:
|
|
GlobalData.gModuleAllCacheStatus.add(item)
|
|
if cache_num == len(self.autogen_workers):
|
|
break
|
|
except:
|
|
print ("cache_q error")
|
|
|
|
def TerminateWorkers(self):
|
|
self.error_event.set()
|
|
def kill(self):
|
|
self.feedback_q.put(None)
|
|
class AutoGenWorkerInProcess(mp.Process):
|
|
def __init__(self,module_queue,data_pipe_file_path,feedback_q,file_lock,cache_q,log_q,error_event):
|
|
mp.Process.__init__(self)
|
|
self.module_queue = module_queue
|
|
self.data_pipe_file_path =data_pipe_file_path
|
|
self.data_pipe = None
|
|
self.feedback_q = feedback_q
|
|
self.PlatformMetaFileSet = {}
|
|
self.file_lock = file_lock
|
|
self.cache_q = cache_q
|
|
self.log_q = log_q
|
|
self.error_event = error_event
|
|
def GetPlatformMetaFile(self,filepath,root):
|
|
try:
|
|
return self.PlatformMetaFileSet[(filepath,root)]
|
|
except:
|
|
self.PlatformMetaFileSet[(filepath,root)] = filepath
|
|
return self.PlatformMetaFileSet[(filepath,root)]
|
|
def run(self):
|
|
try:
|
|
taskname = "Init"
|
|
with self.file_lock:
|
|
try:
|
|
self.data_pipe = MemoryDataPipe()
|
|
self.data_pipe.load(self.data_pipe_file_path)
|
|
except:
|
|
self.feedback_q.put(taskname + ":" + "load data pipe %s failed." % self.data_pipe_file_path)
|
|
EdkLogger.LogClientInitialize(self.log_q)
|
|
loglevel = self.data_pipe.Get("LogLevel")
|
|
if not loglevel:
|
|
loglevel = EdkLogger.INFO
|
|
EdkLogger.SetLevel(loglevel)
|
|
target = self.data_pipe.Get("P_Info").get("Target")
|
|
toolchain = self.data_pipe.Get("P_Info").get("ToolChain")
|
|
archlist = self.data_pipe.Get("P_Info").get("ArchList")
|
|
|
|
active_p = self.data_pipe.Get("P_Info").get("ActivePlatform")
|
|
workspacedir = self.data_pipe.Get("P_Info").get("WorkspaceDir")
|
|
PackagesPath = os.getenv("PACKAGES_PATH")
|
|
mws.setWs(workspacedir, PackagesPath)
|
|
self.Wa = WorkSpaceInfo(
|
|
workspacedir,active_p,target,toolchain,archlist
|
|
)
|
|
self.Wa._SrcTimeStamp = self.data_pipe.Get("Workspace_timestamp")
|
|
GlobalData.gGlobalDefines = self.data_pipe.Get("G_defines")
|
|
GlobalData.gCommandLineDefines = self.data_pipe.Get("CL_defines")
|
|
os.environ._data = self.data_pipe.Get("Env_Var")
|
|
GlobalData.gWorkspace = workspacedir
|
|
GlobalData.gDisableIncludePathCheck = False
|
|
GlobalData.gFdfParser = self.data_pipe.Get("FdfParser")
|
|
GlobalData.gDatabasePath = self.data_pipe.Get("DatabasePath")
|
|
|
|
GlobalData.gUseHashCache = self.data_pipe.Get("UseHashCache")
|
|
GlobalData.gBinCacheSource = self.data_pipe.Get("BinCacheSource")
|
|
GlobalData.gBinCacheDest = self.data_pipe.Get("BinCacheDest")
|
|
GlobalData.gPlatformHashFile = self.data_pipe.Get("PlatformHashFile")
|
|
GlobalData.gModulePreMakeCacheStatus = dict()
|
|
GlobalData.gModuleMakeCacheStatus = dict()
|
|
GlobalData.gHashChainStatus = dict()
|
|
GlobalData.gCMakeHashFile = dict()
|
|
GlobalData.gModuleHashFile = dict()
|
|
GlobalData.gFileHashDict = dict()
|
|
GlobalData.gEnableGenfdsMultiThread = self.data_pipe.Get("EnableGenfdsMultiThread")
|
|
GlobalData.file_lock = self.file_lock
|
|
CommandTarget = self.data_pipe.Get("CommandTarget")
|
|
pcd_from_build_option = []
|
|
for pcd_tuple in self.data_pipe.Get("BuildOptPcd"):
|
|
pcd_id = ".".join((pcd_tuple[0],pcd_tuple[1]))
|
|
if pcd_tuple[2].strip():
|
|
pcd_id = ".".join((pcd_id,pcd_tuple[2]))
|
|
pcd_from_build_option.append("=".join((pcd_id,pcd_tuple[3])))
|
|
GlobalData.BuildOptionPcd = pcd_from_build_option
|
|
module_count = 0
|
|
FfsCmd = self.data_pipe.Get("FfsCommand")
|
|
if FfsCmd is None:
|
|
FfsCmd = {}
|
|
GlobalData.FfsCmd = FfsCmd
|
|
PlatformMetaFile = self.GetPlatformMetaFile(self.data_pipe.Get("P_Info").get("ActivePlatform"),
|
|
self.data_pipe.Get("P_Info").get("WorkspaceDir"))
|
|
while True:
|
|
if self.error_event.is_set():
|
|
break
|
|
module_count += 1
|
|
try:
|
|
module_file,module_root,module_path,module_basename,module_originalpath,module_arch,IsLib = self.module_queue.get_nowait()
|
|
except Empty:
|
|
EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), "Fake Empty."))
|
|
time.sleep(0.01)
|
|
continue
|
|
if module_file is None:
|
|
EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), "Worker get the last item in the queue."))
|
|
self.feedback_q.put("QueueEmpty")
|
|
time.sleep(0.01)
|
|
continue
|
|
|
|
modulefullpath = os.path.join(module_root,module_file)
|
|
taskname = " : ".join((modulefullpath,module_arch))
|
|
module_metafile = PathClass(module_file,module_root)
|
|
if module_path:
|
|
module_metafile.Path = module_path
|
|
if module_basename:
|
|
module_metafile.BaseName = module_basename
|
|
if module_originalpath:
|
|
module_metafile.OriginalPath = PathClass(module_originalpath,module_root)
|
|
arch = module_arch
|
|
target = self.data_pipe.Get("P_Info").get("Target")
|
|
toolchain = self.data_pipe.Get("P_Info").get("ToolChain")
|
|
Ma = ModuleAutoGen(self.Wa,module_metafile,target,toolchain,arch,PlatformMetaFile,self.data_pipe)
|
|
Ma.IsLibrary = IsLib
|
|
# SourceFileList calling sequence impact the makefile string sequence.
|
|
# Create cached SourceFileList here to unify its calling sequence for both
|
|
# CanSkipbyPreMakeCache and CreateCodeFile/CreateMakeFile.
|
|
RetVal = Ma.SourceFileList
|
|
if GlobalData.gUseHashCache and not GlobalData.gBinCacheDest and CommandTarget in [None, "", "all"]:
|
|
try:
|
|
CacheResult = Ma.CanSkipbyPreMakeCache()
|
|
except:
|
|
CacheResult = False
|
|
self.feedback_q.put(taskname)
|
|
|
|
if CacheResult:
|
|
self.cache_q.put((Ma.MetaFile.Path, Ma.Arch, "PreMakeCache", True))
|
|
continue
|
|
else:
|
|
self.cache_q.put((Ma.MetaFile.Path, Ma.Arch, "PreMakeCache", False))
|
|
|
|
Ma.CreateCodeFile(False)
|
|
Ma.CreateMakeFile(False,GenFfsList=FfsCmd.get((Ma.MetaFile.Path, Ma.Arch),[]))
|
|
Ma.CreateAsBuiltInf()
|
|
if GlobalData.gBinCacheSource and CommandTarget in [None, "", "all"]:
|
|
try:
|
|
CacheResult = Ma.CanSkipbyMakeCache()
|
|
except:
|
|
CacheResult = False
|
|
self.feedback_q.put(taskname)
|
|
|
|
if CacheResult:
|
|
self.cache_q.put((Ma.MetaFile.Path, Ma.Arch, "MakeCache", True))
|
|
continue
|
|
else:
|
|
self.cache_q.put((Ma.MetaFile.Path, Ma.Arch, "MakeCache", False))
|
|
|
|
except Exception as e:
|
|
EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), str(e)))
|
|
self.feedback_q.put(taskname)
|
|
finally:
|
|
EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), "Done"))
|
|
self.feedback_q.put("Done")
|
|
self.cache_q.put("CacheDone")
|
|
|
|
def printStatus(self):
|
|
print("Processs ID: %d Run %d modules in AutoGen " % (os.getpid(),len(AutoGen.Cache())))
|
|
print("Processs ID: %d Run %d modules in AutoGenInfo " % (os.getpid(),len(AutoGenInfo.GetCache())))
|
|
groupobj = {}
|
|
for buildobj in BuildDB.BuildObject.GetCache().values():
|
|
if str(buildobj).lower().endswith("dec"):
|
|
try:
|
|
groupobj['dec'].append(str(buildobj))
|
|
except:
|
|
groupobj['dec'] = [str(buildobj)]
|
|
if str(buildobj).lower().endswith("dsc"):
|
|
try:
|
|
groupobj['dsc'].append(str(buildobj))
|
|
except:
|
|
groupobj['dsc'] = [str(buildobj)]
|
|
|
|
if str(buildobj).lower().endswith("inf"):
|
|
try:
|
|
groupobj['inf'].append(str(buildobj))
|
|
except:
|
|
groupobj['inf'] = [str(buildobj)]
|
|
|
|
print("Processs ID: %d Run %d pkg in WDB " % (os.getpid(),len(groupobj.get("dec",[]))))
|
|
print("Processs ID: %d Run %d pla in WDB " % (os.getpid(),len(groupobj.get("dsc",[]))))
|
|
print("Processs ID: %d Run %d inf in WDB " % (os.getpid(),len(groupobj.get("inf",[]))))
|