2010-02-28 23:39:39 +00:00
## @file
# build a platform or a module
#
2014-12-23 05:48:31 +00:00
# Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
2016-02-17 14:48:28 +08:00
# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
2010-02-28 23:39:39 +00:00
#
2010-05-18 05:04:32 +00:00
# This program and the accompanying materials
2010-02-28 23:39:39 +00:00
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
# Import Modules
#
2014-08-15 03:06:48 +00:00
import Common.LongFilePathOs as os
2010-02-28 23:39:39 +00:00
import re
import StringIO
import sys
import glob
import time
import platform
import traceback
2013-08-23 02:18:16 +00:00
import encodings.ascii
2016-03-31 14:05:59 +08:00
import itertools
2010-02-28 23:39:39 +00:00
from struct import *
from threading import *
from optparse import OptionParser
from subprocess import *
from Common import Misc as Utils
2014-08-15 03:06:48 +00:00
from Common.LongFilePathSupport import OpenLongFilePath as open
from Common.LongFilePathSupport import LongFilePath
2010-02-28 23:39:39 +00:00
from Common.TargetTxtClassObject import *
from Common.ToolDefClassObject import *
from Common.DataType import *
2011-09-18 12:17:25 +00:00
from Common.BuildVersion import gBUILD_VERSION
2010-02-28 23:39:39 +00:00
from AutoGen.AutoGen import *
from Common.BuildToolError import *
from Workspace.WorkspaceDatabase import *
2015-10-08 09:27:14 +00:00
from Common.MultipleWorkspace import MultipleWorkspace as mws
2010-02-28 23:39:39 +00:00
from BuildReport import BuildReport
from GenPatchPcdTable.GenPatchPcdTable import *
from PatchPcdValue.PatchPcdValue import *
import Common.EdkLogger
import Common.GlobalData as GlobalData
# Version and Copyright
2014-09-16 09:03:00 +00:00
VersionNumber = "0.60" + ' ' + gBUILD_VERSION
2010-02-28 23:39:39 +00:00
__version__ = "%prog Version " + VersionNumber
2016-02-25 16:13:31 +08:00
__copyright__ = "Copyright (c) 2007 - 2016, Intel Corporation All rights reserved."
2010-02-28 23:39:39 +00:00
## standard targets of build command
gSupportedTarget = [ 'all' , 'genc' , 'genmake' , 'modules' , 'libraries' , 'fds' , 'clean' , 'cleanall' , 'cleanlib' , 'run' ]
## build configuration file
2014-08-28 13:53:34 +00:00
gBuildConfiguration = "target.txt"
gToolsDefinition = "tools_def.txt"
2010-02-28 23:39:39 +00:00
2012-04-10 07:18:20 +00:00
TemporaryTablePattern = re . compile ( r '^_\d+_\d+_[a-fA-F0-9]+$' )
TmpTableDict = {}
2010-02-28 23:39:39 +00:00
## Check environment PATH variable to make sure the specified tool is found
#
# If the tool is found in the PATH, then True is returned
# Otherwise, False is returned
#
def IsToolInPath ( tool ):
if os . environ . has_key ( 'PATHEXT' ):
extns = os . environ [ 'PATHEXT' ] . split ( os . path . pathsep )
else :
extns = ( '' ,)
for pathDir in os . environ [ 'PATH' ] . split ( os . path . pathsep ):
for ext in extns :
if os . path . exists ( os . path . join ( pathDir , tool + ext )):
return True
return False
## Check environment variables
#
# Check environment variables that must be set for build. Currently they are
#
# WORKSPACE The directory all packages/platforms start from
# EDK_TOOLS_PATH The directory contains all tools needed by the build
# PATH $(EDK_TOOLS_PATH)/Bin/<sys> must be set in PATH
#
# If any of above environment variable is not set or has error, the build
# will be broken.
#
def CheckEnvVariable ():
# check WORKSPACE
if "WORKSPACE" not in os . environ :
EdkLogger . error ( "build" , ATTRIBUTE_NOT_AVAILABLE , "Environment variable not found" ,
ExtraData = "WORKSPACE" )
WorkspaceDir = os . path . normcase ( os . path . normpath ( os . environ [ "WORKSPACE" ]))
if not os . path . exists ( WorkspaceDir ):
EdkLogger . error ( "build" , FILE_NOT_FOUND , "WORKSPACE doesn't exist" , ExtraData = " %s " % WorkspaceDir )
elif ' ' in WorkspaceDir :
EdkLogger . error ( "build" , FORMAT_NOT_SUPPORTED , "No space is allowed in WORKSPACE path" ,
ExtraData = WorkspaceDir )
os . environ [ "WORKSPACE" ] = WorkspaceDir
2015-10-08 09:27:14 +00:00
# set multiple workspace
PackagesPath = os . getenv ( "PACKAGES_PATH" )
mws . setWs ( WorkspaceDir , PackagesPath )
2010-02-28 23:39:39 +00:00
#
2011-09-18 12:17:25 +00:00
# Check EFI_SOURCE (Edk build convention). EDK_SOURCE will always point to ECP
2010-02-28 23:39:39 +00:00
#
2011-05-11 10:26:49 +00:00
if "ECP_SOURCE" not in os . environ :
2015-10-08 09:27:14 +00:00
os . environ [ "ECP_SOURCE" ] = mws . join ( WorkspaceDir , GlobalData . gEdkCompatibilityPkg )
2010-02-28 23:39:39 +00:00
if "EFI_SOURCE" not in os . environ :
os . environ [ "EFI_SOURCE" ] = os . environ [ "ECP_SOURCE" ]
if "EDK_SOURCE" not in os . environ :
os . environ [ "EDK_SOURCE" ] = os . environ [ "ECP_SOURCE" ]
#
# Unify case of characters on case-insensitive systems
#
EfiSourceDir = os . path . normcase ( os . path . normpath ( os . environ [ "EFI_SOURCE" ]))
EdkSourceDir = os . path . normcase ( os . path . normpath ( os . environ [ "EDK_SOURCE" ]))
EcpSourceDir = os . path . normcase ( os . path . normpath ( os . environ [ "ECP_SOURCE" ]))
2013-08-23 02:18:16 +00:00
2010-02-28 23:39:39 +00:00
os . environ [ "EFI_SOURCE" ] = EfiSourceDir
os . environ [ "EDK_SOURCE" ] = EdkSourceDir
os . environ [ "ECP_SOURCE" ] = EcpSourceDir
os . environ [ "EDK_TOOLS_PATH" ] = os . path . normcase ( os . environ [ "EDK_TOOLS_PATH" ])
2013-08-23 02:18:16 +00:00
2010-02-28 23:39:39 +00:00
if not os . path . exists ( EcpSourceDir ):
2011-09-18 12:17:25 +00:00
EdkLogger . verbose ( "ECP_SOURCE = %s doesn't exist. Edk modules could not be built." % EcpSourceDir )
2010-02-28 23:39:39 +00:00
elif ' ' in EcpSourceDir :
EdkLogger . error ( "build" , FORMAT_NOT_SUPPORTED , "No space is allowed in ECP_SOURCE path" ,
ExtraData = EcpSourceDir )
if not os . path . exists ( EdkSourceDir ):
if EdkSourceDir == EcpSourceDir :
2011-09-18 12:17:25 +00:00
EdkLogger . verbose ( "EDK_SOURCE = %s doesn't exist. Edk modules could not be built." % EdkSourceDir )
2010-02-28 23:39:39 +00:00
else :
EdkLogger . error ( "build" , PARAMETER_INVALID , "EDK_SOURCE does not exist" ,
ExtraData = EdkSourceDir )
elif ' ' in EdkSourceDir :
EdkLogger . error ( "build" , FORMAT_NOT_SUPPORTED , "No space is allowed in EDK_SOURCE path" ,
ExtraData = EdkSourceDir )
if not os . path . exists ( EfiSourceDir ):
if EfiSourceDir == EcpSourceDir :
2011-09-18 12:17:25 +00:00
EdkLogger . verbose ( "EFI_SOURCE = %s doesn't exist. Edk modules could not be built." % EfiSourceDir )
2010-02-28 23:39:39 +00:00
else :
EdkLogger . error ( "build" , PARAMETER_INVALID , "EFI_SOURCE does not exist" ,
ExtraData = EfiSourceDir )
elif ' ' in EfiSourceDir :
EdkLogger . error ( "build" , FORMAT_NOT_SUPPORTED , "No space is allowed in EFI_SOURCE path" ,
ExtraData = EfiSourceDir )
2015-11-06 01:10:25 +00:00
# check those variables on single workspace case
if not PackagesPath :
# change absolute path to relative path to WORKSPACE
if EfiSourceDir . upper () . find ( WorkspaceDir . upper ()) != 0 :
EdkLogger . error ( "build" , PARAMETER_INVALID , "EFI_SOURCE is not under WORKSPACE" ,
ExtraData = "WORKSPACE = %s \n EFI_SOURCE = %s " % ( WorkspaceDir , EfiSourceDir ))
if EdkSourceDir . upper () . find ( WorkspaceDir . upper ()) != 0 :
EdkLogger . error ( "build" , PARAMETER_INVALID , "EDK_SOURCE is not under WORKSPACE" ,
ExtraData = "WORKSPACE = %s \n EDK_SOURCE = %s " % ( WorkspaceDir , EdkSourceDir ))
if EcpSourceDir . upper () . find ( WorkspaceDir . upper ()) != 0 :
EdkLogger . error ( "build" , PARAMETER_INVALID , "ECP_SOURCE is not under WORKSPACE" ,
ExtraData = "WORKSPACE = %s \n ECP_SOURCE = %s " % ( WorkspaceDir , EcpSourceDir ))
2010-02-28 23:39:39 +00:00
# check EDK_TOOLS_PATH
if "EDK_TOOLS_PATH" not in os . environ :
EdkLogger . error ( "build" , ATTRIBUTE_NOT_AVAILABLE , "Environment variable not found" ,
ExtraData = "EDK_TOOLS_PATH" )
# check PATH
if "PATH" not in os . environ :
EdkLogger . error ( "build" , ATTRIBUTE_NOT_AVAILABLE , "Environment variable not found" ,
ExtraData = "PATH" )
GlobalData . gWorkspace = WorkspaceDir
GlobalData . gEfiSource = EfiSourceDir
GlobalData . gEdkSource = EdkSourceDir
GlobalData . gEcpSource = EcpSourceDir
2011-10-29 06:59:30 +00:00
GlobalData . gGlobalDefines [ "WORKSPACE" ] = WorkspaceDir
GlobalData . gGlobalDefines [ "EFI_SOURCE" ] = EfiSourceDir
GlobalData . gGlobalDefines [ "EDK_SOURCE" ] = EdkSourceDir
GlobalData . gGlobalDefines [ "ECP_SOURCE" ] = EcpSourceDir
GlobalData . gGlobalDefines [ "EDK_TOOLS_PATH" ] = os . environ [ "EDK_TOOLS_PATH" ]
2015-10-08 09:27:14 +00:00
2010-02-28 23:39:39 +00:00
## Get normalized file path
#
# Convert the path to be local format, and remove the WORKSPACE path at the
# beginning if the file path is given in full path.
#
# @param FilePath File path to be normalized
# @param Workspace Workspace path which the FilePath will be checked against
#
# @retval string The normalized file path
#
def NormFile ( FilePath , Workspace ):
# check if the path is absolute or relative
if os . path . isabs ( FilePath ):
FileFullPath = os . path . normpath ( FilePath )
else :
2015-10-08 09:27:14 +00:00
FileFullPath = os . path . normpath ( mws . join ( Workspace , FilePath ))
Workspace = mws . getWs ( Workspace , FilePath )
2010-02-28 23:39:39 +00:00
# check if the file path exists or not
if not os . path . isfile ( FileFullPath ):
2015-12-01 04:22:16 +00:00
EdkLogger . error ( "build" , FILE_NOT_FOUND , ExtraData = " \t %s (Please give file in absolute path or relative to WORKSPACE)" % FileFullPath )
2010-02-28 23:39:39 +00:00
# remove workspace directory from the beginning part of the file path
if Workspace [ - 1 ] in [ " \\ " , "/" ]:
return FileFullPath [ len ( Workspace ):]
else :
return FileFullPath [( len ( Workspace ) + 1 ):]
## Get the output of an external program
#
# This is the entrance method of thread reading output of an external program and
# putting them in STDOUT/STDERR of current program.
#
# @param From The stream message read from
# @param To The stream message put on
# @param ExitFlag The flag used to indicate stopping reading
#
def ReadMessage ( From , To , ExitFlag ):
while True :
# read one line a time
Line = From . readline ()
# empty string means "end"
if Line != None and Line != "" :
To ( Line . rstrip ())
else :
break
if ExitFlag . isSet ():
break
## Launch an external program
#
# This method will call subprocess.Popen to execute an external program with
# given options in specified directory. Because of the dead-lock issue during
# redirecting output of the external program, threads are used to to do the
# redirection work.
#
# @param Command A list or string containing the call of the program
# @param WorkingDir The directory in which the program will be running
#
def LaunchCommand ( Command , WorkingDir ):
# if working directory doesn't exist, Popen() will raise an exception
if not os . path . isdir ( WorkingDir ):
EdkLogger . error ( "build" , FILE_NOT_FOUND , ExtraData = WorkingDir )
2014-08-19 08:22:04 +00:00
# Command is used as the first Argument in following Popen().
# It could be a string or sequence. We find that if command is a string in following Popen(),
# ubuntu may fail with an error message that the command is not found.
# So here we may need convert command from string to list instance.
if not isinstance ( Command , list ):
2014-08-20 07:41:38 +00:00
if platform . system () != 'Windows' :
Command = Command . split ()
2010-02-28 23:39:39 +00:00
Proc = None
EndOfProcedure = None
try :
# launch the command
Proc = Popen ( Command , stdout = PIPE , stderr = PIPE , env = os . environ , cwd = WorkingDir , bufsize =- 1 )
# launch two threads to read the STDOUT and STDERR
EndOfProcedure = Event ()
EndOfProcedure . clear ()
if Proc . stdout :
StdOutThread = Thread ( target = ReadMessage , args = ( Proc . stdout , EdkLogger . info , EndOfProcedure ))
StdOutThread . setName ( "STDOUT-Redirector" )
StdOutThread . setDaemon ( False )
StdOutThread . start ()
if Proc . stderr :
StdErrThread = Thread ( target = ReadMessage , args = ( Proc . stderr , EdkLogger . quiet , EndOfProcedure ))
StdErrThread . setName ( "STDERR-Redirector" )
StdErrThread . setDaemon ( False )
StdErrThread . start ()
# waiting for program exit
Proc . wait ()
except : # in case of aborting
# terminate the threads redirecting the program output
2016-02-17 14:48:28 +08:00
EdkLogger . quiet ( "(Python %s on %s ) " % ( platform . python_version (), sys . platform ) + traceback . format_exc ())
2010-02-28 23:39:39 +00:00
if EndOfProcedure != None :
EndOfProcedure . set ()
if Proc == None :
if type ( Command ) != type ( "" ):
Command = " " . join ( Command )
EdkLogger . error ( "build" , COMMAND_FAILURE , "Failed to start command" , ExtraData = " %s [ %s ]" % ( Command , WorkingDir ))
if Proc . stdout :
StdOutThread . join ()
if Proc . stderr :
StdErrThread . join ()
# check the return code of the program
if Proc . returncode != 0 :
if type ( Command ) != type ( "" ):
Command = " " . join ( Command )
2016-03-16 11:06:44 +08:00
# print out the Response file and its content when make failure
RespFile = os . path . join ( WorkingDir , 'OUTPUT' , 'respfilelist.txt' )
if os . path . isfile ( RespFile ):
f = open ( RespFile )
RespContent = f . read ()
f . close ()
EdkLogger . info ( RespContent )
2010-02-28 23:39:39 +00:00
EdkLogger . error ( "build" , COMMAND_FAILURE , ExtraData = " %s [ %s ]" % ( Command , WorkingDir ))
## The smallest unit that can be built in multi-thread build mode
#
# This is the base class of build unit. The "Obj" parameter must provide
# __str__(), __eq__() and __hash__() methods. Otherwise there could be build units
# missing build.
#
# Currently the "Obj" should be only ModuleAutoGen or PlatformAutoGen objects.
#
class BuildUnit :
## The constructor
#
# @param self The object pointer
# @param Obj The object the build is working on
# @param Target The build target name, one of gSupportedTarget
# @param Dependency The BuildUnit(s) which must be completed in advance
# @param WorkingDir The directory build command starts in
#
def __init__ ( self , Obj , BuildCommand , Target , Dependency , WorkingDir = "." ):
self . BuildObject = Obj
self . Dependency = Dependency
self . WorkingDir = WorkingDir
self . Target = Target
self . BuildCommand = BuildCommand
2011-10-29 06:59:30 +00:00
if not BuildCommand :
EdkLogger . error ( "build" , OPTION_MISSING ,
"No build command found for this module. "
2013-08-23 02:18:16 +00:00
"Please check your setting of %s _ %s _ %s _MAKE_PATH in Conf/tools_def.txt file." %
2011-10-29 06:59:30 +00:00
( Obj . BuildTarget , Obj . ToolChain , Obj . Arch ),
2010-02-28 23:39:39 +00:00
ExtraData = str ( Obj ))
2011-10-29 06:59:30 +00:00
2010-02-28 23:39:39 +00:00
## str() method
#
2010-10-11 06:26:52 +00:00
# It just returns the string representation of self.BuildObject
2010-02-28 23:39:39 +00:00
#
# @param self The object pointer
#
def __str__ ( self ):
return str ( self . BuildObject )
## "==" operator method
#
# It just compares self.BuildObject with "Other". So self.BuildObject must
# provide its own __eq__() method.
#
# @param self The object pointer
# @param Other The other BuildUnit object compared to
#
def __eq__ ( self , Other ):
return Other != None and self . BuildObject == Other . BuildObject \
and self . BuildObject . Arch == Other . BuildObject . Arch
## hash() method
#
# It just returns the hash value of self.BuildObject which must be hashable.
#
# @param self The object pointer
#
def __hash__ ( self ):
return hash ( self . BuildObject ) + hash ( self . BuildObject . Arch )
def __repr__ ( self ):
return repr ( self . BuildObject )
## The smallest module unit that can be built by nmake/make command in multi-thread build mode
#
# This class is for module build by nmake/make build system. The "Obj" parameter
# must provide __str__(), __eq__() and __hash__() methods. Otherwise there could
# be make units missing build.
#
# Currently the "Obj" should be only ModuleAutoGen object.
#
class ModuleMakeUnit ( BuildUnit ):
## The constructor
#
# @param self The object pointer
# @param Obj The ModuleAutoGen object the build is working on
# @param Target The build target name, one of gSupportedTarget
#
def __init__ ( self , Obj , Target ):
Dependency = [ ModuleMakeUnit ( La , Target ) for La in Obj . LibraryAutoGenList ]
BuildUnit . __init__ ( self , Obj , Obj . BuildCommand , Target , Dependency , Obj . MakeFileDir )
if Target in [ None , "" , "all" ]:
self . Target = "tbuild"
## The smallest platform unit that can be built by nmake/make command in multi-thread build mode
#
# This class is for platform build by nmake/make build system. The "Obj" parameter
# must provide __str__(), __eq__() and __hash__() methods. Otherwise there could
# be make units missing build.
#
# Currently the "Obj" should be only PlatformAutoGen object.
#
class PlatformMakeUnit ( BuildUnit ):
## The constructor
#
# @param self The object pointer
# @param Obj The PlatformAutoGen object the build is working on
# @param Target The build target name, one of gSupportedTarget
#
def __init__ ( self , Obj , Target ):
Dependency = [ ModuleMakeUnit ( Lib , Target ) for Lib in self . BuildObject . LibraryAutoGenList ]
Dependency . extend ([ ModuleMakeUnit ( Mod , Target ) for Mod in self . BuildObject . ModuleAutoGenList ])
BuildUnit . __init__ ( self , Obj , Obj . BuildCommand , Target , Dependency , Obj . MakeFileDir )
## The class representing the task of a module build or platform build
#
# This class manages the build tasks in multi-thread build mode. Its jobs include
# scheduling thread running, catching thread error, monitor the thread status, etc.
#
class BuildTask :
# queue for tasks waiting for schedule
_PendingQueue = sdict ()
_PendingQueueLock = threading . Lock ()
# queue for tasks ready for running
_ReadyQueue = sdict ()
_ReadyQueueLock = threading . Lock ()
# queue for run tasks
_RunningQueue = sdict ()
_RunningQueueLock = threading . Lock ()
# queue containing all build tasks, in case duplicate build
_TaskQueue = sdict ()
# flag indicating error occurs in a running thread
_ErrorFlag = threading . Event ()
_ErrorFlag . clear ()
_ErrorMessage = ""
# BoundedSemaphore object used to control the number of running threads
_Thread = None
# flag indicating if the scheduler is started or not
_SchedulerStopped = threading . Event ()
_SchedulerStopped . set ()
## Start the task scheduler thread
#
# @param MaxThreadNumber The maximum thread number
# @param ExitFlag Flag used to end the scheduler
#
@staticmethod
def StartScheduler ( MaxThreadNumber , ExitFlag ):
SchedulerThread = Thread ( target = BuildTask . Scheduler , args = ( MaxThreadNumber , ExitFlag ))
SchedulerThread . setName ( "Build-Task-Scheduler" )
SchedulerThread . setDaemon ( False )
SchedulerThread . start ()
# wait for the scheduler to be started, especially useful in Linux
while not BuildTask . IsOnGoing ():
time . sleep ( 0.01 )
## Scheduler method
#
# @param MaxThreadNumber The maximum thread number
# @param ExitFlag Flag used to end the scheduler
#
@staticmethod
def Scheduler ( MaxThreadNumber , ExitFlag ):
BuildTask . _SchedulerStopped . clear ()
try :
# use BoundedSemaphore to control the maximum running threads
BuildTask . _Thread = BoundedSemaphore ( MaxThreadNumber )
#
# scheduling loop, which will exits when no pending/ready task and
# indicated to do so, or there's error in running thread
#
while ( len ( BuildTask . _PendingQueue ) > 0 or len ( BuildTask . _ReadyQueue ) > 0 \
or not ExitFlag . isSet ()) and not BuildTask . _ErrorFlag . isSet ():
EdkLogger . debug ( EdkLogger . DEBUG_8 , "Pending Queue ( %d ), Ready Queue ( %d )"
% ( len ( BuildTask . _PendingQueue ), len ( BuildTask . _ReadyQueue )))
# get all pending tasks
BuildTask . _PendingQueueLock . acquire ()
BuildObjectList = BuildTask . _PendingQueue . keys ()
#
# check if their dependency is resolved, and if true, move them
# into ready queue
#
for BuildObject in BuildObjectList :
Bt = BuildTask . _PendingQueue [ BuildObject ]
if Bt . IsReady ():
BuildTask . _ReadyQueue [ BuildObject ] = BuildTask . _PendingQueue . pop ( BuildObject )
BuildTask . _PendingQueueLock . release ()
# launch build thread until the maximum number of threads is reached
while not BuildTask . _ErrorFlag . isSet ():
# empty ready queue, do nothing further
if len ( BuildTask . _ReadyQueue ) == 0 :
break
# wait for active thread(s) exit
BuildTask . _Thread . acquire ( True )
# start a new build thread
Bo = BuildTask . _ReadyQueue . keys ()[ 0 ]
Bt = BuildTask . _ReadyQueue . pop ( Bo )
# move into running queue
BuildTask . _RunningQueueLock . acquire ()
BuildTask . _RunningQueue [ Bo ] = Bt
BuildTask . _RunningQueueLock . release ()
Bt . Start ()
# avoid tense loop
time . sleep ( 0.01 )
# avoid tense loop
time . sleep ( 0.01 )
# wait for all running threads exit
if BuildTask . _ErrorFlag . isSet ():
EdkLogger . quiet ( " \n Waiting for all build threads exit..." )
# while not BuildTask._ErrorFlag.isSet() and \
while len ( BuildTask . _RunningQueue ) > 0 :
EdkLogger . verbose ( "Waiting for thread ending...( %d )" % len ( BuildTask . _RunningQueue ))
EdkLogger . debug ( EdkLogger . DEBUG_8 , "Threads [ %s ]" % ", " . join ([ Th . getName () for Th in threading . enumerate ()]))
# avoid tense loop
time . sleep ( 0.1 )
except BaseException , X :
#
# TRICK: hide the output of threads left runing, so that the user can
# catch the error message easily
#
EdkLogger . SetLevel ( EdkLogger . ERROR )
BuildTask . _ErrorFlag . set ()
BuildTask . _ErrorMessage = "build thread scheduler error \n\t %s " % str ( X )
BuildTask . _PendingQueue . clear ()
BuildTask . _ReadyQueue . clear ()
BuildTask . _RunningQueue . clear ()
BuildTask . _TaskQueue . clear ()
BuildTask . _SchedulerStopped . set ()
## Wait for all running method exit
#
@staticmethod
def WaitForComplete ():
BuildTask . _SchedulerStopped . wait ()
## Check if the scheduler is running or not
#
@staticmethod
def IsOnGoing ():
return not BuildTask . _SchedulerStopped . isSet ()
## Abort the build
@staticmethod
def Abort ():
if BuildTask . IsOnGoing ():
BuildTask . _ErrorFlag . set ()
BuildTask . WaitForComplete ()
## Check if there's error in running thread
#
# Since the main thread cannot catch exceptions in other thread, we have to
# use threading.Event to communicate this formation to main thread.
#
@staticmethod
def HasError ():
return BuildTask . _ErrorFlag . isSet ()
## Get error message in running thread
#
# Since the main thread cannot catch exceptions in other thread, we have to
# use a static variable to communicate this message to main thread.
#
@staticmethod
def GetErrorMessage ():
return BuildTask . _ErrorMessage
## Factory method to create a BuildTask object
#
# This method will check if a module is building or has been built. And if
# true, just return the associated BuildTask object in the _TaskQueue. If
# not, create and return a new BuildTask object. The new BuildTask object
# will be appended to the _PendingQueue for scheduling later.
#
# @param BuildItem A BuildUnit object representing a build object
# @param Dependency The dependent build object of BuildItem
#
@staticmethod
def New ( BuildItem , Dependency = None ):
if BuildItem in BuildTask . _TaskQueue :
Bt = BuildTask . _TaskQueue [ BuildItem ]
return Bt
Bt = BuildTask ()
Bt . _Init ( BuildItem , Dependency )
BuildTask . _TaskQueue [ BuildItem ] = Bt
BuildTask . _PendingQueueLock . acquire ()
BuildTask . _PendingQueue [ BuildItem ] = Bt
BuildTask . _PendingQueueLock . release ()
return Bt
## The real constructor of BuildTask
#
# @param BuildItem A BuildUnit object representing a build object
# @param Dependency The dependent build object of BuildItem
#
def _Init ( self , BuildItem , Dependency = None ):
self . BuildItem = BuildItem
self . DependencyList = []
if Dependency == None :
Dependency = BuildItem . Dependency
else :
Dependency . extend ( BuildItem . Dependency )
self . AddDependency ( Dependency )
# flag indicating build completes, used to avoid unnecessary re-build
self . CompleteFlag = False
## Check if all dependent build tasks are completed or not
#
def IsReady ( self ):
ReadyFlag = True
for Dep in self . DependencyList :
if Dep . CompleteFlag == True :
continue
ReadyFlag = False
break
return ReadyFlag
## Add dependent build task
#
# @param Dependency The list of dependent build objects
#
def AddDependency ( self , Dependency ):
for Dep in Dependency :
2014-08-28 13:53:34 +00:00
if not Dep . BuildObject . IsBinaryModule :
self . DependencyList . append ( BuildTask . New ( Dep )) # BuildTask list
2010-02-28 23:39:39 +00:00
## The thread wrapper of LaunchCommand function
#
# @param Command A list or string contains the call of the command
# @param WorkingDir The directory in which the program will be running
#
def _CommandThread ( self , Command , WorkingDir ):
try :
LaunchCommand ( Command , WorkingDir )
self . CompleteFlag = True
except :
#
# TRICK: hide the output of threads left runing, so that the user can
# catch the error message easily
#
if not BuildTask . _ErrorFlag . isSet ():
GlobalData . gBuildingModule = " %s [ %s , %s , %s ]" % ( str ( self . BuildItem . BuildObject ),
self . BuildItem . BuildObject . Arch ,
self . BuildItem . BuildObject . ToolChain ,
self . BuildItem . BuildObject . BuildTarget
)
EdkLogger . SetLevel ( EdkLogger . ERROR )
BuildTask . _ErrorFlag . set ()
BuildTask . _ErrorMessage = " %s broken \n %s [ %s ]" % \
( threading . currentThread () . getName (), Command , WorkingDir )
# indicate there's a thread is available for another build task
BuildTask . _RunningQueueLock . acquire ()
BuildTask . _RunningQueue . pop ( self . BuildItem )
BuildTask . _RunningQueueLock . release ()
BuildTask . _Thread . release ()
## Start build task thread
#
def Start ( self ):
EdkLogger . quiet ( "Building ... %s " % repr ( self . BuildItem ))
Command = self . BuildItem . BuildCommand + [ self . BuildItem . Target ]
self . BuildTread = Thread ( target = self . _CommandThread , args = ( Command , self . BuildItem . WorkingDir ))
self . BuildTread . setName ( "build thread" )
self . BuildTread . setDaemon ( False )
self . BuildTread . start ()
## The class contains the information related to EFI image
#
class PeImageInfo ():
## Constructor
#
# Constructor will load all required image information.
#
2013-08-23 02:18:16 +00:00
# @param BaseName The full file path of image.
2010-02-28 23:39:39 +00:00
# @param Guid The GUID for image.
# @param Arch Arch of this image.
2010-03-19 06:55:07 +00:00
# @param OutputDir The output directory for image.
# @param DebugDir The debug directory for image.
2010-02-28 23:39:39 +00:00
# @param ImageClass PeImage Information
#
2010-03-19 06:55:07 +00:00
def __init__ ( self , BaseName , Guid , Arch , OutputDir , DebugDir , ImageClass ):
2010-02-28 23:39:39 +00:00
self . BaseName = BaseName
self . Guid = Guid
self . Arch = Arch
2010-03-19 06:55:07 +00:00
self . OutputDir = OutputDir
self . DebugDir = DebugDir
2010-02-28 23:39:39 +00:00
self . Image = ImageClass
self . Image . Size = ( self . Image . Size / 0x1000 + 1 ) * 0x1000
## The class implementing the EDK2 build process
#
# The build process includes:
# 1. Load configuration from target.txt and tools_def.txt in $(WORKSPACE)/Conf
# 2. Parse DSC file of active platform
# 3. Parse FDF file if any
# 4. Establish build database, including parse all other files (module, package)
# 5. Create AutoGen files (C code file, depex file, makefile) if necessary
# 6. Call build command
#
class Build ():
## Constructor
#
# Constructor will load all necessary configurations, parse platform, modules
# and packages and the establish a database for AutoGen.
#
# @param Target The build command target, one of gSupportedTarget
# @param WorkspaceDir The directory of workspace
2011-10-29 06:59:30 +00:00
# @param BuildOptions Build options passed from command line
2010-02-28 23:39:39 +00:00
#
2011-10-29 06:59:30 +00:00
def __init__ ( self , Target , WorkspaceDir , BuildOptions ):
self . WorkspaceDir = WorkspaceDir
2010-02-28 23:39:39 +00:00
self . Target = Target
2011-10-29 06:59:30 +00:00
self . PlatformFile = BuildOptions . PlatformFile
self . ModuleFile = BuildOptions . ModuleFile
self . ArchList = BuildOptions . TargetArch
self . ToolChainList = BuildOptions . ToolChain
self . BuildTargetList = BuildOptions . BuildTarget
self . Fdf = BuildOptions . FdfFile
self . FdList = BuildOptions . RomImage
self . FvList = BuildOptions . FvImage
self . CapList = BuildOptions . CapName
self . SilentMode = BuildOptions . SilentMode
self . ThreadNumber = BuildOptions . ThreadNumber
self . SkipAutoGen = BuildOptions . SkipAutoGen
self . Reparse = BuildOptions . Reparse
self . SkuId = BuildOptions . SkuId
2014-08-28 13:53:34 +00:00
self . ConfDirectory = BuildOptions . ConfDirectory
2010-02-28 23:39:39 +00:00
self . SpawnMode = True
2011-10-29 06:59:30 +00:00
self . BuildReport = BuildReport ( BuildOptions . ReportFile , BuildOptions . ReportType )
2010-02-28 23:39:39 +00:00
self . TargetTxt = TargetTxtClassObject ()
self . ToolDef = ToolDefClassObject ()
2016-02-25 16:13:31 +08:00
GlobalData . BuildOptionPcd = BuildOptions . OptionPcd
2014-08-26 07:14:38 +00:00
#Set global flag for build mode
GlobalData . gIgnoreSource = BuildOptions . IgnoreSources
2014-08-28 13:53:34 +00:00
if self . ConfDirectory :
# Get alternate Conf location, if it is absolute, then just use the absolute directory name
ConfDirectoryPath = os . path . normpath ( self . ConfDirectory )
if not os . path . isabs ( ConfDirectoryPath ):
# Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
# This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
2015-10-08 09:27:14 +00:00
ConfDirectoryPath = mws . join ( self . WorkspaceDir , ConfDirectoryPath )
2014-08-28 13:53:34 +00:00
else :
# Get standard WORKSPACE/Conf use the absolute path to the WORKSPACE/Conf
2015-10-08 09:27:14 +00:00
ConfDirectoryPath = mws . join ( self . WorkspaceDir , 'Conf' )
2014-08-28 13:53:34 +00:00
GlobalData . gConfDirectory = ConfDirectoryPath
GlobalData . gDatabasePath = os . path . normpath ( os . path . join ( ConfDirectoryPath , GlobalData . gDatabasePath ))
2011-10-29 06:59:30 +00:00
if BuildOptions . DisableCache :
self . Db = WorkspaceDatabase ( ":memory:" )
else :
2014-08-28 13:53:34 +00:00
self . Db = WorkspaceDatabase ( GlobalData . gDatabasePath , self . Reparse )
self . BuildDatabase = self . Db . BuildObject
self . Platform = None
2010-02-28 23:39:39 +00:00
self . LoadFixAddress = 0
2011-10-29 06:59:30 +00:00
self . UniFlag = BuildOptions . Flag
2014-08-26 02:52:24 +00:00
self . BuildModules = []
2016-03-31 14:05:59 +08:00
self . Db_Flag = False
self . LaunchPrebuildFlag = False
self . PrebuildScript = ''
self . PostbuildScript = ''
self . PlatformBuildPath = os . path . join ( GlobalData . gConfDirectory , '.cache' , '.PlatformBuild' )
2016-03-16 11:06:44 +08:00
if BuildOptions . CommandLength :
GlobalData . gCommandMaxLength = BuildOptions . CommandLength
2010-09-06 01:58:00 +00:00
# print dot character during doing some time-consuming work
2010-02-28 23:39:39 +00:00
self . Progress = Utils . Progressor ()
# print current build environment and configuration
2011-10-29 06:59:30 +00:00
EdkLogger . quiet ( " %-16s = %s " % ( "WORKSPACE" , os . environ [ "WORKSPACE" ]))
2015-11-06 02:57:07 +00:00
if "PACKAGES_PATH" in os . environ :
# WORKSPACE env has been converted before. Print the same path style with WORKSPACE env.
EdkLogger . quiet ( " %-16s = %s " % ( "PACKAGES_PATH" , os . path . normcase ( os . path . normpath ( os . environ [ "PACKAGES_PATH" ]))))
2011-10-29 06:59:30 +00:00
EdkLogger . quiet ( " %-16s = %s " % ( "ECP_SOURCE" , os . environ [ "ECP_SOURCE" ]))
EdkLogger . quiet ( " %-16s = %s " % ( "EDK_SOURCE" , os . environ [ "EDK_SOURCE" ]))
EdkLogger . quiet ( " %-16s = %s " % ( "EFI_SOURCE" , os . environ [ "EFI_SOURCE" ]))
EdkLogger . quiet ( " %-16s = %s " % ( "EDK_TOOLS_PATH" , os . environ [ "EDK_TOOLS_PATH" ]))
2015-11-06 02:57:07 +00:00
if "EDK_TOOLS_BIN" in os . environ :
# Print the same path style with WORKSPACE env.
EdkLogger . quiet ( " %-16s = %s " % ( "EDK_TOOLS_BIN" , os . path . normcase ( os . path . normpath ( os . environ [ "EDK_TOOLS_BIN" ]))))
2010-02-28 23:39:39 +00:00
2016-03-31 14:05:59 +08:00
self . InitPreBuild ()
self . InitPostBuild ()
if self . PrebuildScript :
EdkLogger . quiet ( " %-16s = %s " % ( "PREBUILD" , self . PrebuildScript ))
if self . PostbuildScript :
EdkLogger . quiet ( " %-16s = %s " % ( "POSTBUILD" , self . PostbuildScript ))
if self . PrebuildScript :
self . LaunchPrebuild ()
if not ( self . LaunchPrebuildFlag and os . path . exists ( self . PlatformBuildPath )):
self . InitBuild ()
2010-02-28 23:39:39 +00:00
2016-03-31 14:05:59 +08:00
EdkLogger . info ( "" )
2010-02-28 23:39:39 +00:00
os . chdir ( self . WorkspaceDir )
## Load configuration
#
# This method will parse target.txt and get the build configurations.
#
def LoadConfiguration ( self ):
#
# Check target.txt and tools_def.txt and Init them
#
2014-08-28 13:53:34 +00:00
BuildConfigurationFile = os . path . normpath ( os . path . join ( GlobalData . gConfDirectory , gBuildConfiguration ))
2010-02-28 23:39:39 +00:00
if os . path . isfile ( BuildConfigurationFile ) == True :
StatusCode = self . TargetTxt . LoadTargetTxtFile ( BuildConfigurationFile )
ToolDefinitionFile = self . TargetTxt . TargetTxtDictionary [ DataType . TAB_TAT_DEFINES_TOOL_CHAIN_CONF ]
if ToolDefinitionFile == '' :
ToolDefinitionFile = gToolsDefinition
2015-10-08 09:27:14 +00:00
ToolDefinitionFile = os . path . normpath ( mws . join ( self . WorkspaceDir , 'Conf' , ToolDefinitionFile ))
2010-02-28 23:39:39 +00:00
if os . path . isfile ( ToolDefinitionFile ) == True :
StatusCode = self . ToolDef . LoadToolDefFile ( ToolDefinitionFile )
else :
EdkLogger . error ( "build" , FILE_NOT_FOUND , ExtraData = ToolDefinitionFile )
else :
EdkLogger . error ( "build" , FILE_NOT_FOUND , ExtraData = BuildConfigurationFile )
# if no ARCH given in command line, get it from target.txt
2011-10-29 06:59:30 +00:00
if not self . ArchList :
2010-02-28 23:39:39 +00:00
self . ArchList = self . TargetTxt . TargetTxtDictionary [ DataType . TAB_TAT_DEFINES_TARGET_ARCH ]
2011-10-29 06:59:30 +00:00
self . ArchList = tuple ( self . ArchList )
2010-02-28 23:39:39 +00:00
# if no build target given in command line, get it from target.txt
2011-10-29 06:59:30 +00:00
if not self . BuildTargetList :
2010-02-28 23:39:39 +00:00
self . BuildTargetList = self . TargetTxt . TargetTxtDictionary [ DataType . TAB_TAT_DEFINES_TARGET ]
# if no tool chain given in command line, get it from target.txt
2011-10-29 06:59:30 +00:00
if not self . ToolChainList :
2010-02-28 23:39:39 +00:00
self . ToolChainList = self . TargetTxt . TargetTxtDictionary [ DataType . TAB_TAT_DEFINES_TOOL_CHAIN_TAG ]
if self . ToolChainList == None or len ( self . ToolChainList ) == 0 :
EdkLogger . error ( "build" , RESOURCE_NOT_AVAILABLE , ExtraData = "No toolchain given. Don't know how to build. \n " )
# check if the tool chains are defined or not
NewToolChainList = []
for ToolChain in self . ToolChainList :
if ToolChain not in self . ToolDef . ToolsDefTxtDatabase [ TAB_TOD_DEFINES_TOOL_CHAIN_TAG ]:
EdkLogger . warn ( "build" , "Tool chain [ %s ] is not defined" % ToolChain )
else :
NewToolChainList . append ( ToolChain )
# if no tool chain available, break the build
if len ( NewToolChainList ) == 0 :
EdkLogger . error ( "build" , RESOURCE_NOT_AVAILABLE ,
ExtraData = "[ %s ] not defined. No toolchain available for build! \n " % ", " . join ( self . ToolChainList ))
else :
self . ToolChainList = NewToolChainList
if self . ThreadNumber == None :
self . ThreadNumber = self . TargetTxt . TargetTxtDictionary [ DataType . TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER ]
if self . ThreadNumber == '' :
self . ThreadNumber = 0
else :
self . ThreadNumber = int ( self . ThreadNumber , 0 )
if self . ThreadNumber == 0 :
self . ThreadNumber = 1
if not self . PlatformFile :
PlatformFile = self . TargetTxt . TargetTxtDictionary [ DataType . TAB_TAT_DEFINES_ACTIVE_PLATFORM ]
if not PlatformFile :
# Try to find one in current directory
WorkingDirectory = os . getcwd ()
FileList = glob . glob ( os . path . normpath ( os . path . join ( WorkingDirectory , '*.dsc' )))
FileNum = len ( FileList )
if FileNum >= 2 :
EdkLogger . error ( "build" , OPTION_MISSING ,
ExtraData = "There are %d DSC files in %s . Use '-p' to specify one. \n " % ( FileNum , WorkingDirectory ))
elif FileNum == 1 :
PlatformFile = FileList [ 0 ]
else :
EdkLogger . error ( "build" , RESOURCE_NOT_AVAILABLE ,
ExtraData = "No active platform specified in target.txt or command line! Nothing can be built. \n " )
self . PlatformFile = PathClass ( NormFile ( PlatformFile , self . WorkspaceDir ), self . WorkspaceDir )
## Initialize build configuration
#
# This method will parse DSC file and merge the configurations from
# command line and target.txt, then get the final build configurations.
#
def InitBuild ( self ):
2011-10-29 06:59:30 +00:00
# parse target.txt, tools_def.txt, and platform file
2013-08-23 02:18:16 +00:00
self . LoadConfiguration ()
2011-10-29 06:59:30 +00:00
# Allow case-insensitive for those from command line or configuration file
ErrorCode , ErrorInfo = self . PlatformFile . Validate ( ".dsc" , False )
2010-02-28 23:39:39 +00:00
if ErrorCode != 0 :
EdkLogger . error ( "build" , ErrorCode , ExtraData = ErrorInfo )
# create metafile database
2016-03-31 14:05:59 +08:00
if not self . Db_Flag :
self . Db . InitDatabase ()
2010-02-28 23:39:39 +00:00
2016-03-31 14:05:59 +08:00
def InitPreBuild ( self ):
self . LoadConfiguration ()
if self . BuildTargetList :
GlobalData . gGlobalDefines [ 'TARGET' ] = self . BuildTargetList [ 0 ]
if self . ArchList :
GlobalData . gGlobalDefines [ 'ARCH' ] = self . ArchList [ 0 ]
if self . ToolChainList :
GlobalData . gGlobalDefines [ 'TOOLCHAIN' ] = self . ToolChainList [ 0 ]
GlobalData . gGlobalDefines [ 'TOOL_CHAIN_TAG' ] = self . ToolChainList [ 0 ]
if 'PREBUILD' in GlobalData . gCommandLineDefines . keys ():
self . Prebuild = GlobalData . gCommandLineDefines . get ( 'PREBUILD' )
else :
self . Db . InitDatabase ()
self . Db_Flag = True
Platform = self . Db . _MapPlatform ( str ( self . PlatformFile ))
self . Prebuild = str ( Platform . Prebuild )
if self . Prebuild :
PrebuildList = self . Prebuild . split ()
if not os . path . isabs ( PrebuildList [ 0 ]):
PrebuildList [ 0 ] = mws . join ( self . WorkspaceDir , PrebuildList [ 0 ])
if os . path . isfile ( PrebuildList [ 0 ]):
self . PrebuildScript = PrebuildList [ 0 ]
self . Prebuild = ' ' . join ( PrebuildList )
self . Prebuild += self . PassCommandOption ( self . BuildTargetList , self . ArchList , self . ToolChainList )
#self.LaunchPrebuild()
else :
EdkLogger . error ( "Prebuild" , PREBUILD_ERROR , "the prebuild script %s is not exist. \n If you'd like to disable the Prebuild process, please use the format: -D PREBUILD= \"\" " % ( PrebuildList [ 0 ]))
def InitPostBuild ( self ):
if 'POSTBUILD' in GlobalData . gCommandLineDefines . keys ():
self . Postbuild = GlobalData . gCommandLineDefines . get ( 'POSTBUILD' )
else :
Platform = self . Db . _MapPlatform ( str ( self . PlatformFile ))
self . Postbuild = str ( Platform . Postbuild )
if self . Postbuild :
PostbuildList = self . Postbuild . split ()
if not os . path . isabs ( PostbuildList [ 0 ]):
PostbuildList [ 0 ] = mws . join ( self . WorkspaceDir , PostbuildList [ 0 ])
if os . path . isfile ( PostbuildList [ 0 ]):
self . PostbuildScript = PostbuildList [ 0 ]
self . Postbuild = ' ' . join ( PostbuildList )
self . Postbuild += self . PassCommandOption ( self . BuildTargetList , self . ArchList , self . ToolChainList )
#self.LanuchPostbuild()
else :
EdkLogger . error ( "Postbuild" , POSTBUILD_ERROR , "the postbuild script %s is not exist. \n If you'd like to disable the Postbuild process, please use the format: -D POSTBUILD= \"\" " % ( PostbuildList [ 0 ]))
def PassCommandOption ( self , BuildTarget , TargetArch , ToolChain ):
BuildStr = ''
if GlobalData . gCommand and isinstance ( GlobalData . gCommand , list ):
BuildStr += ' ' + ' ' . join ( GlobalData . gCommand )
TargetFlag = False
ArchFlag = False
ToolChainFlag = False
if GlobalData . gOptions and not GlobalData . gOptions . BuildTarget :
TargetFlag = True
if GlobalData . gOptions and not GlobalData . gOptions . TargetArch :
ArchFlag = True
if GlobalData . gOptions and not GlobalData . gOptions . ToolChain :
ToolChainFlag = True
if TargetFlag and BuildTarget :
if isinstance ( BuildTarget , list ) or isinstance ( BuildTarget , tuple ):
BuildStr += ' -b ' + ' -b ' . join ( BuildTarget )
elif isinstance ( BuildTarget , str ):
BuildStr += ' -b ' + BuildTarget
if ArchFlag and TargetArch :
if isinstance ( TargetArch , list ) or isinstance ( TargetArch , tuple ):
BuildStr += ' -a ' + ' -a ' . join ( TargetArch )
elif isinstance ( TargetArch , str ):
BuildStr += ' -a ' + TargetArch
if ToolChainFlag and ToolChain :
if isinstance ( ToolChain , list ) or isinstance ( ToolChain , tuple ):
BuildStr += ' -t ' + ' -t ' . join ( ToolChain )
elif isinstance ( ToolChain , str ):
BuildStr += ' -t ' + ToolChain
return BuildStr
def LaunchPrebuild ( self ):
if self . Prebuild :
EdkLogger . info ( " \n - Prebuild Start - \n " )
self . LaunchPrebuildFlag = True
PrebuildEnvFile = os . path . join ( GlobalData . gConfDirectory , '.cache' , '.PrebuildEnv' )
if os . path . isfile ( PrebuildEnvFile ):
os . remove ( PrebuildEnvFile )
if os . path . isfile ( self . PlatformBuildPath ):
os . remove ( self . PlatformBuildPath )
if sys . platform == "win32" :
args = ' && ' . join (( self . Prebuild , 'set > ' + PrebuildEnvFile ))
Process = Popen ( args , stdout = PIPE , stderr = PIPE )
else :
args = ' && ' . join (( self . Prebuild , 'env > ' + PrebuildEnvFile ))
Process = Popen ( args , stdout = PIPE , stderr = PIPE , shell = True , executable = "/bin/bash" )
# launch two threads to read the STDOUT and STDERR
EndOfProcedure = Event ()
EndOfProcedure . clear ()
if Process . stdout :
StdOutThread = Thread ( target = ReadMessage , args = ( Process . stdout , EdkLogger . info , EndOfProcedure ))
StdOutThread . setName ( "STDOUT-Redirector" )
StdOutThread . setDaemon ( False )
StdOutThread . start ()
if Process . stderr :
StdErrThread = Thread ( target = ReadMessage , args = ( Process . stderr , EdkLogger . quiet , EndOfProcedure ))
StdErrThread . setName ( "STDERR-Redirector" )
StdErrThread . setDaemon ( False )
StdErrThread . start ()
# waiting for program exit
Process . wait ()
if Process . stdout :
StdOutThread . join ()
if Process . stderr :
StdErrThread . join ()
if Process . returncode != 0 :
EdkLogger . error ( "Prebuild" , PREBUILD_ERROR , 'Prebuild process is not success!' )
if os . path . exists ( PrebuildEnvFile ):
f = open ( PrebuildEnvFile )
envs = f . readlines ()
f . close ()
envs = itertools . imap ( lambda l : l . split ( '=' , 1 ), envs )
envs = itertools . ifilter ( lambda l : len ( l ) == 2 , envs )
envs = itertools . imap ( lambda l : [ i . strip () for i in l ], envs )
os . environ . update ( dict ( envs ))
EdkLogger . info ( " \n - Prebuild Done - \n " )
def LanuchPostbuild ( self ):
if self . Postbuild :
EdkLogger . info ( " \n - Postbuild Start - \n " )
if sys . platform == "win32" :
Process = Popen ( self . Postbuild , stdout = PIPE , stderr = PIPE )
else :
Process = Popen ( self . Postbuild , stdout = PIPE , stderr = PIPE , shell = True , executable = "/bin/bash" )
# launch two threads to read the STDOUT and STDERR
EndOfProcedure = Event ()
EndOfProcedure . clear ()
if Process . stdout :
StdOutThread = Thread ( target = ReadMessage , args = ( Process . stdout , EdkLogger . info , EndOfProcedure ))
StdOutThread . setName ( "STDOUT-Redirector" )
StdOutThread . setDaemon ( False )
StdOutThread . start ()
if Process . stderr :
StdErrThread = Thread ( target = ReadMessage , args = ( Process . stderr , EdkLogger . quiet , EndOfProcedure ))
StdErrThread . setName ( "STDERR-Redirector" )
StdErrThread . setDaemon ( False )
StdErrThread . start ()
# waiting for program exit
Process . wait ()
if Process . stdout :
StdOutThread . join ()
if Process . stderr :
StdErrThread . join ()
if Process . returncode != 0 :
EdkLogger . error ( "Postbuild" , POSTBUILD_ERROR , 'Postbuild process is not success!' )
EdkLogger . info ( " \n - Postbuild Done - \n " )
2010-02-28 23:39:39 +00:00
## Build a module or platform
#
2010-10-11 06:26:52 +00:00
# Create autogen code and makefile for a module or platform, and the launch
2010-02-28 23:39:39 +00:00
# "make" command to build it
#
# @param Target The target of build command
# @param Platform The platform file
# @param Module The module file
# @param BuildTarget The name of build target, one of "DEBUG", "RELEASE"
# @param ToolChain The name of toolchain to build
# @param Arch The arch of the module/platform
# @param CreateDepModuleCodeFile Flag used to indicate creating code
# for dependent modules/Libraries
# @param CreateDepModuleMakeFile Flag used to indicate creating makefile
# for dependent modules/Libraries
#
2014-08-18 04:59:01 +00:00
def _BuildPa ( self , Target , AutoGenObject , CreateDepsCodeFile = True , CreateDepsMakeFile = True , BuildModule = False ):
2010-02-28 23:39:39 +00:00
if AutoGenObject == None :
return False
# skip file generation for cleanxxx targets, run and fds target
if Target not in [ 'clean' , 'cleanlib' , 'cleanall' , 'run' , 'fds' ]:
# for target which must generate AutoGen code and makefile
if not self . SkipAutoGen or Target == 'genc' :
self . Progress . Start ( "Generating code" )
AutoGenObject . CreateCodeFile ( CreateDepsCodeFile )
self . Progress . Stop ( "done!" )
if Target == "genc" :
return True
if not self . SkipAutoGen or Target == 'genmake' :
self . Progress . Start ( "Generating makefile" )
AutoGenObject . CreateMakeFile ( CreateDepsMakeFile )
self . Progress . Stop ( "done!" )
if Target == "genmake" :
return True
else :
# always recreate top/platform makefile when clean, just in case of inconsistency
AutoGenObject . CreateCodeFile ( False )
AutoGenObject . CreateMakeFile ( False )
if EdkLogger . GetLevel () == EdkLogger . QUIET :
EdkLogger . quiet ( "Building ... %s " % repr ( AutoGenObject ))
BuildCommand = AutoGenObject . BuildCommand
if BuildCommand == None or len ( BuildCommand ) == 0 :
2011-10-29 06:59:30 +00:00
EdkLogger . error ( "build" , OPTION_MISSING ,
"No build command found for this module. "
2013-08-23 02:18:16 +00:00
"Please check your setting of %s _ %s _ %s _MAKE_PATH in Conf/tools_def.txt file." %
2011-10-29 06:59:30 +00:00
( AutoGenObject . BuildTarget , AutoGenObject . ToolChain , AutoGenObject . Arch ),
ExtraData = str ( AutoGenObject ))
2010-02-28 23:39:39 +00:00
2014-08-18 04:59:01 +00:00
makefile = GenMake . BuildFile ( AutoGenObject ) . _FILE_NAME_ [ GenMake . gMakeType ]
# run
if Target == 'run' :
2014-12-23 05:48:31 +00:00
RunDir = os . path . normpath ( os . path . join ( AutoGenObject . BuildDir , GlobalData . gGlobalDefines [ 'ARCH' ]))
2014-08-18 04:59:01 +00:00
Command = '.\SecMain'
os . chdir ( RunDir )
LaunchCommand ( Command , RunDir )
return True
# build modules
if BuildModule :
BuildCommand = BuildCommand + [ Target ]
LaunchCommand ( BuildCommand , AutoGenObject . MakeFileDir )
2014-08-26 02:52:24 +00:00
self . CreateAsBuiltInf ()
2014-08-18 04:59:01 +00:00
return True
# build library
if Target == 'libraries' :
for Lib in AutoGenObject . LibraryBuildDirectoryList :
NewBuildCommand = BuildCommand + [ '-f' , os . path . normpath ( os . path . join ( Lib , makefile )), 'pbuild' ]
LaunchCommand ( NewBuildCommand , AutoGenObject . MakeFileDir )
return True
# build module
if Target == 'modules' :
for Lib in AutoGenObject . LibraryBuildDirectoryList :
NewBuildCommand = BuildCommand + [ '-f' , os . path . normpath ( os . path . join ( Lib , makefile )), 'pbuild' ]
LaunchCommand ( NewBuildCommand , AutoGenObject . MakeFileDir )
for Mod in AutoGenObject . ModuleBuildDirectoryList :
NewBuildCommand = BuildCommand + [ '-f' , os . path . normpath ( os . path . join ( Mod , makefile )), 'pbuild' ]
LaunchCommand ( NewBuildCommand , AutoGenObject . MakeFileDir )
2014-08-26 02:52:24 +00:00
self . CreateAsBuiltInf ()
2014-08-18 04:59:01 +00:00
return True
# cleanlib
if Target == 'cleanlib' :
for Lib in AutoGenObject . LibraryBuildDirectoryList :
LibMakefile = os . path . normpath ( os . path . join ( Lib , makefile ))
if os . path . exists ( LibMakefile ):
NewBuildCommand = BuildCommand + [ '-f' , LibMakefile , 'cleanall' ]
LaunchCommand ( NewBuildCommand , AutoGenObject . MakeFileDir )
return True
# clean
if Target == 'clean' :
for Mod in AutoGenObject . ModuleBuildDirectoryList :
ModMakefile = os . path . normpath ( os . path . join ( Mod , makefile ))
if os . path . exists ( ModMakefile ):
NewBuildCommand = BuildCommand + [ '-f' , ModMakefile , 'cleanall' ]
LaunchCommand ( NewBuildCommand , AutoGenObject . MakeFileDir )
for Lib in AutoGenObject . LibraryBuildDirectoryList :
LibMakefile = os . path . normpath ( os . path . join ( Lib , makefile ))
if os . path . exists ( LibMakefile ):
NewBuildCommand = BuildCommand + [ '-f' , LibMakefile , 'cleanall' ]
LaunchCommand ( NewBuildCommand , AutoGenObject . MakeFileDir )
return True
# cleanall
if Target == 'cleanall' :
try :
#os.rmdir(AutoGenObject.BuildDir)
RemoveDirectory ( AutoGenObject . BuildDir , True )
except WindowsError , X :
EdkLogger . error ( "build" , FILE_DELETE_FAILURE , ExtraData = str ( X ))
return True
## Build a module or platform
#
# Create autogen code and makefile for a module or platform, and the launch
# "make" command to build it
#
# @param Target The target of build command
# @param Platform The platform file
# @param Module The module file
# @param BuildTarget The name of build target, one of "DEBUG", "RELEASE"
# @param ToolChain The name of toolchain to build
# @param Arch The arch of the module/platform
# @param CreateDepModuleCodeFile Flag used to indicate creating code
# for dependent modules/Libraries
# @param CreateDepModuleMakeFile Flag used to indicate creating makefile
# for dependent modules/Libraries
#
def _Build ( self , Target , AutoGenObject , CreateDepsCodeFile = True , CreateDepsMakeFile = True , BuildModule = False ):
if AutoGenObject == None :
return False
# skip file generation for cleanxxx targets, run and fds target
if Target not in [ 'clean' , 'cleanlib' , 'cleanall' , 'run' , 'fds' ]:
# for target which must generate AutoGen code and makefile
if not self . SkipAutoGen or Target == 'genc' :
self . Progress . Start ( "Generating code" )
AutoGenObject . CreateCodeFile ( CreateDepsCodeFile )
self . Progress . Stop ( "done!" )
if Target == "genc" :
return True
if not self . SkipAutoGen or Target == 'genmake' :
self . Progress . Start ( "Generating makefile" )
AutoGenObject . CreateMakeFile ( CreateDepsMakeFile )
#AutoGenObject.CreateAsBuiltInf()
self . Progress . Stop ( "done!" )
if Target == "genmake" :
return True
else :
# always recreate top/platform makefile when clean, just in case of inconsistency
AutoGenObject . CreateCodeFile ( False )
AutoGenObject . CreateMakeFile ( False )
if EdkLogger . GetLevel () == EdkLogger . QUIET :
EdkLogger . quiet ( "Building ... %s " % repr ( AutoGenObject ))
BuildCommand = AutoGenObject . BuildCommand
if BuildCommand == None or len ( BuildCommand ) == 0 :
EdkLogger . error ( "build" , OPTION_MISSING ,
"No build command found for this module. "
"Please check your setting of %s _ %s _ %s _MAKE_PATH in Conf/tools_def.txt file." %
( AutoGenObject . BuildTarget , AutoGenObject . ToolChain , AutoGenObject . Arch ),
ExtraData = str ( AutoGenObject ))
2015-01-19 05:01:39 +00:00
# build modules
if BuildModule :
if Target != 'fds' :
BuildCommand = BuildCommand + [ Target ]
LaunchCommand ( BuildCommand , AutoGenObject . MakeFileDir )
self . CreateAsBuiltInf ()
return True
2014-08-18 04:59:01 +00:00
# genfds
if Target == 'fds' :
LaunchCommand ( AutoGenObject . GenFdsCommand , AutoGenObject . MakeFileDir )
return True
# run
if Target == 'run' :
2014-12-23 05:48:31 +00:00
RunDir = os . path . normpath ( os . path . join ( AutoGenObject . BuildDir , GlobalData . gGlobalDefines [ 'ARCH' ]))
2014-08-18 04:59:01 +00:00
Command = '.\SecMain'
os . chdir ( RunDir )
LaunchCommand ( Command , RunDir )
return True
# build library
if Target == 'libraries' :
pass
# not build modules
# cleanall
2010-02-28 23:39:39 +00:00
if Target == 'cleanall' :
try :
#os.rmdir(AutoGenObject.BuildDir)
RemoveDirectory ( AutoGenObject . BuildDir , True )
except WindowsError , X :
EdkLogger . error ( "build" , FILE_DELETE_FAILURE , ExtraData = str ( X ))
return True
2010-11-15 02:51:34 +00:00
## Rebase module image and Get function address for the input module list.
2010-02-28 23:39:39 +00:00
#
def _RebaseModule ( self , MapBuffer , BaseAddress , ModuleList , AddrIsOffset = True , ModeIsSmm = False ):
if ModeIsSmm :
AddrIsOffset = False
InfFileNameList = ModuleList . keys ()
#InfFileNameList.sort()
for InfFile in InfFileNameList :
2011-05-11 10:26:49 +00:00
sys . stdout . write ( "." )
sys . stdout . flush ()
2010-02-28 23:39:39 +00:00
ModuleInfo = ModuleList [ InfFile ]
ModuleName = ModuleInfo . BaseName
2010-03-19 06:55:07 +00:00
ModuleOutputImage = ModuleInfo . Image . FileName
ModuleDebugImage = os . path . join ( ModuleInfo . DebugDir , ModuleInfo . BaseName + '.efi' )
2010-02-28 23:39:39 +00:00
## for SMM module in SMRAM, the SMRAM will be allocated from base to top.
if not ModeIsSmm :
BaseAddress = BaseAddress - ModuleInfo . Image . Size
#
# Update Image to new BaseAddress by GenFw tool
#
2010-03-19 06:55:07 +00:00
LaunchCommand ([ "GenFw" , "--rebase" , str ( BaseAddress ), "-r" , ModuleOutputImage ], ModuleInfo . OutputDir )
2015-12-01 04:22:16 +00:00
LaunchCommand ([ "GenFw" , "--rebase" , str ( BaseAddress ), "-r" , ModuleDebugImage ], ModuleInfo . DebugDir )
2010-02-28 23:39:39 +00:00
else :
#
# Set new address to the section header only for SMM driver.
#
2010-03-19 06:55:07 +00:00
LaunchCommand ([ "GenFw" , "--address" , str ( BaseAddress ), "-r" , ModuleOutputImage ], ModuleInfo . OutputDir )
2015-12-01 04:22:16 +00:00
LaunchCommand ([ "GenFw" , "--address" , str ( BaseAddress ), "-r" , ModuleDebugImage ], ModuleInfo . DebugDir )
2010-02-28 23:39:39 +00:00
#
# Collect funtion address from Map file
#
2010-03-19 06:55:07 +00:00
ImageMapTable = ModuleOutputImage . replace ( '.efi' , '.map' )
2010-02-28 23:39:39 +00:00
FunctionList = []
if os . path . exists ( ImageMapTable ):
OrigImageBaseAddress = 0
2015-12-01 04:22:16 +00:00
ImageMap = open ( ImageMapTable , 'r' )
2010-02-28 23:39:39 +00:00
for LinStr in ImageMap :
if len ( LinStr . strip ()) == 0 :
continue
#
# Get the preferred address set on link time.
#
if LinStr . find ( 'Preferred load address is' ) != - 1 :
StrList = LinStr . split ()
OrigImageBaseAddress = int ( StrList [ len ( StrList ) - 1 ], 16 )
StrList = LinStr . split ()
if len ( StrList ) > 4 :
2015-12-01 04:22:16 +00:00
if StrList [ 3 ] == 'f' or StrList [ 3 ] == 'F' :
2010-02-28 23:39:39 +00:00
Name = StrList [ 1 ]
RelativeAddress = int ( StrList [ 2 ], 16 ) - OrigImageBaseAddress
FunctionList . append (( Name , RelativeAddress ))
if ModuleInfo . Arch == 'IPF' and Name . endswith ( '_ModuleEntryPoint' ):
#
# Get the real entry point address for IPF image.
#
ModuleInfo . Image . EntryPoint = RelativeAddress
ImageMap . close ()
#
# Add general information.
#
if ModeIsSmm :
MapBuffer . write ( ' \n\n %s (Fixed SMRAM Offset, BaseAddress=0x %010X , EntryPoint=0x %010X ) \n ' % ( ModuleName , BaseAddress , BaseAddress + ModuleInfo . Image . EntryPoint ))
elif AddrIsOffset :
MapBuffer . write ( ' \n\n %s (Fixed Memory Offset, BaseAddress=-0x %010X , EntryPoint=-0x %010X ) \n ' % ( ModuleName , 0 - BaseAddress , 0 - ( BaseAddress + ModuleInfo . Image . EntryPoint )))
else :
MapBuffer . write ( ' \n\n %s (Fixed Memory Address, BaseAddress=0x %010X , EntryPoint=0x %010X ) \n ' % ( ModuleName , BaseAddress , BaseAddress + ModuleInfo . Image . EntryPoint ))
#
# Add guid and general seciton section.
#
TextSectionAddress = 0
DataSectionAddress = 0
for SectionHeader in ModuleInfo . Image . SectionHeaderList :
if SectionHeader [ 0 ] == '.text' :
TextSectionAddress = SectionHeader [ 1 ]
elif SectionHeader [ 0 ] in [ '.data' , '.sdata' ]:
DataSectionAddress = SectionHeader [ 1 ]
if AddrIsOffset :
2013-08-23 02:18:16 +00:00
MapBuffer . write ( '(GUID= %s , .textbaseaddress=-0x %010X , .databaseaddress=-0x %010X ) \n ' % ( ModuleInfo . Guid , 0 - ( BaseAddress + TextSectionAddress ), 0 - ( BaseAddress + DataSectionAddress )))
2010-02-28 23:39:39 +00:00
else :
2013-08-23 02:18:16 +00:00
MapBuffer . write ( '(GUID= %s , .textbaseaddress=0x %010X , .databaseaddress=0x %010X ) \n ' % ( ModuleInfo . Guid , BaseAddress + TextSectionAddress , BaseAddress + DataSectionAddress ))
2010-03-19 06:55:07 +00:00
#
# Add debug image full path.
#
MapBuffer . write ( '(IMAGE= %s ) \n\n ' % ( ModuleDebugImage ))
2010-02-28 23:39:39 +00:00
#
# Add funtion address
#
for Function in FunctionList :
if AddrIsOffset :
MapBuffer . write ( ' -0x %010X %s \n ' % ( 0 - ( BaseAddress + Function [ 1 ]), Function [ 0 ]))
else :
MapBuffer . write ( ' 0x %010X %s \n ' % ( BaseAddress + Function [ 1 ], Function [ 0 ]))
ImageMap . close ()
#
# for SMM module in SMRAM, the SMRAM will be allocated from base to top.
#
if ModeIsSmm :
BaseAddress = BaseAddress + ModuleInfo . Image . Size
## Collect MAP information of all FVs
#
2010-03-12 10:54:01 +00:00
def _CollectFvMapBuffer ( self , MapBuffer , Wa , ModuleList ):
2011-10-29 06:59:30 +00:00
if self . Fdf :
2010-02-28 23:39:39 +00:00
# First get the XIP base address for FV map file.
2010-03-12 10:54:01 +00:00
GuidPattern = re . compile ( "[-a-fA-F0-9]+" )
2010-03-19 06:55:07 +00:00
GuidName = re . compile ( "\(GUID=[-a-fA-F0-9]+" )
2010-02-28 23:39:39 +00:00
for FvName in Wa . FdfProfile . FvDict . keys ():
FvMapBuffer = os . path . join ( Wa . FvDir , FvName + '.Fv.map' )
if not os . path . exists ( FvMapBuffer ):
continue
2014-08-15 03:06:48 +00:00
FvMap = open ( FvMapBuffer , 'r' )
2010-02-28 23:39:39 +00:00
#skip FV size information
FvMap . readline ()
FvMap . readline ()
FvMap . readline ()
FvMap . readline ()
2010-03-12 10:54:01 +00:00
for Line in FvMap :
MatchGuid = GuidPattern . match ( Line )
if MatchGuid != None :
#
# Replace GUID with module name
#
GuidString = MatchGuid . group ()
if GuidString . upper () in ModuleList :
Line = Line . replace ( GuidString , ModuleList [ GuidString . upper ()] . Name )
MapBuffer . write ( ' %s ' % ( Line ))
2010-03-19 06:55:07 +00:00
#
# Add the debug image full path.
#
MatchGuid = GuidName . match ( Line )
if MatchGuid != None :
GuidString = MatchGuid . group () . split ( "=" )[ 1 ]
if GuidString . upper () in ModuleList :
MapBuffer . write ( '(IMAGE= %s ) \n ' % ( os . path . join ( ModuleList [ GuidString . upper ()] . DebugDir , ModuleList [ GuidString . upper ()] . Name + '.efi' )))
2010-02-28 23:39:39 +00:00
FvMap . close ()
## Collect MAP information of all modules
#
def _CollectModuleMapBuffer ( self , MapBuffer , ModuleList ):
2011-05-11 10:26:49 +00:00
sys . stdout . write ( "Generate Load Module At Fix Address Map" )
sys . stdout . flush ()
2010-02-28 23:39:39 +00:00
PatchEfiImageList = []
PeiModuleList = {}
BtModuleList = {}
RtModuleList = {}
SmmModuleList = {}
PeiSize = 0
BtSize = 0
RtSize = 0
# reserve 4K size in SMRAM to make SMM module address not from 0.
SmmSize = 0x1000
IsIpfPlatform = False
if 'IPF' in self . ArchList :
IsIpfPlatform = True
2010-03-12 10:54:01 +00:00
for ModuleGuid in ModuleList :
Module = ModuleList [ ModuleGuid ]
2010-02-28 23:39:39 +00:00
GlobalData . gProcessingFile = " %s [ %s , %s , %s ]" % ( Module . MetaFile , Module . Arch , Module . ToolChain , Module . BuildTarget )
2013-08-23 02:18:16 +00:00
2010-02-28 23:39:39 +00:00
OutputImageFile = ''
for ResultFile in Module . CodaTargetList :
if str ( ResultFile . Target ) . endswith ( '.efi' ):
#
# module list for PEI, DXE, RUNTIME and SMM
#
OutputImageFile = os . path . join ( Module . OutputDir , Module . Name + '.efi' )
ImageClass = PeImageClass ( OutputImageFile )
if not ImageClass . IsValid :
EdkLogger . error ( "build" , FILE_PARSE_FAILURE , ExtraData = ImageClass . ErrorInfo )
2010-03-19 06:55:07 +00:00
ImageInfo = PeImageInfo ( Module . Name , Module . Guid , Module . Arch , Module . OutputDir , Module . DebugDir , ImageClass )
2015-12-01 04:22:16 +00:00
if Module . ModuleType in [ 'PEI_CORE' , 'PEIM' , 'COMBINED_PEIM_DRIVER' , 'PIC_PEIM' , 'RELOCATABLE_PEIM' , 'DXE_CORE' ]:
2010-02-28 23:39:39 +00:00
PeiModuleList [ Module . MetaFile ] = ImageInfo
PeiSize += ImageInfo . Image . Size
elif Module . ModuleType in [ 'BS_DRIVER' , 'DXE_DRIVER' , 'UEFI_DRIVER' ]:
BtModuleList [ Module . MetaFile ] = ImageInfo
BtSize += ImageInfo . Image . Size
elif Module . ModuleType in [ 'DXE_RUNTIME_DRIVER' , 'RT_DRIVER' , 'DXE_SAL_DRIVER' , 'SAL_RT_DRIVER' ]:
RtModuleList [ Module . MetaFile ] = ImageInfo
#IPF runtime driver needs to be at 2 page alignment.
if IsIpfPlatform and ImageInfo . Image . Size % 0x2000 != 0 :
ImageInfo . Image . Size = ( ImageInfo . Image . Size / 0x2000 + 1 ) * 0x2000
RtSize += ImageInfo . Image . Size
elif Module . ModuleType in [ 'SMM_CORE' , 'DXE_SMM_DRIVER' ]:
SmmModuleList [ Module . MetaFile ] = ImageInfo
SmmSize += ImageInfo . Image . Size
if Module . ModuleType == 'DXE_SMM_DRIVER' :
2011-05-11 10:26:49 +00:00
PiSpecVersion = '0x00000000'
if 'PI_SPECIFICATION_VERSION' in Module . Module . Specification :
PiSpecVersion = Module . Module . Specification [ 'PI_SPECIFICATION_VERSION' ]
2010-02-28 23:39:39 +00:00
# for PI specification < PI1.1, DXE_SMM_DRIVER also runs as BOOT time driver.
2011-05-11 10:26:49 +00:00
if int ( PiSpecVersion , 16 ) < 0x0001000A :
2010-02-28 23:39:39 +00:00
BtModuleList [ Module . MetaFile ] = ImageInfo
BtSize += ImageInfo . Image . Size
break
#
# EFI image is final target.
# Check EFI image contains patchable FixAddress related PCDs.
#
if OutputImageFile != '' :
ModuleIsPatch = False
for Pcd in Module . ModulePcdList :
if Pcd . Type == TAB_PCDS_PATCHABLE_IN_MODULE and Pcd . TokenCName in TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_LIST :
ModuleIsPatch = True
break
if not ModuleIsPatch :
for Pcd in Module . LibraryPcdList :
if Pcd . Type == TAB_PCDS_PATCHABLE_IN_MODULE and Pcd . TokenCName in TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_LIST :
ModuleIsPatch = True
break
2013-08-23 02:18:16 +00:00
2010-02-28 23:39:39 +00:00
if not ModuleIsPatch :
continue
#
# Module includes the patchable load fix address PCDs.
2013-08-23 02:18:16 +00:00
# It will be fixed up later.
2010-02-28 23:39:39 +00:00
#
PatchEfiImageList . append ( OutputImageFile )
2013-08-23 02:18:16 +00:00
2010-02-28 23:39:39 +00:00
#
# Get Top Memory address
#
ReservedRuntimeMemorySize = 0
TopMemoryAddress = 0
if self . LoadFixAddress == 0xFFFFFFFFFFFFFFFF :
TopMemoryAddress = 0
else :
TopMemoryAddress = self . LoadFixAddress
if TopMemoryAddress < RtSize + BtSize + PeiSize :
EdkLogger . error ( "build" , PARAMETER_INVALID , "FIX_LOAD_TOP_MEMORY_ADDRESS is too low to load driver" )
# Make IPF runtime driver at 2 page alignment.
if IsIpfPlatform :
ReservedRuntimeMemorySize = TopMemoryAddress % 0x2000
RtSize = RtSize + ReservedRuntimeMemorySize
#
# Patch FixAddress related PCDs into EFI image
#
2013-08-23 02:18:16 +00:00
for EfiImage in PatchEfiImageList :
2010-02-28 23:39:39 +00:00
EfiImageMap = EfiImage . replace ( '.efi' , '.map' )
if not os . path . exists ( EfiImageMap ):
continue
#
# Get PCD offset in EFI image by GenPatchPcdTable function
#
2013-08-23 02:18:16 +00:00
PcdTable = parsePcdInfoFromMapFile ( EfiImageMap , EfiImage )
2010-02-28 23:39:39 +00:00
#
# Patch real PCD value by PatchPcdValue tool
#
for PcdInfo in PcdTable :
ReturnValue = 0
if PcdInfo [ 0 ] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_PEI_PAGE_SIZE :
2015-12-01 04:22:16 +00:00
ReturnValue , ErrorInfo = PatchBinaryFile ( EfiImage , PcdInfo [ 1 ], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_PEI_PAGE_SIZE_DATA_TYPE , str ( PeiSize / 0x1000 ))
2010-02-28 23:39:39 +00:00
elif PcdInfo [ 0 ] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_DXE_PAGE_SIZE :
2015-12-01 04:22:16 +00:00
ReturnValue , ErrorInfo = PatchBinaryFile ( EfiImage , PcdInfo [ 1 ], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_DXE_PAGE_SIZE_DATA_TYPE , str ( BtSize / 0x1000 ))
2010-02-28 23:39:39 +00:00
elif PcdInfo [ 0 ] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_RUNTIME_PAGE_SIZE :
2015-12-01 04:22:16 +00:00
ReturnValue , ErrorInfo = PatchBinaryFile ( EfiImage , PcdInfo [ 1 ], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_RUNTIME_PAGE_SIZE_DATA_TYPE , str ( RtSize / 0x1000 ))
2010-02-28 23:39:39 +00:00
elif PcdInfo [ 0 ] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SMM_PAGE_SIZE and len ( SmmModuleList ) > 0 :
2015-12-01 04:22:16 +00:00
ReturnValue , ErrorInfo = PatchBinaryFile ( EfiImage , PcdInfo [ 1 ], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SMM_PAGE_SIZE_DATA_TYPE , str ( SmmSize / 0x1000 ))
2010-02-28 23:39:39 +00:00
if ReturnValue != 0 :
EdkLogger . error ( "build" , PARAMETER_INVALID , "Patch PCD value failed" , ExtraData = ErrorInfo )
2013-08-23 02:18:16 +00:00
2015-12-01 04:22:16 +00:00
MapBuffer . write ( 'PEI_CODE_PAGE_NUMBER = 0x %x \n ' % ( PeiSize / 0x1000 ))
MapBuffer . write ( 'BOOT_CODE_PAGE_NUMBER = 0x %x \n ' % ( BtSize / 0x1000 ))
MapBuffer . write ( 'RUNTIME_CODE_PAGE_NUMBER = 0x %x \n ' % ( RtSize / 0x1000 ))
2010-02-28 23:39:39 +00:00
if len ( SmmModuleList ) > 0 :
2015-12-01 04:22:16 +00:00
MapBuffer . write ( 'SMM_CODE_PAGE_NUMBER = 0x %x \n ' % ( SmmSize / 0x1000 ))
2013-08-23 02:18:16 +00:00
PeiBaseAddr = TopMemoryAddress - RtSize - BtSize
2010-02-28 23:39:39 +00:00
BtBaseAddr = TopMemoryAddress - RtSize
2013-08-23 02:18:16 +00:00
RtBaseAddr = TopMemoryAddress - ReservedRuntimeMemorySize
2010-02-28 23:39:39 +00:00
self . _RebaseModule ( MapBuffer , PeiBaseAddr , PeiModuleList , TopMemoryAddress == 0 )
self . _RebaseModule ( MapBuffer , BtBaseAddr , BtModuleList , TopMemoryAddress == 0 )
self . _RebaseModule ( MapBuffer , RtBaseAddr , RtModuleList , TopMemoryAddress == 0 )
2015-12-01 04:22:16 +00:00
self . _RebaseModule ( MapBuffer , 0x1000 , SmmModuleList , AddrIsOffset = False , ModeIsSmm = True )
2010-02-28 23:39:39 +00:00
MapBuffer . write ( ' \n\n ' )
2011-05-11 10:26:49 +00:00
sys . stdout . write ( " \n " )
sys . stdout . flush ()
2013-08-23 02:18:16 +00:00
2010-02-28 23:39:39 +00:00
## Save platform Map file
#
def _SaveMapFile ( self , MapBuffer , Wa ):
#
# Map file path is got.
#
MapFilePath = os . path . join ( Wa . BuildDir , Wa . Name + '.map' )
#
# Save address map into MAP file.
#
2010-05-18 05:04:32 +00:00
SaveFileOnChange ( MapFilePath , MapBuffer . getvalue (), False )
2011-05-11 10:26:49 +00:00
MapBuffer . close ()
if self . LoadFixAddress != 0 :
2015-12-01 04:22:16 +00:00
sys . stdout . write ( " \n Load Module At Fix Address Map file can be found at %s \n " % ( MapFilePath ))
2011-05-11 10:26:49 +00:00
sys . stdout . flush ()
2010-02-28 23:39:39 +00:00
## Build active platform for different build targets and different tool chains
#
def _BuildPlatform ( self ):
2016-03-31 14:05:59 +08:00
SaveFileOnChange ( self . PlatformBuildPath , '# DO NOT EDIT \n # FILE auto-generated \n ' , False )
2010-02-28 23:39:39 +00:00
for BuildTarget in self . BuildTargetList :
2011-10-29 06:59:30 +00:00
GlobalData . gGlobalDefines [ 'TARGET' ] = BuildTarget
2010-02-28 23:39:39 +00:00
for ToolChain in self . ToolChainList :
2011-10-29 06:59:30 +00:00
GlobalData . gGlobalDefines [ 'TOOLCHAIN' ] = ToolChain
GlobalData . gGlobalDefines [ 'TOOL_CHAIN_TAG' ] = ToolChain
2010-02-28 23:39:39 +00:00
Wa = WorkspaceAutoGen (
self . WorkspaceDir ,
2011-10-29 06:59:30 +00:00
self . PlatformFile ,
2010-02-28 23:39:39 +00:00
BuildTarget ,
ToolChain ,
self . ArchList ,
self . BuildDatabase ,
self . TargetTxt ,
self . ToolDef ,
self . Fdf ,
self . FdList ,
self . FvList ,
2011-08-26 07:46:26 +00:00
self . CapList ,
2010-03-19 06:55:07 +00:00
self . SkuId ,
2011-12-16 08:52:13 +00:00
self . UniFlag ,
self . Progress
2010-02-28 23:39:39 +00:00
)
2011-10-29 06:59:30 +00:00
self . Fdf = Wa . FdfFile
self . LoadFixAddress = Wa . Platform . LoadFixAddress
2010-02-28 23:39:39 +00:00
self . BuildReport . AddPlatformReport ( Wa )
self . Progress . Stop ( "done!" )
2014-08-18 04:59:01 +00:00
for Arch in Wa . ArchList :
GlobalData . gGlobalDefines [ 'ARCH' ] = Arch
Pa = PlatformAutoGen ( Wa , self . PlatformFile , BuildTarget , ToolChain , Arch )
2014-08-26 02:52:24 +00:00
for Module in Pa . Platform . Modules :
# Get ModuleAutoGen object to generate C code file and makefile
Ma = ModuleAutoGen ( Wa , Module , BuildTarget , ToolChain , Arch , self . PlatformFile )
if Ma == None :
continue
self . BuildModules . append ( Ma )
2014-08-18 04:59:01 +00:00
self . _BuildPa ( self . Target , Pa )
2013-08-23 02:18:16 +00:00
2010-02-28 23:39:39 +00:00
# Create MAP file when Load Fix Address is enabled.
2010-03-12 10:54:01 +00:00
if self . Target in [ "" , "all" , "fds" ]:
2011-10-29 06:59:30 +00:00
for Arch in Wa . ArchList :
GlobalData . gGlobalDefines [ 'ARCH' ] = Arch
2010-02-28 23:39:39 +00:00
#
# Check whether the set fix address is above 4G for 32bit image.
#
if ( Arch == 'IA32' or Arch == 'ARM' ) and self . LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self . LoadFixAddress >= 0x100000000 :
2011-10-29 06:59:30 +00:00
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" )
2010-02-28 23:39:39 +00:00
#
# Get Module List
#
2010-03-12 10:54:01 +00:00
ModuleList = {}
2010-02-28 23:39:39 +00:00
for Pa in Wa . AutoGenObjectList :
for Ma in Pa . ModuleAutoGenList :
if Ma == None :
continue
if not Ma . IsLibrary :
2010-03-12 10:54:01 +00:00
ModuleList [ Ma . Guid . upper ()] = Ma
2010-02-28 23:39:39 +00:00
MapBuffer = StringIO ( '' )
2010-03-12 10:54:01 +00:00
if self . LoadFixAddress != 0 :
#
# Rebase module to the preferred memory address before GenFds
#
self . _CollectModuleMapBuffer ( MapBuffer , ModuleList )
2011-10-29 06:59:30 +00:00
if self . Fdf :
2015-01-19 05:01:39 +00:00
#
# create FDS again for the updated EFI image
#
self . _Build ( "fds" , Wa )
2010-02-28 23:39:39 +00:00
#
# Create MAP file for all platform FVs after GenFds.
#
2010-03-12 10:54:01 +00:00
self . _CollectFvMapBuffer ( MapBuffer , Wa , ModuleList )
2010-02-28 23:39:39 +00:00
#
# Save MAP buffer into MAP file.
#
self . _SaveMapFile ( MapBuffer , Wa )
## Build active module for different build targets, different tool chains and different archs
#
def _BuildModule ( self ):
for BuildTarget in self . BuildTargetList :
2011-10-29 06:59:30 +00:00
GlobalData . gGlobalDefines [ 'TARGET' ] = BuildTarget
2010-02-28 23:39:39 +00:00
for ToolChain in self . ToolChainList :
2011-10-29 06:59:30 +00:00
GlobalData . gGlobalDefines [ 'TOOLCHAIN' ] = ToolChain
2013-08-23 02:18:16 +00:00
GlobalData . gGlobalDefines [ 'TOOL_CHAIN_TAG' ] = ToolChain
2010-02-28 23:39:39 +00:00
#
# module build needs platform build information, so get platform
# AutoGen first
#
Wa = WorkspaceAutoGen (
self . WorkspaceDir ,
2011-10-29 06:59:30 +00:00
self . PlatformFile ,
2010-02-28 23:39:39 +00:00
BuildTarget ,
ToolChain ,
self . ArchList ,
self . BuildDatabase ,
self . TargetTxt ,
self . ToolDef ,
self . Fdf ,
self . FdList ,
self . FvList ,
2011-08-26 07:46:26 +00:00
self . CapList ,
2010-03-19 06:55:07 +00:00
self . SkuId ,
2011-12-16 08:52:13 +00:00
self . UniFlag ,
self . Progress ,
self . ModuleFile
2010-02-28 23:39:39 +00:00
)
2011-10-29 06:59:30 +00:00
self . Fdf = Wa . FdfFile
self . LoadFixAddress = Wa . Platform . LoadFixAddress
2010-02-28 23:39:39 +00:00
Wa . CreateMakeFile ( False )
self . Progress . Stop ( "done!" )
MaList = []
2011-10-29 06:59:30 +00:00
for Arch in Wa . ArchList :
GlobalData . gGlobalDefines [ 'ARCH' ] = Arch
2010-02-28 23:39:39 +00:00
Ma = ModuleAutoGen ( Wa , self . ModuleFile , BuildTarget , ToolChain , Arch , self . PlatformFile )
if Ma == None : continue
MaList . append ( Ma )
2014-08-26 02:52:24 +00:00
self . BuildModules . append ( Ma )
2014-08-18 04:59:01 +00:00
if not Ma . IsBinaryModule :
self . _Build ( self . Target , Ma , BuildModule = True )
2010-03-04 05:29:52 +00:00
self . BuildReport . AddPlatformReport ( Wa , MaList )
2010-02-28 23:39:39 +00:00
if MaList == []:
EdkLogger . error (
'build' ,
BUILD_ERROR ,
"Module for [ %s ] is not a component of active platform." \
" Please make sure that the ARCH and inf file path are" \
2015-12-01 04:22:16 +00:00
" given in the same as in [ %s ]" % \
2011-10-29 06:59:30 +00:00
( ', ' . join ( Wa . ArchList ), self . PlatformFile ),
2010-02-28 23:39:39 +00:00
ExtraData = self . ModuleFile
)
# Create MAP file when Load Fix Address is enabled.
2011-10-29 06:59:30 +00:00
if self . Target == "fds" and self . Fdf :
for Arch in Wa . ArchList :
2010-02-28 23:39:39 +00:00
#
# Check whether the set fix address is above 4G for 32bit image.
#
if ( Arch == 'IA32' or Arch == 'ARM' ) and self . LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self . LoadFixAddress >= 0x100000000 :
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" )
#
# Get Module List
#
2010-03-12 10:54:01 +00:00
ModuleList = {}
2010-02-28 23:39:39 +00:00
for Pa in Wa . AutoGenObjectList :
for Ma in Pa . ModuleAutoGenList :
if Ma == None :
continue
if not Ma . IsLibrary :
2010-03-12 10:54:01 +00:00
ModuleList [ Ma . Guid . upper ()] = Ma
2010-02-28 23:39:39 +00:00
MapBuffer = StringIO ( '' )
2010-03-12 10:54:01 +00:00
if self . LoadFixAddress != 0 :
#
# Rebase module to the preferred memory address before GenFds
#
self . _CollectModuleMapBuffer ( MapBuffer , ModuleList )
2015-01-19 05:01:39 +00:00
#
# create FDS again for the updated EFI image
#
self . _Build ( "fds" , Wa )
2010-02-28 23:39:39 +00:00
#
# Create MAP file for all platform FVs after GenFds.
#
2010-03-12 10:54:01 +00:00
self . _CollectFvMapBuffer ( MapBuffer , Wa , ModuleList )
2010-02-28 23:39:39 +00:00
#
# Save MAP buffer into MAP file.
#
self . _SaveMapFile ( MapBuffer , Wa )
## Build a platform in multi-thread mode
#
def _MultiThreadBuildPlatform ( self ):
2016-03-31 14:05:59 +08:00
SaveFileOnChange ( self . PlatformBuildPath , '# DO NOT EDIT \n # FILE auto-generated \n ' , False )
2010-02-28 23:39:39 +00:00
for BuildTarget in self . BuildTargetList :
2011-10-29 06:59:30 +00:00
GlobalData . gGlobalDefines [ 'TARGET' ] = BuildTarget
2010-02-28 23:39:39 +00:00
for ToolChain in self . ToolChainList :
2011-10-29 06:59:30 +00:00
GlobalData . gGlobalDefines [ 'TOOLCHAIN' ] = ToolChain
2013-08-23 02:18:16 +00:00
GlobalData . gGlobalDefines [ 'TOOL_CHAIN_TAG' ] = ToolChain
2010-02-28 23:39:39 +00:00
Wa = WorkspaceAutoGen (
self . WorkspaceDir ,
2011-10-29 06:59:30 +00:00
self . PlatformFile ,
2010-02-28 23:39:39 +00:00
BuildTarget ,
ToolChain ,
self . ArchList ,
self . BuildDatabase ,
self . TargetTxt ,
self . ToolDef ,
self . Fdf ,
self . FdList ,
self . FvList ,
2011-08-26 07:46:26 +00:00
self . CapList ,
2010-03-19 06:55:07 +00:00
self . SkuId ,
2011-12-16 08:52:13 +00:00
self . UniFlag ,
self . Progress
2010-02-28 23:39:39 +00:00
)
2011-10-29 06:59:30 +00:00
self . Fdf = Wa . FdfFile
self . LoadFixAddress = Wa . Platform . LoadFixAddress
2010-02-28 23:39:39 +00:00
self . BuildReport . AddPlatformReport ( Wa )
Wa . CreateMakeFile ( False )
# multi-thread exit flag
ExitFlag = threading . Event ()
ExitFlag . clear ()
2011-10-29 06:59:30 +00:00
for Arch in Wa . ArchList :
GlobalData . gGlobalDefines [ 'ARCH' ] = Arch
2010-02-28 23:39:39 +00:00
Pa = PlatformAutoGen ( Wa , self . PlatformFile , BuildTarget , ToolChain , Arch )
if Pa == None :
continue
2014-08-26 02:52:24 +00:00
ModuleList = []
for Inf in Pa . Platform . Modules :
ModuleList . append ( Inf )
# Add the INF only list in FDF
if GlobalData . gFdfParser != None :
for InfName in GlobalData . gFdfParser . Profile . InfList :
Inf = PathClass ( NormPath ( InfName ), self . WorkspaceDir , Arch )
if Inf in Pa . Platform . Modules :
continue
ModuleList . append ( Inf )
for Module in ModuleList :
2010-02-28 23:39:39 +00:00
# Get ModuleAutoGen object to generate C code file and makefile
Ma = ModuleAutoGen ( Wa , Module , BuildTarget , ToolChain , Arch , self . PlatformFile )
2014-08-26 02:52:24 +00:00
2010-02-28 23:39:39 +00:00
if Ma == None :
continue
# Not to auto-gen for targets 'clean', 'cleanlib', 'cleanall', 'run', 'fds'
if self . Target not in [ 'clean' , 'cleanlib' , 'cleanall' , 'run' , 'fds' ]:
# for target which must generate AutoGen code and makefile
if not self . SkipAutoGen or self . Target == 'genc' :
Ma . CreateCodeFile ( True )
if self . Target == "genc" :
continue
if not self . SkipAutoGen or self . Target == 'genmake' :
Ma . CreateMakeFile ( True )
if self . Target == "genmake" :
continue
2014-08-26 02:52:24 +00:00
self . BuildModules . append ( Ma )
2013-11-18 07:41:21 +00:00
self . Progress . Stop ( "done!" )
2013-08-23 02:18:16 +00:00
2014-08-26 02:52:24 +00:00
for Ma in self . BuildModules :
2010-02-28 23:39:39 +00:00
# Generate build task for the module
2014-08-26 02:52:24 +00:00
if not Ma . IsBinaryModule :
Bt = BuildTask . New ( ModuleMakeUnit ( Ma , self . Target ))
2010-02-28 23:39:39 +00:00
# Break build if any build thread has error
if BuildTask . HasError ():
# we need a full version of makefile for platform
ExitFlag . set ()
BuildTask . WaitForComplete ()
Pa . CreateMakeFile ( False )
EdkLogger . error ( "build" , BUILD_ERROR , "Failed to build module" , ExtraData = GlobalData . gBuildingModule )
# Start task scheduler
if not BuildTask . IsOnGoing ():
BuildTask . StartScheduler ( self . ThreadNumber , ExitFlag )
# in case there's an interruption. we need a full version of makefile for platform
Pa . CreateMakeFile ( False )
if BuildTask . HasError ():
EdkLogger . error ( "build" , BUILD_ERROR , "Failed to build module" , ExtraData = GlobalData . gBuildingModule )
2012-04-10 07:18:20 +00:00
#
# Save temp tables to a TmpTableDict.
#
for Key in Wa . BuildDatabase . _CACHE_ :
if Wa . BuildDatabase . _CACHE_ [ Key ] . _RawData and Wa . BuildDatabase . _CACHE_ [ Key ] . _RawData . _Table and Wa . BuildDatabase . _CACHE_ [ Key ] . _RawData . _Table . Table :
if TemporaryTablePattern . match ( Wa . BuildDatabase . _CACHE_ [ Key ] . _RawData . _Table . Table ):
TmpTableDict [ Wa . BuildDatabase . _CACHE_ [ Key ] . _RawData . _Table . Table ] = Wa . BuildDatabase . _CACHE_ [ Key ] . _RawData . _Table . Cur
#
2010-02-28 23:39:39 +00:00
#
# All modules have been put in build tasks queue. Tell task scheduler
# to exit if all tasks are completed
#
ExitFlag . set ()
BuildTask . WaitForComplete ()
2014-08-26 02:52:24 +00:00
self . CreateAsBuiltInf ()
2010-02-28 23:39:39 +00:00
#
# Check for build error, and raise exception if one
# has been signaled.
#
if BuildTask . HasError ():
EdkLogger . error ( "build" , BUILD_ERROR , "Failed to build module" , ExtraData = GlobalData . gBuildingModule )
# Create MAP file when Load Fix Address is enabled.
2010-03-12 10:54:01 +00:00
if self . Target in [ "" , "all" , "fds" ]:
2011-10-29 06:59:30 +00:00
for Arch in Wa . ArchList :
2010-02-28 23:39:39 +00:00
#
# Check whether the set fix address is above 4G for 32bit image.
#
if ( Arch == 'IA32' or Arch == 'ARM' ) and self . LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self . LoadFixAddress >= 0x100000000 :
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" )
#
# Get Module List
#
2010-03-12 10:54:01 +00:00
ModuleList = {}
2010-02-28 23:39:39 +00:00
for Pa in Wa . AutoGenObjectList :
for Ma in Pa . ModuleAutoGenList :
if Ma == None :
continue
if not Ma . IsLibrary :
2010-03-12 10:54:01 +00:00
ModuleList [ Ma . Guid . upper ()] = Ma
2010-02-28 23:39:39 +00:00
#
# Rebase module to the preferred memory address before GenFds
#
MapBuffer = StringIO ( '' )
2010-03-12 10:54:01 +00:00
if self . LoadFixAddress != 0 :
self . _CollectModuleMapBuffer ( MapBuffer , ModuleList )
2010-02-28 23:39:39 +00:00
2011-10-29 06:59:30 +00:00
if self . Fdf :
2010-03-19 06:55:07 +00:00
#
# Generate FD image if there's a FDF file found
#
2014-08-18 04:59:01 +00:00
LaunchCommand ( Wa . GenFdsCommand , os . getcwd ())
2010-02-28 23:39:39 +00:00
#
# Create MAP file for all platform FVs after GenFds.
#
2010-03-12 10:54:01 +00:00
self . _CollectFvMapBuffer ( MapBuffer , Wa , ModuleList )
2010-02-28 23:39:39 +00:00
#
# Save MAP buffer into MAP file.
#
self . _SaveMapFile ( MapBuffer , Wa )
## Generate GuidedSectionTools.txt in the FV directories.
#
def CreateGuidedSectionToolsFile ( self ):
2011-10-29 06:59:30 +00:00
for BuildTarget in self . BuildTargetList :
for ToolChain in self . ToolChainList :
Wa = WorkspaceAutoGen (
self . WorkspaceDir ,
self . PlatformFile ,
BuildTarget ,
ToolChain ,
self . ArchList ,
self . BuildDatabase ,
self . TargetTxt ,
self . ToolDef ,
self . Fdf ,
self . FdList ,
self . FvList ,
self . CapList ,
self . SkuId ,
self . UniFlag
)
FvDir = Wa . FvDir
if not os . path . exists ( FvDir ):
continue
2013-08-23 02:18:16 +00:00
for Arch in self . ArchList :
2010-02-28 23:39:39 +00:00
# Build up the list of supported architectures for this build
prefix = ' %s _ %s _ %s _' % ( BuildTarget , ToolChain , Arch )
2013-08-23 02:18:16 +00:00
2010-02-28 23:39:39 +00:00
# Look through the tool definitions for GUIDed tools
guidAttribs = []
for ( attrib , value ) in self . ToolDef . ToolsDefTxtDictionary . iteritems ():
if attrib . upper () . endswith ( '_GUID' ):
split = attrib . split ( '_' )
thisPrefix = '_' . join ( split [ 0 : 3 ]) + '_'
if thisPrefix == prefix :
guid = self . ToolDef . ToolsDefTxtDictionary [ attrib ]
guid = guid . lower ()
toolName = split [ 3 ]
path = '_' . join ( split [ 0 : 4 ]) + '_PATH'
path = self . ToolDef . ToolsDefTxtDictionary [ path ]
path = self . GetFullPathOfTool ( path )
guidAttribs . append (( guid , toolName , path ))
2013-08-23 02:18:16 +00:00
2010-02-28 23:39:39 +00:00
# Write out GuidedSecTools.txt
toolsFile = os . path . join ( FvDir , 'GuidedSectionTools.txt' )
toolsFile = open ( toolsFile , 'wt' )
for guidedSectionTool in guidAttribs :
print >> toolsFile , ' ' . join ( guidedSectionTool )
toolsFile . close ()
## Returns the full path of the tool.
#
def GetFullPathOfTool ( self , tool ):
if os . path . exists ( tool ):
return os . path . realpath ( tool )
else :
# We need to search for the tool using the
# PATH environment variable.
for dirInPath in os . environ [ 'PATH' ] . split ( os . pathsep ):
foundPath = os . path . join ( dirInPath , tool )
if os . path . exists ( foundPath ):
return os . path . realpath ( foundPath )
# If the tool was not found in the path then we just return
# the input tool.
return tool
## Launch the module or platform build
#
def Launch ( self ):
2011-10-29 06:59:30 +00:00
if not self . ModuleFile :
2010-02-28 23:39:39 +00:00
if not self . SpawnMode or self . Target not in [ "" , "all" ]:
self . SpawnMode = False
self . _BuildPlatform ()
else :
self . _MultiThreadBuildPlatform ()
self . CreateGuidedSectionToolsFile ()
else :
self . SpawnMode = False
self . _BuildModule ()
2014-11-12 08:26:03 +00:00
if self . Target == 'cleanall' :
self . Db . Close ()
RemoveDirectory ( os . path . dirname ( GlobalData . gDatabasePath ), True )
2014-08-26 02:52:24 +00:00
def CreateAsBuiltInf ( self ):
for Module in self . BuildModules :
Module . CreateAsBuiltInf ()
self . BuildModules = []
2010-02-28 23:39:39 +00:00
## Do some clean-up works when error occurred
def Relinquish ( self ):
OldLogLevel = EdkLogger . GetLevel ()
EdkLogger . SetLevel ( EdkLogger . ERROR )
#self.DumpBuildData()
Utils . Progressor . Abort ()
if self . SpawnMode == True :
BuildTask . Abort ()
EdkLogger . SetLevel ( OldLogLevel )
def DumpBuildData ( self ):
2014-08-28 13:53:34 +00:00
CacheDirectory = os . path . dirname ( GlobalData . gDatabasePath )
2010-02-28 23:39:39 +00:00
Utils . CreateDirectory ( CacheDirectory )
Utils . DataDump ( Utils . gFileTimeStampCache , os . path . join ( CacheDirectory , "gFileTimeStampCache" ))
Utils . DataDump ( Utils . gDependencyDatabase , os . path . join ( CacheDirectory , "gDependencyDatabase" ))
def RestoreBuildData ( self ):
2014-08-28 13:53:34 +00:00
FilePath = os . path . join ( os . path . dirname ( GlobalData . gDatabasePath ), "gFileTimeStampCache" )
2010-02-28 23:39:39 +00:00
if Utils . gFileTimeStampCache == {} and os . path . isfile ( FilePath ):
Utils . gFileTimeStampCache = Utils . DataRestore ( FilePath )
if Utils . gFileTimeStampCache == None :
Utils . gFileTimeStampCache = {}
2014-08-28 13:53:34 +00:00
FilePath = os . path . join ( os . path . dirname ( GlobalData . gDatabasePath ), "gDependencyDatabase" )
2010-02-28 23:39:39 +00:00
if Utils . gDependencyDatabase == {} and os . path . isfile ( FilePath ):
Utils . gDependencyDatabase = Utils . DataRestore ( FilePath )
if Utils . gDependencyDatabase == None :
Utils . gDependencyDatabase = {}
def ParseDefines ( DefineList = []):
DefineDict = {}
if DefineList != None :
for Define in DefineList :
DefineTokenList = Define . split ( "=" , 1 )
2011-10-29 06:59:30 +00:00
if not GlobalData . gMacroNamePattern . match ( DefineTokenList [ 0 ]):
EdkLogger . error ( 'build' , FORMAT_INVALID ,
"The macro name must be in the pattern [A-Z][A-Z0-9_]*" ,
ExtraData = DefineTokenList [ 0 ])
2013-08-23 02:18:16 +00:00
2010-02-28 23:39:39 +00:00
if len ( DefineTokenList ) == 1 :
2011-10-29 06:59:30 +00:00
DefineDict [ DefineTokenList [ 0 ]] = "TRUE"
2010-02-28 23:39:39 +00:00
else :
DefineDict [ DefineTokenList [ 0 ]] = DefineTokenList [ 1 ] . strip ()
return DefineDict
gParamCheck = []
def SingleCheckCallback ( option , opt_str , value , parser ):
if option not in gParamCheck :
setattr ( parser . values , option . dest , value )
gParamCheck . append ( option )
else :
parser . error ( "Option %s only allows one instance in command line!" % option )
## Parse command line options
#
# Using standard Python module optparse to parse command line option of this tool.
#
# @retval Opt A optparse.Values object containing the parsed options
# @retval Args Target of build command
#
def MyOptionParser ():
2015-12-01 04:22:16 +00:00
Parser = OptionParser ( description = __copyright__ , version = __version__ , prog = "build.exe" , usage = "%prog [options] [all|fds|genc|genmake|clean|cleanall|cleanlib|modules|libraries|run]" )
Parser . add_option ( "-a" , "--arch" , action = "append" , type = "choice" , choices = [ 'IA32' , 'X64' , 'IPF' , 'EBC' , 'ARM' , 'AARCH64' ], dest = "TargetArch" ,
2013-08-23 02:18:16 +00:00
help = "ARCHS is one of list: IA32, X64, IPF, ARM, AARCH64 or EBC, which overrides target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option." )
2010-02-28 23:39:39 +00:00
Parser . add_option ( "-p" , "--platform" , action = "callback" , type = "string" , dest = "PlatformFile" , callback = SingleCheckCallback ,
help = "Build the platform specified by the DSC file name argument, overriding target.txt's ACTIVE_PLATFORM definition." )
Parser . add_option ( "-m" , "--module" , action = "callback" , type = "string" , dest = "ModuleFile" , callback = SingleCheckCallback ,
help = "Build the module specified by the INF file name argument." )
2012-04-10 07:18:20 +00:00
Parser . add_option ( "-b" , "--buildtarget" , type = "string" , dest = "BuildTarget" , help = "Using the TARGET to build the platform, overriding target.txt's TARGET definition." ,
action = "append" )
2010-02-28 23:39:39 +00:00
Parser . add_option ( "-t" , "--tagname" , action = "append" , type = "string" , dest = "ToolChain" ,
help = "Using the Tool Chain Tagname to build the platform, overriding target.txt's TOOL_CHAIN_TAG definition." )
Parser . add_option ( "-x" , "--sku-id" , action = "callback" , type = "string" , dest = "SkuId" , callback = SingleCheckCallback ,
help = "Using this name of SKU ID to build the platform, overriding SKUID_IDENTIFIER in DSC file." )
Parser . add_option ( "-n" , action = "callback" , type = "int" , dest = "ThreadNumber" , callback = SingleCheckCallback ,
help = "Build the platform using multi-threaded compiler. The value overrides target.txt's MAX_CONCURRENT_THREAD_NUMBER. Less than 2 will disable multi-thread builds." )
Parser . add_option ( "-f" , "--fdf" , action = "callback" , type = "string" , dest = "FdfFile" , callback = SingleCheckCallback ,
help = "The name of the FDF file to use, which overrides the setting in the DSC file." )
Parser . add_option ( "-r" , "--rom-image" , action = "append" , type = "string" , dest = "RomImage" , default = [],
help = "The name of FD to be generated. The name must be from [FD] section in FDF file." )
Parser . add_option ( "-i" , "--fv-image" , action = "append" , type = "string" , dest = "FvImage" , default = [],
help = "The name of FV to be generated. The name must be from [FV] section in FDF file." )
2011-08-26 07:46:26 +00:00
Parser . add_option ( "-C" , "--capsule-image" , action = "append" , type = "string" , dest = "CapName" , default = [],
help = "The name of Capsule to be generated. The name must be from [Capsule] section in FDF file." )
2010-02-28 23:39:39 +00:00
Parser . add_option ( "-u" , "--skip-autogen" , action = "store_true" , dest = "SkipAutoGen" , help = "Skip AutoGen step." )
Parser . add_option ( "-e" , "--re-parse" , action = "store_true" , dest = "Reparse" , help = "Re-parse all meta-data files." )
2011-10-29 06:59:30 +00:00
Parser . add_option ( "-c" , "--case-insensitive" , action = "store_true" , dest = "CaseInsensitive" , default = False , help = "Don't check case of file name." )
2010-02-28 23:39:39 +00:00
Parser . add_option ( "-w" , "--warning-as-error" , action = "store_true" , dest = "WarningAsError" , help = "Treat warning in tools as error." )
Parser . add_option ( "-j" , "--log" , action = "store" , dest = "LogFile" , help = "Put log in specified file as well as on console." )
Parser . add_option ( "-s" , "--silent" , action = "store_true" , type = None , dest = "SilentMode" ,
help = "Make use of silent mode of (n)make." )
Parser . add_option ( "-q" , "--quiet" , action = "store_true" , type = None , help = "Disable all messages except FATAL ERRORS." )
Parser . add_option ( "-v" , "--verbose" , action = "store_true" , type = None , help = "Turn on verbose output with informational messages printed, " \
"including library instances selected, final dependency expression, " \
"and warning messages, etc." )
Parser . add_option ( "-d" , "--debug" , action = "store" , type = "int" , help = "Enable debug messages at specified level." )
Parser . add_option ( "-D" , "--define" , action = "append" , type = "string" , dest = "Macros" , help = "Macro: \" Name [= Value] \" ." )
Parser . add_option ( "-y" , "--report-file" , action = "store" , dest = "ReportFile" , help = "Create/overwrite the report to the specified filename." )
2016-04-07 13:57:14 +08:00
Parser . add_option ( "-Y" , "--report-type" , action = "append" , type = "choice" , choices = [ 'PCD' , 'LIBRARY' , 'FLASH' , 'DEPEX' , 'BUILD_FLAGS' , 'FIXED_ADDRESS' , 'HASH' , 'EXECUTION_ORDER' ], dest = "ReportType" , default = [],
help = "Flags that control the type of build report to generate. Must be one of: [PCD, LIBRARY, FLASH, DEPEX, BUILD_FLAGS, FIXED_ADDRESS, HASH, EXECUTION_ORDER]. " \
2010-02-28 23:39:39 +00:00
"To specify more than one flag, repeat this option on the command line and the default flag set is [PCD, LIBRARY, FLASH, DEPEX, BUILD_FLAGS, FIXED_ADDRESS]" )
2010-03-19 06:55:07 +00:00
Parser . add_option ( "-F" , "--flag" , action = "store" , type = "string" , dest = "Flag" ,
help = "Specify the specific option to parse EDK UNI file. Must be one of: [-c, -s]. -c is for EDK framework UNI file, and -s is for EDK UEFI UNI file. " \
"This option can also be specified by setting *_*_*_BUILD_FLAGS in [BuildOptions] section of platform DSC. If they are both specified, this value " \
"will override the setting in [BuildOptions] section of platform DSC." )
2011-10-29 06:59:30 +00:00
Parser . add_option ( "-N" , "--no-cache" , action = "store_true" , dest = "DisableCache" , default = False , help = "Disable build cache mechanism" )
2014-08-28 13:53:34 +00:00
Parser . add_option ( "--conf" , action = "store" , type = "string" , dest = "ConfDirectory" , help = "Specify the customized Conf directory." )
Parser . add_option ( "--check-usage" , action = "store_true" , dest = "CheckUsage" , default = False , help = "Check usage content of entries listed in INF file." )
2014-08-26 07:14:38 +00:00
Parser . add_option ( "--ignore-sources" , action = "store_true" , dest = "IgnoreSources" , default = False , help = "Focus to a binary build and ignore all source files" )
2016-04-05 12:29:32 +08:00
Parser . add_option ( "--pcd" , action = "append" , dest = "OptionPcd" , help = "Set PCD value by command line. Format: \" PcdName=Value \" " )
2016-03-16 11:06:44 +08:00
Parser . add_option ( "-l" , "--cmd-len" , action = "store" , type = "int" , dest = "CommandLength" , help = "Specify the maximum line length of build command. Default is 4096." )
2010-02-28 23:39:39 +00:00
2015-12-01 04:22:16 +00:00
( Opt , Args ) = Parser . parse_args ()
2010-02-28 23:39:39 +00:00
return ( Opt , Args )
## Tool entrance method
#
# This method mainly dispatch specific methods per the command line options.
# If no error found, return zero value so the caller of this tool can know
# if it's executed successfully or not.
#
# @retval 0 Tool was successful
# @retval 1 Tool failed
#
def Main ():
StartTime = time . time ()
# Initialize log system
EdkLogger . Initialize ()
2016-03-31 14:05:59 +08:00
GlobalData . gCommand = sys . argv [ 1 :]
2010-02-28 23:39:39 +00:00
#
# Parse the options and args
#
( Option , Target ) = MyOptionParser ()
GlobalData . gOptions = Option
GlobalData . gCaseInsensitive = Option . CaseInsensitive
# Set log level
if Option . verbose != None :
EdkLogger . SetLevel ( EdkLogger . VERBOSE )
elif Option . quiet != None :
EdkLogger . SetLevel ( EdkLogger . QUIET )
elif Option . debug != None :
EdkLogger . SetLevel ( Option . debug + 1 )
else :
EdkLogger . SetLevel ( EdkLogger . INFO )
if Option . LogFile != None :
EdkLogger . SetLogFile ( Option . LogFile )
if Option . WarningAsError == True :
EdkLogger . SetWarningAsError ()
if platform . platform () . find ( "Windows" ) >= 0 :
GlobalData . gIsWindows = True
else :
GlobalData . gIsWindows = False
2010-11-15 02:51:34 +00:00
EdkLogger . quiet ( "Build environment: %s " % platform . platform ())
EdkLogger . quiet ( time . strftime ( "Build start time: %H:%M:%S, %b. %d %Y \n " , time . localtime ()));
2010-02-28 23:39:39 +00:00
ReturnCode = 0
MyBuild = None
2015-06-23 06:49:25 +00:00
BuildError = True
2010-02-28 23:39:39 +00:00
try :
if len ( Target ) == 0 :
Target = "all"
elif len ( Target ) >= 2 :
EdkLogger . error ( "build" , OPTION_NOT_SUPPORTED , "More than one targets are not supported." ,
2015-12-01 04:22:16 +00:00
ExtraData = "Please select one of: %s " % ( ' ' . join ( gSupportedTarget )))
2010-02-28 23:39:39 +00:00
else :
Target = Target [ 0 ] . lower ()
if Target not in gSupportedTarget :
EdkLogger . error ( "build" , OPTION_NOT_SUPPORTED , "Not supported target [ %s ]." % Target ,
2015-12-01 04:22:16 +00:00
ExtraData = "Please select one of: %s " % ( ' ' . join ( gSupportedTarget )))
2010-02-28 23:39:39 +00:00
#
# Check environment variable: EDK_TOOLS_PATH, WORKSPACE, PATH
#
CheckEnvVariable ()
2011-10-29 06:59:30 +00:00
GlobalData . gCommandLineDefines . update ( ParseDefines ( Option . Macros ))
2010-02-28 23:39:39 +00:00
Workspace = os . getenv ( "WORKSPACE" )
#
# Get files real name in workspace dir
#
GlobalData . gAllFiles = Utils . DirCache ( Workspace )
WorkingDirectory = os . getcwd ()
if not Option . ModuleFile :
FileList = glob . glob ( os . path . normpath ( os . path . join ( WorkingDirectory , '*.inf' )))
FileNum = len ( FileList )
if FileNum >= 2 :
EdkLogger . error ( "build" , OPTION_NOT_SUPPORTED , "There are %d INF files in %s ." % ( FileNum , WorkingDirectory ),
ExtraData = "Please use '-m <INF_FILE_PATH>' switch to choose one." )
elif FileNum == 1 :
Option . ModuleFile = NormFile ( FileList [ 0 ], Workspace )
if Option . ModuleFile :
if os . path . isabs ( Option . ModuleFile ):
if os . path . normcase ( os . path . normpath ( Option . ModuleFile )) . find ( Workspace ) == 0 :
Option . ModuleFile = NormFile ( os . path . normpath ( Option . ModuleFile ), Workspace )
Option . ModuleFile = PathClass ( Option . ModuleFile , Workspace )
ErrorCode , ErrorInfo = Option . ModuleFile . Validate ( ".inf" , False )
if ErrorCode != 0 :
EdkLogger . error ( "build" , ErrorCode , ExtraData = ErrorInfo )
if Option . PlatformFile != None :
if os . path . isabs ( Option . PlatformFile ):
if os . path . normcase ( os . path . normpath ( Option . PlatformFile )) . find ( Workspace ) == 0 :
Option . PlatformFile = NormFile ( os . path . normpath ( Option . PlatformFile ), Workspace )
Option . PlatformFile = PathClass ( Option . PlatformFile , Workspace )
if Option . FdfFile != None :
if os . path . isabs ( Option . FdfFile ):
if os . path . normcase ( os . path . normpath ( Option . FdfFile )) . find ( Workspace ) == 0 :
Option . FdfFile = NormFile ( os . path . normpath ( Option . FdfFile ), Workspace )
Option . FdfFile = PathClass ( Option . FdfFile , Workspace )
ErrorCode , ErrorInfo = Option . FdfFile . Validate ( ".fdf" , False )
if ErrorCode != 0 :
EdkLogger . error ( "build" , ErrorCode , ExtraData = ErrorInfo )
2010-03-19 06:55:07 +00:00
if Option . Flag != None and Option . Flag not in [ '-c' , '-s' ]:
EdkLogger . error ( "build" , OPTION_VALUE_INVALID , "UNI flag must be one of -c or -s" )
2011-10-29 06:59:30 +00:00
MyBuild = Build ( Target , Workspace , Option )
2012-04-10 07:18:20 +00:00
GlobalData . gCommandLineDefines [ 'ARCH' ] = ' ' . join ( MyBuild . ArchList )
2016-03-31 14:05:59 +08:00
if not ( MyBuild . LaunchPrebuildFlag and os . path . exists ( MyBuild . PlatformBuildPath )):
MyBuild . Launch ()
2012-04-10 07:18:20 +00:00
# Drop temp tables to avoid database locked.
for TmpTableName in TmpTableDict :
SqlCommand = """drop table IF EXISTS %s """ % TmpTableName
TmpTableDict [ TmpTableName ] . execute ( SqlCommand )
2010-02-28 23:39:39 +00:00
#MyBuild.DumpBuildData()
2015-06-23 06:49:25 +00:00
#
# All job done, no error found and no exception raised
#
BuildError = False
2010-02-28 23:39:39 +00:00
except FatalError , X :
if MyBuild != None :
# for multi-thread build exits safely
MyBuild . Relinquish ()
if Option != None and Option . debug != None :
EdkLogger . quiet ( "(Python %s on %s ) " % ( platform . python_version (), sys . platform ) + traceback . format_exc ())
ReturnCode = X . args [ 0 ]
except Warning , X :
# error from Fdf parser
if MyBuild != None :
# for multi-thread build exits safely
MyBuild . Relinquish ()
if Option != None and Option . debug != None :
EdkLogger . quiet ( "(Python %s on %s ) " % ( platform . python_version (), sys . platform ) + traceback . format_exc ())
else :
2015-12-01 04:22:16 +00:00
EdkLogger . error ( X . ToolName , FORMAT_INVALID , File = X . FileName , Line = X . LineNumber , ExtraData = X . Message , RaiseError = False )
2010-02-28 23:39:39 +00:00
ReturnCode = FORMAT_INVALID
except KeyboardInterrupt :
ReturnCode = ABORT_ERROR
if Option != None and Option . debug != None :
EdkLogger . quiet ( "(Python %s on %s ) " % ( platform . python_version (), sys . platform ) + traceback . format_exc ())
except :
if MyBuild != None :
# for multi-thread build exits safely
MyBuild . Relinquish ()
# try to get the meta-file from the object causing exception
Tb = sys . exc_info ()[ - 1 ]
MetaFile = GlobalData . gProcessingFile
while Tb != None :
if 'self' in Tb . tb_frame . f_locals and hasattr ( Tb . tb_frame . f_locals [ 'self' ], 'MetaFile' ):
MetaFile = Tb . tb_frame . f_locals [ 'self' ] . MetaFile
Tb = Tb . tb_next
EdkLogger . error (
" \n build" ,
CODE_ERROR ,
"Unknown fatal error when processing [ %s ]" % MetaFile ,
2016-02-29 10:32:07 +08:00
ExtraData = " \n (Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!) \n " ,
2010-02-28 23:39:39 +00:00
RaiseError = False
)
2011-12-07 06:19:28 +00:00
EdkLogger . quiet ( "(Python %s on %s ) " % ( platform . python_version (), sys . platform ) + traceback . format_exc ())
2010-02-28 23:39:39 +00:00
ReturnCode = CODE_ERROR
finally :
Utils . Progressor . Abort ()
2014-08-28 13:53:34 +00:00
Utils . ClearDuplicatedInf ()
2010-02-28 23:39:39 +00:00
if ReturnCode == 0 :
2016-03-31 14:05:59 +08:00
try :
MyBuild . LanuchPostbuild ()
Conclusion = "Done"
except :
Conclusion = "Failed"
2010-02-28 23:39:39 +00:00
elif ReturnCode == ABORT_ERROR :
Conclusion = "Aborted"
else :
Conclusion = "Failed"
FinishTime = time . time ()
2011-08-26 07:46:26 +00:00
BuildDuration = time . gmtime ( int ( round ( FinishTime - StartTime )))
BuildDurationStr = ""
if BuildDuration . tm_yday > 1 :
2015-12-01 04:22:16 +00:00
BuildDurationStr = time . strftime ( "%H:%M:%S" , BuildDuration ) + ", %d day(s)" % ( BuildDuration . tm_yday - 1 )
2011-08-26 07:46:26 +00:00
else :
BuildDurationStr = time . strftime ( "%H:%M:%S" , BuildDuration )
2010-02-28 23:39:39 +00:00
if MyBuild != None :
2015-06-23 06:49:25 +00:00
if not BuildError :
MyBuild . BuildReport . GenerateReport ( BuildDurationStr )
2010-02-28 23:39:39 +00:00
MyBuild . Db . Close ()
EdkLogger . SetLevel ( EdkLogger . QUIET )
2010-11-15 02:51:34 +00:00
EdkLogger . quiet ( " \n - %s -" % Conclusion )
EdkLogger . quiet ( time . strftime ( "Build end time: %H:%M:%S, %b. %d %Y" , time . localtime ()))
2011-08-26 07:46:26 +00:00
EdkLogger . quiet ( "Build total time: %s \n " % BuildDurationStr )
2010-02-28 23:39:39 +00:00
return ReturnCode
if __name__ == '__main__' :
r = Main ()
## 0-127 is a safe return range, and 1 is a standard default error
if r < 0 or r > 127 : r = 1
sys . exit ( r )