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