# build a platform or a module\r
#\r
# Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>\r
-# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>\r
# Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>\r
+# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>\r
#\r
# SPDX-License-Identifier: BSD-2-Clause-Patent\r
#\r
# Import Modules\r
#\r
from __future__ import print_function\r
-import Common.LongFilePathOs as os\r
-import re\r
+from __future__ import absolute_import\r
+import os.path as path\r
import sys\r
+import os\r
+import re\r
import glob\r
import time\r
import platform\r
import traceback\r
-import encodings.ascii\r
import multiprocessing\r
-\r
-from struct import *\r
-from threading import *\r
+from threading import Thread,Event,BoundedSemaphore\r
import threading\r
-from optparse import OptionParser\r
-from subprocess import *\r
+from linecache import getlines\r
+from subprocess import Popen,PIPE, STDOUT\r
+from collections import OrderedDict, defaultdict\r
+\r
+from AutoGen.PlatformAutoGen import PlatformAutoGen\r
+from AutoGen.ModuleAutoGen import ModuleAutoGen\r
+from AutoGen.WorkspaceAutoGen import WorkspaceAutoGen\r
+from AutoGen.AutoGenWorker import AutoGenWorkerInProcess,AutoGenManager,\\r
+ LogAgent\r
+from AutoGen import GenMake\r
from Common import Misc as Utils\r
\r
-from Common.LongFilePathSupport import OpenLongFilePath as open\r
-from Common.TargetTxtClassObject import TargetTxtClassObject\r
-from Common.ToolDefClassObject import ToolDefClassObject\r
-from Common.DataType import *\r
-from Common.BuildVersion import gBUILD_VERSION\r
-from AutoGen.AutoGen import *\r
-from Common.BuildToolError import *\r
-from Workspace.WorkspaceDatabase import WorkspaceDatabase\r
+from Common.TargetTxtClassObject import TargetTxtDict\r
+from Common.ToolDefClassObject import ToolDefDict\r
+from buildoptions import MyOptionParser\r
+from Common.Misc import PathClass,SaveFileOnChange,RemoveDirectory\r
+from Common.StringUtils import NormPath\r
from Common.MultipleWorkspace import MultipleWorkspace as mws\r
+from Common.BuildToolError import *\r
+from Common.DataType import *\r
+import Common.EdkLogger as EdkLogger\r
+\r
+from Workspace.WorkspaceDatabase import BuildDB\r
\r
from BuildReport import BuildReport\r
-from GenPatchPcdTable.GenPatchPcdTable import *\r
-from PatchPcdValue.PatchPcdValue import *\r
+from GenPatchPcdTable.GenPatchPcdTable import PeImageClass,parsePcdInfoFromMapFile\r
+from PatchPcdValue.PatchPcdValue import PatchBinaryFile\r
\r
-import Common.EdkLogger\r
import Common.GlobalData as GlobalData\r
from GenFds.GenFds import GenFds, GenFdsApi\r
-\r
-from collections import OrderedDict, defaultdict\r
-\r
-# Version and Copyright\r
-VersionNumber = "0.60" + ' ' + gBUILD_VERSION\r
-__version__ = "%prog Version " + VersionNumber\r
-__copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation All rights reserved."\r
+import multiprocessing as mp\r
+from multiprocessing import Manager\r
+from AutoGen.DataPipe import MemoryDataPipe\r
+from AutoGen.ModuleAutoGenHelper import WorkSpaceInfo, PlatformInfo\r
+from GenFds.FdfParser import FdfParser\r
+from AutoGen.IncludesAutoGen import IncludesAutoGen\r
+from GenFds.GenFds import resetFdsGlobalVariable\r
\r
## standard targets of build command\r
gSupportedTarget = ['all', 'genc', 'genmake', 'modules', 'libraries', 'fds', 'clean', 'cleanall', 'cleanlib', 'run']\r
# @param To The stream message put on\r
# @param ExitFlag The flag used to indicate stopping reading\r
#\r
-def ReadMessage(From, To, ExitFlag):\r
+def ReadMessage(From, To, ExitFlag,MemTo=None):\r
while True:\r
# read one line a time\r
Line = From.readline()\r
# empty string means "end"\r
if Line is not None and Line != b"":\r
- To(Line.rstrip().decode(encoding='utf-8', errors='ignore'))\r
+ LineStr = Line.rstrip().decode(encoding='utf-8', errors='ignore')\r
+ if MemTo is not None:\r
+ if "Note: including file:" == LineStr.lstrip()[:21]:\r
+ MemTo.append(LineStr)\r
+ else:\r
+ To(LineStr)\r
+ MemTo.append(LineStr)\r
+ else:\r
+ To(LineStr)\r
else:\r
break\r
if ExitFlag.isSet():\r
break\r
\r
+class MakeSubProc(Popen):\r
+ def __init__(self,*args, **argv):\r
+ super(MakeSubProc,self).__init__(*args, **argv)\r
+ self.ProcOut = []\r
+\r
## Launch an external program\r
#\r
# This method will call subprocess.Popen to execute an external program with\r
# @param Command A list or string containing the call of the program\r
# @param WorkingDir The directory in which the program will be running\r
#\r
-def LaunchCommand(Command, WorkingDir):\r
+def LaunchCommand(Command, WorkingDir,ModuleAuto = None):\r
BeginTime = time.time()\r
# if working directory doesn't exist, Popen() will raise an exception\r
if not os.path.isdir(WorkingDir):\r
EndOfProcedure = None\r
try:\r
# launch the command\r
- Proc = Popen(Command, stdout=PIPE, stderr=PIPE, env=os.environ, cwd=WorkingDir, bufsize=-1, shell=True)\r
+ Proc = MakeSubProc(Command, stdout=PIPE, stderr=STDOUT, env=os.environ, cwd=WorkingDir, bufsize=-1, shell=True)\r
\r
# launch two threads to read the STDOUT and STDERR\r
EndOfProcedure = Event()\r
EndOfProcedure.clear()\r
if Proc.stdout:\r
- StdOutThread = Thread(target=ReadMessage, args=(Proc.stdout, EdkLogger.info, EndOfProcedure))\r
+ StdOutThread = Thread(target=ReadMessage, args=(Proc.stdout, EdkLogger.info, EndOfProcedure,Proc.ProcOut))\r
StdOutThread.setName("STDOUT-Redirector")\r
StdOutThread.setDaemon(False)\r
StdOutThread.start()\r
\r
- if Proc.stderr:\r
- StdErrThread = Thread(target=ReadMessage, args=(Proc.stderr, EdkLogger.quiet, EndOfProcedure))\r
- StdErrThread.setName("STDERR-Redirector")\r
- StdErrThread.setDaemon(False)\r
- StdErrThread.start()\r
\r
# waiting for program exit\r
Proc.wait()\r
\r
if Proc.stdout:\r
StdOutThread.join()\r
- if Proc.stderr:\r
- StdErrThread.join()\r
\r
# check the return code of the program\r
if Proc.returncode != 0:\r
EdkLogger.info(RespContent)\r
\r
EdkLogger.error("build", COMMAND_FAILURE, ExtraData="%s [%s]" % (Command, WorkingDir))\r
+ if ModuleAuto:\r
+ iau = IncludesAutoGen(WorkingDir,ModuleAuto)\r
+ if ModuleAuto.ToolChainFamily == TAB_COMPILER_MSFT:\r
+ iau.CreateDepsFileForMsvc(Proc.ProcOut)\r
+ else:\r
+ iau.UpdateDepsFileforNonMsvc()\r
+ iau.UpdateDepsFileforTrim()\r
+ iau.CreateModuleDeps()\r
+ iau.CreateDepsInclude()\r
+ iau.CreateDepsTarget()\r
return "%dms" % (int(round((time.time() - BeginTime) * 1000)))\r
\r
## The smallest unit that can be built in multi-thread build mode\r
# @param Obj The ModuleAutoGen object the build is working on\r
# @param Target The build target name, one of gSupportedTarget\r
#\r
- def __init__(self, Obj, Target):\r
- Dependency = [ModuleMakeUnit(La, Target) for La in Obj.LibraryAutoGenList]\r
- BuildUnit.__init__(self, Obj, Obj.BuildCommand, Target, Dependency, Obj.MakeFileDir)\r
+ def __init__(self, Obj, BuildCommand,Target):\r
+ Dependency = [ModuleMakeUnit(La, BuildCommand,Target) for La in Obj.LibraryAutoGenList]\r
+ BuildUnit.__init__(self, Obj, BuildCommand, Target, Dependency, Obj.MakeFileDir)\r
if Target in [None, "", "all"]:\r
self.Target = "tbuild"\r
\r
# @param Obj The PlatformAutoGen object the build is working on\r
# @param Target The build target name, one of gSupportedTarget\r
#\r
- def __init__(self, Obj, Target):\r
- Dependency = [ModuleMakeUnit(Lib, Target) for Lib in self.BuildObject.LibraryAutoGenList]\r
- Dependency.extend([ModuleMakeUnit(Mod, Target) for Mod in self.BuildObject.ModuleAutoGenList])\r
- BuildUnit.__init__(self, Obj, Obj.BuildCommand, Target, Dependency, Obj.MakeFileDir)\r
+ def __init__(self, Obj, BuildCommand, Target):\r
+ Dependency = [ModuleMakeUnit(Lib, BuildCommand, Target) for Lib in self.BuildObject.LibraryAutoGenList]\r
+ Dependency.extend([ModuleMakeUnit(Mod, BuildCommand,Target) for Mod in self.BuildObject.ModuleAutoGenList])\r
+ BuildUnit.__init__(self, Obj, BuildCommand, Target, Dependency, Obj.MakeFileDir)\r
\r
## The class representing the task of a module build or platform build\r
#\r
#\r
def AddDependency(self, Dependency):\r
for Dep in Dependency:\r
- if not Dep.BuildObject.IsBinaryModule and not Dep.BuildObject.CanSkipbyHash():\r
+ if not Dep.BuildObject.IsBinaryModule and not Dep.BuildObject.CanSkipbyCache(GlobalData.gModuleCacheHit):\r
self.DependencyList.append(BuildTask.New(Dep)) # BuildTask list\r
\r
## The thread wrapper of LaunchCommand function\r
#\r
def _CommandThread(self, Command, WorkingDir):\r
try:\r
- self.BuildItem.BuildObject.BuildTime = LaunchCommand(Command, WorkingDir)\r
+ self.BuildItem.BuildObject.BuildTime = LaunchCommand(Command, WorkingDir,self.BuildItem.BuildObject)\r
self.CompleteFlag = True\r
\r
- # Run hash operation post dependency, to account for libs\r
- if GlobalData.gUseHashCache and self.BuildItem.BuildObject.IsLibrary:\r
- HashFile = path.join(self.BuildItem.BuildObject.BuildDir, self.BuildItem.BuildObject.Name + ".hash")\r
- SaveFileOnChange(HashFile, self.BuildItem.BuildObject.GenModuleHash(), True)\r
+ # Run hash operation post dependency to account for libs\r
+ # Run if --hash or --binary-destination\r
+ if GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
+ self.BuildItem.BuildObject.GenModuleHash()\r
+ if GlobalData.gBinCacheDest:\r
+ self.BuildItem.BuildObject.GenCMakeHash()\r
+\r
except:\r
#\r
# TRICK: hide the output of threads left running, so that the user can\r
BuildTask._ErrorMessage = "%s broken\n %s [%s]" % \\r
(threading.currentThread().getName(), Command, WorkingDir)\r
\r
- # Set the value used by hash invalidation flow in GlobalData.gModuleBuildTracking to 'SUCCESS'\r
- # If Module or Lib is being tracked, it did not fail header check test, and built successfully\r
- if (self.BuildItem.BuildObject.Arch in GlobalData.gModuleBuildTracking and\r
- self.BuildItem.BuildObject in GlobalData.gModuleBuildTracking[self.BuildItem.BuildObject.Arch] and\r
- GlobalData.gModuleBuildTracking[self.BuildItem.BuildObject.Arch][self.BuildItem.BuildObject] != 'FAIL_METAFILE' and\r
- not BuildTask._ErrorFlag.isSet()\r
- ):\r
- GlobalData.gModuleBuildTracking[self.BuildItem.BuildObject.Arch][self.BuildItem.BuildObject] = 'SUCCESS'\r
-\r
# indicate there's a thread is available for another build task\r
BuildTask._RunningQueueLock.acquire()\r
BuildTask._RunningQueue.pop(self.BuildItem)\r
# @param WorkspaceDir The directory of workspace\r
# @param BuildOptions Build options passed from command line\r
#\r
- def __init__(self, Target, WorkspaceDir, BuildOptions):\r
+ def __init__(self, Target, WorkspaceDir, BuildOptions,log_q):\r
self.WorkspaceDir = WorkspaceDir\r
self.Target = Target\r
self.PlatformFile = BuildOptions.PlatformFile\r
self.FvList = BuildOptions.FvImage\r
self.CapList = BuildOptions.CapName\r
self.SilentMode = BuildOptions.SilentMode\r
- self.ThreadNumber = BuildOptions.ThreadNumber\r
+ self.ThreadNumber = 1\r
self.SkipAutoGen = BuildOptions.SkipAutoGen\r
self.Reparse = BuildOptions.Reparse\r
self.SkuId = BuildOptions.SkuId\r
self.ConfDirectory = BuildOptions.ConfDirectory\r
self.SpawnMode = True\r
self.BuildReport = BuildReport(BuildOptions.ReportFile, BuildOptions.ReportType)\r
- self.TargetTxt = TargetTxtClassObject()\r
- self.ToolDef = ToolDefClassObject()\r
self.AutoGenTime = 0\r
self.MakeTime = 0\r
self.GenFdsTime = 0\r
+ self.MakeFileName = ""\r
+ TargetObj = TargetTxtDict()\r
+ ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"),"Conf")))\r
+ self.TargetTxt = TargetObj.Target\r
+ self.ToolDef = ToolDefObj.ToolDef\r
GlobalData.BuildOptionPcd = BuildOptions.OptionPcd if BuildOptions.OptionPcd else []\r
#Set global flag for build mode\r
GlobalData.gIgnoreSource = BuildOptions.IgnoreSources\r
GlobalData.gUseHashCache = BuildOptions.UseHashCache\r
GlobalData.gBinCacheDest = BuildOptions.BinCacheDest\r
GlobalData.gBinCacheSource = BuildOptions.BinCacheSource\r
- GlobalData.gEnableGenfdsMultiThread = BuildOptions.GenfdsMultiThread\r
+ GlobalData.gEnableGenfdsMultiThread = not BuildOptions.NoGenfdsMultiThread\r
GlobalData.gDisableIncludePathCheck = BuildOptions.DisableIncludePathCheck\r
\r
if GlobalData.gBinCacheDest and not GlobalData.gUseHashCache:\r
if GlobalData.gBinCacheDest is not None:\r
EdkLogger.error("build", OPTION_VALUE_INVALID, ExtraData="Invalid value of option --binary-destination.")\r
\r
- if self.ConfDirectory:\r
- # Get alternate Conf location, if it is absolute, then just use the absolute directory name\r
- ConfDirectoryPath = os.path.normpath(self.ConfDirectory)\r
-\r
- if not os.path.isabs(ConfDirectoryPath):\r
- # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE\r
- # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf\r
- ConfDirectoryPath = mws.join(self.WorkspaceDir, ConfDirectoryPath)\r
- else:\r
- if "CONF_PATH" in os.environ:\r
- ConfDirectoryPath = os.path.normcase(os.path.normpath(os.environ["CONF_PATH"]))\r
- else:\r
- # Get standard WORKSPACE/Conf use the absolute path to the WORKSPACE/Conf\r
- ConfDirectoryPath = mws.join(self.WorkspaceDir, 'Conf')\r
- GlobalData.gConfDirectory = ConfDirectoryPath\r
- GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))\r
-\r
- self.Db = WorkspaceDatabase()\r
+ GlobalData.gDatabasePath = os.path.normpath(os.path.join(GlobalData.gConfDirectory, GlobalData.gDatabasePath))\r
+ if not os.path.exists(os.path.join(GlobalData.gConfDirectory, '.cache')):\r
+ os.makedirs(os.path.join(GlobalData.gConfDirectory, '.cache'))\r
+ self.Db = BuildDB\r
self.BuildDatabase = self.Db.BuildObject\r
self.Platform = None\r
self.ToolChainFamily = None\r
EdkLogger.quiet("%-16s = %s" % ("POSTBUILD", self.Postbuild))\r
if self.Prebuild:\r
self.LaunchPrebuild()\r
- self.TargetTxt = TargetTxtClassObject()\r
- self.ToolDef = ToolDefClassObject()\r
+ TargetObj = TargetTxtDict()\r
+ ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))\r
+ self.TargetTxt = TargetObj.Target\r
+ self.ToolDef = ToolDefObj.ToolDef\r
if not (self.LaunchPrebuildFlag and os.path.exists(self.PlatformBuildPath)):\r
self.InitBuild()\r
\r
+ self.AutoGenMgr = None\r
EdkLogger.info("")\r
os.chdir(self.WorkspaceDir)\r
+ self.log_q = log_q\r
+ GlobalData.file_lock = mp.Lock()\r
+ # Init cache data for local only\r
+ GlobalData.gPackageHashFile = dict()\r
+ GlobalData.gModulePreMakeCacheStatus = dict()\r
+ GlobalData.gModuleMakeCacheStatus = dict()\r
+ GlobalData.gHashChainStatus = dict()\r
+ GlobalData.gCMakeHashFile = dict()\r
+ GlobalData.gModuleHashFile = dict()\r
+ GlobalData.gFileHashDict = dict()\r
+ GlobalData.gModuleAllCacheStatus = set()\r
+ GlobalData.gModuleCacheHit = set()\r
+\r
+ def StartAutoGen(self,mqueue, DataPipe,SkipAutoGen,PcdMaList,cqueue):\r
+ try:\r
+ if SkipAutoGen:\r
+ return True,0\r
+ feedback_q = mp.Queue()\r
+ error_event = mp.Event()\r
+ FfsCmd = DataPipe.Get("FfsCommand")\r
+ if FfsCmd is None:\r
+ FfsCmd = {}\r
+ GlobalData.FfsCmd = FfsCmd\r
+ auto_workers = [AutoGenWorkerInProcess(mqueue,DataPipe.dump_file,feedback_q,GlobalData.file_lock,cqueue,self.log_q,error_event) for _ in range(self.ThreadNumber)]\r
+ self.AutoGenMgr = AutoGenManager(auto_workers,feedback_q,error_event)\r
+ self.AutoGenMgr.start()\r
+ for w in auto_workers:\r
+ w.start()\r
+ if PcdMaList is not None:\r
+ for PcdMa in PcdMaList:\r
+ # SourceFileList calling sequence impact the makefile string sequence.\r
+ # Create cached SourceFileList here to unify its calling sequence for both\r
+ # CanSkipbyPreMakeCache and CreateCodeFile/CreateMakeFile.\r
+ RetVal = PcdMa.SourceFileList\r
+ # Force cache miss for PCD driver\r
+ if GlobalData.gUseHashCache and not GlobalData.gBinCacheDest and self.Target in [None, "", "all"]:\r
+ cqueue.put((PcdMa.MetaFile.Path, PcdMa.Arch, "PreMakeCache", False))\r
+\r
+ PcdMa.CreateCodeFile(False)\r
+ PcdMa.CreateMakeFile(False,GenFfsList = DataPipe.Get("FfsCommand").get((PcdMa.MetaFile.Path, PcdMa.Arch),[]))\r
+\r
+ # Force cache miss for PCD driver\r
+ if GlobalData.gBinCacheSource and self.Target in [None, "", "all"]:\r
+ cqueue.put((PcdMa.MetaFile.Path, PcdMa.Arch, "MakeCache", False))\r
+\r
+ self.AutoGenMgr.join()\r
+ rt = self.AutoGenMgr.Status\r
+ err = 0\r
+ if not rt:\r
+ err = UNKNOWN_ERROR\r
+ return rt, err\r
+ except FatalError as e:\r
+ return False, e.args[0]\r
+ except:\r
+ return False, UNKNOWN_ERROR\r
\r
## Load configuration\r
#\r
# This method will parse target.txt and get the build configurations.\r
#\r
def LoadConfiguration(self):\r
- #\r
- # Check target.txt and tools_def.txt and Init them\r
- #\r
- BuildConfigurationFile = os.path.normpath(os.path.join(GlobalData.gConfDirectory, gBuildConfiguration))\r
- if os.path.isfile(BuildConfigurationFile) == True:\r
- StatusCode = self.TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)\r
-\r
- ToolDefinitionFile = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_CONF]\r
- if ToolDefinitionFile == '':\r
- ToolDefinitionFile = gToolsDefinition\r
- ToolDefinitionFile = os.path.normpath(mws.join(self.WorkspaceDir, 'Conf', ToolDefinitionFile))\r
- if os.path.isfile(ToolDefinitionFile) == True:\r
- StatusCode = self.ToolDef.LoadToolDefFile(ToolDefinitionFile)\r
- else:\r
- EdkLogger.error("build", FILE_NOT_FOUND, ExtraData=ToolDefinitionFile)\r
- else:\r
- EdkLogger.error("build", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile)\r
\r
# if no ARCH given in command line, get it from target.txt\r
if not self.ArchList:\r
ToolChainFamily.append(ToolDefinition[TAB_TOD_DEFINES_FAMILY][Tool])\r
self.ToolChainFamily = ToolChainFamily\r
\r
- if self.ThreadNumber is None:\r
- self.ThreadNumber = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER]\r
- if self.ThreadNumber == '':\r
- self.ThreadNumber = 0\r
- else:\r
- self.ThreadNumber = int(self.ThreadNumber, 0)\r
-\r
- if self.ThreadNumber == 0:\r
- try:\r
- self.ThreadNumber = multiprocessing.cpu_count()\r
- except (ImportError, NotImplementedError):\r
- self.ThreadNumber = 1\r
-\r
if not self.PlatformFile:\r
PlatformFile = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_ACTIVE_PLATFORM]\r
if not PlatformFile:\r
ExtraData="No active platform specified in target.txt or command line! Nothing can be built.\n")\r
\r
self.PlatformFile = PathClass(NormFile(PlatformFile, self.WorkspaceDir), self.WorkspaceDir)\r
-\r
+ self.ThreadNumber = ThreadNum()\r
## Initialize build configuration\r
#\r
# This method will parse DSC file and merge the configurations from\r
EdkLogger.error("Postbuild", POSTBUILD_ERROR, 'Postbuild process is not success!')\r
EdkLogger.info("\n- Postbuild Done -\n")\r
\r
- ## Error handling for hash feature\r
- #\r
- # On BuildTask error, iterate through the Module Build tracking\r
- # dictionary to determine wheather a module failed to build. Invalidate\r
- # the hash associated with that module by removing it from storage.\r
- #\r
- #\r
- def invalidateHash(self):\r
- # Only for hashing feature\r
- if not GlobalData.gUseHashCache:\r
- return\r
-\r
- # GlobalData.gModuleBuildTracking contains only modules or libs that cannot be skipped by hash\r
- for moduleAutoGenObjArch in GlobalData.gModuleBuildTracking.keys():\r
- for moduleAutoGenObj in GlobalData.gModuleBuildTracking[moduleAutoGenObjArch].keys():\r
- # Skip invalidating for Successful Module/Lib builds\r
- if GlobalData.gModuleBuildTracking[moduleAutoGenObjArch][moduleAutoGenObj] == 'SUCCESS':\r
- continue\r
-\r
- # The module failed to build, failed to start building, or failed the header check test from this point on\r
-\r
- # Remove .hash from build\r
- ModuleHashFile = os.path.join(moduleAutoGenObj.BuildDir, moduleAutoGenObj.Name + ".hash")\r
- if os.path.exists(ModuleHashFile):\r
- os.remove(ModuleHashFile)\r
-\r
- # Remove .hash file from cache\r
- if GlobalData.gBinCacheDest:\r
- FileDir = os.path.join(GlobalData.gBinCacheDest, moduleAutoGenObj.Arch, moduleAutoGenObj.SourceDir, moduleAutoGenObj.MetaFile.BaseName)\r
- HashFile = os.path.join(FileDir, moduleAutoGenObj.Name + '.hash')\r
- if os.path.exists(HashFile):\r
- os.remove(HashFile)\r
-\r
## Build a module or platform\r
#\r
# Create autogen code and makefile for a module or platform, and the launch\r
# @param CreateDepModuleMakeFile Flag used to indicate creating makefile\r
# for dependent modules/Libraries\r
#\r
- def _BuildPa(self, Target, AutoGenObject, CreateDepsCodeFile=True, CreateDepsMakeFile=True, BuildModule=False, FfsCommand={}):\r
+ def _BuildPa(self, Target, AutoGenObject, CreateDepsCodeFile=True, CreateDepsMakeFile=True, BuildModule=False, FfsCommand=None, PcdMaList=None):\r
if AutoGenObject is None:\r
return False\r
-\r
+ if FfsCommand is None:\r
+ FfsCommand = {}\r
# skip file generation for cleanxxx targets, run and fds target\r
if Target not in ['clean', 'cleanlib', 'cleanall', 'run', 'fds']:\r
# for target which must generate AutoGen code and makefile\r
- if not self.SkipAutoGen or Target == 'genc':\r
- self.Progress.Start("Generating code")\r
- AutoGenObject.CreateCodeFile(CreateDepsCodeFile)\r
- self.Progress.Stop("done!")\r
- if Target == "genc":\r
- return True\r
-\r
- if not self.SkipAutoGen or Target == 'genmake':\r
- self.Progress.Start("Generating makefile")\r
- AutoGenObject.CreateMakeFile(CreateDepsMakeFile, FfsCommand)\r
- self.Progress.Stop("done!")\r
- if Target == "genmake":\r
- return True\r
- else:\r
- # always recreate top/platform makefile when clean, just in case of inconsistency\r
+ mqueue = mp.Queue()\r
+ for m in AutoGenObject.GetAllModuleInfo:\r
+ mqueue.put(m)\r
+\r
+ AutoGenObject.DataPipe.DataContainer = {"CommandTarget": self.Target}\r
+ AutoGenObject.DataPipe.DataContainer = {"Workspace_timestamp": AutoGenObject.Workspace._SrcTimeStamp}\r
+ AutoGenObject.CreateLibModuelDirs()\r
+ AutoGenObject.DataPipe.DataContainer = {"LibraryBuildDirectoryList":AutoGenObject.LibraryBuildDirectoryList}\r
+ AutoGenObject.DataPipe.DataContainer = {"ModuleBuildDirectoryList":AutoGenObject.ModuleBuildDirectoryList}\r
+ AutoGenObject.DataPipe.DataContainer = {"FdsCommandDict": AutoGenObject.Workspace.GenFdsCommandDict}\r
+ self.Progress.Start("Generating makefile and code")\r
+ data_pipe_file = os.path.join(AutoGenObject.BuildDir, "GlobalVar_%s_%s.bin" % (str(AutoGenObject.Guid),AutoGenObject.Arch))\r
+ AutoGenObject.DataPipe.dump(data_pipe_file)\r
+ cqueue = mp.Queue()\r
+ autogen_rt,errorcode = self.StartAutoGen(mqueue, AutoGenObject.DataPipe, self.SkipAutoGen, PcdMaList, cqueue)\r
+ AutoGenIdFile = os.path.join(GlobalData.gConfDirectory,".AutoGenIdFile.txt")\r
+ with open(AutoGenIdFile,"w") as fw:\r
+ fw.write("Arch=%s\n" % "|".join((AutoGenObject.Workspace.ArchList)))\r
+ fw.write("BuildDir=%s\n" % AutoGenObject.Workspace.BuildDir)\r
+ fw.write("PlatformGuid=%s\n" % str(AutoGenObject.Guid))\r
+ self.Progress.Stop("done!")\r
+ if not autogen_rt:\r
+ self.AutoGenMgr.TerminateWorkers()\r
+ self.AutoGenMgr.join(1)\r
+ raise FatalError(errorcode)\r
AutoGenObject.CreateCodeFile(False)\r
AutoGenObject.CreateMakeFile(False)\r
+ else:\r
+ # always recreate top/platform makefile when clean, just in case of inconsistency\r
+ AutoGenObject.CreateCodeFile(True)\r
+ AutoGenObject.CreateMakeFile(True)\r
\r
if EdkLogger.GetLevel() == EdkLogger.QUIET:\r
EdkLogger.quiet("Building ... %s" % repr(AutoGenObject))\r
(AutoGenObject.BuildTarget, AutoGenObject.ToolChain, AutoGenObject.Arch),\r
ExtraData=str(AutoGenObject))\r
\r
- makefile = GenMake.BuildFile(AutoGenObject)._FILE_NAME_[GenMake.gMakeType]\r
-\r
# run\r
if Target == 'run':\r
return True\r
BuildCommand = BuildCommand + [Target]\r
LaunchCommand(BuildCommand, AutoGenObject.MakeFileDir)\r
self.CreateAsBuiltInf()\r
+ if GlobalData.gBinCacheDest:\r
+ self.GenDestCache()\r
+ elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
+ # Only for --hash\r
+ # Update PreMakeCacheChain files\r
+ self.GenLocalPreMakeCache()\r
+ self.BuildModules = []\r
return True\r
\r
# build library\r
if Target == 'libraries':\r
- for Lib in AutoGenObject.LibraryBuildDirectoryList:\r
- NewBuildCommand = BuildCommand + ['-f', os.path.normpath(os.path.join(Lib, makefile)), 'pbuild']\r
- LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir)\r
+ DirList = []\r
+ for Lib in AutoGenObject.LibraryAutoGenList:\r
+ if not Lib.IsBinaryModule:\r
+ DirList.append((os.path.join(AutoGenObject.BuildDir, Lib.BuildDir),Lib))\r
+ for Lib, LibAutoGen in DirList:\r
+ NewBuildCommand = BuildCommand + ['-f', os.path.normpath(os.path.join(Lib, self.MakeFileName)), 'pbuild']\r
+ LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir,LibAutoGen)\r
return True\r
\r
# build module\r
if Target == 'modules':\r
- for Lib in AutoGenObject.LibraryBuildDirectoryList:\r
- NewBuildCommand = BuildCommand + ['-f', os.path.normpath(os.path.join(Lib, makefile)), 'pbuild']\r
- LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir)\r
- for Mod in AutoGenObject.ModuleBuildDirectoryList:\r
- NewBuildCommand = BuildCommand + ['-f', os.path.normpath(os.path.join(Mod, makefile)), 'pbuild']\r
- LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir)\r
+ DirList = []\r
+ for Lib in AutoGenObject.LibraryAutoGenList:\r
+ if not Lib.IsBinaryModule:\r
+ DirList.append((os.path.join(AutoGenObject.BuildDir, Lib.BuildDir),Lib))\r
+ for Lib, LibAutoGen in DirList:\r
+ NewBuildCommand = BuildCommand + ['-f', os.path.normpath(os.path.join(Lib, self.MakeFileName)), 'pbuild']\r
+ LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir,LibAutoGen)\r
+\r
+ DirList = []\r
+ for ModuleAutoGen in AutoGenObject.ModuleAutoGenList:\r
+ if not ModuleAutoGen.IsBinaryModule:\r
+ DirList.append((os.path.join(AutoGenObject.BuildDir, ModuleAutoGen.BuildDir),ModuleAutoGen))\r
+ for Mod,ModAutoGen in DirList:\r
+ NewBuildCommand = BuildCommand + ['-f', os.path.normpath(os.path.join(Mod, self.MakeFileName)), 'pbuild']\r
+ LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir,ModAutoGen)\r
self.CreateAsBuiltInf()\r
+ if GlobalData.gBinCacheDest:\r
+ self.GenDestCache()\r
+ elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
+ # Only for --hash\r
+ # Update PreMakeCacheChain files\r
+ self.GenLocalPreMakeCache()\r
+ self.BuildModules = []\r
return True\r
\r
# cleanlib\r
if Target == 'cleanlib':\r
for Lib in AutoGenObject.LibraryBuildDirectoryList:\r
- LibMakefile = os.path.normpath(os.path.join(Lib, makefile))\r
+ LibMakefile = os.path.normpath(os.path.join(Lib, self.MakeFileName))\r
if os.path.exists(LibMakefile):\r
NewBuildCommand = BuildCommand + ['-f', LibMakefile, 'cleanall']\r
LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir)\r
# clean\r
if Target == 'clean':\r
for Mod in AutoGenObject.ModuleBuildDirectoryList:\r
- ModMakefile = os.path.normpath(os.path.join(Mod, makefile))\r
+ ModMakefile = os.path.normpath(os.path.join(Mod, self.MakeFileName))\r
if os.path.exists(ModMakefile):\r
NewBuildCommand = BuildCommand + ['-f', ModMakefile, 'cleanall']\r
LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir)\r
for Lib in AutoGenObject.LibraryBuildDirectoryList:\r
- LibMakefile = os.path.normpath(os.path.join(Lib, makefile))\r
+ LibMakefile = os.path.normpath(os.path.join(Lib, self.MakeFileName))\r
if os.path.exists(LibMakefile):\r
NewBuildCommand = BuildCommand + ['-f', LibMakefile, 'cleanall']\r
LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir)\r
return True\r
else:\r
# always recreate top/platform makefile when clean, just in case of inconsistency\r
- AutoGenObject.CreateCodeFile(False)\r
- AutoGenObject.CreateMakeFile(False)\r
+ AutoGenObject.CreateCodeFile(True)\r
+ AutoGenObject.CreateMakeFile(True)\r
\r
if EdkLogger.GetLevel() == EdkLogger.QUIET:\r
EdkLogger.quiet("Building ... %s" % repr(AutoGenObject))\r
BuildCommand = BuildCommand + [Target]\r
AutoGenObject.BuildTime = LaunchCommand(BuildCommand, AutoGenObject.MakeFileDir)\r
self.CreateAsBuiltInf()\r
+ if GlobalData.gBinCacheDest:\r
+ self.GenDestCache()\r
+ elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
+ # Only for --hash\r
+ # Update PreMakeCacheChain files\r
+ self.GenLocalPreMakeCache()\r
+ self.BuildModules = []\r
return True\r
\r
# genfds\r
if Target == 'fds':\r
if GenFdsApi(AutoGenObject.GenFdsCommandDict, self.Db):\r
EdkLogger.error("build", COMMAND_FAILURE)\r
+ Threshold = self.GetFreeSizeThreshold()\r
+ if Threshold:\r
+ self.CheckFreeSizeThreshold(Threshold, AutoGenObject.FvDir)\r
return True\r
\r
# run\r
if self.Fdf:\r
# First get the XIP base address for FV map file.\r
GuidPattern = re.compile("[-a-fA-F0-9]+")\r
- GuidName = re.compile("\(GUID=[-a-fA-F0-9]+")\r
+ GuidName = re.compile(r"\(GUID=[-a-fA-F0-9]+")\r
for FvName in Wa.FdfProfile.FvDict:\r
FvMapBuffer = os.path.join(Wa.FvDir, FvName + '.Fv.map')\r
if not os.path.exists(FvMapBuffer):\r
CmdListDict = self._GenFfsCmd(Wa.ArchList)\r
\r
for Arch in Wa.ArchList:\r
+ PcdMaList = []\r
GlobalData.gGlobalDefines['ARCH'] = Arch\r
Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)\r
for Module in Pa.Platform.Modules:\r
# Get ModuleAutoGen object to generate C code file and makefile\r
- Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile)\r
+ Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
if Ma is None:\r
continue\r
+ if Ma.PcdIsDriver:\r
+ Ma.PlatformInfo = Pa\r
+ Ma.Workspace = Wa\r
+ PcdMaList.append(Ma)\r
self.BuildModules.append(Ma)\r
- self._BuildPa(self.Target, Pa, FfsCommand=CmdListDict)\r
+ Pa.DataPipe.DataContainer = {"FfsCommand":CmdListDict}\r
+ Pa.DataPipe.DataContainer = {"Workspace_timestamp": Wa._SrcTimeStamp}\r
+ self._BuildPa(self.Target, Pa, FfsCommand=CmdListDict,PcdMaList=PcdMaList)\r
\r
# Create MAP file when Load Fix Address is enabled.\r
if self.Target in ["", "all", "fds"]:\r
# Save MAP buffer into MAP file.\r
#\r
self._SaveMapFile (MapBuffer, Wa)\r
+ self.CreateGuidedSectionToolsFile(Wa)\r
\r
## Build active module for different build targets, different tool chains and different archs\r
#\r
CmdListDict = None\r
if GlobalData.gEnableGenfdsMultiThread and self.Fdf:\r
CmdListDict = self._GenFfsCmd(Wa.ArchList)\r
+\r
+ GlobalData.file_lock = mp.Lock()\r
+ GlobalData.FfsCmd = CmdListDict\r
+\r
self.Progress.Stop("done!")\r
MaList = []\r
ExitFlag = threading.Event()\r
Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)\r
for Module in Pa.Platform.Modules:\r
if self.ModuleFile.Dir == Module.Dir and self.ModuleFile.Name == Module.Name:\r
- Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile)\r
+ Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
if Ma is None:\r
continue\r
+ if Ma.PcdIsDriver:\r
+ Ma.PlatformInfo = Pa\r
+ Ma.Workspace = Wa\r
MaList.append(Ma)\r
- if Ma.CanSkipbyHash():\r
- self.HashSkipModules.append(Ma)\r
- if GlobalData.gBinCacheSource:\r
- EdkLogger.quiet("cache hit: %s[%s]" % (Ma.MetaFile.Path, Ma.Arch))\r
- continue\r
- else:\r
- if GlobalData.gBinCacheSource:\r
- EdkLogger.quiet("cache miss: %s[%s]" % (Ma.MetaFile.Path, Ma.Arch))\r
+\r
+ if GlobalData.gUseHashCache and not GlobalData.gBinCacheDest and self.Target in [None, "", "all"]:\r
+ if Ma.CanSkipbyPreMakeCache():\r
+ continue\r
+ else:\r
+ self.PreMakeCacheMiss.add(Ma)\r
+\r
# Not to auto-gen for targets 'clean', 'cleanlib', 'cleanall', 'run', 'fds'\r
if self.Target not in ['clean', 'cleanlib', 'cleanall', 'run', 'fds']:\r
# for target which must generate AutoGen code and makefile\r
return True\r
if not self.SkipAutoGen or self.Target == 'genmake':\r
self.Progress.Start("Generating makefile")\r
- if CmdListDict and self.Fdf and (Module.File, Arch) in CmdListDict:\r
- Ma.CreateMakeFile(True, CmdListDict[Module.File, Arch])\r
- del CmdListDict[Module.File, Arch]\r
+ if CmdListDict and self.Fdf and (Module.Path, Arch) in CmdListDict:\r
+ Ma.CreateMakeFile(True, CmdListDict[Module.Path, Arch])\r
+ del CmdListDict[Module.Path, Arch]\r
else:\r
Ma.CreateMakeFile(True)\r
self.Progress.Stop("done!")\r
if self.Target == "genmake":\r
return True\r
+\r
+ if GlobalData.gBinCacheSource and self.Target in [None, "", "all"]:\r
+ if Ma.CanSkipbyMakeCache():\r
+ continue\r
+ else:\r
+ self.MakeCacheMiss.add(Ma)\r
+\r
self.BuildModules.append(Ma)\r
- # Initialize all modules in tracking to 'FAIL'\r
- if Ma.Arch not in GlobalData.gModuleBuildTracking:\r
- GlobalData.gModuleBuildTracking[Ma.Arch] = dict()\r
- if Ma not in GlobalData.gModuleBuildTracking[Ma.Arch]:\r
- GlobalData.gModuleBuildTracking[Ma.Arch][Ma] = 'FAIL'\r
self.AutoGenTime += int(round((time.time() - AutoGenStart)))\r
MakeStart = time.time()\r
for Ma in self.BuildModules:\r
if not Ma.IsBinaryModule:\r
- Bt = BuildTask.New(ModuleMakeUnit(Ma, self.Target))\r
+ Bt = BuildTask.New(ModuleMakeUnit(Ma, Pa.BuildCommand,self.Target))\r
# Break build if any build thread has error\r
if BuildTask.HasError():\r
# we need a full version of makefile for platform\r
ExitFlag.set()\r
BuildTask.WaitForComplete()\r
- self.invalidateHash()\r
Pa.CreateMakeFile(False)\r
EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
# Start task scheduler\r
# in case there's an interruption. we need a full version of makefile for platform\r
Pa.CreateMakeFile(False)\r
if BuildTask.HasError():\r
- self.invalidateHash()\r
EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
self.MakeTime += int(round((time.time() - MakeStart)))\r
\r
ExitFlag.set()\r
BuildTask.WaitForComplete()\r
self.CreateAsBuiltInf()\r
+ if GlobalData.gBinCacheDest:\r
+ self.GenDestCache()\r
+ elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
+ # Only for --hash\r
+ # Update PreMakeCacheChain files\r
+ self.GenLocalPreMakeCache()\r
+ self.BuildModules = []\r
self.MakeTime += int(round((time.time() - MakeContiue)))\r
if BuildTask.HasError():\r
- self.invalidateHash()\r
EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
\r
self.BuildReport.AddPlatformReport(Wa, MaList)\r
# Save MAP buffer into MAP file.\r
#\r
self._SaveMapFile (MapBuffer, Wa)\r
- self.invalidateHash()\r
\r
def _GenFfsCmd(self,ArchList):\r
# convert dictionary of Cmd:(Inf,Arch)\r
tmpInf, tmpArch = GenFfsDict[Cmd]\r
CmdSetDict[tmpInf, tmpArch].add(Cmd)\r
return CmdSetDict\r
+ def VerifyAutoGenFiles(self):\r
+ AutoGenIdFile = os.path.join(GlobalData.gConfDirectory,".AutoGenIdFile.txt")\r
+ try:\r
+ with open(AutoGenIdFile) as fd:\r
+ lines = fd.readlines()\r
+ except:\r
+ return None\r
+ for line in lines:\r
+ if "Arch" in line:\r
+ ArchList = line.strip().split("=")[1].split("|")\r
+ if "BuildDir" in line:\r
+ BuildDir = line.split("=")[1].strip()\r
+ if "PlatformGuid" in line:\r
+ PlatformGuid = line.split("=")[1].strip()\r
+ GlobalVarList = []\r
+ for arch in ArchList:\r
+ global_var = os.path.join(BuildDir, "GlobalVar_%s_%s.bin" % (str(PlatformGuid),arch))\r
+ if not os.path.exists(global_var):\r
+ return None\r
+ GlobalVarList.append(global_var)\r
+ for global_var in GlobalVarList:\r
+ data_pipe = MemoryDataPipe()\r
+ data_pipe.load(global_var)\r
+ target = data_pipe.Get("P_Info").get("Target")\r
+ toolchain = data_pipe.Get("P_Info").get("ToolChain")\r
+ archlist = data_pipe.Get("P_Info").get("ArchList")\r
+ Arch = data_pipe.Get("P_Info").get("Arch")\r
+ active_p = data_pipe.Get("P_Info").get("ActivePlatform")\r
+ workspacedir = data_pipe.Get("P_Info").get("WorkspaceDir")\r
+ PackagesPath = os.getenv("PACKAGES_PATH")\r
+ mws.setWs(workspacedir, PackagesPath)\r
+ LibraryBuildDirectoryList = data_pipe.Get("LibraryBuildDirectoryList")\r
+ ModuleBuildDirectoryList = data_pipe.Get("ModuleBuildDirectoryList")\r
+\r
+ for m_build_dir in LibraryBuildDirectoryList:\r
+ if not os.path.exists(os.path.join(m_build_dir,self.MakeFileName)):\r
+ return None\r
+ for m_build_dir in ModuleBuildDirectoryList:\r
+ if not os.path.exists(os.path.join(m_build_dir,self.MakeFileName)):\r
+ return None\r
+ Wa = WorkSpaceInfo(\r
+ workspacedir,active_p,target,toolchain,archlist\r
+ )\r
+ Pa = PlatformInfo(Wa, active_p, target, toolchain, Arch,data_pipe)\r
+ Wa.AutoGenObjectList.append(Pa)\r
+ return Wa\r
+ def SetupMakeSetting(self,Wa):\r
+ BuildModules = []\r
+ for Pa in Wa.AutoGenObjectList:\r
+ for m in Pa._MbList:\r
+ ma = ModuleAutoGen(Wa,m.MetaFile, Pa.BuildTarget, Wa.ToolChain, Pa.Arch, Pa.MetaFile,Pa.DataPipe)\r
+ BuildModules.append(ma)\r
+ fdf_file = Wa.FlashDefinition\r
+ if fdf_file:\r
+ Fdf = FdfParser(fdf_file.Path)\r
+ Fdf.ParseFile()\r
+ GlobalData.gFdfParser = Fdf\r
+ if Fdf.CurrentFdName and Fdf.CurrentFdName in Fdf.Profile.FdDict:\r
+ FdDict = Fdf.Profile.FdDict[Fdf.CurrentFdName]\r
+ for FdRegion in FdDict.RegionList:\r
+ if str(FdRegion.RegionType) == 'FILE' and self.Platform.VpdToolGuid in str(FdRegion.RegionDataList):\r
+ if int(FdRegion.Offset) % 8 != 0:\r
+ EdkLogger.error("build", FORMAT_INVALID, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion.Offset))\r
+ Wa.FdfProfile = Fdf.Profile\r
+ self.Fdf = Fdf\r
+ else:\r
+ self.Fdf = None\r
+ return BuildModules\r
\r
## Build a platform in multi-thread mode\r
#\r
+ def PerformAutoGen(self,BuildTarget,ToolChain):\r
+ WorkspaceAutoGenTime = time.time()\r
+ Wa = WorkspaceAutoGen(\r
+ self.WorkspaceDir,\r
+ self.PlatformFile,\r
+ BuildTarget,\r
+ ToolChain,\r
+ self.ArchList,\r
+ self.BuildDatabase,\r
+ self.TargetTxt,\r
+ self.ToolDef,\r
+ self.Fdf,\r
+ self.FdList,\r
+ self.FvList,\r
+ self.CapList,\r
+ self.SkuId,\r
+ self.UniFlag,\r
+ self.Progress\r
+ )\r
+ self.Fdf = Wa.FdfFile\r
+ self.LoadFixAddress = Wa.Platform.LoadFixAddress\r
+ self.BuildReport.AddPlatformReport(Wa)\r
+ Wa.CreateMakeFile(False)\r
+\r
+ # Add ffs build to makefile\r
+ CmdListDict = {}\r
+ if GlobalData.gEnableGenfdsMultiThread and self.Fdf:\r
+ CmdListDict = self._GenFfsCmd(Wa.ArchList)\r
+\r
+ self.AutoGenTime += int(round((time.time() - WorkspaceAutoGenTime)))\r
+ BuildModules = []\r
+ for Arch in Wa.ArchList:\r
+ PcdMaList = []\r
+ AutoGenStart = time.time()\r
+ GlobalData.gGlobalDefines['ARCH'] = Arch\r
+ Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)\r
+ if Pa is None:\r
+ continue\r
+ ModuleList = []\r
+ for Inf in Pa.Platform.Modules:\r
+ ModuleList.append(Inf)\r
+ # Add the INF only list in FDF\r
+ if GlobalData.gFdfParser is not None:\r
+ for InfName in GlobalData.gFdfParser.Profile.InfList:\r
+ Inf = PathClass(NormPath(InfName), self.WorkspaceDir, Arch)\r
+ if Inf in Pa.Platform.Modules:\r
+ continue\r
+ ModuleList.append(Inf)\r
+ Pa.DataPipe.DataContainer = {"FfsCommand":CmdListDict}\r
+ Pa.DataPipe.DataContainer = {"Workspace_timestamp": Wa._SrcTimeStamp}\r
+ Pa.DataPipe.DataContainer = {"CommandTarget": self.Target}\r
+ Pa.CreateLibModuelDirs()\r
+ # Fetch the MakeFileName.\r
+ self.MakeFileName = Pa.MakeFileName\r
+ if not self.MakeFileName:\r
+ self.MakeFileName = Pa.MakeFile\r
+\r
+ Pa.DataPipe.DataContainer = {"LibraryBuildDirectoryList":Pa.LibraryBuildDirectoryList}\r
+ Pa.DataPipe.DataContainer = {"ModuleBuildDirectoryList":Pa.ModuleBuildDirectoryList}\r
+ Pa.DataPipe.DataContainer = {"FdsCommandDict": Wa.GenFdsCommandDict}\r
+ # Prepare the cache share data for multiprocessing\r
+ Pa.DataPipe.DataContainer = {"gPlatformHashFile":GlobalData.gPlatformHashFile}\r
+ ModuleCodaFile = {}\r
+ for ma in Pa.ModuleAutoGenList:\r
+ ModuleCodaFile[(ma.MetaFile.File,ma.MetaFile.Root,ma.Arch,ma.MetaFile.Path)] = [item.Target for item in ma.CodaTargetList]\r
+ Pa.DataPipe.DataContainer = {"ModuleCodaFile":ModuleCodaFile}\r
+ # ModuleList contains all driver modules only\r
+ for Module in ModuleList:\r
+ # Get ModuleAutoGen object to generate C code file and makefile\r
+ Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
+ if Ma is None:\r
+ continue\r
+ if Ma.PcdIsDriver:\r
+ Ma.PlatformInfo = Pa\r
+ Ma.Workspace = Wa\r
+ PcdMaList.append(Ma)\r
+ self.AllDrivers.add(Ma)\r
+ self.AllModules.add(Ma)\r
+\r
+ mqueue = mp.Queue()\r
+ cqueue = mp.Queue()\r
+ for m in Pa.GetAllModuleInfo:\r
+ mqueue.put(m)\r
+ module_file,module_root,module_path,module_basename,\\r
+ module_originalpath,module_arch,IsLib = m\r
+ Ma = ModuleAutoGen(Wa, PathClass(module_path, Wa), BuildTarget,\\r
+ ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
+ self.AllModules.add(Ma)\r
+ data_pipe_file = os.path.join(Pa.BuildDir, "GlobalVar_%s_%s.bin" % (str(Pa.Guid),Pa.Arch))\r
+ Pa.DataPipe.dump(data_pipe_file)\r
+\r
+ autogen_rt, errorcode = self.StartAutoGen(mqueue, Pa.DataPipe, self.SkipAutoGen, PcdMaList, cqueue)\r
+\r
+ if not autogen_rt:\r
+ self.AutoGenMgr.TerminateWorkers()\r
+ self.AutoGenMgr.join(1)\r
+ raise FatalError(errorcode)\r
+\r
+ if GlobalData.gUseHashCache:\r
+ for item in GlobalData.gModuleAllCacheStatus:\r
+ (MetaFilePath, Arch, CacheStr, Status) = item\r
+ Ma = ModuleAutoGen(Wa, PathClass(MetaFilePath, Wa), BuildTarget,\\r
+ ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
+ if CacheStr == "PreMakeCache" and Status == False:\r
+ self.PreMakeCacheMiss.add(Ma)\r
+ if CacheStr == "PreMakeCache" and Status == True:\r
+ self.PreMakeCacheHit.add(Ma)\r
+ GlobalData.gModuleCacheHit.add(Ma)\r
+ if CacheStr == "MakeCache" and Status == False:\r
+ self.MakeCacheMiss.add(Ma)\r
+ if CacheStr == "MakeCache" and Status == True:\r
+ self.MakeCacheHit.add(Ma)\r
+ GlobalData.gModuleCacheHit.add(Ma)\r
+ self.AutoGenTime += int(round((time.time() - AutoGenStart)))\r
+ AutoGenIdFile = os.path.join(GlobalData.gConfDirectory,".AutoGenIdFile.txt")\r
+ with open(AutoGenIdFile,"w") as fw:\r
+ fw.write("Arch=%s\n" % "|".join((Wa.ArchList)))\r
+ fw.write("BuildDir=%s\n" % Wa.BuildDir)\r
+ fw.write("PlatformGuid=%s\n" % str(Wa.AutoGenObjectList[0].Guid))\r
+\r
+ if GlobalData.gBinCacheSource:\r
+ BuildModules.extend(self.MakeCacheMiss)\r
+ elif GlobalData.gUseHashCache and not GlobalData.gBinCacheDest:\r
+ BuildModules.extend(self.PreMakeCacheMiss)\r
+ else:\r
+ BuildModules.extend(self.AllDrivers)\r
+\r
+ self.Progress.Stop("done!")\r
+ return Wa, BuildModules\r
+\r
def _MultiThreadBuildPlatform(self):\r
SaveFileOnChange(self.PlatformBuildPath, '# DO NOT EDIT \n# FILE auto-generated\n', False)\r
for BuildTarget in self.BuildTargetList:\r
GlobalData.gGlobalDefines['TARGET'] = BuildTarget\r
index = 0\r
for ToolChain in self.ToolChainList:\r
- WorkspaceAutoGenTime = time.time()\r
+ resetFdsGlobalVariable()\r
GlobalData.gGlobalDefines['TOOLCHAIN'] = ToolChain\r
GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = ToolChain\r
GlobalData.gGlobalDefines['FAMILY'] = self.ToolChainFamily[index]\r
index += 1\r
- Wa = WorkspaceAutoGen(\r
- self.WorkspaceDir,\r
- self.PlatformFile,\r
- BuildTarget,\r
- ToolChain,\r
- self.ArchList,\r
- self.BuildDatabase,\r
- self.TargetTxt,\r
- self.ToolDef,\r
- self.Fdf,\r
- self.FdList,\r
- self.FvList,\r
- self.CapList,\r
- self.SkuId,\r
- self.UniFlag,\r
- self.Progress\r
- )\r
- self.Fdf = Wa.FdfFile\r
- self.LoadFixAddress = Wa.Platform.LoadFixAddress\r
- self.BuildReport.AddPlatformReport(Wa)\r
- Wa.CreateMakeFile(False)\r
-\r
- # Add ffs build to makefile\r
- CmdListDict = None\r
- if GlobalData.gEnableGenfdsMultiThread and self.Fdf:\r
- CmdListDict = self._GenFfsCmd(Wa.ArchList)\r
-\r
- # multi-thread exit flag\r
ExitFlag = threading.Event()\r
ExitFlag.clear()\r
- self.AutoGenTime += int(round((time.time() - WorkspaceAutoGenTime)))\r
- for Arch in Wa.ArchList:\r
- AutoGenStart = time.time()\r
- GlobalData.gGlobalDefines['ARCH'] = Arch\r
- Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)\r
- if Pa is None:\r
- continue\r
- ModuleList = []\r
- for Inf in Pa.Platform.Modules:\r
- ModuleList.append(Inf)\r
- # Add the INF only list in FDF\r
- if GlobalData.gFdfParser is not None:\r
- for InfName in GlobalData.gFdfParser.Profile.InfList:\r
- Inf = PathClass(NormPath(InfName), self.WorkspaceDir, Arch)\r
- if Inf in Pa.Platform.Modules:\r
- continue\r
- ModuleList.append(Inf)\r
- for Module in ModuleList:\r
- # Get ModuleAutoGen object to generate C code file and makefile\r
- Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile)\r
+ if self.SkipAutoGen:\r
+ Wa = self.VerifyAutoGenFiles()\r
+ if Wa is None:\r
+ self.SkipAutoGen = False\r
+ Wa, self.BuildModules = self.PerformAutoGen(BuildTarget,ToolChain)\r
+ else:\r
+ GlobalData.gAutoGenPhase = True\r
+ self.BuildModules = self.SetupMakeSetting(Wa)\r
+ else:\r
+ Wa, self.BuildModules = self.PerformAutoGen(BuildTarget,ToolChain)\r
+ Pa = Wa.AutoGenObjectList[0]\r
+ GlobalData.gAutoGenPhase = False\r
\r
- if Ma is None:\r
- continue\r
- if Ma.CanSkipbyHash():\r
- self.HashSkipModules.append(Ma)\r
- if GlobalData.gBinCacheSource:\r
- EdkLogger.quiet("cache hit: %s[%s]" % (Ma.MetaFile.Path, Ma.Arch))\r
- continue\r
- else:\r
- if GlobalData.gBinCacheSource:\r
- EdkLogger.quiet("cache miss: %s[%s]" % (Ma.MetaFile.Path, Ma.Arch))\r
-\r
- # Not to auto-gen for targets 'clean', 'cleanlib', 'cleanall', 'run', 'fds'\r
- if self.Target not in ['clean', 'cleanlib', 'cleanall', 'run', 'fds']:\r
- # for target which must generate AutoGen code and makefile\r
- if not self.SkipAutoGen or self.Target == 'genc':\r
- Ma.CreateCodeFile(True)\r
- if self.Target == "genc":\r
- continue\r
+ if GlobalData.gBinCacheSource:\r
+ EdkLogger.quiet("[cache Summary]: Total module num: %s" % len(self.AllModules))\r
+ EdkLogger.quiet("[cache Summary]: PreMakecache miss num: %s " % len(self.PreMakeCacheMiss))\r
+ EdkLogger.quiet("[cache Summary]: Makecache miss num: %s " % len(self.MakeCacheMiss))\r
\r
- if not self.SkipAutoGen or self.Target == 'genmake':\r
- if CmdListDict and self.Fdf and (Module.File, Arch) in CmdListDict:\r
- Ma.CreateMakeFile(True, CmdListDict[Module.File, Arch])\r
- del CmdListDict[Module.File, Arch]\r
- else:\r
- Ma.CreateMakeFile(True)\r
- if self.Target == "genmake":\r
- continue\r
- self.BuildModules.append(Ma)\r
- # Initialize all modules in tracking to 'FAIL'\r
- if Ma.Arch not in GlobalData.gModuleBuildTracking:\r
- GlobalData.gModuleBuildTracking[Ma.Arch] = dict()\r
- if Ma not in GlobalData.gModuleBuildTracking[Ma.Arch]:\r
- GlobalData.gModuleBuildTracking[Ma.Arch][Ma] = 'FAIL'\r
- self.Progress.Stop("done!")\r
- self.AutoGenTime += int(round((time.time() - AutoGenStart)))\r
+ for Arch in Wa.ArchList:\r
MakeStart = time.time()\r
- for Ma in self.BuildModules:\r
+ for Ma in set(self.BuildModules):\r
# Generate build task for the module\r
if not Ma.IsBinaryModule:\r
- Bt = BuildTask.New(ModuleMakeUnit(Ma, self.Target))\r
+ Bt = BuildTask.New(ModuleMakeUnit(Ma, Pa.BuildCommand,self.Target))\r
# Break build if any build thread has error\r
if BuildTask.HasError():\r
# we need a full version of makefile for platform\r
ExitFlag.set()\r
BuildTask.WaitForComplete()\r
- self.invalidateHash()\r
Pa.CreateMakeFile(False)\r
EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
# Start task scheduler\r
BuildTask.StartScheduler(self.ThreadNumber, ExitFlag)\r
\r
# in case there's an interruption. we need a full version of makefile for platform\r
- Pa.CreateMakeFile(False)\r
+\r
if BuildTask.HasError():\r
- self.invalidateHash()\r
EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
self.MakeTime += int(round((time.time() - MakeStart)))\r
\r
MakeContiue = time.time()\r
-\r
#\r
#\r
# All modules have been put in build tasks queue. Tell task scheduler\r
ExitFlag.set()\r
BuildTask.WaitForComplete()\r
self.CreateAsBuiltInf()\r
+ if GlobalData.gBinCacheDest:\r
+ self.GenDestCache()\r
+ elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
+ # Only for --hash\r
+ # Update PreMakeCacheChain files\r
+ self.GenLocalPreMakeCache()\r
+ #\r
+ # Get Module List\r
+ #\r
+ ModuleList = {ma.Guid.upper(): ma for ma in self.BuildModules}\r
+ self.BuildModules = []\r
self.MakeTime += int(round((time.time() - MakeContiue)))\r
#\r
# Check for build error, and raise exception if one\r
# has been signaled.\r
#\r
if BuildTask.HasError():\r
- self.invalidateHash()\r
EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
\r
# Create MAP file when Load Fix Address is enabled.\r
#\r
if (Arch == 'IA32' or Arch == 'ARM') and self.LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self.LoadFixAddress >= 0x100000000:\r
EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS can't be set to larger than or equal to 4G for the platorm with IA32 or ARM arch modules")\r
- #\r
- # Get Module List\r
- #\r
- ModuleList = {}\r
- for Pa in Wa.AutoGenObjectList:\r
- for Ma in Pa.ModuleAutoGenList:\r
- if Ma is None:\r
- continue\r
- if not Ma.IsLibrary:\r
- ModuleList[Ma.Guid.upper()] = Ma\r
+\r
#\r
# Rebase module to the preferred memory address before GenFds\r
#\r
GenFdsStart = time.time()\r
if GenFdsApi(Wa.GenFdsCommandDict, self.Db):\r
EdkLogger.error("build", COMMAND_FAILURE)\r
+ Threshold = self.GetFreeSizeThreshold()\r
+ if Threshold:\r
+ self.CheckFreeSizeThreshold(Threshold, Wa.FvDir)\r
\r
#\r
# Create MAP file for all platform FVs after GenFds.\r
# Save MAP buffer into MAP file.\r
#\r
self._SaveMapFile(MapBuffer, Wa)\r
- self.invalidateHash()\r
+ self.CreateGuidedSectionToolsFile(Wa)\r
+\r
+ ## GetFreeSizeThreshold()\r
+ #\r
+ # @retval int Threshold value\r
+ #\r
+ def GetFreeSizeThreshold(self):\r
+ Threshold = None\r
+ Threshold_Str = GlobalData.gCommandLineDefines.get('FV_SPARE_SPACE_THRESHOLD')\r
+ if Threshold_Str:\r
+ try:\r
+ if Threshold_Str.lower().startswith('0x'):\r
+ Threshold = int(Threshold_Str, 16)\r
+ else:\r
+ Threshold = int(Threshold_Str)\r
+ except:\r
+ EdkLogger.warn("build", 'incorrect value for FV_SPARE_SPACE_THRESHOLD %s.Only decimal or hex format is allowed.' % Threshold_Str)\r
+ return Threshold\r
+\r
+ def CheckFreeSizeThreshold(self, Threshold=None, FvDir=None):\r
+ if not isinstance(Threshold, int):\r
+ return\r
+ if not isinstance(FvDir, str) or not FvDir:\r
+ return\r
+ FdfParserObject = GlobalData.gFdfParser\r
+ FvRegionNameList = [FvName for FvName in FdfParserObject.Profile.FvDict if FdfParserObject.Profile.FvDict[FvName].FvRegionInFD]\r
+ for FvName in FdfParserObject.Profile.FvDict:\r
+ if FvName in FvRegionNameList:\r
+ FvSpaceInfoFileName = os.path.join(FvDir, FvName.upper() + '.Fv.map')\r
+ if os.path.exists(FvSpaceInfoFileName):\r
+ FileLinesList = getlines(FvSpaceInfoFileName)\r
+ for Line in FileLinesList:\r
+ NameValue = Line.split('=')\r
+ if len(NameValue) == 2 and NameValue[0].strip() == 'EFI_FV_SPACE_SIZE':\r
+ FreeSizeValue = int(NameValue[1].strip(), 0)\r
+ if FreeSizeValue < Threshold:\r
+ EdkLogger.error("build", FV_FREESIZE_ERROR,\r
+ '%s FV free space %d is not enough to meet with the required spare space %d set by -D FV_SPARE_SPACE_THRESHOLD option.' % (\r
+ FvName, FreeSizeValue, Threshold))\r
+ break\r
\r
## Generate GuidedSectionTools.txt in the FV directories.\r
#\r
- def CreateGuidedSectionToolsFile(self):\r
+ def CreateGuidedSectionToolsFile(self,Wa):\r
for BuildTarget in self.BuildTargetList:\r
for ToolChain in self.ToolChainList:\r
- Wa = WorkspaceAutoGen(\r
- self.WorkspaceDir,\r
- self.PlatformFile,\r
- BuildTarget,\r
- ToolChain,\r
- self.ArchList,\r
- self.BuildDatabase,\r
- self.TargetTxt,\r
- self.ToolDef,\r
- self.Fdf,\r
- self.FdList,\r
- self.FvList,\r
- self.CapList,\r
- self.SkuId,\r
- self.UniFlag\r
- )\r
FvDir = Wa.FvDir\r
if not os.path.exists(FvDir):\r
continue\r
toolName = split[3]\r
path = '_'.join(split[0:4]) + '_PATH'\r
path = self.ToolDef.ToolsDefTxtDictionary[path]\r
- path = self.GetFullPathOfTool(path)\r
+ path = self.GetRealPathOfTool(path)\r
guidAttribs.append((guid, toolName, path))\r
\r
# Write out GuidedSecTools.txt\r
print(' '.join(guidedSectionTool), file=toolsFile)\r
toolsFile.close()\r
\r
- ## Returns the full path of the tool.\r
+ ## Returns the real path of the tool.\r
#\r
- def GetFullPathOfTool (self, tool):\r
+ def GetRealPathOfTool (self, tool):\r
if os.path.exists(tool):\r
return os.path.realpath(tool)\r
- else:\r
- # We need to search for the tool using the\r
- # PATH environment variable.\r
- for dirInPath in os.environ['PATH'].split(os.pathsep):\r
- foundPath = os.path.join(dirInPath, tool)\r
- if os.path.exists(foundPath):\r
- return os.path.realpath(foundPath)\r
-\r
- # If the tool was not found in the path then we just return\r
- # the input tool.\r
return tool\r
\r
## Launch the module or platform build\r
#\r
def Launch(self):\r
+ self.AllDrivers = set()\r
+ self.AllModules = set()\r
+ self.PreMakeCacheMiss = set()\r
+ self.PreMakeCacheHit = set()\r
+ self.MakeCacheMiss = set()\r
+ self.MakeCacheHit = set()\r
if not self.ModuleFile:\r
if not self.SpawnMode or self.Target not in ["", "all"]:\r
self.SpawnMode = False\r
self._BuildPlatform()\r
else:\r
self._MultiThreadBuildPlatform()\r
- self.CreateGuidedSectionToolsFile()\r
else:\r
self.SpawnMode = False\r
self._BuildModule()\r
RemoveDirectory(os.path.dirname(GlobalData.gDatabasePath), True)\r
\r
def CreateAsBuiltInf(self):\r
- all_lib_set = set()\r
- all_mod_set = set()\r
for Module in self.BuildModules:\r
Module.CreateAsBuiltInf()\r
- all_mod_set.add(Module)\r
- for Module in self.HashSkipModules:\r
- Module.CreateAsBuiltInf(True)\r
- all_mod_set.add(Module)\r
- for Module in all_mod_set:\r
- for lib in Module.LibraryAutoGenList:\r
- all_lib_set.add(lib)\r
- for lib in all_lib_set:\r
- lib.CreateAsBuiltInf(True)\r
- all_lib_set.clear()\r
- all_mod_set.clear()\r
- self.BuildModules = []\r
- self.HashSkipModules = []\r
+\r
+ def GenDestCache(self):\r
+ for Module in self.AllModules:\r
+ Module.GenPreMakefileHashList()\r
+ Module.GenMakefileHashList()\r
+ Module.CopyModuleToCache()\r
+\r
+ def GenLocalPreMakeCache(self):\r
+ for Module in self.PreMakeCacheMiss:\r
+ Module.GenPreMakefileHashList()\r
+\r
## Do some clean-up works when error occurred\r
def Relinquish(self):\r
OldLogLevel = EdkLogger.GetLevel()\r
DefineDict[DefineTokenList[0]] = DefineTokenList[1].strip()\r
return DefineDict\r
\r
-gParamCheck = []\r
-def SingleCheckCallback(option, opt_str, value, parser):\r
- if option not in gParamCheck:\r
- setattr(parser.values, option.dest, value)\r
- gParamCheck.append(option)\r
- else:\r
- parser.error("Option %s only allows one instance in command line!" % option)\r
+\r
\r
def LogBuildTime(Time):\r
if Time:\r
return TimeDurStr\r
else:\r
return None\r
+def ThreadNum():\r
+ OptionParser = MyOptionParser()\r
+ if not OptionParser.BuildOption and not OptionParser.BuildTarget:\r
+ OptionParser.GetOption()\r
+ BuildOption, BuildTarget = OptionParser.BuildOption, OptionParser.BuildTarget\r
+ ThreadNumber = BuildOption.ThreadNumber\r
+ GlobalData.gCmdConfDir = BuildOption.ConfDirectory\r
+ if ThreadNumber is None:\r
+ TargetObj = TargetTxtDict()\r
+ ThreadNumber = TargetObj.Target.TargetTxtDictionary[TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER]\r
+ if ThreadNumber == '':\r
+ ThreadNumber = 0\r
+ else:\r
+ ThreadNumber = int(ThreadNumber, 0)\r
\r
-## Parse command line options\r
-#\r
-# Using standard Python module optparse to parse command line option of this tool.\r
-#\r
-# @retval Opt A optparse.Values object containing the parsed options\r
-# @retval Args Target of build command\r
-#\r
-def MyOptionParser():\r
- Parser = OptionParser(description=__copyright__, version=__version__, prog="build.exe", usage="%prog [options] [all|fds|genc|genmake|clean|cleanall|cleanlib|modules|libraries|run]")\r
- Parser.add_option("-a", "--arch", action="append", type="choice", choices=['IA32', 'X64', 'EBC', 'ARM', 'AARCH64'], dest="TargetArch",\r
- help="ARCHS is one of list: IA32, X64, ARM, AARCH64 or EBC, which overrides target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option.")\r
- Parser.add_option("-p", "--platform", action="callback", type="string", dest="PlatformFile", callback=SingleCheckCallback,\r
- help="Build the platform specified by the DSC file name argument, overriding target.txt's ACTIVE_PLATFORM definition.")\r
- Parser.add_option("-m", "--module", action="callback", type="string", dest="ModuleFile", callback=SingleCheckCallback,\r
- help="Build the module specified by the INF file name argument.")\r
- Parser.add_option("-b", "--buildtarget", type="string", dest="BuildTarget", help="Using the TARGET to build the platform, overriding target.txt's TARGET definition.",\r
- action="append")\r
- Parser.add_option("-t", "--tagname", action="append", type="string", dest="ToolChain",\r
- help="Using the Tool Chain Tagname to build the platform, overriding target.txt's TOOL_CHAIN_TAG definition.")\r
- Parser.add_option("-x", "--sku-id", action="callback", type="string", dest="SkuId", callback=SingleCheckCallback,\r
- help="Using this name of SKU ID to build the platform, overriding SKUID_IDENTIFIER in DSC file.")\r
-\r
- Parser.add_option("-n", action="callback", type="int", dest="ThreadNumber", callback=SingleCheckCallback,\r
- help="Build the platform using multi-threaded compiler. The value overrides target.txt's MAX_CONCURRENT_THREAD_NUMBER. When value is set to 0, tool automatically detect number of "\\r
- "processor threads, set value to 1 means disable multi-thread build, and set value to more than 1 means user specify the threads number to build.")\r
-\r
- Parser.add_option("-f", "--fdf", action="callback", type="string", dest="FdfFile", callback=SingleCheckCallback,\r
- help="The name of the FDF file to use, which overrides the setting in the DSC file.")\r
- Parser.add_option("-r", "--rom-image", action="append", type="string", dest="RomImage", default=[],\r
- help="The name of FD to be generated. The name must be from [FD] section in FDF file.")\r
- Parser.add_option("-i", "--fv-image", action="append", type="string", dest="FvImage", default=[],\r
- help="The name of FV to be generated. The name must be from [FV] section in FDF file.")\r
- Parser.add_option("-C", "--capsule-image", action="append", type="string", dest="CapName", default=[],\r
- help="The name of Capsule to be generated. The name must be from [Capsule] section in FDF file.")\r
- Parser.add_option("-u", "--skip-autogen", action="store_true", dest="SkipAutoGen", help="Skip AutoGen step.")\r
- Parser.add_option("-e", "--re-parse", action="store_true", dest="Reparse", help="Re-parse all meta-data files.")\r
-\r
- Parser.add_option("-c", "--case-insensitive", action="store_true", dest="CaseInsensitive", default=False, help="Don't check case of file name.")\r
-\r
- Parser.add_option("-w", "--warning-as-error", action="store_true", dest="WarningAsError", help="Treat warning in tools as error.")\r
- Parser.add_option("-j", "--log", action="store", dest="LogFile", help="Put log in specified file as well as on console.")\r
-\r
- Parser.add_option("-s", "--silent", action="store_true", type=None, dest="SilentMode",\r
- help="Make use of silent mode of (n)make.")\r
- Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")\r
- Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\\r
- "including library instances selected, final dependency expression, "\\r
- "and warning messages, etc.")\r
- Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")\r
- Parser.add_option("-D", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".")\r
-\r
- Parser.add_option("-y", "--report-file", action="store", dest="ReportFile", help="Create/overwrite the report to the specified filename.")\r
- Parser.add_option("-Y", "--report-type", action="append", type="choice", choices=['PCD', 'LIBRARY', 'FLASH', 'DEPEX', 'BUILD_FLAGS', 'FIXED_ADDRESS', 'HASH', 'EXECUTION_ORDER'], dest="ReportType", default=[],\r
- help="Flags that control the type of build report to generate. Must be one of: [PCD, LIBRARY, FLASH, DEPEX, BUILD_FLAGS, FIXED_ADDRESS, HASH, EXECUTION_ORDER]. "\\r
- "To specify more than one flag, repeat this option on the command line and the default flag set is [PCD, LIBRARY, FLASH, DEPEX, HASH, BUILD_FLAGS, FIXED_ADDRESS]")\r
- Parser.add_option("-F", "--flag", action="store", type="string", dest="Flag",\r
- help="Specify the specific option to parse EDK UNI file. Must be one of: [-c, -s]. -c is for EDK framework UNI file, and -s is for EDK UEFI UNI file. "\\r
- "This option can also be specified by setting *_*_*_BUILD_FLAGS in [BuildOptions] section of platform DSC. If they are both specified, this value "\\r
- "will override the setting in [BuildOptions] section of platform DSC.")\r
- Parser.add_option("-N", "--no-cache", action="store_true", dest="DisableCache", default=False, help="Disable build cache mechanism")\r
- Parser.add_option("--conf", action="store", type="string", dest="ConfDirectory", help="Specify the customized Conf directory.")\r
- Parser.add_option("--check-usage", action="store_true", dest="CheckUsage", default=False, help="Check usage content of entries listed in INF file.")\r
- Parser.add_option("--ignore-sources", action="store_true", dest="IgnoreSources", default=False, help="Focus to a binary build and ignore all source files")\r
- Parser.add_option("--pcd", action="append", dest="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")\r
- Parser.add_option("-l", "--cmd-len", action="store", type="int", dest="CommandLength", help="Specify the maximum line length of build command. Default is 4096.")\r
- Parser.add_option("--hash", action="store_true", dest="UseHashCache", default=False, help="Enable hash-based caching during build process.")\r
- Parser.add_option("--binary-destination", action="store", type="string", dest="BinCacheDest", help="Generate a cache of binary files in the specified directory.")\r
- Parser.add_option("--binary-source", action="store", type="string", dest="BinCacheSource", help="Consume a cache of binary files from the specified directory.")\r
- Parser.add_option("--genfds-multi-thread", action="store_true", dest="GenfdsMultiThread", default=False, help="Enable GenFds multi thread to generate ffs file.")\r
- Parser.add_option("--disable-include-path-check", action="store_true", dest="DisableIncludePathCheck", default=False, help="Disable the include path check for outside of package.")\r
- (Opt, Args) = Parser.parse_args()\r
- return (Opt, Args)\r
-\r
+ if ThreadNumber == 0:\r
+ try:\r
+ ThreadNumber = multiprocessing.cpu_count()\r
+ except (ImportError, NotImplementedError):\r
+ ThreadNumber = 1\r
+ return ThreadNumber\r
## Tool entrance method\r
#\r
# This method mainly dispatch specific methods per the command line options.\r
# @retval 0 Tool was successful\r
# @retval 1 Tool failed\r
#\r
+LogQMaxSize = ThreadNum() * 10\r
def Main():\r
StartTime = time.time()\r
\r
+ #\r
+ # Create a log Queue\r
+ #\r
+ LogQ = mp.Queue(LogQMaxSize)\r
# Initialize log system\r
- EdkLogger.Initialize()\r
+ EdkLogger.LogClientInitialize(LogQ)\r
GlobalData.gCommand = sys.argv[1:]\r
#\r
# Parse the options and args\r
#\r
- (Option, Target) = MyOptionParser()\r
+ OptionParser = MyOptionParser()\r
+ if not OptionParser.BuildOption and not OptionParser.BuildTarget:\r
+ OptionParser.GetOption()\r
+ Option, Target = OptionParser.BuildOption, OptionParser.BuildTarget\r
GlobalData.gOptions = Option\r
GlobalData.gCaseInsensitive = Option.CaseInsensitive\r
\r
# Set log level\r
+ LogLevel = EdkLogger.INFO\r
if Option.verbose is not None:\r
EdkLogger.SetLevel(EdkLogger.VERBOSE)\r
+ LogLevel = EdkLogger.VERBOSE\r
elif Option.quiet is not None:\r
EdkLogger.SetLevel(EdkLogger.QUIET)\r
+ LogLevel = EdkLogger.QUIET\r
elif Option.debug is not None:\r
EdkLogger.SetLevel(Option.debug + 1)\r
+ LogLevel = Option.debug + 1\r
else:\r
EdkLogger.SetLevel(EdkLogger.INFO)\r
\r
- if Option.LogFile is not None:\r
- EdkLogger.SetLogFile(Option.LogFile)\r
-\r
if Option.WarningAsError == True:\r
EdkLogger.SetWarningAsError()\r
+ Log_Agent = LogAgent(LogQ,LogLevel,Option.LogFile)\r
+ Log_Agent.start()\r
\r
if platform.platform().find("Windows") >= 0:\r
GlobalData.gIsWindows = True\r
if Option.Flag is not None and Option.Flag not in ['-c', '-s']:\r
EdkLogger.error("build", OPTION_VALUE_INVALID, "UNI flag must be one of -c or -s")\r
\r
- MyBuild = Build(Target, Workspace, Option)\r
+ MyBuild = Build(Target, Workspace, Option,LogQ)\r
GlobalData.gCommandLineDefines['ARCH'] = ' '.join(MyBuild.ArchList)\r
if not (MyBuild.LaunchPrebuildFlag and os.path.exists(MyBuild.PlatformBuildPath)):\r
MyBuild.Launch()\r
EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError=False)\r
ReturnCode = FORMAT_INVALID\r
except KeyboardInterrupt:\r
+ if MyBuild is not None:\r
+\r
+ # for multi-thread build exits safely\r
+ MyBuild.Relinquish()\r
ReturnCode = ABORT_ERROR\r
if Option is not None and Option.debug is not None:\r
EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r
EdkLogger.quiet("\n- %s -" % Conclusion)\r
EdkLogger.quiet(time.strftime("Build end time: %H:%M:%S, %b.%d %Y", time.localtime()))\r
EdkLogger.quiet("Build total time: %s\n" % BuildDurationStr)\r
+ Log_Agent.kill()\r
+ Log_Agent.join()\r
return ReturnCode\r
\r
if __name__ == '__main__':\r
+ try:\r
+ mp.set_start_method('spawn')\r
+ except:\r
+ pass\r
r = Main()\r
## 0-127 is a safe return range, and 1 is a standard default error\r
if r < 0 or r > 127: r = 1\r
sys.exit(r)\r
-\r