## @file
# build a platform or a module
#
# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# 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
#
# 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
#
import os
import re
import StringIO
import sys
import glob
import time
import platform
import traceback
from struct import *
from threading import *
from subprocess import *
from Common.TargetTxtClassObject import *
from Common.ToolDefClassObject import *
from Common.BuildToolError import *
from Workspace.WorkspaceDatabase import *
from GenPatchPcdTable.GenPatchPcdTable import *
from PatchPcdValue.PatchPcdValue import *
# Version and Copyright
## standard targets of build command
gSupportedTarget = ['all', 'genc', 'genmake', 'modules', 'libraries', 'fds', 'clean', 'cleanall', 'cleanlib', 'run']
## build configuration file
TmpTableDict = {}
## 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
#
else:
extns = ('',)
return True
return False
## Check environment variables
#
# Check environment variables that must be set for build. Currently they are
#
# 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
ExtraData="WORKSPACE")
elif ' ' in WorkspaceDir:
#
# Check EFI_SOURCE (Edk build convention). EDK_SOURCE will always point to ECP
#
#
# Unify case of characters on case-insensitive systems
#
elif ' ' in EcpSourceDir:
if EdkSourceDir == EcpSourceDir:
else:
elif ' ' in EdkSourceDir:
if EfiSourceDir == EcpSourceDir:
else:
elif ' ' in EfiSourceDir:
# change absolute path to relative path to WORKSPACE
# check EDK_TOOLS_PATH
ExtraData="EDK_TOOLS_PATH")
# check PATH
ExtraData="PATH")
## 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
#
# check if the path is absolute or relative
else:
# check if the file path exists or not
EdkLogger.error("build", FILE_NOT_FOUND, ExtraData="\t%s (Please give file in absolute path or relative to WORKSPACE)" % FileFullPath)
# remove workspace directory from the beginning part of the file path
else:
## Get the output of an external program
#
# This is the entrance method of thread reading output of an external program and
#
# @param From The stream message read from
# @param To The stream message put on
# @param ExitFlag The flag used to indicate stopping reading
#
while True:
# read one line a time
# empty string means "end"
else:
break
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
#
# if working directory doesn't exist, Popen() will raise an exception
Proc = None
EndOfProcedure = None
try:
# launch the command
# launch two threads to read the STDOUT and STDERR
EndOfProcedure = Event()
# waiting for program exit
except: # in case of aborting
# terminate the threads redirecting the program output
if EndOfProcedure != None:
if Proc == None:
EdkLogger.error("build", COMMAND_FAILURE, "Failed to start command", ExtraData="%s [%s]" % (Command, WorkingDir))
# check the return code of the program
## 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
#
if not BuildCommand:
"No build command found for this module. "
"Please check your setting of %s_%s_%s_MAKE_PATH in Conf/tools_def.txt file." %
## str() method
#
# It just returns the string representation of self.BuildObject
#
# @param self The object pointer
#
## "==" 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
#
## hash() method
#
# It just returns the hash value of self.BuildObject which must be hashable.
#
# @param self The object pointer
#
#
# must provide __str__(), __eq__() and __hash__() methods. Otherwise there could
# be make units missing build.
#
# Currently the "Obj" should be only ModuleAutoGen object.
#
## 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
#
#
# must provide __str__(), __eq__() and __hash__() methods. Otherwise there could
# be make units missing build.
#
# Currently the "Obj" should be only PlatformAutoGen object.
#
## 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
#
## 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
# queue for tasks ready for running
# queue for run tasks
# queue containing all build tasks, in case duplicate build
# flag indicating error occurs in a running thread
# BoundedSemaphore object used to control the number of running threads
_Thread = None
# flag indicating if the scheduler is started or not
## Start the task scheduler thread
#
# @param MaxThreadNumber The maximum thread number
# @param ExitFlag Flag used to end the scheduler
#
# wait for the scheduler to be started, especially useful in Linux
## Scheduler method
#
# @param MaxThreadNumber The maximum thread number
# @param ExitFlag Flag used to end the scheduler
#
try:
# use BoundedSemaphore to control the maximum running threads
#
# indicated to do so, or there's error in running thread
#
# get all pending tasks
#
# check if their dependency is resolved, and if true, move them
# into ready queue
#
for BuildObject in BuildObjectList:
# launch build thread until the maximum number of threads is reached
# empty ready queue, do nothing further
break
# wait for active thread(s) exit
# start a new build thread
# move into running queue
# avoid tense loop
# avoid tense loop
# wait for all running threads exit
# while not BuildTask._ErrorFlag.isSet() and \
EdkLogger.debug(EdkLogger.DEBUG_8, "Threads [%s]" % ", ".join([Th.getName() for Th in threading.enumerate()]))
# avoid tense loop
except BaseException, X:
#
# TRICK: hide the output of threads left runing, so that the user can
# catch the error message easily
#
## Wait for all running method exit
#
def WaitForComplete():
## Check if the scheduler is running or not
#
def IsOnGoing():
## Abort the build
def Abort():
## 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.
#
def HasError():
## 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.
#
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
#
return Bt
return Bt
## The real constructor of BuildTask
#
# @param BuildItem A BuildUnit object representing a build object
# @param Dependency The dependent build object of BuildItem
#
self.DependencyList = []
if Dependency == None:
else:
# flag indicating build completes, used to avoid unnecessary re-build
## Check if all dependent build tasks are completed or not
#
continue
break
return ReadyFlag
## Add dependent build task
#
# @param Dependency The list of dependent build objects
#
for Dep in Dependency:
## 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
#
try:
except:
#
# TRICK: hide the output of threads left runing, so that the user can
# catch the error message easily
#
)
# indicate there's a thread is available for another build task
## Start build task thread
#
## The class contains the information related to EFI image
#
class PeImageInfo():
## Constructor
#
# Constructor will load all required image information.
#
# @param BaseName The full file path of image.
# @param Guid The GUID for image.
# @param Arch Arch of this image.
# @param OutputDir The output directory for image.
# @param DebugDir The debug directory for image.
# @param ImageClass PeImage Information
#
## 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
# @param BuildOptions Build options passed from command line
#
else:
# print dot character during doing some time-consuming work
# print current build environment and configuration
## Load configuration
#
# This method will parse target.txt and get the build configurations.
#
#
# Check target.txt and tools_def.txt and Init them
#
if ToolDefinitionFile == '':
else:
else:
# if no ARCH given in command line, get it from target.txt
# if no build target given in command line, get it from target.txt
if not self.BuildTargetList:
# if no tool chain given in command line, get it from target.txt
if not self.ToolChainList:
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 = []
else:
# if no tool chain available, break the build
else:
if self.ThreadNumber == None:
self.ThreadNumber = self.TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER]
else:
if not self.PlatformFile:
if not PlatformFile:
# Try to find one in current directory
if FileNum >= 2:
elif FileNum == 1:
else:
ExtraData="No active platform specified in target.txt or command line! Nothing can be built.\n")
## 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.
#
# parse target.txt, tools_def.txt, and platform file
# Allow case-insensitive for those from command line or configuration file
if ErrorCode != 0:
# create metafile database
## 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 CreateDepModuleCodeFile Flag used to indicate creating code
# @param CreateDepModuleMakeFile Flag used to indicate creating makefile
#
if AutoGenObject == None:
return False
# skip file generation for cleanxxx targets, run and fds target
# for target which must generate AutoGen code and makefile
if Target == "genc":
return True
if Target == "genmake":
return True
else:
"No build command found for this module. "
"Please check your setting of %s_%s_%s_MAKE_PATH in Conf/tools_def.txt file." %
if Target == 'cleanall':
try:
#os.rmdir(AutoGenObject.BuildDir)
#
# First should close DB.
#
except WindowsError, X:
return True
## Rebase module image and Get function address for the input module list.
#
def _RebaseModule (self, MapBuffer, BaseAddress, ModuleList, AddrIsOffset = True, ModeIsSmm = False):
if ModeIsSmm:
#InfFileNameList.sort()
for InfFile in InfFileNameList:
## for SMM module in SMRAM, the SMRAM will be allocated from base to top.
if not ModeIsSmm:
#
# Update Image to new BaseAddress by GenFw tool
#
LaunchCommand(["GenFw", "--rebase", str(BaseAddress), "-r", ModuleOutputImage], ModuleInfo.OutputDir)
else:
#
# Set new address to the section header only for SMM driver.
#
LaunchCommand(["GenFw", "--address", str(BaseAddress), "-r", ModuleOutputImage], ModuleInfo.OutputDir)
LaunchCommand(["GenFw", "--address", str(BaseAddress), "-r", ModuleDebugImage], ModuleInfo.DebugDir)
#
# Collect funtion address from Map file
#
FunctionList = []
continue
#
# Get the preferred address set on link time.
#
#
# Get the real entry point address for IPF image.
#
#
# 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.
#
if AddrIsOffset:
MapBuffer.write('(GUID=%s, .textbaseaddress=-0x%010X, .databaseaddress=-0x%010X)\n' % (ModuleInfo.Guid, 0 - (BaseAddress + TextSectionAddress), 0 - (BaseAddress + DataSectionAddress)))
else:
MapBuffer.write('(GUID=%s, .textbaseaddress=0x%010X, .databaseaddress=0x%010X)\n' % (ModuleInfo.Guid, BaseAddress + TextSectionAddress, BaseAddress + DataSectionAddress))
#
# Add debug image full path.
#
#
# Add funtion address
#
for Function in FunctionList:
if AddrIsOffset:
else:
#
# for SMM module in SMRAM, the SMRAM will be allocated from base to top.
#
if ModeIsSmm:
## Collect MAP information of all FVs
#
# First get the XIP base address for FV map file.
continue
#skip FV size information
if MatchGuid != None:
#
# Replace GUID with module name
#
#
# Add the debug image full path.
#
if MatchGuid != None:
MapBuffer.write('(IMAGE=%s)\n' % (os.path.join(ModuleList[GuidString.upper()].DebugDir, ModuleList[GuidString.upper()].Name + '.efi')))
## Collect MAP information of all modules
#
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
for ModuleGuid in ModuleList:
GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (Module.MetaFile, Module.Arch, Module.ToolChain, Module.BuildTarget)
OutputImageFile = ''
#
# module list for PEI, DXE, RUNTIME and SMM
#
if not ImageClass.IsValid:
ImageInfo = PeImageInfo(Module.Name, Module.Guid, Module.Arch, Module.OutputDir, Module.DebugDir, ImageClass)
if Module.ModuleType in ['PEI_CORE', 'PEIM', 'COMBINED_PEIM_DRIVER','PIC_PEIM', 'RELOCATABLE_PEIM', 'DXE_CORE']:
#IPF runtime driver needs to be at 2 page alignment.
PiSpecVersion = '0x00000000'
# for PI specification < PI1.1, DXE_SMM_DRIVER also runs as BOOT time driver.
break
#
# EFI image is final target.
# Check EFI image contains patchable FixAddress related PCDs.
#
if OutputImageFile != '':
if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE and Pcd.TokenCName in TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_LIST:
break
if not ModuleIsPatch:
if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE and Pcd.TokenCName in TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_LIST:
break
if not ModuleIsPatch:
continue
#
# Module includes the patchable load fix address PCDs.
# It will be fixed up later.
#
#
# Get Top Memory address
#
TopMemoryAddress = 0
TopMemoryAddress = 0
else:
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:
#
# Patch FixAddress related PCDs into EFI image
#
for EfiImage in PatchEfiImageList:
continue
#
# Get PCD offset in EFI image by GenPatchPcdTable function
#
#
# Patch real PCD value by PatchPcdValue tool
#
ReturnValue = 0
ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_PEI_PAGE_SIZE_DATA_TYPE, str (PeiSize/0x1000))
ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_DXE_PAGE_SIZE_DATA_TYPE, str (BtSize/0x1000))
ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_RUNTIME_PAGE_SIZE_DATA_TYPE, str (RtSize/0x1000))
ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SMM_PAGE_SIZE_DATA_TYPE, str (SmmSize/0x1000))
if ReturnValue != 0:
## Save platform Map file
#
#
# Map file path is got.
#
#
# Save address map into MAP file.
#
## Build active platform for different build targets and different tool chains
#
)
# Create MAP file when Load Fix Address is enabled.
#
# 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 platform with IA32 or ARM arch modules")
#
# Get Module List
#
ModuleList = {}
if Ma == None:
continue
#
# Rebase module to the preferred memory address before GenFds
#
#
# create FDS again for the updated EFI image
#
#
# Create MAP file for all platform FVs after GenFds.
#
#
# Save MAP buffer into MAP file.
#
## Build active module for different build targets, different tool chains and different archs
#
#
# module build needs platform build information, so get platform
# AutoGen first
#
)
MaList = []
if Ma == None: continue
if MaList == []:
'build',
"Module for [%s] is not a component of active platform."\
" Please make sure that the ARCH and inf file path are"\
" given in the same as in [%s]" %\
)
# Create MAP file when Load Fix Address is enabled.
#
# 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
#
ModuleList = {}
if Ma == None:
continue
#
# Rebase module to the preferred memory address before GenFds
#
#
# create FDS again for the updated EFI image
#
#
# Create MAP file for all platform FVs after GenFds.
#
#
# Save MAP buffer into MAP file.
#
## Build a platform in multi-thread mode
#
)
# multi-thread exit flag
if Pa == None:
continue
# Get ModuleAutoGen object to generate C code file and makefile
if Ma == None:
continue
# Not to auto-gen for targets 'clean', 'cleanlib', 'cleanall', 'run', 'fds'
# for target which must generate AutoGen code and makefile
continue
continue
# Generate build task for the module
# Break build if any build thread has error
# we need a full version of makefile for platform
EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)
# Start task scheduler
# in case there's an interruption. we need a full version of makefile for platform
EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)
#
# Save temp tables to a TmpTableDict.
#
if Wa.BuildDatabase._CACHE_[Key]._RawData and Wa.BuildDatabase._CACHE_[Key]._RawData._Table and Wa.BuildDatabase._CACHE_[Key]._RawData._Table.Table:
TmpTableDict[Wa.BuildDatabase._CACHE_[Key]._RawData._Table.Table] = Wa.BuildDatabase._CACHE_[Key]._RawData._Table.Cur
#
#
# All modules have been put in build tasks queue. Tell task scheduler
# to exit if all tasks are completed
#
#
# Check for build error, and raise exception if one
# has been signaled.
#
EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)
# Create MAP file when Load Fix Address is enabled.
#
# 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
#
ModuleList = {}
if Ma == None:
continue
#
# Rebase module to the preferred memory address before GenFds
#
#
# Generate FD image if there's a FDF file found
#
#
# Create MAP file for all platform FVs after GenFds.
#
#
# Save MAP buffer into MAP file.
#
## Generate GuidedSectionTools.txt in the FV directories.
#
)
continue
# Build up the list of supported architectures for this build
# Look through the tool definitions for GUIDed tools
guidAttribs = []
if thisPrefix == prefix:
# Write out GuidedSecTools.txt
for guidedSectionTool in guidAttribs:
## Returns the full path of the tool.
#
else:
# We need to search for the tool using the
# PATH environment variable.
# If the tool was not found in the path then we just return
# the input tool.
return tool
## Launch the module or platform build
#
if not self.ModuleFile:
else:
else:
## Do some clean-up works when error occurred
#self.DumpBuildData()
if Utils.gFileTimeStampCache == None:
Utils.gFileTimeStampCache = {}
if Utils.gDependencyDatabase == None:
Utils.gDependencyDatabase = {}
DefineDict = {}
if DefineList != None:
for Define in DefineList:
"The macro name must be in the pattern [A-Z][A-Z0-9_]*",
else:
return DefineDict
gParamCheck = []
if option not in gParamCheck:
else:
## 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():
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'], dest="TargetArch",
help="ARCHS is one of list: IA32, X64, IPF, ARM or EBC, which overrides target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option.")
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.")
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")
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.")
help="The name of FD to be generated. The name must be from [FD] section in FDF file.")
help="The name of FV to be generated. The name must be from [FV] section in FDF file.")
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.")
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.")
Parser.add_option("-c", "--case-insensitive", action="store_true", dest="CaseInsensitive", default=False, help="Don't check case of file name.")
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.")
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.")
Parser.add_option("-Y", "--report-type", action="append", type="choice", choices=['PCD','LIBRARY','FLASH','DEPEX','BUILD_FLAGS','FIXED_ADDRESS', '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, EXECUTION_ORDER]. "\
"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]")
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.")
Parser.add_option("-N", "--no-cache", action="store_true", dest="DisableCache", default=False, help="Disable build cache mechanism")
# VBox start
global gBuildConfiguration;
Parser.add_option("--vbox-target-conf", action="store", dest="VBoxTargetConf", default=TargetTxtFile,
# VBox end
# VBox start - again
# VBox end
## 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():
# Initialize log system
#
# Parse the options and args
#
# Set log level
else:
else:
ReturnCode = 0
MyBuild = None
try:
Target = "all"
else:
if Target not in gSupportedTarget:
#
# Check environment variable: EDK_TOOLS_PATH, WORKSPACE, PATH
#
#
# Get files real name in workspace dir
#
if not Option.ModuleFile:
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:
if Option.ModuleFile:
if ErrorCode != 0:
if Option.PlatformFile != None:
if ErrorCode != 0:
# Drop temp tables to avoid database locked.
for TmpTableName in TmpTableDict:
#MyBuild.DumpBuildData()
except FatalError, X:
if MyBuild != None:
# for multi-thread build exits safely
EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())
except Warning, X:
# error from Fdf parser
if MyBuild != None:
# for multi-thread build exits safely
EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())
else:
EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError = False)
except KeyboardInterrupt:
EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())
except:
if MyBuild != None:
# for multi-thread build exits safely
# try to get the meta-file from the object causing exception
while Tb != None:
"\nbuild",
"Unknown fatal error when processing [%s]" % MetaFile,
ExtraData="\n(Please send email to edk2-buildtools-devel@lists.sourceforge.net for help, attaching following call stack trace!)\n",
)
EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())
finally:
if ReturnCode == 0:
Conclusion = "Done"
elif ReturnCode == ABORT_ERROR:
Conclusion = "Aborted"
else:
Conclusion = "Failed"
BuildDurationStr = ""
BuildDurationStr = time.strftime("%H:%M:%S", BuildDuration) + ", %d day(s)"%(BuildDuration.tm_yday - 1)
else:
if MyBuild != None:
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