summaryrefslogtreecommitdiff
path: root/BaseTools/Source/Python/build/build.py
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Source/Python/build/build.py')
-rw-r--r--BaseTools/Source/Python/build/build.py198
1 files changed, 189 insertions, 9 deletions
diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py
index ece79ea109..37afe52ac2 100644
--- a/BaseTools/Source/Python/build/build.py
+++ b/BaseTools/Source/Python/build/build.py
@@ -25,6 +25,7 @@ import time
import platform
import traceback
import encodings.ascii
+import itertools
from struct import *
from threading import *
@@ -782,15 +783,16 @@ class Build():
self.LoadFixAddress = 0
self.UniFlag = BuildOptions.Flag
self.BuildModules = []
-
+ self.Db_Flag = False
+ self.LaunchPrebuildFlag = False
+ self.PrebuildScript = ''
+ self.PostbuildScript = ''
+ self.PlatformBuildPath = os.path.join(GlobalData.gConfDirectory,'.cache', '.PlatformBuild')
if BuildOptions.CommandLength:
GlobalData.gCommandMaxLength = BuildOptions.CommandLength
# print dot character during doing some time-consuming work
self.Progress = Utils.Progressor()
-
- self.InitBuild()
-
# print current build environment and configuration
EdkLogger.quiet("%-16s = %s" % ("WORKSPACE", os.environ["WORKSPACE"]))
if "PACKAGES_PATH" in os.environ:
@@ -804,8 +806,18 @@ class Build():
# 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"]))))
- EdkLogger.info("")
+ 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()
+ EdkLogger.info("")
os.chdir(self.WorkspaceDir)
## Load configuration
@@ -903,8 +915,169 @@ class Build():
EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo)
# create metafile database
- self.Db.InitDatabase()
+ if not self.Db_Flag:
+ self.Db.InitDatabase()
+
+ 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")
## Build a module or platform
#
# Create autogen code and makefile for a module or platform, and the launch
@@ -1414,6 +1587,7 @@ class Build():
## Build active platform for different build targets and different tool chains
#
def _BuildPlatform(self):
+ SaveFileOnChange(self.PlatformBuildPath, '# DO NOT EDIT \n# FILE auto-generated\n', False)
for BuildTarget in self.BuildTargetList:
GlobalData.gGlobalDefines['TARGET'] = BuildTarget
for ToolChain in self.ToolChainList:
@@ -1587,6 +1761,7 @@ class Build():
## Build a platform in multi-thread mode
#
def _MultiThreadBuildPlatform(self):
+ SaveFileOnChange(self.PlatformBuildPath, '# DO NOT EDIT \n# FILE auto-generated\n', False)
for BuildTarget in self.BuildTargetList:
GlobalData.gGlobalDefines['TARGET'] = BuildTarget
for ToolChain in self.ToolChainList:
@@ -1961,7 +2136,7 @@ def Main():
# Initialize log system
EdkLogger.Initialize()
-
+ GlobalData.gCommand = sys.argv[1:]
#
# Parse the options and args
#
@@ -2059,7 +2234,8 @@ def Main():
MyBuild = Build(Target, Workspace, Option)
GlobalData.gCommandLineDefines['ARCH'] = ' '.join(MyBuild.ArchList)
- MyBuild.Launch()
+ if not (MyBuild.LaunchPrebuildFlag and os.path.exists(MyBuild.PlatformBuildPath)):
+ MyBuild.Launch()
# Drop temp tables to avoid database locked.
for TmpTableName in TmpTableDict:
SqlCommand = """drop table IF EXISTS %s""" % TmpTableName
@@ -2116,7 +2292,11 @@ def Main():
Utils.ClearDuplicatedInf()
if ReturnCode == 0:
- Conclusion = "Done"
+ try:
+ MyBuild.LanuchPostbuild()
+ Conclusion = "Done"
+ except:
+ Conclusion = "Failed"
elif ReturnCode == ABORT_ERROR:
Conclusion = "Aborted"
else: