]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/build/build.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Source / Python / build / build.py
CommitLineData
52302d4d
LG
1## @file\r
2# build a platform or a module\r
3#\r
997a5d1b 4# Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>\r
ab957f03 5# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>\r
370544d1 6# Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>\r
259c184c 7# Copyright (c) 2020 - 2021, ARM Limited. All rights reserved.<BR>\r
52302d4d 8#\r
2e351cbe 9# SPDX-License-Identifier: BSD-2-Clause-Patent\r
52302d4d
LG
10#\r
11\r
12##\r
13# Import Modules\r
14#\r
1ccc4d89 15from __future__ import print_function\r
e8449e1d
FB
16from __future__ import absolute_import\r
17import os.path as path\r
52302d4d 18import sys\r
e8449e1d
FB
19import os\r
20import re\r
52302d4d
LG
21import glob\r
22import time\r
23import platform\r
24import traceback\r
29af38b0 25import multiprocessing\r
e8449e1d 26from threading import Thread,Event,BoundedSemaphore\r
b2985672 27import threading\r
3a3a3af4 28from linecache import getlines\r
01b6090b 29from subprocess import Popen,PIPE, STDOUT\r
e8449e1d 30from collections import OrderedDict, defaultdict\r
4465cd12 31\r
e8449e1d
FB
32from AutoGen.PlatformAutoGen import PlatformAutoGen\r
33from AutoGen.ModuleAutoGen import ModuleAutoGen\r
34from AutoGen.WorkspaceAutoGen import WorkspaceAutoGen\r
636ed13a
FB
35from AutoGen.AutoGenWorker import AutoGenWorkerInProcess,AutoGenManager,\\r
36 LogAgent\r
e8449e1d 37from AutoGen import GenMake\r
52302d4d
LG
38from Common import Misc as Utils\r
39\r
4465cd12
FZ
40from Common.TargetTxtClassObject import TargetTxtDict\r
41from Common.ToolDefClassObject import ToolDefDict\r
42from buildoptions import MyOptionParser\r
e8449e1d
FB
43from Common.Misc import PathClass,SaveFileOnChange,RemoveDirectory\r
44from Common.StringUtils import NormPath\r
45from Common.MultipleWorkspace import MultipleWorkspace as mws\r
46from Common.BuildToolError import *\r
52302d4d 47from Common.DataType import *\r
e8449e1d 48import Common.EdkLogger as EdkLogger\r
c60fb00f 49\r
e8449e1d 50from Workspace.WorkspaceDatabase import BuildDB\r
52302d4d
LG
51\r
52from BuildReport import BuildReport\r
e8449e1d
FB
53from GenPatchPcdTable.GenPatchPcdTable import PeImageClass,parsePcdInfoFromMapFile\r
54from PatchPcdValue.PatchPcdValue import PatchBinaryFile\r
52302d4d 55\r
52302d4d 56import Common.GlobalData as GlobalData\r
b3497bad 57from GenFds.GenFds import GenFds, GenFdsApi\r
673d09a2 58import multiprocessing as mp\r
3285fbda 59from multiprocessing import Manager\r
373298ca
FB
60from AutoGen.DataPipe import MemoryDataPipe\r
61from AutoGen.ModuleAutoGenHelper import WorkSpaceInfo, PlatformInfo\r
62from GenFds.FdfParser import FdfParser\r
0c3e8e99 63from AutoGen.IncludesAutoGen import IncludesAutoGen\r
78fb6b0e 64from GenFds.GenFds import resetFdsGlobalVariable\r
ef3840c1 65from AutoGen.AutoGen import CalculatePriorityValue\r
52302d4d
LG
66\r
67## standard targets of build command\r
68gSupportedTarget = ['all', 'genc', 'genmake', 'modules', 'libraries', 'fds', 'clean', 'cleanall', 'cleanlib', 'run']\r
69\r
64b2609f
LG
70TemporaryTablePattern = re.compile(r'^_\d+_\d+_[a-fA-F0-9]+$')\r
71TmpTableDict = {}\r
72\r
52302d4d
LG
73## Check environment PATH variable to make sure the specified tool is found\r
74#\r
75# If the tool is found in the PATH, then True is returned\r
76# Otherwise, False is returned\r
77#\r
78def IsToolInPath(tool):\r
27c4ceb4 79 if 'PATHEXT' in os.environ:\r
52302d4d
LG
80 extns = os.environ['PATHEXT'].split(os.path.pathsep)\r
81 else:\r
82 extns = ('',)\r
83 for pathDir in os.environ['PATH'].split(os.path.pathsep):\r
84 for ext in extns:\r
85 if os.path.exists(os.path.join(pathDir, tool + ext)):\r
86 return True\r
87 return False\r
88\r
89## Check environment variables\r
90#\r
91# Check environment variables that must be set for build. Currently they are\r
92#\r
93# WORKSPACE The directory all packages/platforms start from\r
94# EDK_TOOLS_PATH The directory contains all tools needed by the build\r
95# PATH $(EDK_TOOLS_PATH)/Bin/<sys> must be set in PATH\r
96#\r
97# If any of above environment variable is not set or has error, the build\r
98# will be broken.\r
99#\r
100def CheckEnvVariable():\r
101 # check WORKSPACE\r
102 if "WORKSPACE" not in os.environ:\r
103 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",\r
104 ExtraData="WORKSPACE")\r
105\r
106 WorkspaceDir = os.path.normcase(os.path.normpath(os.environ["WORKSPACE"]))\r
107 if not os.path.exists(WorkspaceDir):\r
caf74495 108 EdkLogger.error("build", FILE_NOT_FOUND, "WORKSPACE doesn't exist", ExtraData=WorkspaceDir)\r
52302d4d
LG
109 elif ' ' in WorkspaceDir:\r
110 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in WORKSPACE path",\r
111 ExtraData=WorkspaceDir)\r
112 os.environ["WORKSPACE"] = WorkspaceDir\r
f7496d71 113\r
05cc51ad
LY
114 # set multiple workspace\r
115 PackagesPath = os.getenv("PACKAGES_PATH")\r
116 mws.setWs(WorkspaceDir, PackagesPath)\r
f6190a01
YZ
117 if mws.PACKAGES_PATH:\r
118 for Path in mws.PACKAGES_PATH:\r
119 if not os.path.exists(Path):\r
caf74495 120 EdkLogger.error("build", FILE_NOT_FOUND, "One Path in PACKAGES_PATH doesn't exist", ExtraData=Path)\r
f6190a01
YZ
121 elif ' ' in Path:\r
122 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in PACKAGES_PATH", ExtraData=Path)\r
52302d4d 123\r
4afd3d04 124\r
52302d4d 125 os.environ["EDK_TOOLS_PATH"] = os.path.normcase(os.environ["EDK_TOOLS_PATH"])\r
4afd3d04 126\r
52302d4d
LG
127 # check EDK_TOOLS_PATH\r
128 if "EDK_TOOLS_PATH" not in os.environ:\r
129 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",\r
130 ExtraData="EDK_TOOLS_PATH")\r
131\r
132 # check PATH\r
133 if "PATH" not in os.environ:\r
134 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",\r
135 ExtraData="PATH")\r
136\r
137 GlobalData.gWorkspace = WorkspaceDir\r
52302d4d 138\r
0d2711a6 139 GlobalData.gGlobalDefines["WORKSPACE"] = WorkspaceDir\r
0d2711a6 140 GlobalData.gGlobalDefines["EDK_TOOLS_PATH"] = os.environ["EDK_TOOLS_PATH"]\r
f7496d71 141\r
52302d4d
LG
142## Get normalized file path\r
143#\r
144# Convert the path to be local format, and remove the WORKSPACE path at the\r
145# beginning if the file path is given in full path.\r
146#\r
147# @param FilePath File path to be normalized\r
148# @param Workspace Workspace path which the FilePath will be checked against\r
149#\r
150# @retval string The normalized file path\r
151#\r
152def NormFile(FilePath, Workspace):\r
153 # check if the path is absolute or relative\r
154 if os.path.isabs(FilePath):\r
155 FileFullPath = os.path.normpath(FilePath)\r
156 else:\r
05cc51ad
LY
157 FileFullPath = os.path.normpath(mws.join(Workspace, FilePath))\r
158 Workspace = mws.getWs(Workspace, FilePath)\r
52302d4d
LG
159\r
160 # check if the file path exists or not\r
161 if not os.path.isfile(FileFullPath):\r
47fea6af 162 EdkLogger.error("build", FILE_NOT_FOUND, ExtraData="\t%s (Please give file in absolute path or relative to WORKSPACE)" % FileFullPath)\r
52302d4d
LG
163\r
164 # remove workspace directory from the beginning part of the file path\r
165 if Workspace[-1] in ["\\", "/"]:\r
166 return FileFullPath[len(Workspace):]\r
167 else:\r
168 return FileFullPath[(len(Workspace) + 1):]\r
169\r
170## Get the output of an external program\r
171#\r
172# This is the entrance method of thread reading output of an external program and\r
173# putting them in STDOUT/STDERR of current program.\r
174#\r
175# @param From The stream message read from\r
176# @param To The stream message put on\r
177# @param ExitFlag The flag used to indicate stopping reading\r
178#\r
0c3e8e99 179def ReadMessage(From, To, ExitFlag,MemTo=None):\r
52302d4d
LG
180 while True:\r
181 # read one line a time\r
182 Line = From.readline()\r
183 # empty string means "end"\r
d943b0c3 184 if Line is not None and Line != b"":\r
0c3e8e99
BF
185 LineStr = Line.rstrip().decode(encoding='utf-8', errors='ignore')\r
186 if MemTo is not None:\r
187 if "Note: including file:" == LineStr.lstrip()[:21]:\r
188 MemTo.append(LineStr)\r
189 else:\r
190 To(LineStr)\r
191 MemTo.append(LineStr)\r
192 else:\r
193 To(LineStr)\r
52302d4d
LG
194 else:\r
195 break\r
2e1fb413 196 if ExitFlag.is_set():\r
52302d4d
LG
197 break\r
198\r
0c3e8e99
BF
199class MakeSubProc(Popen):\r
200 def __init__(self,*args, **argv):\r
201 super(MakeSubProc,self).__init__(*args, **argv)\r
202 self.ProcOut = []\r
203\r
52302d4d
LG
204## Launch an external program\r
205#\r
206# This method will call subprocess.Popen to execute an external program with\r
207# given options in specified directory. Because of the dead-lock issue during\r
b03dceb8 208# redirecting output of the external program, threads are used to do the\r
52302d4d
LG
209# redirection work.\r
210#\r
211# @param Command A list or string containing the call of the program\r
212# @param WorkingDir The directory in which the program will be running\r
213#\r
0c3e8e99 214def LaunchCommand(Command, WorkingDir,ModuleAuto = None):\r
1b8eca8b 215 BeginTime = time.time()\r
52302d4d
LG
216 # if working directory doesn't exist, Popen() will raise an exception\r
217 if not os.path.isdir(WorkingDir):\r
218 EdkLogger.error("build", FILE_NOT_FOUND, ExtraData=WorkingDir)\r
f7496d71 219\r
01ce3538
HC
220 # Command is used as the first Argument in following Popen().\r
221 # It could be a string or sequence. We find that if command is a string in following Popen(),\r
222 # ubuntu may fail with an error message that the command is not found.\r
223 # So here we may need convert command from string to list instance.\r
ed728046
HW
224 if platform.system() != 'Windows':\r
225 if not isinstance(Command, list):\r
df0cee8d 226 Command = Command.split()\r
ed728046 227 Command = ' '.join(Command)\r
df0cee8d 228\r
52302d4d
LG
229 Proc = None\r
230 EndOfProcedure = None\r
231 try:\r
232 # launch the command\r
01b6090b 233 Proc = MakeSubProc(Command, stdout=PIPE, stderr=STDOUT, env=os.environ, cwd=WorkingDir, bufsize=-1, shell=True)\r
52302d4d
LG
234\r
235 # launch two threads to read the STDOUT and STDERR\r
236 EndOfProcedure = Event()\r
237 EndOfProcedure.clear()\r
238 if Proc.stdout:\r
0c3e8e99 239 StdOutThread = Thread(target=ReadMessage, args=(Proc.stdout, EdkLogger.info, EndOfProcedure,Proc.ProcOut))\r
2e1fb413
C
240 StdOutThread.name = "STDOUT-Redirector"\r
241 StdOutThread.daemon = False\r
52302d4d
LG
242 StdOutThread.start()\r
243\r
52302d4d
LG
244\r
245 # waiting for program exit\r
246 Proc.wait()\r
247 except: # in case of aborting\r
248 # terminate the threads redirecting the program output\r
790f60f2 249 EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r
4231a819 250 if EndOfProcedure is not None:\r
52302d4d 251 EndOfProcedure.set()\r
4231a819 252 if Proc is None:\r
0d1f5b2b 253 if not isinstance(Command, type("")):\r
52302d4d
LG
254 Command = " ".join(Command)\r
255 EdkLogger.error("build", COMMAND_FAILURE, "Failed to start command", ExtraData="%s [%s]" % (Command, WorkingDir))\r
256\r
257 if Proc.stdout:\r
258 StdOutThread.join()\r
52302d4d
LG
259\r
260 # check the return code of the program\r
261 if Proc.returncode != 0:\r
0d1f5b2b 262 if not isinstance(Command, type("")):\r
52302d4d 263 Command = " ".join(Command)\r
725cdb8f
YZ
264 # print out the Response file and its content when make failure\r
265 RespFile = os.path.join(WorkingDir, 'OUTPUT', 'respfilelist.txt')\r
266 if os.path.isfile(RespFile):\r
267 f = open(RespFile)\r
268 RespContent = f.read()\r
269 f.close()\r
270 EdkLogger.info(RespContent)\r
271\r
52302d4d 272 EdkLogger.error("build", COMMAND_FAILURE, ExtraData="%s [%s]" % (Command, WorkingDir))\r
0c3e8e99
BF
273 if ModuleAuto:\r
274 iau = IncludesAutoGen(WorkingDir,ModuleAuto)\r
275 if ModuleAuto.ToolChainFamily == TAB_COMPILER_MSFT:\r
276 iau.CreateDepsFileForMsvc(Proc.ProcOut)\r
277 else:\r
278 iau.UpdateDepsFileforNonMsvc()\r
279 iau.UpdateDepsFileforTrim()\r
280 iau.CreateModuleDeps()\r
281 iau.CreateDepsInclude()\r
5cd3d4bc 282 iau.CreateDepsTarget()\r
1b8eca8b 283 return "%dms" % (int(round((time.time() - BeginTime) * 1000)))\r
52302d4d
LG
284\r
285## The smallest unit that can be built in multi-thread build mode\r
286#\r
287# This is the base class of build unit. The "Obj" parameter must provide\r
288# __str__(), __eq__() and __hash__() methods. Otherwise there could be build units\r
289# missing build.\r
290#\r
291# Currently the "Obj" should be only ModuleAutoGen or PlatformAutoGen objects.\r
292#\r
293class BuildUnit:\r
294 ## The constructor\r
295 #\r
296 # @param self The object pointer\r
297 # @param Obj The object the build is working on\r
298 # @param Target The build target name, one of gSupportedTarget\r
299 # @param Dependency The BuildUnit(s) which must be completed in advance\r
300 # @param WorkingDir The directory build command starts in\r
301 #\r
302 def __init__(self, Obj, BuildCommand, Target, Dependency, WorkingDir="."):\r
303 self.BuildObject = Obj\r
304 self.Dependency = Dependency\r
305 self.WorkingDir = WorkingDir\r
306 self.Target = Target\r
307 self.BuildCommand = BuildCommand\r
0d2711a6
LG
308 if not BuildCommand:\r
309 EdkLogger.error("build", OPTION_MISSING,\r
310 "No build command found for this module. "\r
4afd3d04 311 "Please check your setting of %s_%s_%s_MAKE_PATH in Conf/tools_def.txt file." %\r
0d2711a6 312 (Obj.BuildTarget, Obj.ToolChain, Obj.Arch),\r
52302d4d
LG
313 ExtraData=str(Obj))\r
314\r
0d2711a6 315\r
52302d4d
LG
316 ## str() method\r
317 #\r
08dd311f 318 # It just returns the string representation of self.BuildObject\r
52302d4d
LG
319 #\r
320 # @param self The object pointer\r
321 #\r
322 def __str__(self):\r
323 return str(self.BuildObject)\r
324\r
325 ## "==" operator method\r
326 #\r
327 # It just compares self.BuildObject with "Other". So self.BuildObject must\r
328 # provide its own __eq__() method.\r
329 #\r
330 # @param self The object pointer\r
331 # @param Other The other BuildUnit object compared to\r
332 #\r
333 def __eq__(self, Other):\r
b7b51025
CJ
334 return Other and self.BuildObject == Other.BuildObject \\r
335 and Other.BuildObject \\r
52302d4d
LG
336 and self.BuildObject.Arch == Other.BuildObject.Arch\r
337\r
338 ## hash() method\r
339 #\r
340 # It just returns the hash value of self.BuildObject which must be hashable.\r
341 #\r
342 # @param self The object pointer\r
343 #\r
344 def __hash__(self):\r
345 return hash(self.BuildObject) + hash(self.BuildObject.Arch)\r
346\r
347 def __repr__(self):\r
348 return repr(self.BuildObject)\r
349\r
350## The smallest module unit that can be built by nmake/make command in multi-thread build mode\r
351#\r
352# This class is for module build by nmake/make build system. The "Obj" parameter\r
353# must provide __str__(), __eq__() and __hash__() methods. Otherwise there could\r
354# be make units missing build.\r
355#\r
356# Currently the "Obj" should be only ModuleAutoGen object.\r
357#\r
358class ModuleMakeUnit(BuildUnit):\r
359 ## The constructor\r
360 #\r
361 # @param self The object pointer\r
362 # @param Obj The ModuleAutoGen object the build is working on\r
363 # @param Target The build target name, one of gSupportedTarget\r
364 #\r
673d09a2
FB
365 def __init__(self, Obj, BuildCommand,Target):\r
366 Dependency = [ModuleMakeUnit(La, BuildCommand,Target) for La in Obj.LibraryAutoGenList]\r
367 BuildUnit.__init__(self, Obj, BuildCommand, Target, Dependency, Obj.MakeFileDir)\r
52302d4d
LG
368 if Target in [None, "", "all"]:\r
369 self.Target = "tbuild"\r
370\r
371## The smallest platform unit that can be built by nmake/make command in multi-thread build mode\r
372#\r
373# This class is for platform build by nmake/make build system. The "Obj" parameter\r
374# must provide __str__(), __eq__() and __hash__() methods. Otherwise there could\r
375# be make units missing build.\r
376#\r
377# Currently the "Obj" should be only PlatformAutoGen object.\r
378#\r
379class PlatformMakeUnit(BuildUnit):\r
380 ## The constructor\r
381 #\r
382 # @param self The object pointer\r
383 # @param Obj The PlatformAutoGen object the build is working on\r
384 # @param Target The build target name, one of gSupportedTarget\r
385 #\r
673d09a2
FB
386 def __init__(self, Obj, BuildCommand, Target):\r
387 Dependency = [ModuleMakeUnit(Lib, BuildCommand, Target) for Lib in self.BuildObject.LibraryAutoGenList]\r
388 Dependency.extend([ModuleMakeUnit(Mod, BuildCommand,Target) for Mod in self.BuildObject.ModuleAutoGenList])\r
389 BuildUnit.__init__(self, Obj, BuildCommand, Target, Dependency, Obj.MakeFileDir)\r
52302d4d
LG
390\r
391## The class representing the task of a module build or platform build\r
392#\r
393# This class manages the build tasks in multi-thread build mode. Its jobs include\r
394# scheduling thread running, catching thread error, monitor the thread status, etc.\r
395#\r
396class BuildTask:\r
397 # queue for tasks waiting for schedule\r
6e6d767e 398 _PendingQueue = OrderedDict()\r
52302d4d
LG
399 _PendingQueueLock = threading.Lock()\r
400\r
401 # queue for tasks ready for running\r
6e6d767e 402 _ReadyQueue = OrderedDict()\r
52302d4d
LG
403 _ReadyQueueLock = threading.Lock()\r
404\r
405 # queue for run tasks\r
6e6d767e 406 _RunningQueue = OrderedDict()\r
52302d4d
LG
407 _RunningQueueLock = threading.Lock()\r
408\r
409 # queue containing all build tasks, in case duplicate build\r
6e6d767e 410 _TaskQueue = OrderedDict()\r
52302d4d
LG
411\r
412 # flag indicating error occurs in a running thread\r
413 _ErrorFlag = threading.Event()\r
414 _ErrorFlag.clear()\r
415 _ErrorMessage = ""\r
416\r
417 # BoundedSemaphore object used to control the number of running threads\r
418 _Thread = None\r
419\r
420 # flag indicating if the scheduler is started or not\r
421 _SchedulerStopped = threading.Event()\r
422 _SchedulerStopped.set()\r
423\r
424 ## Start the task scheduler thread\r
425 #\r
426 # @param MaxThreadNumber The maximum thread number\r
427 # @param ExitFlag Flag used to end the scheduler\r
428 #\r
429 @staticmethod\r
430 def StartScheduler(MaxThreadNumber, ExitFlag):\r
431 SchedulerThread = Thread(target=BuildTask.Scheduler, args=(MaxThreadNumber, ExitFlag))\r
2e1fb413
C
432 SchedulerThread.name = "Build-Task-Scheduler"\r
433 SchedulerThread.daemon = False\r
52302d4d
LG
434 SchedulerThread.start()\r
435 # wait for the scheduler to be started, especially useful in Linux\r
436 while not BuildTask.IsOnGoing():\r
437 time.sleep(0.01)\r
438\r
439 ## Scheduler method\r
440 #\r
441 # @param MaxThreadNumber The maximum thread number\r
442 # @param ExitFlag Flag used to end the scheduler\r
443 #\r
444 @staticmethod\r
445 def Scheduler(MaxThreadNumber, ExitFlag):\r
446 BuildTask._SchedulerStopped.clear()\r
447 try:\r
448 # use BoundedSemaphore to control the maximum running threads\r
449 BuildTask._Thread = BoundedSemaphore(MaxThreadNumber)\r
450 #\r
451 # scheduling loop, which will exits when no pending/ready task and\r
452 # indicated to do so, or there's error in running thread\r
453 #\r
454 while (len(BuildTask._PendingQueue) > 0 or len(BuildTask._ReadyQueue) > 0 \\r
2e1fb413 455 or not ExitFlag.is_set()) and not BuildTask._ErrorFlag.is_set():\r
52302d4d
LG
456 EdkLogger.debug(EdkLogger.DEBUG_8, "Pending Queue (%d), Ready Queue (%d)"\r
457 % (len(BuildTask._PendingQueue), len(BuildTask._ReadyQueue)))\r
458\r
459 # get all pending tasks\r
460 BuildTask._PendingQueueLock.acquire()\r
f8d11e5a 461 BuildObjectList = list(BuildTask._PendingQueue.keys())\r
52302d4d
LG
462 #\r
463 # check if their dependency is resolved, and if true, move them\r
464 # into ready queue\r
465 #\r
466 for BuildObject in BuildObjectList:\r
467 Bt = BuildTask._PendingQueue[BuildObject]\r
468 if Bt.IsReady():\r
469 BuildTask._ReadyQueue[BuildObject] = BuildTask._PendingQueue.pop(BuildObject)\r
470 BuildTask._PendingQueueLock.release()\r
471\r
472 # launch build thread until the maximum number of threads is reached\r
2e1fb413 473 while not BuildTask._ErrorFlag.is_set():\r
52302d4d
LG
474 # empty ready queue, do nothing further\r
475 if len(BuildTask._ReadyQueue) == 0:\r
476 break\r
477\r
478 # wait for active thread(s) exit\r
479 BuildTask._Thread.acquire(True)\r
480\r
481 # start a new build thread\r
ccaa7754 482 Bo, Bt = BuildTask._ReadyQueue.popitem()\r
52302d4d
LG
483\r
484 # move into running queue\r
485 BuildTask._RunningQueueLock.acquire()\r
486 BuildTask._RunningQueue[Bo] = Bt\r
487 BuildTask._RunningQueueLock.release()\r
488\r
489 Bt.Start()\r
490 # avoid tense loop\r
491 time.sleep(0.01)\r
492\r
493 # avoid tense loop\r
494 time.sleep(0.01)\r
495\r
496 # wait for all running threads exit\r
2e1fb413 497 if BuildTask._ErrorFlag.is_set():\r
52302d4d 498 EdkLogger.quiet("\nWaiting for all build threads exit...")\r
2e1fb413 499 # while not BuildTask._ErrorFlag.is_set() and \\r
52302d4d
LG
500 while len(BuildTask._RunningQueue) > 0:\r
501 EdkLogger.verbose("Waiting for thread ending...(%d)" % len(BuildTask._RunningQueue))\r
2e1fb413 502 EdkLogger.debug(EdkLogger.DEBUG_8, "Threads [%s]" % ", ".join(Th.name for Th in threading.enumerate()))\r
52302d4d
LG
503 # avoid tense loop\r
504 time.sleep(0.1)\r
5b0671c1 505 except BaseException as X:\r
52302d4d 506 #\r
fb0b35e0 507 # TRICK: hide the output of threads left running, so that the user can\r
52302d4d
LG
508 # catch the error message easily\r
509 #\r
510 EdkLogger.SetLevel(EdkLogger.ERROR)\r
511 BuildTask._ErrorFlag.set()\r
512 BuildTask._ErrorMessage = "build thread scheduler error\n\t%s" % str(X)\r
513\r
514 BuildTask._PendingQueue.clear()\r
515 BuildTask._ReadyQueue.clear()\r
516 BuildTask._RunningQueue.clear()\r
517 BuildTask._TaskQueue.clear()\r
518 BuildTask._SchedulerStopped.set()\r
519\r
520 ## Wait for all running method exit\r
521 #\r
522 @staticmethod\r
523 def WaitForComplete():\r
524 BuildTask._SchedulerStopped.wait()\r
525\r
526 ## Check if the scheduler is running or not\r
527 #\r
528 @staticmethod\r
529 def IsOnGoing():\r
2e1fb413 530 return not BuildTask._SchedulerStopped.is_set()\r
52302d4d
LG
531\r
532 ## Abort the build\r
533 @staticmethod\r
534 def Abort():\r
535 if BuildTask.IsOnGoing():\r
536 BuildTask._ErrorFlag.set()\r
537 BuildTask.WaitForComplete()\r
538\r
539 ## Check if there's error in running thread\r
540 #\r
541 # Since the main thread cannot catch exceptions in other thread, we have to\r
542 # use threading.Event to communicate this formation to main thread.\r
543 #\r
544 @staticmethod\r
545 def HasError():\r
2e1fb413 546 return BuildTask._ErrorFlag.is_set()\r
52302d4d
LG
547\r
548 ## Get error message in running thread\r
549 #\r
550 # Since the main thread cannot catch exceptions in other thread, we have to\r
551 # use a static variable to communicate this message to main thread.\r
552 #\r
553 @staticmethod\r
554 def GetErrorMessage():\r
555 return BuildTask._ErrorMessage\r
556\r
557 ## Factory method to create a BuildTask object\r
558 #\r
559 # This method will check if a module is building or has been built. And if\r
560 # true, just return the associated BuildTask object in the _TaskQueue. If\r
561 # not, create and return a new BuildTask object. The new BuildTask object\r
562 # will be appended to the _PendingQueue for scheduling later.\r
563 #\r
564 # @param BuildItem A BuildUnit object representing a build object\r
565 # @param Dependency The dependent build object of BuildItem\r
566 #\r
567 @staticmethod\r
568 def New(BuildItem, Dependency=None):\r
569 if BuildItem in BuildTask._TaskQueue:\r
570 Bt = BuildTask._TaskQueue[BuildItem]\r
571 return Bt\r
572\r
573 Bt = BuildTask()\r
574 Bt._Init(BuildItem, Dependency)\r
575 BuildTask._TaskQueue[BuildItem] = Bt\r
576\r
577 BuildTask._PendingQueueLock.acquire()\r
578 BuildTask._PendingQueue[BuildItem] = Bt\r
579 BuildTask._PendingQueueLock.release()\r
580\r
581 return Bt\r
582\r
583 ## The real constructor of BuildTask\r
584 #\r
585 # @param BuildItem A BuildUnit object representing a build object\r
586 # @param Dependency The dependent build object of BuildItem\r
587 #\r
588 def _Init(self, BuildItem, Dependency=None):\r
589 self.BuildItem = BuildItem\r
590\r
591 self.DependencyList = []\r
4231a819 592 if Dependency is None:\r
52302d4d
LG
593 Dependency = BuildItem.Dependency\r
594 else:\r
595 Dependency.extend(BuildItem.Dependency)\r
596 self.AddDependency(Dependency)\r
597 # flag indicating build completes, used to avoid unnecessary re-build\r
598 self.CompleteFlag = False\r
599\r
600 ## Check if all dependent build tasks are completed or not\r
601 #\r
602 def IsReady(self):\r
603 ReadyFlag = True\r
604 for Dep in self.DependencyList:\r
605 if Dep.CompleteFlag == True:\r
606 continue\r
607 ReadyFlag = False\r
608 break\r
609\r
610 return ReadyFlag\r
611\r
612 ## Add dependent build task\r
613 #\r
614 # @param Dependency The list of dependent build objects\r
615 #\r
616 def AddDependency(self, Dependency):\r
617 for Dep in Dependency:\r
fc8b8dea 618 if not Dep.BuildObject.IsBinaryModule and not Dep.BuildObject.CanSkipbyCache(GlobalData.gModuleCacheHit):\r
97fa0ee9 619 self.DependencyList.append(BuildTask.New(Dep)) # BuildTask list\r
52302d4d
LG
620\r
621 ## The thread wrapper of LaunchCommand function\r
622 #\r
623 # @param Command A list or string contains the call of the command\r
624 # @param WorkingDir The directory in which the program will be running\r
625 #\r
626 def _CommandThread(self, Command, WorkingDir):\r
627 try:\r
0c3e8e99 628 self.BuildItem.BuildObject.BuildTime = LaunchCommand(Command, WorkingDir,self.BuildItem.BuildObject)\r
52302d4d 629 self.CompleteFlag = True\r
a7ef158b 630\r
fc8b8dea
SS
631 # Run hash operation post dependency to account for libs\r
632 # Run if --hash or --binary-destination\r
633 if GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
634 self.BuildItem.BuildObject.GenModuleHash()\r
635 if GlobalData.gBinCacheDest:\r
636 self.BuildItem.BuildObject.GenCMakeHash()\r
637\r
52302d4d
LG
638 except:\r
639 #\r
fb0b35e0 640 # TRICK: hide the output of threads left running, so that the user can\r
52302d4d
LG
641 # catch the error message easily\r
642 #\r
2e1fb413 643 if not BuildTask._ErrorFlag.is_set():\r
52302d4d
LG
644 GlobalData.gBuildingModule = "%s [%s, %s, %s]" % (str(self.BuildItem.BuildObject),\r
645 self.BuildItem.BuildObject.Arch,\r
646 self.BuildItem.BuildObject.ToolChain,\r
647 self.BuildItem.BuildObject.BuildTarget\r
648 )\r
649 EdkLogger.SetLevel(EdkLogger.ERROR)\r
650 BuildTask._ErrorFlag.set()\r
651 BuildTask._ErrorMessage = "%s broken\n %s [%s]" % \\r
2e1fb413 652 (threading.current_thread().name, Command, WorkingDir)\r
48b0bf64 653\r
52302d4d
LG
654 # indicate there's a thread is available for another build task\r
655 BuildTask._RunningQueueLock.acquire()\r
656 BuildTask._RunningQueue.pop(self.BuildItem)\r
657 BuildTask._RunningQueueLock.release()\r
658 BuildTask._Thread.release()\r
659\r
660 ## Start build task thread\r
661 #\r
662 def Start(self):\r
663 EdkLogger.quiet("Building ... %s" % repr(self.BuildItem))\r
664 Command = self.BuildItem.BuildCommand + [self.BuildItem.Target]\r
665 self.BuildTread = Thread(target=self._CommandThread, args=(Command, self.BuildItem.WorkingDir))\r
2e1fb413
C
666 self.BuildTread.name = "build thread"\r
667 self.BuildTread.daemon = False\r
52302d4d
LG
668 self.BuildTread.start()\r
669\r
670## The class contains the information related to EFI image\r
671#\r
672class PeImageInfo():\r
673 ## Constructor\r
674 #\r
675 # Constructor will load all required image information.\r
676 #\r
4afd3d04 677 # @param BaseName The full file path of image.\r
52302d4d
LG
678 # @param Guid The GUID for image.\r
679 # @param Arch Arch of this image.\r
f3decdc3
LG
680 # @param OutputDir The output directory for image.\r
681 # @param DebugDir The debug directory for image.\r
52302d4d
LG
682 # @param ImageClass PeImage Information\r
683 #\r
f3decdc3 684 def __init__(self, BaseName, Guid, Arch, OutputDir, DebugDir, ImageClass):\r
52302d4d
LG
685 self.BaseName = BaseName\r
686 self.Guid = Guid\r
687 self.Arch = Arch\r
f3decdc3
LG
688 self.OutputDir = OutputDir\r
689 self.DebugDir = DebugDir\r
52302d4d 690 self.Image = ImageClass\r
b3e94a06 691 self.Image.Size = (self.Image.Size // 0x1000 + 1) * 0x1000\r
52302d4d
LG
692\r
693## The class implementing the EDK2 build process\r
694#\r
695# The build process includes:\r
696# 1. Load configuration from target.txt and tools_def.txt in $(WORKSPACE)/Conf\r
697# 2. Parse DSC file of active platform\r
698# 3. Parse FDF file if any\r
699# 4. Establish build database, including parse all other files (module, package)\r
700# 5. Create AutoGen files (C code file, depex file, makefile) if necessary\r
701# 6. Call build command\r
702#\r
703class Build():\r
704 ## Constructor\r
705 #\r
706 # Constructor will load all necessary configurations, parse platform, modules\r
707 # and packages and the establish a database for AutoGen.\r
708 #\r
709 # @param Target The build command target, one of gSupportedTarget\r
710 # @param WorkspaceDir The directory of workspace\r
0d2711a6
LG
711 # @param BuildOptions Build options passed from command line\r
712 #\r
636ed13a 713 def __init__(self, Target, WorkspaceDir, BuildOptions,log_q):\r
0d2711a6 714 self.WorkspaceDir = WorkspaceDir\r
52302d4d 715 self.Target = Target\r
0d2711a6
LG
716 self.PlatformFile = BuildOptions.PlatformFile\r
717 self.ModuleFile = BuildOptions.ModuleFile\r
718 self.ArchList = BuildOptions.TargetArch\r
719 self.ToolChainList = BuildOptions.ToolChain\r
720 self.BuildTargetList= BuildOptions.BuildTarget\r
721 self.Fdf = BuildOptions.FdfFile\r
722 self.FdList = BuildOptions.RomImage\r
723 self.FvList = BuildOptions.FvImage\r
724 self.CapList = BuildOptions.CapName\r
725 self.SilentMode = BuildOptions.SilentMode\r
1a624dd7 726 self.ThreadNumber = 1\r
0d2711a6
LG
727 self.SkipAutoGen = BuildOptions.SkipAutoGen\r
728 self.Reparse = BuildOptions.Reparse\r
729 self.SkuId = BuildOptions.SkuId\r
e651d06c
LG
730 if self.SkuId:\r
731 GlobalData.gSKUID_CMD = self.SkuId\r
97fa0ee9 732 self.ConfDirectory = BuildOptions.ConfDirectory\r
52302d4d 733 self.SpawnMode = True\r
0d2711a6 734 self.BuildReport = BuildReport(BuildOptions.ReportFile, BuildOptions.ReportType)\r
1b8eca8b
YZ
735 self.AutoGenTime = 0\r
736 self.MakeTime = 0\r
737 self.GenFdsTime = 0\r
818283de 738 self.MakeFileName = ""\r
4465cd12
FZ
739 TargetObj = TargetTxtDict()\r
740 ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"),"Conf")))\r
741 self.TargetTxt = TargetObj.Target\r
742 self.ToolDef = ToolDefObj.ToolDef\r
b854e2bf 743 GlobalData.BuildOptionPcd = BuildOptions.OptionPcd if BuildOptions.OptionPcd else []\r
fae62ff2
HC
744 #Set global flag for build mode\r
745 GlobalData.gIgnoreSource = BuildOptions.IgnoreSources\r
36d083ef
YZ
746 GlobalData.gUseHashCache = BuildOptions.UseHashCache\r
747 GlobalData.gBinCacheDest = BuildOptions.BinCacheDest\r
748 GlobalData.gBinCacheSource = BuildOptions.BinCacheSource\r
7809492c 749 GlobalData.gEnableGenfdsMultiThread = not BuildOptions.NoGenfdsMultiThread\r
d868846a 750 GlobalData.gDisableIncludePathCheck = BuildOptions.DisableIncludePathCheck\r
36d083ef
YZ
751\r
752 if GlobalData.gBinCacheDest and not GlobalData.gUseHashCache:\r
753 EdkLogger.error("build", OPTION_NOT_SUPPORTED, ExtraData="--binary-destination must be used together with --hash.")\r
754\r
755 if GlobalData.gBinCacheSource and not GlobalData.gUseHashCache:\r
756 EdkLogger.error("build", OPTION_NOT_SUPPORTED, ExtraData="--binary-source must be used together with --hash.")\r
757\r
758 if GlobalData.gBinCacheDest and GlobalData.gBinCacheSource:\r
759 EdkLogger.error("build", OPTION_NOT_SUPPORTED, ExtraData="--binary-destination can not be used together with --binary-source.")\r
760\r
761 if GlobalData.gBinCacheSource:\r
762 BinCacheSource = os.path.normpath(GlobalData.gBinCacheSource)\r
763 if not os.path.isabs(BinCacheSource):\r
764 BinCacheSource = mws.join(self.WorkspaceDir, BinCacheSource)\r
765 GlobalData.gBinCacheSource = BinCacheSource\r
f21547ff 766 else:\r
4231a819 767 if GlobalData.gBinCacheSource is not None:\r
f21547ff 768 EdkLogger.error("build", OPTION_VALUE_INVALID, ExtraData="Invalid value of option --binary-source.")\r
36d083ef
YZ
769\r
770 if GlobalData.gBinCacheDest:\r
771 BinCacheDest = os.path.normpath(GlobalData.gBinCacheDest)\r
772 if not os.path.isabs(BinCacheDest):\r
773 BinCacheDest = mws.join(self.WorkspaceDir, BinCacheDest)\r
774 GlobalData.gBinCacheDest = BinCacheDest\r
f21547ff 775 else:\r
4231a819 776 if GlobalData.gBinCacheDest is not None:\r
f21547ff 777 EdkLogger.error("build", OPTION_VALUE_INVALID, ExtraData="Invalid value of option --binary-destination.")\r
97fa0ee9 778\r
c60fb00f 779 GlobalData.gDatabasePath = os.path.normpath(os.path.join(GlobalData.gConfDirectory, GlobalData.gDatabasePath))\r
5f89bcc4
FB
780 if not os.path.exists(os.path.join(GlobalData.gConfDirectory, '.cache')):\r
781 os.makedirs(os.path.join(GlobalData.gConfDirectory, '.cache'))\r
e8449e1d 782 self.Db = BuildDB\r
97fa0ee9
YL
783 self.BuildDatabase = self.Db.BuildObject\r
784 self.Platform = None\r
40b4e21d 785 self.ToolChainFamily = None\r
52302d4d 786 self.LoadFixAddress = 0\r
0d2711a6 787 self.UniFlag = BuildOptions.Flag\r
a0a2cd1e 788 self.BuildModules = []\r
83397f95 789 self.HashSkipModules = []\r
f0dc69e6
YZ
790 self.Db_Flag = False\r
791 self.LaunchPrebuildFlag = False\r
ccaa7754 792 self.PlatformBuildPath = os.path.join(GlobalData.gConfDirectory, '.cache', '.PlatformBuild')\r
725cdb8f
YZ
793 if BuildOptions.CommandLength:\r
794 GlobalData.gCommandMaxLength = BuildOptions.CommandLength\r
795\r
e56468c0 796 # print dot character during doing some time-consuming work\r
52302d4d 797 self.Progress = Utils.Progressor()\r
52302d4d 798 # print current build environment and configuration\r
0d2711a6 799 EdkLogger.quiet("%-16s = %s" % ("WORKSPACE", os.environ["WORKSPACE"]))\r
f25da33d 800 if "PACKAGES_PATH" in os.environ:\r
f7496d71 801 # WORKSPACE env has been converted before. Print the same path style with WORKSPACE env.\r
f25da33d 802 EdkLogger.quiet("%-16s = %s" % ("PACKAGES_PATH", os.path.normcase(os.path.normpath(os.environ["PACKAGES_PATH"]))))\r
0d2711a6 803 EdkLogger.quiet("%-16s = %s" % ("EDK_TOOLS_PATH", os.environ["EDK_TOOLS_PATH"]))\r
f25da33d 804 if "EDK_TOOLS_BIN" in os.environ:\r
f7496d71 805 # Print the same path style with WORKSPACE env.\r
f25da33d 806 EdkLogger.quiet("%-16s = %s" % ("EDK_TOOLS_BIN", os.path.normcase(os.path.normpath(os.environ["EDK_TOOLS_BIN"]))))\r
00bcb5c2 807 EdkLogger.quiet("%-16s = %s" % ("CONF_PATH", GlobalData.gConfDirectory))\r
fd2d7400
ZF
808 if "PYTHON3_ENABLE" in os.environ:\r
809 PYTHON3_ENABLE = os.environ["PYTHON3_ENABLE"]\r
810 if PYTHON3_ENABLE != "TRUE":\r
811 PYTHON3_ENABLE = "FALSE"\r
812 EdkLogger.quiet("%-16s = %s" % ("PYTHON3_ENABLE", PYTHON3_ENABLE))\r
7aef7b7c
LG
813 if "PYTHON_COMMAND" in os.environ:\r
814 EdkLogger.quiet("%-16s = %s" % ("PYTHON_COMMAND", os.environ["PYTHON_COMMAND"]))\r
f0dc69e6
YZ
815 self.InitPreBuild()\r
816 self.InitPostBuild()\r
af9c4e5e
MK
817 if self.Prebuild:\r
818 EdkLogger.quiet("%-16s = %s" % ("PREBUILD", self.Prebuild))\r
819 if self.Postbuild:\r
820 EdkLogger.quiet("%-16s = %s" % ("POSTBUILD", self.Postbuild))\r
821 if self.Prebuild:\r
f0dc69e6 822 self.LaunchPrebuild()\r
4465cd12
FZ
823 TargetObj = TargetTxtDict()\r
824 ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))\r
825 self.TargetTxt = TargetObj.Target\r
826 self.ToolDef = ToolDefObj.ToolDef\r
f0dc69e6
YZ
827 if not (self.LaunchPrebuildFlag and os.path.exists(self.PlatformBuildPath)):\r
828 self.InitBuild()\r
52302d4d 829\r
673d09a2 830 self.AutoGenMgr = None\r
f0dc69e6 831 EdkLogger.info("")\r
52302d4d 832 os.chdir(self.WorkspaceDir)\r
636ed13a 833 self.log_q = log_q\r
53e2eaba 834 GlobalData.file_lock = mp.Lock()\r
fc8b8dea
SS
835 # Init cache data for local only\r
836 GlobalData.gPackageHashFile = dict()\r
837 GlobalData.gModulePreMakeCacheStatus = dict()\r
838 GlobalData.gModuleMakeCacheStatus = dict()\r
839 GlobalData.gHashChainStatus = dict()\r
840 GlobalData.gCMakeHashFile = dict()\r
841 GlobalData.gModuleHashFile = dict()\r
842 GlobalData.gFileHashDict = dict()\r
843 GlobalData.gModuleAllCacheStatus = set()\r
844 GlobalData.gModuleCacheHit = set()\r
845\r
846 def StartAutoGen(self,mqueue, DataPipe,SkipAutoGen,PcdMaList,cqueue):\r
673d09a2
FB
847 try:\r
848 if SkipAutoGen:\r
849 return True,0\r
850 feedback_q = mp.Queue()\r
673d09a2 851 error_event = mp.Event()\r
0e7e7a26
SS
852 FfsCmd = DataPipe.Get("FfsCommand")\r
853 if FfsCmd is None:\r
854 FfsCmd = {}\r
855 GlobalData.FfsCmd = FfsCmd\r
fc8b8dea 856 auto_workers = [AutoGenWorkerInProcess(mqueue,DataPipe.dump_file,feedback_q,GlobalData.file_lock,cqueue,self.log_q,error_event) for _ in range(self.ThreadNumber)]\r
673d09a2
FB
857 self.AutoGenMgr = AutoGenManager(auto_workers,feedback_q,error_event)\r
858 self.AutoGenMgr.start()\r
859 for w in auto_workers:\r
860 w.start()\r
861 if PcdMaList is not None:\r
862 for PcdMa in PcdMaList:\r
fc8b8dea
SS
863 # SourceFileList calling sequence impact the makefile string sequence.\r
864 # Create cached SourceFileList here to unify its calling sequence for both\r
865 # CanSkipbyPreMakeCache and CreateCodeFile/CreateMakeFile.\r
866 RetVal = PcdMa.SourceFileList\r
867 # Force cache miss for PCD driver\r
868 if GlobalData.gUseHashCache and not GlobalData.gBinCacheDest and self.Target in [None, "", "all"]:\r
869 cqueue.put((PcdMa.MetaFile.Path, PcdMa.Arch, "PreMakeCache", False))\r
0e7e7a26 870\r
673d09a2 871 PcdMa.CreateCodeFile(False)\r
e3c8311f 872 PcdMa.CreateMakeFile(False,GenFfsList = DataPipe.Get("FfsCommand").get((PcdMa.MetaFile.Path, PcdMa.Arch),[]))\r
5dc2699d 873 PcdMa.CreateAsBuiltInf()\r
fc8b8dea 874 # Force cache miss for PCD driver\r
0e7e7a26 875 if GlobalData.gBinCacheSource and self.Target in [None, "", "all"]:\r
fc8b8dea 876 cqueue.put((PcdMa.MetaFile.Path, PcdMa.Arch, "MakeCache", False))\r
0e7e7a26 877\r
673d09a2
FB
878 self.AutoGenMgr.join()\r
879 rt = self.AutoGenMgr.Status\r
28dd887d
IP
880 err = 0\r
881 if not rt:\r
882 err = UNKNOWN_ERROR\r
883 return rt, err\r
0e7e7a26
SS
884 except FatalError as e:\r
885 return False, e.args[0]\r
886 except:\r
887 return False, UNKNOWN_ERROR\r
52302d4d 888\r
ab957f03
MK
889 ## Add TOOLCHAIN and FAMILY declared in DSC [BuildOptions] to ToolsDefTxtDatabase.\r
890 #\r
891 # Loop through the set of build targets, tool chains, and archs provided on either\r
892 # the command line or in target.txt to discover FAMILY and TOOLCHAIN delclarations\r
893 # in [BuildOptions] sections that may be within !if expressions that may use\r
894 # $(TARGET), $(TOOLCHAIN), $(TOOLCHAIN_TAG), or $(ARCH) operands.\r
895 #\r
896 def GetToolChainAndFamilyFromDsc (self, File):\r
8c8f49f0 897 SavedGlobalDefines = GlobalData.gGlobalDefines.copy()\r
ab957f03
MK
898 for BuildTarget in self.BuildTargetList:\r
899 GlobalData.gGlobalDefines['TARGET'] = BuildTarget\r
900 for BuildToolChain in self.ToolChainList:\r
901 GlobalData.gGlobalDefines['TOOLCHAIN'] = BuildToolChain\r
902 GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = BuildToolChain\r
903 for BuildArch in self.ArchList:\r
904 GlobalData.gGlobalDefines['ARCH'] = BuildArch\r
905 dscobj = self.BuildDatabase[File, BuildArch]\r
906 for KeyFamily, Key, KeyCodeBase in dscobj.BuildOptions:\r
907 try:\r
908 Target, ToolChain, Arch, Tool, Attr = Key.split('_')\r
909 except:\r
910 continue\r
911 if ToolChain == TAB_STAR or Attr != TAB_TOD_DEFINES_FAMILY:\r
912 continue\r
913 try:\r
914 Family = dscobj.BuildOptions[(KeyFamily, Key, KeyCodeBase)]\r
915 Family = Family.strip().strip('=').strip()\r
916 except:\r
917 continue\r
918 if TAB_TOD_DEFINES_FAMILY not in self.ToolDef.ToolsDefTxtDatabase:\r
919 self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY] = {}\r
920 if ToolChain not in self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:\r
921 self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][ToolChain] = Family\r
922 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in self.ToolDef.ToolsDefTxtDatabase:\r
923 self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY] = {}\r
924 if ToolChain not in self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
925 self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][ToolChain] = Family\r
926 if TAB_TOD_DEFINES_TOOL_CHAIN_TAG not in self.ToolDef.ToolsDefTxtDatabase:\r
927 self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] = []\r
928 if ToolChain not in self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG]:\r
929 self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG].append(ToolChain)\r
8c8f49f0 930 GlobalData.gGlobalDefines = SavedGlobalDefines\r
ab957f03 931\r
52302d4d
LG
932 ## Load configuration\r
933 #\r
934 # This method will parse target.txt and get the build configurations.\r
935 #\r
936 def LoadConfiguration(self):\r
52302d4d
LG
937\r
938 # if no ARCH given in command line, get it from target.txt\r
0d2711a6 939 if not self.ArchList:\r
938cf4c3 940 self.ArchList = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TARGET_ARCH]\r
0d2711a6 941 self.ArchList = tuple(self.ArchList)\r
52302d4d
LG
942\r
943 # if no build target given in command line, get it from target.txt\r
0d2711a6 944 if not self.BuildTargetList:\r
938cf4c3 945 self.BuildTargetList = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TARGET]\r
52302d4d
LG
946\r
947 # if no tool chain given in command line, get it from target.txt\r
0d2711a6 948 if not self.ToolChainList:\r
938cf4c3 949 self.ToolChainList = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_TAG]\r
4231a819 950 if self.ToolChainList is None or len(self.ToolChainList) == 0:\r
52302d4d
LG
951 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.\n")\r
952\r
ab957f03
MK
953 if not self.PlatformFile:\r
954 PlatformFile = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_ACTIVE_PLATFORM]\r
955 if not PlatformFile:\r
956 # Try to find one in current directory\r
957 WorkingDirectory = os.getcwd()\r
958 FileList = glob.glob(os.path.normpath(os.path.join(WorkingDirectory, '*.dsc')))\r
959 FileNum = len(FileList)\r
960 if FileNum >= 2:\r
961 EdkLogger.error("build", OPTION_MISSING,\r
962 ExtraData="There are %d DSC files in %s. Use '-p' to specify one.\n" % (FileNum, WorkingDirectory))\r
963 elif FileNum == 1:\r
964 PlatformFile = FileList[0]\r
965 else:\r
966 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,\r
967 ExtraData="No active platform specified in target.txt or command line! Nothing can be built.\n")\r
968\r
969 self.PlatformFile = PathClass(NormFile(PlatformFile, self.WorkspaceDir), self.WorkspaceDir)\r
970\r
971 self.GetToolChainAndFamilyFromDsc (self.PlatformFile)\r
972\r
52302d4d
LG
973 # check if the tool chains are defined or not\r
974 NewToolChainList = []\r
975 for ToolChain in self.ToolChainList:\r
976 if ToolChain not in self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG]:\r
977 EdkLogger.warn("build", "Tool chain [%s] is not defined" % ToolChain)\r
978 else:\r
979 NewToolChainList.append(ToolChain)\r
980 # if no tool chain available, break the build\r
981 if len(NewToolChainList) == 0:\r
982 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,\r
983 ExtraData="[%s] not defined. No toolchain available for build!\n" % ", ".join(self.ToolChainList))\r
984 else:\r
985 self.ToolChainList = NewToolChainList\r
986\r
40b4e21d
YZ
987 ToolChainFamily = []\r
988 ToolDefinition = self.ToolDef.ToolsDefTxtDatabase\r
989 for Tool in self.ToolChainList:\r
990 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition or Tool not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
991 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][Tool]:\r
688c7d21 992 EdkLogger.warn("build", "No tool chain family found in configuration for %s. Default to MSFT." % Tool)\r
94c04559 993 ToolChainFamily.append(TAB_COMPILER_MSFT)\r
40b4e21d
YZ
994 else:\r
995 ToolChainFamily.append(ToolDefinition[TAB_TOD_DEFINES_FAMILY][Tool])\r
996 self.ToolChainFamily = ToolChainFamily\r
997\r
1a624dd7 998 self.ThreadNumber = ThreadNum()\r
52302d4d
LG
999 ## Initialize build configuration\r
1000 #\r
1001 # This method will parse DSC file and merge the configurations from\r
1002 # command line and target.txt, then get the final build configurations.\r
1003 #\r
1004 def InitBuild(self):\r
0d2711a6 1005 # parse target.txt, tools_def.txt, and platform file\r
4afd3d04 1006 self.LoadConfiguration()\r
0d2711a6
LG
1007\r
1008 # Allow case-insensitive for those from command line or configuration file\r
1009 ErrorCode, ErrorInfo = self.PlatformFile.Validate(".dsc", False)\r
52302d4d
LG
1010 if ErrorCode != 0:\r
1011 EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo)\r
1012\r
f0dc69e6
YZ
1013\r
1014 def InitPreBuild(self):\r
1015 self.LoadConfiguration()\r
d429fcd0
YZ
1016 ErrorCode, ErrorInfo = self.PlatformFile.Validate(".dsc", False)\r
1017 if ErrorCode != 0:\r
1018 EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo)\r
f0dc69e6
YZ
1019 if self.BuildTargetList:\r
1020 GlobalData.gGlobalDefines['TARGET'] = self.BuildTargetList[0]\r
1021 if self.ArchList:\r
1022 GlobalData.gGlobalDefines['ARCH'] = self.ArchList[0]\r
1023 if self.ToolChainList:\r
1024 GlobalData.gGlobalDefines['TOOLCHAIN'] = self.ToolChainList[0]\r
1025 GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = self.ToolChainList[0]\r
40b4e21d
YZ
1026 if self.ToolChainFamily:\r
1027 GlobalData.gGlobalDefines['FAMILY'] = self.ToolChainFamily[0]\r
9eb87141 1028 if 'PREBUILD' in GlobalData.gCommandLineDefines:\r
f0dc69e6
YZ
1029 self.Prebuild = GlobalData.gCommandLineDefines.get('PREBUILD')\r
1030 else:\r
f0dc69e6 1031 self.Db_Flag = True\r
71cac3f7 1032 Platform = self.Db.MapPlatform(str(self.PlatformFile))\r
f0dc69e6
YZ
1033 self.Prebuild = str(Platform.Prebuild)\r
1034 if self.Prebuild:\r
af9c4e5e
MK
1035 PrebuildList = []\r
1036 #\r
1037 # Evaluate all arguments and convert arguments that are WORKSPACE\r
1038 # relative paths to absolute paths. Filter arguments that look like\r
1039 # flags or do not follow the file/dir naming rules to avoid false\r
1040 # positives on this conversion.\r
1041 #\r
1042 for Arg in self.Prebuild.split():\r
1043 #\r
1044 # Do not modify Arg if it looks like a flag or an absolute file path\r
1045 #\r
1046 if Arg.startswith('-') or os.path.isabs(Arg):\r
1047 PrebuildList.append(Arg)\r
1048 continue\r
1049 #\r
1050 # Do not modify Arg if it does not look like a Workspace relative\r
1051 # path that starts with a valid package directory name\r
1052 #\r
1053 if not Arg[0].isalpha() or os.path.dirname(Arg) == '':\r
1054 PrebuildList.append(Arg)\r
1055 continue\r
1056 #\r
1057 # If Arg looks like a WORKSPACE relative path, then convert to an\r
1058 # absolute path and check to see if the file exists.\r
1059 #\r
1060 Temp = mws.join(self.WorkspaceDir, Arg)\r
1061 if os.path.isfile(Temp):\r
1062 Arg = Temp\r
1063 PrebuildList.append(Arg)\r
1064 self.Prebuild = ' '.join(PrebuildList)\r
1065 self.Prebuild += self.PassCommandOption(self.BuildTargetList, self.ArchList, self.ToolChainList, self.PlatformFile, self.Target)\r
52302d4d 1066\r
f0dc69e6 1067 def InitPostBuild(self):\r
9eb87141 1068 if 'POSTBUILD' in GlobalData.gCommandLineDefines:\r
f0dc69e6
YZ
1069 self.Postbuild = GlobalData.gCommandLineDefines.get('POSTBUILD')\r
1070 else:\r
71cac3f7 1071 Platform = self.Db.MapPlatform(str(self.PlatformFile))\r
f0dc69e6
YZ
1072 self.Postbuild = str(Platform.Postbuild)\r
1073 if self.Postbuild:\r
af9c4e5e
MK
1074 PostbuildList = []\r
1075 #\r
1076 # Evaluate all arguments and convert arguments that are WORKSPACE\r
1077 # relative paths to absolute paths. Filter arguments that look like\r
1078 # flags or do not follow the file/dir naming rules to avoid false\r
1079 # positives on this conversion.\r
1080 #\r
1081 for Arg in self.Postbuild.split():\r
1082 #\r
1083 # Do not modify Arg if it looks like a flag or an absolute file path\r
1084 #\r
1085 if Arg.startswith('-') or os.path.isabs(Arg):\r
1086 PostbuildList.append(Arg)\r
1087 continue\r
1088 #\r
1089 # Do not modify Arg if it does not look like a Workspace relative\r
1090 # path that starts with a valid package directory name\r
1091 #\r
1092 if not Arg[0].isalpha() or os.path.dirname(Arg) == '':\r
1093 PostbuildList.append(Arg)\r
1094 continue\r
1095 #\r
1096 # If Arg looks like a WORKSPACE relative path, then convert to an\r
1097 # absolute path and check to see if the file exists.\r
1098 #\r
1099 Temp = mws.join(self.WorkspaceDir, Arg)\r
1100 if os.path.isfile(Temp):\r
1101 Arg = Temp\r
1102 PostbuildList.append(Arg)\r
1103 self.Postbuild = ' '.join(PostbuildList)\r
1104 self.Postbuild += self.PassCommandOption(self.BuildTargetList, self.ArchList, self.ToolChainList, self.PlatformFile, self.Target)\r
1105\r
1106 def PassCommandOption(self, BuildTarget, TargetArch, ToolChain, PlatformFile, Target):\r
f0dc69e6
YZ
1107 BuildStr = ''\r
1108 if GlobalData.gCommand and isinstance(GlobalData.gCommand, list):\r
1109 BuildStr += ' ' + ' '.join(GlobalData.gCommand)\r
1110 TargetFlag = False\r
1111 ArchFlag = False\r
1112 ToolChainFlag = False\r
af9c4e5e 1113 PlatformFileFlag = False\r
f0dc69e6
YZ
1114\r
1115 if GlobalData.gOptions and not GlobalData.gOptions.BuildTarget:\r
1116 TargetFlag = True\r
1117 if GlobalData.gOptions and not GlobalData.gOptions.TargetArch:\r
1118 ArchFlag = True\r
1119 if GlobalData.gOptions and not GlobalData.gOptions.ToolChain:\r
1120 ToolChainFlag = True\r
af9c4e5e
MK
1121 if GlobalData.gOptions and not GlobalData.gOptions.PlatformFile:\r
1122 PlatformFileFlag = True\r
f0dc69e6
YZ
1123\r
1124 if TargetFlag and BuildTarget:\r
1125 if isinstance(BuildTarget, list) or isinstance(BuildTarget, tuple):\r
1126 BuildStr += ' -b ' + ' -b '.join(BuildTarget)\r
1127 elif isinstance(BuildTarget, str):\r
1128 BuildStr += ' -b ' + BuildTarget\r
1129 if ArchFlag and TargetArch:\r
1130 if isinstance(TargetArch, list) or isinstance(TargetArch, tuple):\r
1131 BuildStr += ' -a ' + ' -a '.join(TargetArch)\r
1132 elif isinstance(TargetArch, str):\r
1133 BuildStr += ' -a ' + TargetArch\r
1134 if ToolChainFlag and ToolChain:\r
1135 if isinstance(ToolChain, list) or isinstance(ToolChain, tuple):\r
1136 BuildStr += ' -t ' + ' -t '.join(ToolChain)\r
1137 elif isinstance(ToolChain, str):\r
1138 BuildStr += ' -t ' + ToolChain\r
af9c4e5e
MK
1139 if PlatformFileFlag and PlatformFile:\r
1140 if isinstance(PlatformFile, list) or isinstance(PlatformFile, tuple):\r
1141 BuildStr += ' -p ' + ' -p '.join(PlatformFile)\r
1142 elif isinstance(PlatformFile, str):\r
1143 BuildStr += ' -p' + PlatformFile\r
1144 BuildStr += ' --conf=' + GlobalData.gConfDirectory\r
1145 if Target:\r
1146 BuildStr += ' ' + Target\r
f0dc69e6
YZ
1147\r
1148 return BuildStr\r
1149\r
1150 def LaunchPrebuild(self):\r
1151 if self.Prebuild:\r
1152 EdkLogger.info("\n- Prebuild Start -\n")\r
1153 self.LaunchPrebuildFlag = True\r
134bbe88
YZ
1154 #\r
1155 # The purpose of .PrebuildEnv file is capture environment variable settings set by the prebuild script\r
1156 # and preserve them for the rest of the main build step, because the child process environment will\r
1157 # evaporate as soon as it exits, we cannot get it in build step.\r
1158 #\r
ccaa7754 1159 PrebuildEnvFile = os.path.join(GlobalData.gConfDirectory, '.cache', '.PrebuildEnv')\r
f0dc69e6
YZ
1160 if os.path.isfile(PrebuildEnvFile):\r
1161 os.remove(PrebuildEnvFile)\r
1162 if os.path.isfile(self.PlatformBuildPath):\r
1163 os.remove(self.PlatformBuildPath)\r
1164 if sys.platform == "win32":\r
1165 args = ' && '.join((self.Prebuild, 'set > ' + PrebuildEnvFile))\r
b926f2f2 1166 Process = Popen(args, stdout=PIPE, stderr=PIPE, shell=True)\r
f0dc69e6
YZ
1167 else:\r
1168 args = ' && '.join((self.Prebuild, 'env > ' + PrebuildEnvFile))\r
34816e7e 1169 Process = Popen(args, stdout=PIPE, stderr=PIPE, shell=True)\r
f0dc69e6
YZ
1170\r
1171 # launch two threads to read the STDOUT and STDERR\r
1172 EndOfProcedure = Event()\r
1173 EndOfProcedure.clear()\r
1174 if Process.stdout:\r
1175 StdOutThread = Thread(target=ReadMessage, args=(Process.stdout, EdkLogger.info, EndOfProcedure))\r
2e1fb413
C
1176 StdOutThread.name = "STDOUT-Redirector"\r
1177 StdOutThread.daemon = False\r
f0dc69e6
YZ
1178 StdOutThread.start()\r
1179\r
1180 if Process.stderr:\r
1181 StdErrThread = Thread(target=ReadMessage, args=(Process.stderr, EdkLogger.quiet, EndOfProcedure))\r
2e1fb413
C
1182 StdErrThread.name = "STDERR-Redirector"\r
1183 StdErrThread.daemon = False\r
f0dc69e6
YZ
1184 StdErrThread.start()\r
1185 # waiting for program exit\r
1186 Process.wait()\r
1187\r
1188 if Process.stdout:\r
1189 StdOutThread.join()\r
1190 if Process.stderr:\r
1191 StdErrThread.join()\r
1192 if Process.returncode != 0 :\r
1193 EdkLogger.error("Prebuild", PREBUILD_ERROR, 'Prebuild process is not success!')\r
1194\r
1195 if os.path.exists(PrebuildEnvFile):\r
1196 f = open(PrebuildEnvFile)\r
1197 envs = f.readlines()\r
1198 f.close()\r
2f28dca1
ZF
1199 envs = [l.split("=", 1) for l in envs ]\r
1200 envs = [[I.strip() for I in item] for item in envs if len(item) == 2]\r
f0dc69e6
YZ
1201 os.environ.update(dict(envs))\r
1202 EdkLogger.info("\n- Prebuild Done -\n")\r
1203\r
91048b0d 1204 def LaunchPostbuild(self):\r
f0dc69e6
YZ
1205 if self.Postbuild:\r
1206 EdkLogger.info("\n- Postbuild Start -\n")\r
1207 if sys.platform == "win32":\r
b926f2f2 1208 Process = Popen(self.Postbuild, stdout=PIPE, stderr=PIPE, shell=True)\r
f0dc69e6 1209 else:\r
34816e7e 1210 Process = Popen(self.Postbuild, stdout=PIPE, stderr=PIPE, shell=True)\r
f0dc69e6
YZ
1211 # launch two threads to read the STDOUT and STDERR\r
1212 EndOfProcedure = Event()\r
1213 EndOfProcedure.clear()\r
1214 if Process.stdout:\r
1215 StdOutThread = Thread(target=ReadMessage, args=(Process.stdout, EdkLogger.info, EndOfProcedure))\r
2e1fb413
C
1216 StdOutThread.name = "STDOUT-Redirector"\r
1217 StdOutThread.daemon = False\r
f0dc69e6
YZ
1218 StdOutThread.start()\r
1219\r
1220 if Process.stderr:\r
1221 StdErrThread = Thread(target=ReadMessage, args=(Process.stderr, EdkLogger.quiet, EndOfProcedure))\r
2e1fb413
C
1222 StdErrThread.name = "STDERR-Redirector"\r
1223 StdErrThread.daemon = False\r
f0dc69e6
YZ
1224 StdErrThread.start()\r
1225 # waiting for program exit\r
1226 Process.wait()\r
1227\r
1228 if Process.stdout:\r
1229 StdOutThread.join()\r
1230 if Process.stderr:\r
1231 StdErrThread.join()\r
1232 if Process.returncode != 0 :\r
1233 EdkLogger.error("Postbuild", POSTBUILD_ERROR, 'Postbuild process is not success!')\r
1234 EdkLogger.info("\n- Postbuild Done -\n")\r
0eccea3f 1235\r
52302d4d
LG
1236 ## Build a module or platform\r
1237 #\r
08dd311f 1238 # Create autogen code and makefile for a module or platform, and the launch\r
52302d4d
LG
1239 # "make" command to build it\r
1240 #\r
1241 # @param Target The target of build command\r
1242 # @param Platform The platform file\r
1243 # @param Module The module file\r
1244 # @param BuildTarget The name of build target, one of "DEBUG", "RELEASE"\r
1245 # @param ToolChain The name of toolchain to build\r
1246 # @param Arch The arch of the module/platform\r
1247 # @param CreateDepModuleCodeFile Flag used to indicate creating code\r
1248 # for dependent modules/Libraries\r
1249 # @param CreateDepModuleMakeFile Flag used to indicate creating makefile\r
1250 # for dependent modules/Libraries\r
1251 #\r
673d09a2 1252 def _BuildPa(self, Target, AutoGenObject, CreateDepsCodeFile=True, CreateDepsMakeFile=True, BuildModule=False, FfsCommand=None, PcdMaList=None):\r
4231a819 1253 if AutoGenObject is None:\r
52302d4d 1254 return False\r
673d09a2
FB
1255 if FfsCommand is None:\r
1256 FfsCommand = {}\r
52302d4d
LG
1257 # skip file generation for cleanxxx targets, run and fds target\r
1258 if Target not in ['clean', 'cleanlib', 'cleanall', 'run', 'fds']:\r
1259 # for target which must generate AutoGen code and makefile\r
673d09a2
FB
1260 mqueue = mp.Queue()\r
1261 for m in AutoGenObject.GetAllModuleInfo:\r
1262 mqueue.put(m)\r
bfe36cb4 1263 mqueue.put((None,None,None,None,None,None,None))\r
0e7e7a26 1264 AutoGenObject.DataPipe.DataContainer = {"CommandTarget": self.Target}\r
373298ca
FB
1265 AutoGenObject.DataPipe.DataContainer = {"Workspace_timestamp": AutoGenObject.Workspace._SrcTimeStamp}\r
1266 AutoGenObject.CreateLibModuelDirs()\r
1267 AutoGenObject.DataPipe.DataContainer = {"LibraryBuildDirectoryList":AutoGenObject.LibraryBuildDirectoryList}\r
1268 AutoGenObject.DataPipe.DataContainer = {"ModuleBuildDirectoryList":AutoGenObject.ModuleBuildDirectoryList}\r
1269 AutoGenObject.DataPipe.DataContainer = {"FdsCommandDict": AutoGenObject.Workspace.GenFdsCommandDict}\r
673d09a2
FB
1270 self.Progress.Start("Generating makefile and code")\r
1271 data_pipe_file = os.path.join(AutoGenObject.BuildDir, "GlobalVar_%s_%s.bin" % (str(AutoGenObject.Guid),AutoGenObject.Arch))\r
1272 AutoGenObject.DataPipe.dump(data_pipe_file)\r
fc8b8dea
SS
1273 cqueue = mp.Queue()\r
1274 autogen_rt,errorcode = self.StartAutoGen(mqueue, AutoGenObject.DataPipe, self.SkipAutoGen, PcdMaList, cqueue)\r
373298ca
FB
1275 AutoGenIdFile = os.path.join(GlobalData.gConfDirectory,".AutoGenIdFile.txt")\r
1276 with open(AutoGenIdFile,"w") as fw:\r
1277 fw.write("Arch=%s\n" % "|".join((AutoGenObject.Workspace.ArchList)))\r
1278 fw.write("BuildDir=%s\n" % AutoGenObject.Workspace.BuildDir)\r
1279 fw.write("PlatformGuid=%s\n" % str(AutoGenObject.Guid))\r
673d09a2
FB
1280 self.Progress.Stop("done!")\r
1281 if not autogen_rt:\r
1282 self.AutoGenMgr.TerminateWorkers()\r
373298ca 1283 self.AutoGenMgr.join(1)\r
673d09a2 1284 raise FatalError(errorcode)\r
52302d4d
LG
1285 AutoGenObject.CreateCodeFile(False)\r
1286 AutoGenObject.CreateMakeFile(False)\r
673d09a2
FB
1287 else:\r
1288 # always recreate top/platform makefile when clean, just in case of inconsistency\r
1289 AutoGenObject.CreateCodeFile(True)\r
1290 AutoGenObject.CreateMakeFile(True)\r
52302d4d
LG
1291\r
1292 if EdkLogger.GetLevel() == EdkLogger.QUIET:\r
1293 EdkLogger.quiet("Building ... %s" % repr(AutoGenObject))\r
1294\r
1295 BuildCommand = AutoGenObject.BuildCommand\r
4231a819 1296 if BuildCommand is None or len(BuildCommand) == 0:\r
0d2711a6
LG
1297 EdkLogger.error("build", OPTION_MISSING,\r
1298 "No build command found for this module. "\r
4afd3d04 1299 "Please check your setting of %s_%s_%s_MAKE_PATH in Conf/tools_def.txt file." %\r
0d2711a6
LG
1300 (AutoGenObject.BuildTarget, AutoGenObject.ToolChain, AutoGenObject.Arch),\r
1301 ExtraData=str(AutoGenObject))\r
52302d4d 1302\r
03af2753
HC
1303 # run\r
1304 if Target == 'run':\r
03af2753
HC
1305 return True\r
1306\r
259c184c
PG
1307 # Fetch the MakeFileName.\r
1308 self.MakeFileName = AutoGenObject.MakeFileName\r
1309\r
03af2753
HC
1310 # build modules\r
1311 if BuildModule:\r
1312 BuildCommand = BuildCommand + [Target]\r
1313 LaunchCommand(BuildCommand, AutoGenObject.MakeFileDir)\r
b8ac0b7f 1314 if GlobalData.gBinCacheDest:\r
fc8b8dea
SS
1315 self.GenDestCache()\r
1316 elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
1317 # Only for --hash\r
1318 # Update PreMakeCacheChain files\r
1319 self.GenLocalPreMakeCache()\r
b8ac0b7f 1320 self.BuildModules = []\r
03af2753
HC
1321 return True\r
1322\r
1323 # build library\r
1324 if Target == 'libraries':\r
0c3e8e99
BF
1325 DirList = []\r
1326 for Lib in AutoGenObject.LibraryAutoGenList:\r
1327 if not Lib.IsBinaryModule:\r
1328 DirList.append((os.path.join(AutoGenObject.BuildDir, Lib.BuildDir),Lib))\r
1329 for Lib, LibAutoGen in DirList:\r
818283de 1330 NewBuildCommand = BuildCommand + ['-f', os.path.normpath(os.path.join(Lib, self.MakeFileName)), 'pbuild']\r
0c3e8e99 1331 LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir,LibAutoGen)\r
03af2753
HC
1332 return True\r
1333\r
1334 # build module\r
1335 if Target == 'modules':\r
0c3e8e99
BF
1336 DirList = []\r
1337 for Lib in AutoGenObject.LibraryAutoGenList:\r
1338 if not Lib.IsBinaryModule:\r
1339 DirList.append((os.path.join(AutoGenObject.BuildDir, Lib.BuildDir),Lib))\r
1340 for Lib, LibAutoGen in DirList:\r
818283de 1341 NewBuildCommand = BuildCommand + ['-f', os.path.normpath(os.path.join(Lib, self.MakeFileName)), 'pbuild']\r
0c3e8e99
BF
1342 LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir,LibAutoGen)\r
1343\r
1344 DirList = []\r
1345 for ModuleAutoGen in AutoGenObject.ModuleAutoGenList:\r
1346 if not ModuleAutoGen.IsBinaryModule:\r
1347 DirList.append((os.path.join(AutoGenObject.BuildDir, ModuleAutoGen.BuildDir),ModuleAutoGen))\r
1348 for Mod,ModAutoGen in DirList:\r
818283de 1349 NewBuildCommand = BuildCommand + ['-f', os.path.normpath(os.path.join(Mod, self.MakeFileName)), 'pbuild']\r
0c3e8e99 1350 LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir,ModAutoGen)\r
a0a2cd1e 1351 self.CreateAsBuiltInf()\r
b8ac0b7f 1352 if GlobalData.gBinCacheDest:\r
fc8b8dea
SS
1353 self.GenDestCache()\r
1354 elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
1355 # Only for --hash\r
1356 # Update PreMakeCacheChain files\r
1357 self.GenLocalPreMakeCache()\r
b8ac0b7f 1358 self.BuildModules = []\r
03af2753
HC
1359 return True\r
1360\r
1361 # cleanlib\r
1362 if Target == 'cleanlib':\r
1363 for Lib in AutoGenObject.LibraryBuildDirectoryList:\r
818283de 1364 LibMakefile = os.path.normpath(os.path.join(Lib, self.MakeFileName))\r
03af2753
HC
1365 if os.path.exists(LibMakefile):\r
1366 NewBuildCommand = BuildCommand + ['-f', LibMakefile, 'cleanall']\r
1367 LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir)\r
1368 return True\r
1369\r
1370 # clean\r
1371 if Target == 'clean':\r
1372 for Mod in AutoGenObject.ModuleBuildDirectoryList:\r
818283de 1373 ModMakefile = os.path.normpath(os.path.join(Mod, self.MakeFileName))\r
03af2753
HC
1374 if os.path.exists(ModMakefile):\r
1375 NewBuildCommand = BuildCommand + ['-f', ModMakefile, 'cleanall']\r
1376 LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir)\r
1377 for Lib in AutoGenObject.LibraryBuildDirectoryList:\r
818283de 1378 LibMakefile = os.path.normpath(os.path.join(Lib, self.MakeFileName))\r
03af2753
HC
1379 if os.path.exists(LibMakefile):\r
1380 NewBuildCommand = BuildCommand + ['-f', LibMakefile, 'cleanall']\r
1381 LaunchCommand(NewBuildCommand, AutoGenObject.MakeFileDir)\r
1382 return True\r
1383\r
1384 # cleanall\r
1385 if Target == 'cleanall':\r
1386 try:\r
1387 #os.rmdir(AutoGenObject.BuildDir)\r
1388 RemoveDirectory(AutoGenObject.BuildDir, True)\r
5b0671c1 1389 except WindowsError as X:\r
03af2753
HC
1390 EdkLogger.error("build", FILE_DELETE_FAILURE, ExtraData=str(X))\r
1391 return True\r
1392\r
1393 ## Build a module or platform\r
1394 #\r
1395 # Create autogen code and makefile for a module or platform, and the launch\r
1396 # "make" command to build it\r
1397 #\r
1398 # @param Target The target of build command\r
1399 # @param Platform The platform file\r
1400 # @param Module The module file\r
1401 # @param BuildTarget The name of build target, one of "DEBUG", "RELEASE"\r
1402 # @param ToolChain The name of toolchain to build\r
1403 # @param Arch The arch of the module/platform\r
1404 # @param CreateDepModuleCodeFile Flag used to indicate creating code\r
1405 # for dependent modules/Libraries\r
1406 # @param CreateDepModuleMakeFile Flag used to indicate creating makefile\r
1407 # for dependent modules/Libraries\r
1408 #\r
1409 def _Build(self, Target, AutoGenObject, CreateDepsCodeFile=True, CreateDepsMakeFile=True, BuildModule=False):\r
4231a819 1410 if AutoGenObject is None:\r
03af2753
HC
1411 return False\r
1412\r
1413 # skip file generation for cleanxxx targets, run and fds target\r
1414 if Target not in ['clean', 'cleanlib', 'cleanall', 'run', 'fds']:\r
1415 # for target which must generate AutoGen code and makefile\r
1416 if not self.SkipAutoGen or Target == 'genc':\r
1417 self.Progress.Start("Generating code")\r
1418 AutoGenObject.CreateCodeFile(CreateDepsCodeFile)\r
1419 self.Progress.Stop("done!")\r
1420 if Target == "genc":\r
1421 return True\r
1422\r
1423 if not self.SkipAutoGen or Target == 'genmake':\r
1424 self.Progress.Start("Generating makefile")\r
1425 AutoGenObject.CreateMakeFile(CreateDepsMakeFile)\r
1426 #AutoGenObject.CreateAsBuiltInf()\r
1427 self.Progress.Stop("done!")\r
1428 if Target == "genmake":\r
1429 return True\r
1430 else:\r
1431 # always recreate top/platform makefile when clean, just in case of inconsistency\r
673d09a2
FB
1432 AutoGenObject.CreateCodeFile(True)\r
1433 AutoGenObject.CreateMakeFile(True)\r
03af2753
HC
1434\r
1435 if EdkLogger.GetLevel() == EdkLogger.QUIET:\r
1436 EdkLogger.quiet("Building ... %s" % repr(AutoGenObject))\r
1437\r
1438 BuildCommand = AutoGenObject.BuildCommand\r
4231a819 1439 if BuildCommand is None or len(BuildCommand) == 0:\r
03af2753
HC
1440 EdkLogger.error("build", OPTION_MISSING,\r
1441 "No build command found for this module. "\r
1442 "Please check your setting of %s_%s_%s_MAKE_PATH in Conf/tools_def.txt file." %\r
1443 (AutoGenObject.BuildTarget, AutoGenObject.ToolChain, AutoGenObject.Arch),\r
1444 ExtraData=str(AutoGenObject))\r
1445\r
b0e23cf3
YL
1446 # build modules\r
1447 if BuildModule:\r
1448 if Target != 'fds':\r
1449 BuildCommand = BuildCommand + [Target]\r
1b8eca8b 1450 AutoGenObject.BuildTime = LaunchCommand(BuildCommand, AutoGenObject.MakeFileDir)\r
b0e23cf3 1451 self.CreateAsBuiltInf()\r
b8ac0b7f 1452 if GlobalData.gBinCacheDest:\r
fc8b8dea
SS
1453 self.GenDestCache()\r
1454 elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
1455 # Only for --hash\r
1456 # Update PreMakeCacheChain files\r
1457 self.GenLocalPreMakeCache()\r
b8ac0b7f 1458 self.BuildModules = []\r
b0e23cf3
YL
1459 return True\r
1460\r
03af2753
HC
1461 # genfds\r
1462 if Target == 'fds':\r
370544d1
DL
1463 if GenFdsApi(AutoGenObject.GenFdsCommandDict, self.Db):\r
1464 EdkLogger.error("build", COMMAND_FAILURE)\r
3a3a3af4
FZ
1465 Threshold = self.GetFreeSizeThreshold()\r
1466 if Threshold:\r
1467 self.CheckFreeSizeThreshold(Threshold, AutoGenObject.FvDir)\r
03af2753
HC
1468 return True\r
1469\r
1470 # run\r
1471 if Target == 'run':\r
03af2753
HC
1472 return True\r
1473\r
03af2753
HC
1474 # build library\r
1475 if Target == 'libraries':\r
1476 pass\r
1477\r
1478 # not build modules\r
1479\r
1480\r
1481 # cleanall\r
52302d4d
LG
1482 if Target == 'cleanall':\r
1483 try:\r
1484 #os.rmdir(AutoGenObject.BuildDir)\r
1485 RemoveDirectory(AutoGenObject.BuildDir, True)\r
5b0671c1 1486 except WindowsError as X:\r
52302d4d
LG
1487 EdkLogger.error("build", FILE_DELETE_FAILURE, ExtraData=str(X))\r
1488 return True\r
1489\r
6780eef1 1490 ## Rebase module image and Get function address for the input module list.\r
52302d4d
LG
1491 #\r
1492 def _RebaseModule (self, MapBuffer, BaseAddress, ModuleList, AddrIsOffset = True, ModeIsSmm = False):\r
1493 if ModeIsSmm:\r
1494 AddrIsOffset = False\r
98120f5f 1495 for InfFile in ModuleList:\r
da92f276
LG
1496 sys.stdout.write (".")\r
1497 sys.stdout.flush()\r
52302d4d
LG
1498 ModuleInfo = ModuleList[InfFile]\r
1499 ModuleName = ModuleInfo.BaseName\r
f3decdc3
LG
1500 ModuleOutputImage = ModuleInfo.Image.FileName\r
1501 ModuleDebugImage = os.path.join(ModuleInfo.DebugDir, ModuleInfo.BaseName + '.efi')\r
52302d4d
LG
1502 ## for SMM module in SMRAM, the SMRAM will be allocated from base to top.\r
1503 if not ModeIsSmm:\r
1504 BaseAddress = BaseAddress - ModuleInfo.Image.Size\r
1505 #\r
1506 # Update Image to new BaseAddress by GenFw tool\r
1507 #\r
f3decdc3 1508 LaunchCommand(["GenFw", "--rebase", str(BaseAddress), "-r", ModuleOutputImage], ModuleInfo.OutputDir)\r
47fea6af 1509 LaunchCommand(["GenFw", "--rebase", str(BaseAddress), "-r", ModuleDebugImage], ModuleInfo.DebugDir)\r
52302d4d
LG
1510 else:\r
1511 #\r
1512 # Set new address to the section header only for SMM driver.\r
1513 #\r
f3decdc3 1514 LaunchCommand(["GenFw", "--address", str(BaseAddress), "-r", ModuleOutputImage], ModuleInfo.OutputDir)\r
47fea6af 1515 LaunchCommand(["GenFw", "--address", str(BaseAddress), "-r", ModuleDebugImage], ModuleInfo.DebugDir)\r
52302d4d 1516 #\r
fb0b35e0 1517 # Collect function address from Map file\r
52302d4d 1518 #\r
f3decdc3 1519 ImageMapTable = ModuleOutputImage.replace('.efi', '.map')\r
52302d4d
LG
1520 FunctionList = []\r
1521 if os.path.exists(ImageMapTable):\r
1522 OrigImageBaseAddress = 0\r
47fea6af 1523 ImageMap = open(ImageMapTable, 'r')\r
52302d4d
LG
1524 for LinStr in ImageMap:\r
1525 if len (LinStr.strip()) == 0:\r
1526 continue\r
1527 #\r
1528 # Get the preferred address set on link time.\r
1529 #\r
1530 if LinStr.find ('Preferred load address is') != -1:\r
1531 StrList = LinStr.split()\r
1532 OrigImageBaseAddress = int (StrList[len(StrList) - 1], 16)\r
1533\r
1534 StrList = LinStr.split()\r
1535 if len (StrList) > 4:\r
47fea6af 1536 if StrList[3] == 'f' or StrList[3] == 'F':\r
52302d4d
LG
1537 Name = StrList[1]\r
1538 RelativeAddress = int (StrList[2], 16) - OrigImageBaseAddress\r
1539 FunctionList.append ((Name, RelativeAddress))\r
39879ef2 1540\r
52302d4d
LG
1541 ImageMap.close()\r
1542 #\r
1543 # Add general information.\r
1544 #\r
1545 if ModeIsSmm:\r
d943b0c3 1546 MapBuffer.append('\n\n%s (Fixed SMRAM Offset, BaseAddress=0x%010X, EntryPoint=0x%010X)\n' % (ModuleName, BaseAddress, BaseAddress + ModuleInfo.Image.EntryPoint))\r
52302d4d 1547 elif AddrIsOffset:\r
d943b0c3 1548 MapBuffer.append('\n\n%s (Fixed Memory Offset, BaseAddress=-0x%010X, EntryPoint=-0x%010X)\n' % (ModuleName, 0 - BaseAddress, 0 - (BaseAddress + ModuleInfo.Image.EntryPoint)))\r
52302d4d 1549 else:\r
d943b0c3 1550 MapBuffer.append('\n\n%s (Fixed Memory Address, BaseAddress=0x%010X, EntryPoint=0x%010X)\n' % (ModuleName, BaseAddress, BaseAddress + ModuleInfo.Image.EntryPoint))\r
52302d4d
LG
1551 #\r
1552 # Add guid and general seciton section.\r
1553 #\r
1554 TextSectionAddress = 0\r
1555 DataSectionAddress = 0\r
1556 for SectionHeader in ModuleInfo.Image.SectionHeaderList:\r
1557 if SectionHeader[0] == '.text':\r
1558 TextSectionAddress = SectionHeader[1]\r
1559 elif SectionHeader[0] in ['.data', '.sdata']:\r
1560 DataSectionAddress = SectionHeader[1]\r
1561 if AddrIsOffset:\r
d943b0c3 1562 MapBuffer.append('(GUID=%s, .textbaseaddress=-0x%010X, .databaseaddress=-0x%010X)\n' % (ModuleInfo.Guid, 0 - (BaseAddress + TextSectionAddress), 0 - (BaseAddress + DataSectionAddress)))\r
52302d4d 1563 else:\r
d943b0c3 1564 MapBuffer.append('(GUID=%s, .textbaseaddress=0x%010X, .databaseaddress=0x%010X)\n' % (ModuleInfo.Guid, BaseAddress + TextSectionAddress, BaseAddress + DataSectionAddress))\r
f3decdc3
LG
1565 #\r
1566 # Add debug image full path.\r
1567 #\r
d943b0c3 1568 MapBuffer.append('(IMAGE=%s)\n\n' % (ModuleDebugImage))\r
52302d4d 1569 #\r
fb0b35e0 1570 # Add function address\r
52302d4d
LG
1571 #\r
1572 for Function in FunctionList:\r
1573 if AddrIsOffset:\r
d943b0c3 1574 MapBuffer.append(' -0x%010X %s\n' % (0 - (BaseAddress + Function[1]), Function[0]))\r
52302d4d 1575 else:\r
d943b0c3 1576 MapBuffer.append(' 0x%010X %s\n' % (BaseAddress + Function[1], Function[0]))\r
52302d4d
LG
1577 ImageMap.close()\r
1578\r
1579 #\r
1580 # for SMM module in SMRAM, the SMRAM will be allocated from base to top.\r
1581 #\r
1582 if ModeIsSmm:\r
1583 BaseAddress = BaseAddress + ModuleInfo.Image.Size\r
1584\r
1585 ## Collect MAP information of all FVs\r
1586 #\r
636f2be6 1587 def _CollectFvMapBuffer (self, MapBuffer, Wa, ModuleList):\r
0d2711a6 1588 if self.Fdf:\r
52302d4d 1589 # First get the XIP base address for FV map file.\r
636f2be6 1590 GuidPattern = re.compile("[-a-fA-F0-9]+")\r
eebc135f 1591 GuidName = re.compile(r"\(GUID=[-a-fA-F0-9]+")\r
9eb87141 1592 for FvName in Wa.FdfProfile.FvDict:\r
52302d4d
LG
1593 FvMapBuffer = os.path.join(Wa.FvDir, FvName + '.Fv.map')\r
1594 if not os.path.exists(FvMapBuffer):\r
1595 continue\r
1be2ed90 1596 FvMap = open(FvMapBuffer, 'r')\r
52302d4d
LG
1597 #skip FV size information\r
1598 FvMap.readline()\r
1599 FvMap.readline()\r
1600 FvMap.readline()\r
1601 FvMap.readline()\r
636f2be6
LG
1602 for Line in FvMap:\r
1603 MatchGuid = GuidPattern.match(Line)\r
4231a819 1604 if MatchGuid is not None:\r
636f2be6
LG
1605 #\r
1606 # Replace GUID with module name\r
1607 #\r
1608 GuidString = MatchGuid.group()\r
1609 if GuidString.upper() in ModuleList:\r
1610 Line = Line.replace(GuidString, ModuleList[GuidString.upper()].Name)\r
d943b0c3 1611 MapBuffer.append(Line)\r
f3decdc3
LG
1612 #\r
1613 # Add the debug image full path.\r
1614 #\r
1615 MatchGuid = GuidName.match(Line)\r
4231a819 1616 if MatchGuid is not None:\r
f3decdc3
LG
1617 GuidString = MatchGuid.group().split("=")[1]\r
1618 if GuidString.upper() in ModuleList:\r
d943b0c3 1619 MapBuffer.append('(IMAGE=%s)\n' % (os.path.join(ModuleList[GuidString.upper()].DebugDir, ModuleList[GuidString.upper()].Name + '.efi')))\r
f3decdc3 1620\r
52302d4d
LG
1621 FvMap.close()\r
1622\r
1623 ## Collect MAP information of all modules\r
1624 #\r
1625 def _CollectModuleMapBuffer (self, MapBuffer, ModuleList):\r
da92f276
LG
1626 sys.stdout.write ("Generate Load Module At Fix Address Map")\r
1627 sys.stdout.flush()\r
52302d4d
LG
1628 PatchEfiImageList = []\r
1629 PeiModuleList = {}\r
1630 BtModuleList = {}\r
1631 RtModuleList = {}\r
1632 SmmModuleList = {}\r
1633 PeiSize = 0\r
1634 BtSize = 0\r
1635 RtSize = 0\r
1636 # reserve 4K size in SMRAM to make SMM module address not from 0.\r
1637 SmmSize = 0x1000\r
636f2be6
LG
1638 for ModuleGuid in ModuleList:\r
1639 Module = ModuleList[ModuleGuid]\r
52302d4d 1640 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (Module.MetaFile, Module.Arch, Module.ToolChain, Module.BuildTarget)\r
4afd3d04 1641\r
52302d4d
LG
1642 OutputImageFile = ''\r
1643 for ResultFile in Module.CodaTargetList:\r
1644 if str(ResultFile.Target).endswith('.efi'):\r
1645 #\r
1646 # module list for PEI, DXE, RUNTIME and SMM\r
1647 #\r
1648 OutputImageFile = os.path.join(Module.OutputDir, Module.Name + '.efi')\r
1649 ImageClass = PeImageClass (OutputImageFile)\r
1650 if not ImageClass.IsValid:\r
1651 EdkLogger.error("build", FILE_PARSE_FAILURE, ExtraData=ImageClass.ErrorInfo)\r
f3decdc3 1652 ImageInfo = PeImageInfo(Module.Name, Module.Guid, Module.Arch, Module.OutputDir, Module.DebugDir, ImageClass)\r
0c60e60b 1653 if Module.ModuleType in [SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, EDK_COMPONENT_TYPE_COMBINED_PEIM_DRIVER, EDK_COMPONENT_TYPE_PIC_PEIM, EDK_COMPONENT_TYPE_RELOCATABLE_PEIM, SUP_MODULE_DXE_CORE]:\r
52302d4d
LG
1654 PeiModuleList[Module.MetaFile] = ImageInfo\r
1655 PeiSize += ImageInfo.Image.Size\r
0c60e60b 1656 elif Module.ModuleType in [EDK_COMPONENT_TYPE_BS_DRIVER, SUP_MODULE_DXE_DRIVER, SUP_MODULE_UEFI_DRIVER]:\r
52302d4d
LG
1657 BtModuleList[Module.MetaFile] = ImageInfo\r
1658 BtSize += ImageInfo.Image.Size\r
0c60e60b 1659 elif Module.ModuleType in [SUP_MODULE_DXE_RUNTIME_DRIVER, EDK_COMPONENT_TYPE_RT_DRIVER, SUP_MODULE_DXE_SAL_DRIVER, EDK_COMPONENT_TYPE_SAL_RT_DRIVER]:\r
52302d4d 1660 RtModuleList[Module.MetaFile] = ImageInfo\r
52302d4d 1661 RtSize += ImageInfo.Image.Size\r
8bb63e37 1662 elif Module.ModuleType in [SUP_MODULE_SMM_CORE, SUP_MODULE_DXE_SMM_DRIVER, SUP_MODULE_MM_STANDALONE, SUP_MODULE_MM_CORE_STANDALONE]:\r
52302d4d
LG
1663 SmmModuleList[Module.MetaFile] = ImageInfo\r
1664 SmmSize += ImageInfo.Image.Size\r
8bb63e37 1665 if Module.ModuleType == SUP_MODULE_DXE_SMM_DRIVER:\r
888d7f19 1666 PiSpecVersion = Module.Module.Specification.get('PI_SPECIFICATION_VERSION', '0x00000000')\r
52302d4d 1667 # for PI specification < PI1.1, DXE_SMM_DRIVER also runs as BOOT time driver.\r
da92f276 1668 if int(PiSpecVersion, 16) < 0x0001000A:\r
52302d4d
LG
1669 BtModuleList[Module.MetaFile] = ImageInfo\r
1670 BtSize += ImageInfo.Image.Size\r
1671 break\r
1672 #\r
1673 # EFI image is final target.\r
1674 # Check EFI image contains patchable FixAddress related PCDs.\r
1675 #\r
1676 if OutputImageFile != '':\r
1677 ModuleIsPatch = False\r
1678 for Pcd in Module.ModulePcdList:\r
eece4292 1679 if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE and Pcd.TokenCName in TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SET:\r
52302d4d
LG
1680 ModuleIsPatch = True\r
1681 break\r
1682 if not ModuleIsPatch:\r
1683 for Pcd in Module.LibraryPcdList:\r
eece4292 1684 if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE and Pcd.TokenCName in TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SET:\r
52302d4d
LG
1685 ModuleIsPatch = True\r
1686 break\r
4afd3d04 1687\r
52302d4d
LG
1688 if not ModuleIsPatch:\r
1689 continue\r
1690 #\r
1691 # Module includes the patchable load fix address PCDs.\r
4afd3d04 1692 # It will be fixed up later.\r
52302d4d
LG
1693 #\r
1694 PatchEfiImageList.append (OutputImageFile)\r
4afd3d04 1695\r
52302d4d
LG
1696 #\r
1697 # Get Top Memory address\r
1698 #\r
1699 ReservedRuntimeMemorySize = 0\r
1700 TopMemoryAddress = 0\r
1701 if self.LoadFixAddress == 0xFFFFFFFFFFFFFFFF:\r
1702 TopMemoryAddress = 0\r
1703 else:\r
1704 TopMemoryAddress = self.LoadFixAddress\r
1705 if TopMemoryAddress < RtSize + BtSize + PeiSize:\r
1706 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is too low to load driver")\r
52302d4d
LG
1707\r
1708 #\r
1709 # Patch FixAddress related PCDs into EFI image\r
1710 #\r
4afd3d04 1711 for EfiImage in PatchEfiImageList:\r
52302d4d
LG
1712 EfiImageMap = EfiImage.replace('.efi', '.map')\r
1713 if not os.path.exists(EfiImageMap):\r
1714 continue\r
1715 #\r
1716 # Get PCD offset in EFI image by GenPatchPcdTable function\r
1717 #\r
4afd3d04 1718 PcdTable = parsePcdInfoFromMapFile(EfiImageMap, EfiImage)\r
52302d4d
LG
1719 #\r
1720 # Patch real PCD value by PatchPcdValue tool\r
1721 #\r
1722 for PcdInfo in PcdTable:\r
1723 ReturnValue = 0\r
1724 if PcdInfo[0] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_PEI_PAGE_SIZE:\r
b3e94a06 1725 ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_PEI_PAGE_SIZE_DATA_TYPE, str (PeiSize // 0x1000))\r
52302d4d 1726 elif PcdInfo[0] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_DXE_PAGE_SIZE:\r
b3e94a06 1727 ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_DXE_PAGE_SIZE_DATA_TYPE, str (BtSize // 0x1000))\r
52302d4d 1728 elif PcdInfo[0] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_RUNTIME_PAGE_SIZE:\r
b3e94a06 1729 ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_RUNTIME_PAGE_SIZE_DATA_TYPE, str (RtSize // 0x1000))\r
52302d4d 1730 elif PcdInfo[0] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SMM_PAGE_SIZE and len (SmmModuleList) > 0:\r
b3e94a06 1731 ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SMM_PAGE_SIZE_DATA_TYPE, str (SmmSize // 0x1000))\r
52302d4d
LG
1732 if ReturnValue != 0:\r
1733 EdkLogger.error("build", PARAMETER_INVALID, "Patch PCD value failed", ExtraData=ErrorInfo)\r
4afd3d04 1734\r
d943b0c3
FB
1735 MapBuffer.append('PEI_CODE_PAGE_NUMBER = 0x%x\n' % (PeiSize // 0x1000))\r
1736 MapBuffer.append('BOOT_CODE_PAGE_NUMBER = 0x%x\n' % (BtSize // 0x1000))\r
1737 MapBuffer.append('RUNTIME_CODE_PAGE_NUMBER = 0x%x\n' % (RtSize // 0x1000))\r
52302d4d 1738 if len (SmmModuleList) > 0:\r
d943b0c3 1739 MapBuffer.append('SMM_CODE_PAGE_NUMBER = 0x%x\n' % (SmmSize // 0x1000))\r
4afd3d04
LG
1740\r
1741 PeiBaseAddr = TopMemoryAddress - RtSize - BtSize\r
52302d4d 1742 BtBaseAddr = TopMemoryAddress - RtSize\r
4afd3d04 1743 RtBaseAddr = TopMemoryAddress - ReservedRuntimeMemorySize\r
52302d4d
LG
1744\r
1745 self._RebaseModule (MapBuffer, PeiBaseAddr, PeiModuleList, TopMemoryAddress == 0)\r
1746 self._RebaseModule (MapBuffer, BtBaseAddr, BtModuleList, TopMemoryAddress == 0)\r
1747 self._RebaseModule (MapBuffer, RtBaseAddr, RtModuleList, TopMemoryAddress == 0)\r
47fea6af 1748 self._RebaseModule (MapBuffer, 0x1000, SmmModuleList, AddrIsOffset=False, ModeIsSmm=True)\r
d943b0c3 1749 MapBuffer.append('\n\n')\r
da92f276
LG
1750 sys.stdout.write ("\n")\r
1751 sys.stdout.flush()\r
4afd3d04 1752\r
52302d4d
LG
1753 ## Save platform Map file\r
1754 #\r
1755 def _SaveMapFile (self, MapBuffer, Wa):\r
1756 #\r
1757 # Map file path is got.\r
1758 #\r
1759 MapFilePath = os.path.join(Wa.BuildDir, Wa.Name + '.map')\r
1760 #\r
1761 # Save address map into MAP file.\r
1762 #\r
d943b0c3 1763 SaveFileOnChange(MapFilePath, ''.join(MapBuffer), False)\r
da92f276 1764 if self.LoadFixAddress != 0:\r
47fea6af 1765 sys.stdout.write ("\nLoad Module At Fix Address Map file can be found at %s\n" % (MapFilePath))\r
da92f276 1766 sys.stdout.flush()\r
52302d4d
LG
1767\r
1768 ## Build active platform for different build targets and different tool chains\r
1769 #\r
1770 def _BuildPlatform(self):\r
f0dc69e6 1771 SaveFileOnChange(self.PlatformBuildPath, '# DO NOT EDIT \n# FILE auto-generated\n', False)\r
52302d4d 1772 for BuildTarget in self.BuildTargetList:\r
0d2711a6 1773 GlobalData.gGlobalDefines['TARGET'] = BuildTarget\r
40b4e21d 1774 index = 0\r
52302d4d 1775 for ToolChain in self.ToolChainList:\r
0d2711a6
LG
1776 GlobalData.gGlobalDefines['TOOLCHAIN'] = ToolChain\r
1777 GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = ToolChain\r
40b4e21d
YZ
1778 GlobalData.gGlobalDefines['FAMILY'] = self.ToolChainFamily[index]\r
1779 index += 1\r
52302d4d
LG
1780 Wa = WorkspaceAutoGen(\r
1781 self.WorkspaceDir,\r
0d2711a6 1782 self.PlatformFile,\r
52302d4d
LG
1783 BuildTarget,\r
1784 ToolChain,\r
1785 self.ArchList,\r
1786 self.BuildDatabase,\r
1787 self.TargetTxt,\r
1788 self.ToolDef,\r
1789 self.Fdf,\r
1790 self.FdList,\r
1791 self.FvList,\r
4234283c 1792 self.CapList,\r
f3decdc3 1793 self.SkuId,\r
9508d0fa
LG
1794 self.UniFlag,\r
1795 self.Progress\r
52302d4d 1796 )\r
0d2711a6
LG
1797 self.Fdf = Wa.FdfFile\r
1798 self.LoadFixAddress = Wa.Platform.LoadFixAddress\r
52302d4d
LG
1799 self.BuildReport.AddPlatformReport(Wa)\r
1800 self.Progress.Stop("done!")\r
37de70b7
YZ
1801\r
1802 # Add ffs build to makefile\r
1803 CmdListDict = {}\r
1804 if GlobalData.gEnableGenfdsMultiThread and self.Fdf:\r
b1e27d17 1805 CmdListDict = self._GenFfsCmd(Wa.ArchList)\r
37de70b7 1806\r
03af2753 1807 for Arch in Wa.ArchList:\r
e8449e1d 1808 PcdMaList = []\r
03af2753
HC
1809 GlobalData.gGlobalDefines['ARCH'] = Arch\r
1810 Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)\r
a0a2cd1e
FB
1811 for Module in Pa.Platform.Modules:\r
1812 # Get ModuleAutoGen object to generate C code file and makefile\r
e8449e1d 1813 Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
4231a819 1814 if Ma is None:\r
a0a2cd1e 1815 continue\r
e8449e1d
FB
1816 if Ma.PcdIsDriver:\r
1817 Ma.PlatformInfo = Pa\r
673d09a2 1818 Ma.Workspace = Wa\r
e8449e1d 1819 PcdMaList.append(Ma)\r
a0a2cd1e 1820 self.BuildModules.append(Ma)\r
5f7bb391
FB
1821 Pa.DataPipe.DataContainer = {"FfsCommand":CmdListDict}\r
1822 Pa.DataPipe.DataContainer = {"Workspace_timestamp": Wa._SrcTimeStamp}\r
673d09a2 1823 self._BuildPa(self.Target, Pa, FfsCommand=CmdListDict,PcdMaList=PcdMaList)\r
4afd3d04 1824\r
52302d4d 1825 # Create MAP file when Load Fix Address is enabled.\r
636f2be6 1826 if self.Target in ["", "all", "fds"]:\r
0d2711a6
LG
1827 for Arch in Wa.ArchList:\r
1828 GlobalData.gGlobalDefines['ARCH'] = Arch\r
52302d4d
LG
1829 #\r
1830 # Check whether the set fix address is above 4G for 32bit image.\r
1831 #\r
1832 if (Arch == 'IA32' or Arch == 'ARM') and self.LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self.LoadFixAddress >= 0x100000000:\r
0d2711a6 1833 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS can't be set to larger than or equal to 4G for the platform with IA32 or ARM arch modules")\r
52302d4d
LG
1834 #\r
1835 # Get Module List\r
1836 #\r
636f2be6 1837 ModuleList = {}\r
52302d4d
LG
1838 for Pa in Wa.AutoGenObjectList:\r
1839 for Ma in Pa.ModuleAutoGenList:\r
4231a819 1840 if Ma is None:\r
52302d4d
LG
1841 continue\r
1842 if not Ma.IsLibrary:\r
636f2be6 1843 ModuleList[Ma.Guid.upper()] = Ma\r
52302d4d 1844\r
d943b0c3 1845 MapBuffer = []\r
636f2be6
LG
1846 if self.LoadFixAddress != 0:\r
1847 #\r
1848 # Rebase module to the preferred memory address before GenFds\r
1849 #\r
1850 self._CollectModuleMapBuffer(MapBuffer, ModuleList)\r
0d2711a6 1851 if self.Fdf:\r
b0e23cf3
YL
1852 #\r
1853 # create FDS again for the updated EFI image\r
1854 #\r
1855 self._Build("fds", Wa)\r
52302d4d
LG
1856 #\r
1857 # Create MAP file for all platform FVs after GenFds.\r
1858 #\r
636f2be6 1859 self._CollectFvMapBuffer(MapBuffer, Wa, ModuleList)\r
52302d4d
LG
1860 #\r
1861 # Save MAP buffer into MAP file.\r
1862 #\r
1863 self._SaveMapFile (MapBuffer, Wa)\r
373298ca 1864 self.CreateGuidedSectionToolsFile(Wa)\r
52302d4d
LG
1865\r
1866 ## Build active module for different build targets, different tool chains and different archs\r
1867 #\r
1868 def _BuildModule(self):\r
1869 for BuildTarget in self.BuildTargetList:\r
0d2711a6 1870 GlobalData.gGlobalDefines['TARGET'] = BuildTarget\r
40b4e21d 1871 index = 0\r
52302d4d 1872 for ToolChain in self.ToolChainList:\r
1b8eca8b 1873 WorkspaceAutoGenTime = time.time()\r
0d2711a6 1874 GlobalData.gGlobalDefines['TOOLCHAIN'] = ToolChain\r
4afd3d04 1875 GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = ToolChain\r
40b4e21d
YZ
1876 GlobalData.gGlobalDefines['FAMILY'] = self.ToolChainFamily[index]\r
1877 index += 1\r
52302d4d
LG
1878 #\r
1879 # module build needs platform build information, so get platform\r
1880 # AutoGen first\r
1881 #\r
1882 Wa = WorkspaceAutoGen(\r
1883 self.WorkspaceDir,\r
0d2711a6 1884 self.PlatformFile,\r
52302d4d
LG
1885 BuildTarget,\r
1886 ToolChain,\r
1887 self.ArchList,\r
1888 self.BuildDatabase,\r
1889 self.TargetTxt,\r
1890 self.ToolDef,\r
1891 self.Fdf,\r
1892 self.FdList,\r
1893 self.FvList,\r
4234283c 1894 self.CapList,\r
f3decdc3 1895 self.SkuId,\r
9508d0fa
LG
1896 self.UniFlag,\r
1897 self.Progress,\r
1898 self.ModuleFile\r
52302d4d 1899 )\r
0d2711a6
LG
1900 self.Fdf = Wa.FdfFile\r
1901 self.LoadFixAddress = Wa.Platform.LoadFixAddress\r
52302d4d 1902 Wa.CreateMakeFile(False)\r
37de70b7
YZ
1903 # Add ffs build to makefile\r
1904 CmdListDict = None\r
1905 if GlobalData.gEnableGenfdsMultiThread and self.Fdf:\r
b1e27d17 1906 CmdListDict = self._GenFfsCmd(Wa.ArchList)\r
0e7e7a26 1907\r
0e7e7a26
SS
1908 GlobalData.file_lock = mp.Lock()\r
1909 GlobalData.FfsCmd = CmdListDict\r
1910\r
52302d4d
LG
1911 self.Progress.Stop("done!")\r
1912 MaList = []\r
1b8eca8b
YZ
1913 ExitFlag = threading.Event()\r
1914 ExitFlag.clear()\r
1915 self.AutoGenTime += int(round((time.time() - WorkspaceAutoGenTime)))\r
0d2711a6 1916 for Arch in Wa.ArchList:\r
1b8eca8b 1917 AutoGenStart = time.time()\r
0d2711a6 1918 GlobalData.gGlobalDefines['ARCH'] = Arch\r
16bad1fb
YZ
1919 Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)\r
1920 for Module in Pa.Platform.Modules:\r
fbe53845 1921 if self.ModuleFile.Dir == Module.Dir and self.ModuleFile.Name == Module.Name:\r
e8449e1d 1922 Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
db4d47fd
CR
1923 if Ma is None:\r
1924 continue\r
b67735a7
FZ
1925 if Ma.PcdIsDriver:\r
1926 Ma.PlatformInfo = Pa\r
1927 Ma.Workspace = Wa\r
19bf8314 1928 MaList.append(Ma)\r
0e7e7a26 1929\r
fc8b8dea
SS
1930 if GlobalData.gUseHashCache and not GlobalData.gBinCacheDest and self.Target in [None, "", "all"]:\r
1931 if Ma.CanSkipbyPreMakeCache():\r
373298ca 1932 continue\r
fc8b8dea
SS
1933 else:\r
1934 self.PreMakeCacheMiss.add(Ma)\r
0e7e7a26 1935\r
119d8c42
YZ
1936 # Not to auto-gen for targets 'clean', 'cleanlib', 'cleanall', 'run', 'fds'\r
1937 if self.Target not in ['clean', 'cleanlib', 'cleanall', 'run', 'fds']:\r
1938 # for target which must generate AutoGen code and makefile\r
1939 if not self.SkipAutoGen or self.Target == 'genc':\r
cd498216 1940 self.Progress.Start("Generating code")\r
119d8c42 1941 Ma.CreateCodeFile(True)\r
cd498216
YZ
1942 self.Progress.Stop("done!")\r
1943 if self.Target == "genc":\r
1944 return True\r
119d8c42 1945 if not self.SkipAutoGen or self.Target == 'genmake':\r
cd498216 1946 self.Progress.Start("Generating makefile")\r
e3c8311f
FB
1947 if CmdListDict and self.Fdf and (Module.Path, Arch) in CmdListDict:\r
1948 Ma.CreateMakeFile(True, CmdListDict[Module.Path, Arch])\r
1949 del CmdListDict[Module.Path, Arch]\r
37de70b7
YZ
1950 else:\r
1951 Ma.CreateMakeFile(True)\r
cd498216
YZ
1952 self.Progress.Stop("done!")\r
1953 if self.Target == "genmake":\r
1954 return True\r
0e7e7a26
SS
1955\r
1956 if GlobalData.gBinCacheSource and self.Target in [None, "", "all"]:\r
fc8b8dea 1957 if Ma.CanSkipbyMakeCache():\r
0e7e7a26
SS
1958 continue\r
1959 else:\r
fc8b8dea 1960 self.MakeCacheMiss.add(Ma)\r
0e7e7a26 1961\r
16bad1fb 1962 self.BuildModules.append(Ma)\r
1b8eca8b
YZ
1963 self.AutoGenTime += int(round((time.time() - AutoGenStart)))\r
1964 MakeStart = time.time()\r
1965 for Ma in self.BuildModules:\r
1966 if not Ma.IsBinaryModule:\r
673d09a2 1967 Bt = BuildTask.New(ModuleMakeUnit(Ma, Pa.BuildCommand,self.Target))\r
1b8eca8b
YZ
1968 # Break build if any build thread has error\r
1969 if BuildTask.HasError():\r
1970 # we need a full version of makefile for platform\r
1971 ExitFlag.set()\r
1972 BuildTask.WaitForComplete()\r
1973 Pa.CreateMakeFile(False)\r
1974 EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
1975 # Start task scheduler\r
1976 if not BuildTask.IsOnGoing():\r
1977 BuildTask.StartScheduler(self.ThreadNumber, ExitFlag)\r
1978\r
1979 # in case there's an interruption. we need a full version of makefile for platform\r
1980 Pa.CreateMakeFile(False)\r
1981 if BuildTask.HasError():\r
1982 EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
1983 self.MakeTime += int(round((time.time() - MakeStart)))\r
1984\r
1985 MakeContiue = time.time()\r
1986 ExitFlag.set()\r
1987 BuildTask.WaitForComplete()\r
1988 self.CreateAsBuiltInf()\r
b8ac0b7f 1989 if GlobalData.gBinCacheDest:\r
fc8b8dea
SS
1990 self.GenDestCache()\r
1991 elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
1992 # Only for --hash\r
1993 # Update PreMakeCacheChain files\r
1994 self.GenLocalPreMakeCache()\r
b8ac0b7f 1995 self.BuildModules = []\r
1b8eca8b
YZ
1996 self.MakeTime += int(round((time.time() - MakeContiue)))\r
1997 if BuildTask.HasError():\r
1998 EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
d5d56f1b
LG
1999\r
2000 self.BuildReport.AddPlatformReport(Wa, MaList)\r
52302d4d
LG
2001 if MaList == []:\r
2002 EdkLogger.error(\r
2003 'build',\r
2004 BUILD_ERROR,\r
2005 "Module for [%s] is not a component of active platform."\\r
2006 " Please make sure that the ARCH and inf file path are"\\r
47fea6af 2007 " given in the same as in [%s]" % \\r
0d2711a6 2008 (', '.join(Wa.ArchList), self.PlatformFile),\r
52302d4d
LG
2009 ExtraData=self.ModuleFile\r
2010 )\r
2011 # Create MAP file when Load Fix Address is enabled.\r
0d2711a6
LG
2012 if self.Target == "fds" and self.Fdf:\r
2013 for Arch in Wa.ArchList:\r
52302d4d
LG
2014 #\r
2015 # Check whether the set fix address is above 4G for 32bit image.\r
2016 #\r
2017 if (Arch == 'IA32' or Arch == 'ARM') and self.LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self.LoadFixAddress >= 0x100000000:\r
2018 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
2019 #\r
2020 # Get Module List\r
2021 #\r
636f2be6 2022 ModuleList = {}\r
52302d4d
LG
2023 for Pa in Wa.AutoGenObjectList:\r
2024 for Ma in Pa.ModuleAutoGenList:\r
4231a819 2025 if Ma is None:\r
52302d4d
LG
2026 continue\r
2027 if not Ma.IsLibrary:\r
636f2be6 2028 ModuleList[Ma.Guid.upper()] = Ma\r
52302d4d 2029\r
d943b0c3 2030 MapBuffer = []\r
636f2be6
LG
2031 if self.LoadFixAddress != 0:\r
2032 #\r
2033 # Rebase module to the preferred memory address before GenFds\r
2034 #\r
2035 self._CollectModuleMapBuffer(MapBuffer, ModuleList)\r
b0e23cf3
YL
2036 #\r
2037 # create FDS again for the updated EFI image\r
2038 #\r
1b8eca8b 2039 GenFdsStart = time.time()\r
b0e23cf3 2040 self._Build("fds", Wa)\r
1b8eca8b 2041 self.GenFdsTime += int(round((time.time() - GenFdsStart)))\r
52302d4d
LG
2042 #\r
2043 # Create MAP file for all platform FVs after GenFds.\r
2044 #\r
636f2be6 2045 self._CollectFvMapBuffer(MapBuffer, Wa, ModuleList)\r
52302d4d
LG
2046 #\r
2047 # Save MAP buffer into MAP file.\r
2048 #\r
2049 self._SaveMapFile (MapBuffer, Wa)\r
2050\r
b1e27d17 2051 def _GenFfsCmd(self,ArchList):\r
f7496d71 2052 # convert dictionary of Cmd:(Inf,Arch)\r
9eb87141
CJ
2053 # to a new dictionary of (Inf,Arch):Cmd,Cmd,Cmd...\r
2054 CmdSetDict = defaultdict(set)\r
b1e27d17 2055 GenFfsDict = GenFds.GenFfsMakefile('', GlobalData.gFdfParser, self, ArchList, GlobalData)\r
37de70b7
YZ
2056 for Cmd in GenFfsDict:\r
2057 tmpInf, tmpArch = GenFfsDict[Cmd]\r
9eb87141
CJ
2058 CmdSetDict[tmpInf, tmpArch].add(Cmd)\r
2059 return CmdSetDict\r
373298ca
FB
2060 def VerifyAutoGenFiles(self):\r
2061 AutoGenIdFile = os.path.join(GlobalData.gConfDirectory,".AutoGenIdFile.txt")\r
2062 try:\r
2063 with open(AutoGenIdFile) as fd:\r
2064 lines = fd.readlines()\r
2065 except:\r
2066 return None\r
2067 for line in lines:\r
2068 if "Arch" in line:\r
2069 ArchList = line.strip().split("=")[1].split("|")\r
2070 if "BuildDir" in line:\r
2071 BuildDir = line.split("=")[1].strip()\r
2072 if "PlatformGuid" in line:\r
2073 PlatformGuid = line.split("=")[1].strip()\r
2074 GlobalVarList = []\r
2075 for arch in ArchList:\r
2076 global_var = os.path.join(BuildDir, "GlobalVar_%s_%s.bin" % (str(PlatformGuid),arch))\r
2077 if not os.path.exists(global_var):\r
2078 return None\r
2079 GlobalVarList.append(global_var)\r
2080 for global_var in GlobalVarList:\r
2081 data_pipe = MemoryDataPipe()\r
2082 data_pipe.load(global_var)\r
2083 target = data_pipe.Get("P_Info").get("Target")\r
2084 toolchain = data_pipe.Get("P_Info").get("ToolChain")\r
2085 archlist = data_pipe.Get("P_Info").get("ArchList")\r
2086 Arch = data_pipe.Get("P_Info").get("Arch")\r
2087 active_p = data_pipe.Get("P_Info").get("ActivePlatform")\r
2088 workspacedir = data_pipe.Get("P_Info").get("WorkspaceDir")\r
2089 PackagesPath = os.getenv("PACKAGES_PATH")\r
2090 mws.setWs(workspacedir, PackagesPath)\r
2091 LibraryBuildDirectoryList = data_pipe.Get("LibraryBuildDirectoryList")\r
2092 ModuleBuildDirectoryList = data_pipe.Get("ModuleBuildDirectoryList")\r
2093\r
2094 for m_build_dir in LibraryBuildDirectoryList:\r
818283de 2095 if not os.path.exists(os.path.join(m_build_dir,self.MakeFileName)):\r
373298ca
FB
2096 return None\r
2097 for m_build_dir in ModuleBuildDirectoryList:\r
818283de 2098 if not os.path.exists(os.path.join(m_build_dir,self.MakeFileName)):\r
373298ca
FB
2099 return None\r
2100 Wa = WorkSpaceInfo(\r
2101 workspacedir,active_p,target,toolchain,archlist\r
2102 )\r
2103 Pa = PlatformInfo(Wa, active_p, target, toolchain, Arch,data_pipe)\r
2104 Wa.AutoGenObjectList.append(Pa)\r
2105 return Wa\r
2106 def SetupMakeSetting(self,Wa):\r
2107 BuildModules = []\r
2108 for Pa in Wa.AutoGenObjectList:\r
2109 for m in Pa._MbList:\r
2110 ma = ModuleAutoGen(Wa,m.MetaFile, Pa.BuildTarget, Wa.ToolChain, Pa.Arch, Pa.MetaFile,Pa.DataPipe)\r
2111 BuildModules.append(ma)\r
2112 fdf_file = Wa.FlashDefinition\r
2113 if fdf_file:\r
2114 Fdf = FdfParser(fdf_file.Path)\r
2115 Fdf.ParseFile()\r
2116 GlobalData.gFdfParser = Fdf\r
2117 if Fdf.CurrentFdName and Fdf.CurrentFdName in Fdf.Profile.FdDict:\r
2118 FdDict = Fdf.Profile.FdDict[Fdf.CurrentFdName]\r
2119 for FdRegion in FdDict.RegionList:\r
49fb9f7e 2120 if str(FdRegion.RegionType) == 'FILE' and self.Platform.VpdToolGuid in str(FdRegion.RegionDataList):\r
373298ca
FB
2121 if int(FdRegion.Offset) % 8 != 0:\r
2122 EdkLogger.error("build", FORMAT_INVALID, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion.Offset))\r
2123 Wa.FdfProfile = Fdf.Profile\r
2124 self.Fdf = Fdf\r
2125 else:\r
2126 self.Fdf = None\r
2127 return BuildModules\r
37de70b7 2128\r
52302d4d
LG
2129 ## Build a platform in multi-thread mode\r
2130 #\r
373298ca
FB
2131 def PerformAutoGen(self,BuildTarget,ToolChain):\r
2132 WorkspaceAutoGenTime = time.time()\r
2133 Wa = WorkspaceAutoGen(\r
2134 self.WorkspaceDir,\r
2135 self.PlatformFile,\r
2136 BuildTarget,\r
2137 ToolChain,\r
2138 self.ArchList,\r
2139 self.BuildDatabase,\r
2140 self.TargetTxt,\r
2141 self.ToolDef,\r
2142 self.Fdf,\r
2143 self.FdList,\r
2144 self.FvList,\r
2145 self.CapList,\r
2146 self.SkuId,\r
2147 self.UniFlag,\r
2148 self.Progress\r
2149 )\r
2150 self.Fdf = Wa.FdfFile\r
2151 self.LoadFixAddress = Wa.Platform.LoadFixAddress\r
2152 self.BuildReport.AddPlatformReport(Wa)\r
2153 Wa.CreateMakeFile(False)\r
2154\r
fc8b8dea 2155 # Add ffs build to makefile\r
373298ca
FB
2156 CmdListDict = {}\r
2157 if GlobalData.gEnableGenfdsMultiThread and self.Fdf:\r
2158 CmdListDict = self._GenFfsCmd(Wa.ArchList)\r
2159\r
373298ca
FB
2160 self.AutoGenTime += int(round((time.time() - WorkspaceAutoGenTime)))\r
2161 BuildModules = []\r
373298ca
FB
2162 for Arch in Wa.ArchList:\r
2163 PcdMaList = []\r
2164 AutoGenStart = time.time()\r
2165 GlobalData.gGlobalDefines['ARCH'] = Arch\r
2166 Pa = PlatformAutoGen(Wa, self.PlatformFile, BuildTarget, ToolChain, Arch)\r
2167 if Pa is None:\r
2168 continue\r
2169 ModuleList = []\r
2170 for Inf in Pa.Platform.Modules:\r
2171 ModuleList.append(Inf)\r
fc8b8dea 2172 # Add the INF only list in FDF\r
373298ca
FB
2173 if GlobalData.gFdfParser is not None:\r
2174 for InfName in GlobalData.gFdfParser.Profile.InfList:\r
2175 Inf = PathClass(NormPath(InfName), self.WorkspaceDir, Arch)\r
2176 if Inf in Pa.Platform.Modules:\r
2177 continue\r
2178 ModuleList.append(Inf)\r
2179 Pa.DataPipe.DataContainer = {"FfsCommand":CmdListDict}\r
2180 Pa.DataPipe.DataContainer = {"Workspace_timestamp": Wa._SrcTimeStamp}\r
2181 Pa.DataPipe.DataContainer = {"CommandTarget": self.Target}\r
2182 Pa.CreateLibModuelDirs()\r
818283de
PG
2183 # Fetch the MakeFileName.\r
2184 self.MakeFileName = Pa.MakeFileName\r
818283de 2185\r
373298ca
FB
2186 Pa.DataPipe.DataContainer = {"LibraryBuildDirectoryList":Pa.LibraryBuildDirectoryList}\r
2187 Pa.DataPipe.DataContainer = {"ModuleBuildDirectoryList":Pa.ModuleBuildDirectoryList}\r
2188 Pa.DataPipe.DataContainer = {"FdsCommandDict": Wa.GenFdsCommandDict}\r
fc8b8dea
SS
2189 # Prepare the cache share data for multiprocessing\r
2190 Pa.DataPipe.DataContainer = {"gPlatformHashFile":GlobalData.gPlatformHashFile}\r
373298ca
FB
2191 ModuleCodaFile = {}\r
2192 for ma in Pa.ModuleAutoGenList:\r
2193 ModuleCodaFile[(ma.MetaFile.File,ma.MetaFile.Root,ma.Arch,ma.MetaFile.Path)] = [item.Target for item in ma.CodaTargetList]\r
2194 Pa.DataPipe.DataContainer = {"ModuleCodaFile":ModuleCodaFile}\r
fc8b8dea 2195 # ModuleList contains all driver modules only\r
373298ca 2196 for Module in ModuleList:\r
fc8b8dea 2197 # Get ModuleAutoGen object to generate C code file and makefile\r
373298ca 2198 Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
373298ca
FB
2199 if Ma is None:\r
2200 continue\r
2201 if Ma.PcdIsDriver:\r
2202 Ma.PlatformInfo = Pa\r
2203 Ma.Workspace = Wa\r
2204 PcdMaList.append(Ma)\r
fc8b8dea
SS
2205 self.AllDrivers.add(Ma)\r
2206 self.AllModules.add(Ma)\r
373298ca
FB
2207\r
2208 mqueue = mp.Queue()\r
fc8b8dea 2209 cqueue = mp.Queue()\r
373298ca
FB
2210 for m in Pa.GetAllModuleInfo:\r
2211 mqueue.put(m)\r
fc8b8dea
SS
2212 module_file,module_root,module_path,module_basename,\\r
2213 module_originalpath,module_arch,IsLib = m\r
2214 Ma = ModuleAutoGen(Wa, PathClass(module_path, Wa), BuildTarget,\\r
2215 ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
2216 self.AllModules.add(Ma)\r
373298ca
FB
2217 data_pipe_file = os.path.join(Pa.BuildDir, "GlobalVar_%s_%s.bin" % (str(Pa.Guid),Pa.Arch))\r
2218 Pa.DataPipe.dump(data_pipe_file)\r
2219\r
bfe36cb4 2220 mqueue.put((None,None,None,None,None,None,None))\r
fc8b8dea 2221 autogen_rt, errorcode = self.StartAutoGen(mqueue, Pa.DataPipe, self.SkipAutoGen, PcdMaList, cqueue)\r
373298ca
FB
2222\r
2223 if not autogen_rt:\r
2224 self.AutoGenMgr.TerminateWorkers()\r
2225 self.AutoGenMgr.join(1)\r
2226 raise FatalError(errorcode)\r
fc8b8dea
SS
2227\r
2228 if GlobalData.gUseHashCache:\r
2229 for item in GlobalData.gModuleAllCacheStatus:\r
2230 (MetaFilePath, Arch, CacheStr, Status) = item\r
2231 Ma = ModuleAutoGen(Wa, PathClass(MetaFilePath, Wa), BuildTarget,\\r
2232 ToolChain, Arch, self.PlatformFile,Pa.DataPipe)\r
2233 if CacheStr == "PreMakeCache" and Status == False:\r
2234 self.PreMakeCacheMiss.add(Ma)\r
2235 if CacheStr == "PreMakeCache" and Status == True:\r
2236 self.PreMakeCacheHit.add(Ma)\r
2237 GlobalData.gModuleCacheHit.add(Ma)\r
2238 if CacheStr == "MakeCache" and Status == False:\r
2239 self.MakeCacheMiss.add(Ma)\r
2240 if CacheStr == "MakeCache" and Status == True:\r
2241 self.MakeCacheHit.add(Ma)\r
2242 GlobalData.gModuleCacheHit.add(Ma)\r
373298ca
FB
2243 self.AutoGenTime += int(round((time.time() - AutoGenStart)))\r
2244 AutoGenIdFile = os.path.join(GlobalData.gConfDirectory,".AutoGenIdFile.txt")\r
2245 with open(AutoGenIdFile,"w") as fw:\r
2246 fw.write("Arch=%s\n" % "|".join((Wa.ArchList)))\r
2247 fw.write("BuildDir=%s\n" % Wa.BuildDir)\r
2248 fw.write("PlatformGuid=%s\n" % str(Wa.AutoGenObjectList[0].Guid))\r
fc8b8dea
SS
2249\r
2250 if GlobalData.gBinCacheSource:\r
2251 BuildModules.extend(self.MakeCacheMiss)\r
2252 elif GlobalData.gUseHashCache and not GlobalData.gBinCacheDest:\r
2253 BuildModules.extend(self.PreMakeCacheMiss)\r
2254 else:\r
2255 BuildModules.extend(self.AllDrivers)\r
2256\r
373298ca
FB
2257 self.Progress.Stop("done!")\r
2258 return Wa, BuildModules\r
2259\r
52302d4d 2260 def _MultiThreadBuildPlatform(self):\r
f0dc69e6 2261 SaveFileOnChange(self.PlatformBuildPath, '# DO NOT EDIT \n# FILE auto-generated\n', False)\r
52302d4d 2262 for BuildTarget in self.BuildTargetList:\r
0d2711a6 2263 GlobalData.gGlobalDefines['TARGET'] = BuildTarget\r
40b4e21d 2264 index = 0\r
52302d4d 2265 for ToolChain in self.ToolChainList:\r
78fb6b0e 2266 resetFdsGlobalVariable()\r
0d2711a6 2267 GlobalData.gGlobalDefines['TOOLCHAIN'] = ToolChain\r
4afd3d04 2268 GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = ToolChain\r
40b4e21d
YZ
2269 GlobalData.gGlobalDefines['FAMILY'] = self.ToolChainFamily[index]\r
2270 index += 1\r
52302d4d
LG
2271 ExitFlag = threading.Event()\r
2272 ExitFlag.clear()\r
373298ca
FB
2273 if self.SkipAutoGen:\r
2274 Wa = self.VerifyAutoGenFiles()\r
2275 if Wa is None:\r
5a9db858 2276 self.SkipAutoGen = False\r
373298ca 2277 Wa, self.BuildModules = self.PerformAutoGen(BuildTarget,ToolChain)\r
0e7e7a26 2278 else:\r
373298ca
FB
2279 GlobalData.gAutoGenPhase = True\r
2280 self.BuildModules = self.SetupMakeSetting(Wa)\r
2281 else:\r
2282 Wa, self.BuildModules = self.PerformAutoGen(BuildTarget,ToolChain)\r
2283 Pa = Wa.AutoGenObjectList[0]\r
2284 GlobalData.gAutoGenPhase = False\r
0e7e7a26
SS
2285\r
2286 if GlobalData.gBinCacheSource:\r
fc8b8dea
SS
2287 EdkLogger.quiet("[cache Summary]: Total module num: %s" % len(self.AllModules))\r
2288 EdkLogger.quiet("[cache Summary]: PreMakecache miss num: %s " % len(self.PreMakeCacheMiss))\r
2289 EdkLogger.quiet("[cache Summary]: Makecache miss num: %s " % len(self.MakeCacheMiss))\r
0e7e7a26 2290\r
673d09a2 2291 for Arch in Wa.ArchList:\r
1b8eca8b 2292 MakeStart = time.time()\r
0e7e7a26 2293 for Ma in set(self.BuildModules):\r
52302d4d 2294 # Generate build task for the module\r
a0a2cd1e 2295 if not Ma.IsBinaryModule:\r
673d09a2 2296 Bt = BuildTask.New(ModuleMakeUnit(Ma, Pa.BuildCommand,self.Target))\r
52302d4d
LG
2297 # Break build if any build thread has error\r
2298 if BuildTask.HasError():\r
2299 # we need a full version of makefile for platform\r
2300 ExitFlag.set()\r
2301 BuildTask.WaitForComplete()\r
2302 Pa.CreateMakeFile(False)\r
2303 EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
2304 # Start task scheduler\r
2305 if not BuildTask.IsOnGoing():\r
2306 BuildTask.StartScheduler(self.ThreadNumber, ExitFlag)\r
2307\r
2308 # in case there's an interruption. we need a full version of makefile for platform\r
373298ca 2309\r
52302d4d
LG
2310 if BuildTask.HasError():\r
2311 EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
1b8eca8b 2312 self.MakeTime += int(round((time.time() - MakeStart)))\r
52302d4d 2313\r
1b8eca8b 2314 MakeContiue = time.time()\r
64b2609f 2315 #\r
52302d4d
LG
2316 #\r
2317 # All modules have been put in build tasks queue. Tell task scheduler\r
2318 # to exit if all tasks are completed\r
2319 #\r
2320 ExitFlag.set()\r
2321 BuildTask.WaitForComplete()\r
b8ac0b7f 2322 if GlobalData.gBinCacheDest:\r
fc8b8dea
SS
2323 self.GenDestCache()\r
2324 elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:\r
2325 # Only for --hash\r
2326 # Update PreMakeCacheChain files\r
2327 self.GenLocalPreMakeCache()\r
e0f8261a
FZ
2328 #\r
2329 # Get Module List\r
2330 #\r
2331 ModuleList = {ma.Guid.upper(): ma for ma in self.BuildModules}\r
b8ac0b7f 2332 self.BuildModules = []\r
1b8eca8b 2333 self.MakeTime += int(round((time.time() - MakeContiue)))\r
52302d4d
LG
2334 #\r
2335 # Check for build error, and raise exception if one\r
2336 # has been signaled.\r
2337 #\r
2338 if BuildTask.HasError():\r
2339 EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
2340\r
2341 # Create MAP file when Load Fix Address is enabled.\r
636f2be6 2342 if self.Target in ["", "all", "fds"]:\r
0d2711a6 2343 for Arch in Wa.ArchList:\r
52302d4d
LG
2344 #\r
2345 # Check whether the set fix address is above 4G for 32bit image.\r
2346 #\r
2347 if (Arch == 'IA32' or Arch == 'ARM') and self.LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self.LoadFixAddress >= 0x100000000:\r
2348 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
373298ca 2349\r
52302d4d
LG
2350 #\r
2351 # Rebase module to the preferred memory address before GenFds\r
2352 #\r
d943b0c3 2353 MapBuffer = []\r
636f2be6
LG
2354 if self.LoadFixAddress != 0:\r
2355 self._CollectModuleMapBuffer(MapBuffer, ModuleList)\r
52302d4d 2356\r
0d2711a6 2357 if self.Fdf:\r
f3decdc3
LG
2358 #\r
2359 # Generate FD image if there's a FDF file found\r
2360 #\r
1b8eca8b 2361 GenFdsStart = time.time()\r
370544d1
DL
2362 if GenFdsApi(Wa.GenFdsCommandDict, self.Db):\r
2363 EdkLogger.error("build", COMMAND_FAILURE)\r
3a3a3af4
FZ
2364 Threshold = self.GetFreeSizeThreshold()\r
2365 if Threshold:\r
2366 self.CheckFreeSizeThreshold(Threshold, Wa.FvDir)\r
03af2753 2367\r
52302d4d
LG
2368 #\r
2369 # Create MAP file for all platform FVs after GenFds.\r
2370 #\r
636f2be6 2371 self._CollectFvMapBuffer(MapBuffer, Wa, ModuleList)\r
1b8eca8b 2372 self.GenFdsTime += int(round((time.time() - GenFdsStart)))\r
52302d4d
LG
2373 #\r
2374 # Save MAP buffer into MAP file.\r
2375 #\r
2376 self._SaveMapFile(MapBuffer, Wa)\r
373298ca 2377 self.CreateGuidedSectionToolsFile(Wa)\r
3a3a3af4
FZ
2378\r
2379 ## GetFreeSizeThreshold()\r
2380 #\r
2381 # @retval int Threshold value\r
2382 #\r
2383 def GetFreeSizeThreshold(self):\r
2384 Threshold = None\r
2385 Threshold_Str = GlobalData.gCommandLineDefines.get('FV_SPARE_SPACE_THRESHOLD')\r
2386 if Threshold_Str:\r
2387 try:\r
2388 if Threshold_Str.lower().startswith('0x'):\r
2389 Threshold = int(Threshold_Str, 16)\r
2390 else:\r
2391 Threshold = int(Threshold_Str)\r
2392 except:\r
2393 EdkLogger.warn("build", 'incorrect value for FV_SPARE_SPACE_THRESHOLD %s.Only decimal or hex format is allowed.' % Threshold_Str)\r
2394 return Threshold\r
2395\r
2396 def CheckFreeSizeThreshold(self, Threshold=None, FvDir=None):\r
2397 if not isinstance(Threshold, int):\r
2398 return\r
2399 if not isinstance(FvDir, str) or not FvDir:\r
2400 return\r
2401 FdfParserObject = GlobalData.gFdfParser\r
2402 FvRegionNameList = [FvName for FvName in FdfParserObject.Profile.FvDict if FdfParserObject.Profile.FvDict[FvName].FvRegionInFD]\r
2403 for FvName in FdfParserObject.Profile.FvDict:\r
2404 if FvName in FvRegionNameList:\r
2405 FvSpaceInfoFileName = os.path.join(FvDir, FvName.upper() + '.Fv.map')\r
2406 if os.path.exists(FvSpaceInfoFileName):\r
2407 FileLinesList = getlines(FvSpaceInfoFileName)\r
2408 for Line in FileLinesList:\r
2409 NameValue = Line.split('=')\r
2410 if len(NameValue) == 2 and NameValue[0].strip() == 'EFI_FV_SPACE_SIZE':\r
2411 FreeSizeValue = int(NameValue[1].strip(), 0)\r
2412 if FreeSizeValue < Threshold:\r
2413 EdkLogger.error("build", FV_FREESIZE_ERROR,\r
2414 '%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
2415 FvName, FreeSizeValue, Threshold))\r
2416 break\r
2417\r
52302d4d
LG
2418 ## Generate GuidedSectionTools.txt in the FV directories.\r
2419 #\r
373298ca 2420 def CreateGuidedSectionToolsFile(self,Wa):\r
0d2711a6
LG
2421 for BuildTarget in self.BuildTargetList:\r
2422 for ToolChain in self.ToolChainList:\r
0d2711a6
LG
2423 FvDir = Wa.FvDir\r
2424 if not os.path.exists(FvDir):\r
2425 continue\r
4afd3d04 2426 for Arch in self.ArchList:\r
ef3840c1
MK
2427 guidList = []\r
2428 tooldefguidList = []\r
52302d4d 2429 guidAttribs = []\r
ef3840c1
MK
2430 for Platform in Wa.AutoGenObjectList:\r
2431 if Platform.BuildTarget != BuildTarget:\r
2432 continue\r
2433 if Platform.ToolChain != ToolChain:\r
2434 continue\r
2435 if Platform.Arch != Arch:\r
2436 continue\r
2437 if hasattr (Platform, 'BuildOption'):\r
2438 for Tool in Platform.BuildOption:\r
2439 if 'GUID' in Platform.BuildOption[Tool]:\r
2440 if 'PATH' in Platform.BuildOption[Tool]:\r
2441 value = Platform.BuildOption[Tool]['GUID']\r
2442 if value in guidList:\r
2443 EdkLogger.error("build", FORMAT_INVALID, "Duplicate GUID value %s used with Tool %s in DSC [BuildOptions]." % (value, Tool))\r
2444 path = Platform.BuildOption[Tool]['PATH']\r
2445 guidList.append(value)\r
2446 guidAttribs.append((value, Tool, path))\r
2447 for Tool in Platform.ToolDefinition:\r
2448 if 'GUID' in Platform.ToolDefinition[Tool]:\r
2449 if 'PATH' in Platform.ToolDefinition[Tool]:\r
2450 value = Platform.ToolDefinition[Tool]['GUID']\r
2451 if value in tooldefguidList:\r
2452 EdkLogger.error("build", FORMAT_INVALID, "Duplicate GUID value %s used with Tool %s in tools_def.txt." % (value, Tool))\r
2453 tooldefguidList.append(value)\r
2454 if value in guidList:\r
2455 # Already added by platform\r
2456 continue\r
2457 path = Platform.ToolDefinition[Tool]['PATH']\r
2458 guidList.append(value)\r
2459 guidAttribs.append((value, Tool, path))\r
ab957f03 2460 # Sort by GuidTool name\r
ef3840c1 2461 guidAttribs = sorted (guidAttribs, key=lambda x: x[1])\r
52302d4d
LG
2462 # Write out GuidedSecTools.txt\r
2463 toolsFile = os.path.join(FvDir, 'GuidedSectionTools.txt')\r
2464 toolsFile = open(toolsFile, 'wt')\r
2465 for guidedSectionTool in guidAttribs:\r
72443dd2 2466 print(' '.join(guidedSectionTool), file=toolsFile)\r
52302d4d
LG
2467 toolsFile.close()\r
2468\r
8c944c93 2469 ## Returns the real path of the tool.\r
52302d4d 2470 #\r
8c944c93 2471 def GetRealPathOfTool (self, tool):\r
52302d4d
LG
2472 if os.path.exists(tool):\r
2473 return os.path.realpath(tool)\r
52302d4d
LG
2474 return tool\r
2475\r
2476 ## Launch the module or platform build\r
2477 #\r
2478 def Launch(self):\r
fc8b8dea
SS
2479 self.AllDrivers = set()\r
2480 self.AllModules = set()\r
2481 self.PreMakeCacheMiss = set()\r
2482 self.PreMakeCacheHit = set()\r
2483 self.MakeCacheMiss = set()\r
2484 self.MakeCacheHit = set()\r
0d2711a6 2485 if not self.ModuleFile:\r
52302d4d
LG
2486 if not self.SpawnMode or self.Target not in ["", "all"]:\r
2487 self.SpawnMode = False\r
2488 self._BuildPlatform()\r
2489 else:\r
2490 self._MultiThreadBuildPlatform()\r
52302d4d
LG
2491 else:\r
2492 self.SpawnMode = False\r
2493 self._BuildModule()\r
2494\r
bcbdc755 2495 if self.Target == 'cleanall':\r
bcbdc755
YL
2496 RemoveDirectory(os.path.dirname(GlobalData.gDatabasePath), True)\r
2497\r
a0a2cd1e 2498 def CreateAsBuiltInf(self):\r
b8ac0b7f
BF
2499 for Module in self.BuildModules:\r
2500 Module.CreateAsBuiltInf()\r
2501\r
fc8b8dea
SS
2502 def GenDestCache(self):\r
2503 for Module in self.AllModules:\r
2504 Module.GenPreMakefileHashList()\r
2505 Module.GenMakefileHashList()\r
b8ac0b7f 2506 Module.CopyModuleToCache()\r
fc8b8dea
SS
2507\r
2508 def GenLocalPreMakeCache(self):\r
2509 for Module in self.PreMakeCacheMiss:\r
2510 Module.GenPreMakefileHashList()\r
2511\r
52302d4d
LG
2512 ## Do some clean-up works when error occurred\r
2513 def Relinquish(self):\r
2514 OldLogLevel = EdkLogger.GetLevel()\r
2515 EdkLogger.SetLevel(EdkLogger.ERROR)\r
52302d4d
LG
2516 Utils.Progressor.Abort()\r
2517 if self.SpawnMode == True:\r
2518 BuildTask.Abort()\r
2519 EdkLogger.SetLevel(OldLogLevel)\r
2520\r
52302d4d
LG
2521def ParseDefines(DefineList=[]):\r
2522 DefineDict = {}\r
4231a819 2523 if DefineList is not None:\r
52302d4d
LG
2524 for Define in DefineList:\r
2525 DefineTokenList = Define.split("=", 1)\r
0d2711a6
LG
2526 if not GlobalData.gMacroNamePattern.match(DefineTokenList[0]):\r
2527 EdkLogger.error('build', FORMAT_INVALID,\r
2528 "The macro name must be in the pattern [A-Z][A-Z0-9_]*",\r
2529 ExtraData=DefineTokenList[0])\r
4afd3d04 2530\r
52302d4d 2531 if len(DefineTokenList) == 1:\r
0d2711a6 2532 DefineDict[DefineTokenList[0]] = "TRUE"\r
52302d4d
LG
2533 else:\r
2534 DefineDict[DefineTokenList[0]] = DefineTokenList[1].strip()\r
2535 return DefineDict\r
2536\r
c60fb00f 2537\r
52302d4d 2538\r
1b8eca8b
YZ
2539def LogBuildTime(Time):\r
2540 if Time:\r
2541 TimeDurStr = ''\r
2542 TimeDur = time.gmtime(Time)\r
2543 if TimeDur.tm_yday > 1:\r
2544 TimeDurStr = time.strftime("%H:%M:%S", TimeDur) + ", %d day(s)" % (TimeDur.tm_yday - 1)\r
2545 else:\r
2546 TimeDurStr = time.strftime("%H:%M:%S", TimeDur)\r
2547 return TimeDurStr\r
2548 else:\r
2549 return None\r
1a624dd7 2550def ThreadNum():\r
4465cd12
FZ
2551 OptionParser = MyOptionParser()\r
2552 if not OptionParser.BuildOption and not OptionParser.BuildTarget:\r
2553 OptionParser.GetOption()\r
2554 BuildOption, BuildTarget = OptionParser.BuildOption, OptionParser.BuildTarget\r
1a624dd7 2555 ThreadNumber = BuildOption.ThreadNumber\r
4465cd12 2556 GlobalData.gCmdConfDir = BuildOption.ConfDirectory\r
1a624dd7 2557 if ThreadNumber is None:\r
4465cd12
FZ
2558 TargetObj = TargetTxtDict()\r
2559 ThreadNumber = TargetObj.Target.TargetTxtDictionary[TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER]\r
1a624dd7
FB
2560 if ThreadNumber == '':\r
2561 ThreadNumber = 0\r
2562 else:\r
2563 ThreadNumber = int(ThreadNumber, 0)\r
1b8eca8b 2564\r
1a624dd7
FB
2565 if ThreadNumber == 0:\r
2566 try:\r
2567 ThreadNumber = multiprocessing.cpu_count()\r
2568 except (ImportError, NotImplementedError):\r
2569 ThreadNumber = 1\r
2570 return ThreadNumber\r
52302d4d
LG
2571## Tool entrance method\r
2572#\r
2573# This method mainly dispatch specific methods per the command line options.\r
2574# If no error found, return zero value so the caller of this tool can know\r
2575# if it's executed successfully or not.\r
2576#\r
2577# @retval 0 Tool was successful\r
2578# @retval 1 Tool failed\r
2579#\r
1a624dd7 2580LogQMaxSize = ThreadNum() * 10\r
52302d4d
LG
2581def Main():\r
2582 StartTime = time.time()\r
2583\r
636ed13a
FB
2584 #\r
2585 # Create a log Queue\r
2586 #\r
1a624dd7 2587 LogQ = mp.Queue(LogQMaxSize)\r
52302d4d 2588 # Initialize log system\r
636ed13a 2589 EdkLogger.LogClientInitialize(LogQ)\r
f0dc69e6 2590 GlobalData.gCommand = sys.argv[1:]\r
52302d4d
LG
2591 #\r
2592 # Parse the options and args\r
2593 #\r
4465cd12
FZ
2594 OptionParser = MyOptionParser()\r
2595 if not OptionParser.BuildOption and not OptionParser.BuildTarget:\r
2596 OptionParser.GetOption()\r
2597 Option, Target = OptionParser.BuildOption, OptionParser.BuildTarget\r
52302d4d
LG
2598 GlobalData.gOptions = Option\r
2599 GlobalData.gCaseInsensitive = Option.CaseInsensitive\r
2600\r
2601 # Set log level\r
636ed13a 2602 LogLevel = EdkLogger.INFO\r
4231a819 2603 if Option.verbose is not None:\r
52302d4d 2604 EdkLogger.SetLevel(EdkLogger.VERBOSE)\r
636ed13a 2605 LogLevel = EdkLogger.VERBOSE\r
4231a819 2606 elif Option.quiet is not None:\r
52302d4d 2607 EdkLogger.SetLevel(EdkLogger.QUIET)\r
636ed13a 2608 LogLevel = EdkLogger.QUIET\r
4231a819 2609 elif Option.debug is not None:\r
52302d4d 2610 EdkLogger.SetLevel(Option.debug + 1)\r
636ed13a 2611 LogLevel = Option.debug + 1\r
52302d4d
LG
2612 else:\r
2613 EdkLogger.SetLevel(EdkLogger.INFO)\r
2614\r
52302d4d
LG
2615 if Option.WarningAsError == True:\r
2616 EdkLogger.SetWarningAsError()\r
636ed13a
FB
2617 Log_Agent = LogAgent(LogQ,LogLevel,Option.LogFile)\r
2618 Log_Agent.start()\r
52302d4d
LG
2619\r
2620 if platform.platform().find("Windows") >= 0:\r
2621 GlobalData.gIsWindows = True\r
2622 else:\r
2623 GlobalData.gIsWindows = False\r
2624\r
6780eef1
LG
2625 EdkLogger.quiet("Build environment: %s" % platform.platform())\r
2626 EdkLogger.quiet(time.strftime("Build start time: %H:%M:%S, %b.%d %Y\n", time.localtime()));\r
52302d4d
LG
2627 ReturnCode = 0\r
2628 MyBuild = None\r
09ae0f11 2629 BuildError = True\r
52302d4d
LG
2630 try:\r
2631 if len(Target) == 0:\r
2632 Target = "all"\r
2633 elif len(Target) >= 2:\r
2634 EdkLogger.error("build", OPTION_NOT_SUPPORTED, "More than one targets are not supported.",\r
47fea6af 2635 ExtraData="Please select one of: %s" % (' '.join(gSupportedTarget)))\r
52302d4d
LG
2636 else:\r
2637 Target = Target[0].lower()\r
2638\r
2639 if Target not in gSupportedTarget:\r
2640 EdkLogger.error("build", OPTION_NOT_SUPPORTED, "Not supported target [%s]." % Target,\r
47fea6af 2641 ExtraData="Please select one of: %s" % (' '.join(gSupportedTarget)))\r
52302d4d 2642\r
52302d4d
LG
2643 #\r
2644 # Check environment variable: EDK_TOOLS_PATH, WORKSPACE, PATH\r
2645 #\r
2646 CheckEnvVariable()\r
0d2711a6
LG
2647 GlobalData.gCommandLineDefines.update(ParseDefines(Option.Macros))\r
2648\r
52302d4d
LG
2649 Workspace = os.getenv("WORKSPACE")\r
2650 #\r
2651 # Get files real name in workspace dir\r
2652 #\r
2653 GlobalData.gAllFiles = Utils.DirCache(Workspace)\r
2654\r
2655 WorkingDirectory = os.getcwd()\r
2656 if not Option.ModuleFile:\r
2657 FileList = glob.glob(os.path.normpath(os.path.join(WorkingDirectory, '*.inf')))\r
2658 FileNum = len(FileList)\r
2659 if FileNum >= 2:\r
2660 EdkLogger.error("build", OPTION_NOT_SUPPORTED, "There are %d INF files in %s." % (FileNum, WorkingDirectory),\r
2661 ExtraData="Please use '-m <INF_FILE_PATH>' switch to choose one.")\r
2662 elif FileNum == 1:\r
2663 Option.ModuleFile = NormFile(FileList[0], Workspace)\r
2664\r
2665 if Option.ModuleFile:\r
2666 if os.path.isabs (Option.ModuleFile):\r
2667 if os.path.normcase (os.path.normpath(Option.ModuleFile)).find (Workspace) == 0:\r
2668 Option.ModuleFile = NormFile(os.path.normpath(Option.ModuleFile), Workspace)\r
2669 Option.ModuleFile = PathClass(Option.ModuleFile, Workspace)\r
2670 ErrorCode, ErrorInfo = Option.ModuleFile.Validate(".inf", False)\r
2671 if ErrorCode != 0:\r
2672 EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo)\r
2673\r
4231a819 2674 if Option.PlatformFile is not None:\r
52302d4d
LG
2675 if os.path.isabs (Option.PlatformFile):\r
2676 if os.path.normcase (os.path.normpath(Option.PlatformFile)).find (Workspace) == 0:\r
2677 Option.PlatformFile = NormFile(os.path.normpath(Option.PlatformFile), Workspace)\r
2678 Option.PlatformFile = PathClass(Option.PlatformFile, Workspace)\r
52302d4d 2679\r
4231a819 2680 if Option.FdfFile is not None:\r
52302d4d
LG
2681 if os.path.isabs (Option.FdfFile):\r
2682 if os.path.normcase (os.path.normpath(Option.FdfFile)).find (Workspace) == 0:\r
2683 Option.FdfFile = NormFile(os.path.normpath(Option.FdfFile), Workspace)\r
2684 Option.FdfFile = PathClass(Option.FdfFile, Workspace)\r
2685 ErrorCode, ErrorInfo = Option.FdfFile.Validate(".fdf", False)\r
2686 if ErrorCode != 0:\r
2687 EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo)\r
2688\r
4231a819 2689 if Option.Flag is not None and Option.Flag not in ['-c', '-s']:\r
f3decdc3
LG
2690 EdkLogger.error("build", OPTION_VALUE_INVALID, "UNI flag must be one of -c or -s")\r
2691\r
636ed13a 2692 MyBuild = Build(Target, Workspace, Option,LogQ)\r
64b2609f 2693 GlobalData.gCommandLineDefines['ARCH'] = ' '.join(MyBuild.ArchList)\r
f0dc69e6
YZ
2694 if not (MyBuild.LaunchPrebuildFlag and os.path.exists(MyBuild.PlatformBuildPath)):\r
2695 MyBuild.Launch()\r
2f818ed0 2696\r
09ae0f11
YL
2697 #\r
2698 # All job done, no error found and no exception raised\r
2699 #\r
2700 BuildError = False\r
5b0671c1 2701 except FatalError as X:\r
4231a819 2702 if MyBuild is not None:\r
52302d4d
LG
2703 # for multi-thread build exits safely\r
2704 MyBuild.Relinquish()\r
4231a819 2705 if Option is not None and Option.debug is not None:\r
52302d4d
LG
2706 EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r
2707 ReturnCode = X.args[0]\r
5b0671c1 2708 except Warning as X:\r
52302d4d 2709 # error from Fdf parser\r
4231a819 2710 if MyBuild is not None:\r
52302d4d
LG
2711 # for multi-thread build exits safely\r
2712 MyBuild.Relinquish()\r
4231a819 2713 if Option is not None and Option.debug is not None:\r
52302d4d
LG
2714 EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r
2715 else:\r
47fea6af 2716 EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError=False)\r
52302d4d
LG
2717 ReturnCode = FORMAT_INVALID\r
2718 except KeyboardInterrupt:\r
673d09a2
FB
2719 if MyBuild is not None:\r
2720\r
2721 # for multi-thread build exits safely\r
2722 MyBuild.Relinquish()\r
52302d4d 2723 ReturnCode = ABORT_ERROR\r
4231a819 2724 if Option is not None and Option.debug is not None:\r
52302d4d
LG
2725 EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r
2726 except:\r
4231a819 2727 if MyBuild is not None:\r
52302d4d
LG
2728 # for multi-thread build exits safely\r
2729 MyBuild.Relinquish()\r
2730\r
2731 # try to get the meta-file from the object causing exception\r
2732 Tb = sys.exc_info()[-1]\r
2733 MetaFile = GlobalData.gProcessingFile\r
4231a819 2734 while Tb is not None:\r
52302d4d
LG
2735 if 'self' in Tb.tb_frame.f_locals and hasattr(Tb.tb_frame.f_locals['self'], 'MetaFile'):\r
2736 MetaFile = Tb.tb_frame.f_locals['self'].MetaFile\r
2737 Tb = Tb.tb_next\r
2738 EdkLogger.error(\r
2739 "\nbuild",\r
2740 CODE_ERROR,\r
2741 "Unknown fatal error when processing [%s]" % MetaFile,\r
c1387446 2742 ExtraData="\n(Please send email to %s for help, attaching following call stack trace!)\n" % MSG_EDKII_MAIL_ADDR,\r
52302d4d
LG
2743 RaiseError=False\r
2744 )\r
d0acc87a 2745 EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r
52302d4d
LG
2746 ReturnCode = CODE_ERROR\r
2747 finally:\r
2748 Utils.Progressor.Abort()\r
97fa0ee9 2749 Utils.ClearDuplicatedInf()\r
52302d4d
LG
2750\r
2751 if ReturnCode == 0:\r
f0dc69e6 2752 try:\r
91048b0d 2753 MyBuild.LaunchPostbuild()\r
f0dc69e6
YZ
2754 Conclusion = "Done"\r
2755 except:\r
2756 Conclusion = "Failed"\r
04ae1721 2757 ReturnCode = POSTBUILD_ERROR\r
52302d4d
LG
2758 elif ReturnCode == ABORT_ERROR:\r
2759 Conclusion = "Aborted"\r
2760 else:\r
2761 Conclusion = "Failed"\r
2762 FinishTime = time.time()\r
4234283c
LG
2763 BuildDuration = time.gmtime(int(round(FinishTime - StartTime)))\r
2764 BuildDurationStr = ""\r
2765 if BuildDuration.tm_yday > 1:\r
47fea6af 2766 BuildDurationStr = time.strftime("%H:%M:%S", BuildDuration) + ", %d day(s)" % (BuildDuration.tm_yday - 1)\r
4234283c
LG
2767 else:\r
2768 BuildDurationStr = time.strftime("%H:%M:%S", BuildDuration)\r
4231a819 2769 if MyBuild is not None:\r
09ae0f11 2770 if not BuildError:\r
1b8eca8b 2771 MyBuild.BuildReport.GenerateReport(BuildDurationStr, LogBuildTime(MyBuild.AutoGenTime), LogBuildTime(MyBuild.MakeTime), LogBuildTime(MyBuild.GenFdsTime))\r
2f818ed0 2772\r
52302d4d 2773 EdkLogger.SetLevel(EdkLogger.QUIET)\r
6780eef1
LG
2774 EdkLogger.quiet("\n- %s -" % Conclusion)\r
2775 EdkLogger.quiet(time.strftime("Build end time: %H:%M:%S, %b.%d %Y", time.localtime()))\r
4234283c 2776 EdkLogger.quiet("Build total time: %s\n" % BuildDurationStr)\r
636ed13a
FB
2777 Log_Agent.kill()\r
2778 Log_Agent.join()\r
52302d4d
LG
2779 return ReturnCode\r
2780\r
2781if __name__ == '__main__':\r
673d09a2
FB
2782 try:\r
2783 mp.set_start_method('spawn')\r
2784 except:\r
2785 pass\r
52302d4d
LG
2786 r = Main()\r
2787 ## 0-127 is a safe return range, and 1 is a standard default error\r
2788 if r < 0 or r > 127: r = 1\r
2789 sys.exit(r)\r