public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH V2] BaseTools: AutoGen and GenFds share the parser data.
@ 2018-11-23  7:04 Zhaozh1x
  2018-11-26  5:28 ` Feng, Bob C
  2018-12-20 10:28 ` Ard Biesheuvel
  0 siblings, 2 replies; 4+ messages in thread
From: Zhaozh1x @ 2018-11-23  7:04 UTC (permalink / raw)
  To: edk2-devel; +Cc: Zhaozh1x, Liming Gao, Carsey Jaben, Bob Feng

V2:
Extract the common part of new API and the original main() function
into one function.

V1:
https://bugzilla.tianocore.org/show_bug.cgi?id=1288

Currently, AutoGen and GenFds run in different python interpreters. The
parser are duplicated. This patch is going to create new API for GenFds
and have the build to call that API instead of executing GenFds.py. As
such, the GenFds and build can share the parser data.

This patch is expected to save the time of GenFds about 2~3 seconds.
More details will be logged in BZ.

This is the summary measure data generated from python cProfile for
building Ovmf.

Currently:
8379147 function calls (8135450 primitive calls) in 12.580 seconds

After applying this patch:
3428712 function calls (3418881 primitive calls) in 8.944 seconds

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: ZhiqiangX Zhao <zhiqiangx.zhao@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Carsey Jaben <jaben.carsey@intel.com>
Cc: Bob Feng <bob.c.feng@intel.com>
---
 BaseTools/Source/Python/AutoGen/AutoGen.py |   4 +
 BaseTools/Source/Python/GenFds/GenFds.py   | 141 ++++++++++++++++++-----------
 BaseTools/Source/Python/build/build.py     |   6 +-
 3 files changed, 94 insertions(+), 57 deletions(-)

diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py
index f3560bfc78..10ce7eb962 100644
--- a/BaseTools/Source/Python/AutoGen/AutoGen.py
+++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
@@ -935,6 +935,10 @@ class WorkspaceAutoGen(AutoGen):
     def GenFdsCommand(self):
         return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
 
+    @property
+    def GenFdsCommandDict(self):
+        return GenMake.TopLevelMakefile(self)._TemplateDict
+
     ## Create makefile for the platform and modules in it
     #
     #   @param      CreateDepsMakeFile      Flag indicating if the makefile for
diff --git a/BaseTools/Source/Python/GenFds/GenFds.py b/BaseTools/Source/Python/GenFds/GenFds.py
index 0c8091b798..d24091c06c 100644
--- a/BaseTools/Source/Python/GenFds/GenFds.py
+++ b/BaseTools/Source/Python/GenFds/GenFds.py
@@ -35,7 +35,7 @@ from Common.Misc import DirCache, PathClass, GuidStructureStringToGuidString
 from Common.Misc import SaveFileOnChange, ClearDuplicatedInf
 from Common.BuildVersion import gBUILD_VERSION
 from Common.MultipleWorkspace import MultipleWorkspace as mws
-from Common.BuildToolError import FatalError, GENFDS_ERROR, CODE_ERROR, FORMAT_INVALID, RESOURCE_NOT_AVAILABLE, FILE_NOT_FOUND, OPTION_MISSING, FORMAT_NOT_SUPPORTED,OPTION_VALUE_INVALID
+from Common.BuildToolError import FatalError, GENFDS_ERROR, CODE_ERROR, FORMAT_INVALID, RESOURCE_NOT_AVAILABLE, FILE_NOT_FOUND, OPTION_MISSING, FORMAT_NOT_SUPPORTED, OPTION_VALUE_INVALID, PARAMETER_INVALID
 from Workspace.WorkspaceDatabase import WorkspaceDatabase
 
 from .FdfParser import FdfParser, Warning
@@ -59,43 +59,45 @@ __copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation  All rights reserv
 def main():
     global Options
     Options = myOptionParser()
+    EdkLogger.Initialize()
+    return GenFdsApi(OptionsToCommandDict(Options))
 
+def GenFdsApi(FdsCommandDict, WorkSpaceDataBase=None):
     global Workspace
     Workspace = ""
     ArchList = None
     ReturnCode = 0
 
-    EdkLogger.Initialize()
     try:
-        if Options.verbose:
+        if FdsCommandDict.get("verbose"):
             EdkLogger.SetLevel(EdkLogger.VERBOSE)
             GenFdsGlobalVariable.VerboseMode = True
 
-        if Options.FixedAddress:
+        if FdsCommandDict.get("FixedAddress"):
             GenFdsGlobalVariable.FixedLoadAddress = True
 
-        if Options.quiet:
+        if FdsCommandDict.get("quiet"):
             EdkLogger.SetLevel(EdkLogger.QUIET)
-        if Options.debug:
-            EdkLogger.SetLevel(Options.debug + 1)
-            GenFdsGlobalVariable.DebugLevel = Options.debug
+        if FdsCommandDict.get("debug"):
+            EdkLogger.SetLevel(FdsCommandDict.get("debug") + 1)
+            GenFdsGlobalVariable.DebugLevel = FdsCommandDict.get("debug")
         else:
             EdkLogger.SetLevel(EdkLogger.INFO)
 
-        if not Options.Workspace:
+        if not FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE')):
             EdkLogger.error("GenFds", OPTION_MISSING, "WORKSPACE not defined",
                             ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
-        elif not os.path.exists(Options.Workspace):
+        elif not os.path.exists(FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE'))):
             EdkLogger.error("GenFds", PARAMETER_INVALID, "WORKSPACE is invalid",
                             ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
         else:
-            Workspace = os.path.normcase(Options.Workspace)
+            Workspace = os.path.normcase(FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE')))
             GenFdsGlobalVariable.WorkSpaceDir = Workspace
             if 'EDK_SOURCE' in os.environ:
                 GenFdsGlobalVariable.EdkSourceDir = os.path.normcase(os.environ['EDK_SOURCE'])
-            if Options.debug:
+            if FdsCommandDict.get("debug"):
                 GenFdsGlobalVariable.VerboseLogger("Using Workspace:" + Workspace)
-            if Options.GenfdsMultiThread:
+            if FdsCommandDict.get("GenfdsMultiThread"):
                 GenFdsGlobalVariable.EnableGenfdsMultiThread = True
         os.chdir(GenFdsGlobalVariable.WorkSpaceDir)
 
@@ -103,8 +105,8 @@ def main():
         PackagesPath = os.getenv("PACKAGES_PATH")
         mws.setWs(GenFdsGlobalVariable.WorkSpaceDir, PackagesPath)
 
-        if Options.filename:
-            FdfFilename = Options.filename
+        if FdsCommandDict.get("fdf_file"):
+            FdfFilename = FdsCommandDict.get("fdf_file")[0].Path
             FdfFilename = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename)
 
             if FdfFilename[0:2] == '..':
@@ -119,14 +121,14 @@ def main():
         else:
             EdkLogger.error("GenFds", OPTION_MISSING, "Missing FDF filename")
 
-        if Options.BuildTarget:
-            GenFdsGlobalVariable.TargetName = Options.BuildTarget
+        if FdsCommandDict.get("build_target"):
+            GenFdsGlobalVariable.TargetName = FdsCommandDict.get("build_target")
 
-        if Options.ToolChain:
-            GenFdsGlobalVariable.ToolChainTag = Options.ToolChain
+        if FdsCommandDict.get("toolchain_tag"):
+            GenFdsGlobalVariable.ToolChainTag = FdsCommandDict.get("toolchain_tag")
 
-        if Options.activePlatform:
-            ActivePlatform = Options.activePlatform
+        if FdsCommandDict.get("active_platform"):
+            ActivePlatform = FdsCommandDict.get("active_platform")
             ActivePlatform = GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform)
 
             if ActivePlatform[0:2] == '..':
@@ -140,12 +142,12 @@ def main():
         else:
             EdkLogger.error("GenFds", OPTION_MISSING, "Missing active platform")
 
-        GlobalData.BuildOptionPcd = Options.OptionPcd if Options.OptionPcd else {}
+        GlobalData.BuildOptionPcd = FdsCommandDict.get("OptionPcd") if FdsCommandDict.get("OptionPcd") else {}
         GenFdsGlobalVariable.ActivePlatform = PathClass(NormPath(ActivePlatform))
 
-        if Options.ConfDirectory:
+        if FdsCommandDict.get("conf_directory"):
             # Get alternate Conf location, if it is absolute, then just use the absolute directory name
-            ConfDirectoryPath = os.path.normpath(Options.ConfDirectory)
+            ConfDirectoryPath = os.path.normpath(FdsCommandDict.get("conf_directory"))
             if ConfDirectoryPath.startswith('"'):
                 ConfDirectoryPath = ConfDirectoryPath[1:]
             if ConfDirectoryPath.endswith('"'):
@@ -169,14 +171,14 @@ def main():
             TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)
             # if no build target given in command line, get it from target.txt
             if not GenFdsGlobalVariable.TargetName:
-                BuildTargetList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TARGET]
+                BuildTargetList = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TARGET]
                 if len(BuildTargetList) != 1:
                     EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for Target.")
                 GenFdsGlobalVariable.TargetName = BuildTargetList[0]
 
             # if no tool chain given in command line, get it from target.txt
             if not GenFdsGlobalVariable.ToolChainTag:
-                ToolChainList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_TAG]
+                ToolChainList = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_TAG]
                 if ToolChainList is None or len(ToolChainList) == 0:
                     EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.")
                 if len(ToolChainList) != 1:
@@ -186,10 +188,10 @@ def main():
             EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile)
 
         #Set global flag for build mode
-        GlobalData.gIgnoreSource = Options.IgnoreSources
+        GlobalData.gIgnoreSource = FdsCommandDict.get("IgnoreSources")
 
-        if Options.Macros:
-            for Pair in Options.Macros:
+        if FdsCommandDict.get("macro"):
+            for Pair in FdsCommandDict.get("macro"):
                 if Pair.startswith('"'):
                     Pair = Pair[1:]
                 if Pair.endswith('"'):
@@ -224,8 +226,11 @@ def main():
 
         """call Workspace build create database"""
         GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))
-        BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath)
-        BuildWorkSpace.InitDatabase()
+        if WorkSpaceDataBase:
+            BuildWorkSpace = WorkSpaceDataBase
+        else:
+            BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath)
+            BuildWorkSpace.InitDatabase()
 
         #
         # Get files real name in workspace dir
@@ -233,23 +238,23 @@ def main():
         GlobalData.gAllFiles = DirCache(Workspace)
         GlobalData.gWorkspace = Workspace
 
-        if Options.archList:
-            ArchList = Options.archList.split(',')
+        if FdsCommandDict.get("build_architecture_list"):
+            ArchList = FdsCommandDict.get("build_architecture_list").split(',')
         else:
-            ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, Options.BuildTarget, Options.ToolChain].SupArchList
+            ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].SupArchList
 
-        TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, Options.BuildTarget, Options.ToolChain].SupArchList) & set(ArchList)
+        TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].SupArchList) & set(ArchList)
         if len(TargetArchList) == 0:
             EdkLogger.error("GenFds", GENFDS_ERROR, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList), str(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON].SupArchList)))
 
         for Arch in ArchList:
-            GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, Options.BuildTarget, Options.ToolChain].OutputDirectory)
+            GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].OutputDirectory)
 
         # assign platform name based on last entry in ArchList
-        GenFdsGlobalVariable.PlatformName = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, ArchList[-1], Options.BuildTarget, Options.ToolChain].PlatformName
+        GenFdsGlobalVariable.PlatformName = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, ArchList[-1], FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].PlatformName
 
-        if Options.outputDir:
-            OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(Options.outputDir)
+        if FdsCommandDict.get("platform_build_directory"):
+            OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdsCommandDict.get("platform_build_directory"))
             if not os.path.isabs (OutputDirFromCommandLine):
                 OutputDirFromCommandLine = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, OutputDirFromCommandLine)
             for Arch in ArchList:
@@ -271,32 +276,35 @@ def main():
             GenFdsGlobalVariable.OutputDirDict[Key] = OutputDir
 
         """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
-        FdfParserObj = FdfParser(FdfFilename)
-        FdfParserObj.ParseFile()
+        if WorkSpaceDataBase:
+            FdfParserObj = GlobalData.gFdfParser
+        else:
+            FdfParserObj = FdfParser(FdfFilename)
+            FdfParserObj.ParseFile()
 
         if FdfParserObj.CycleReferenceCheck():
             EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Cycle Reference Detected in FDF file")
 
-        if Options.uiFdName:
-            if Options.uiFdName.upper() in FdfParserObj.Profile.FdDict:
-                GenFds.OnlyGenerateThisFd = Options.uiFdName
+        if FdsCommandDict.get("fd"):
+            if FdsCommandDict.get("fd")[0].upper() in FdfParserObj.Profile.FdDict:
+                GenFds.OnlyGenerateThisFd = FdsCommandDict.get("fd")[0]
             else:
                 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
-                                "No such an FD in FDF file: %s" % Options.uiFdName)
+                                "No such an FD in FDF file: %s" % FdsCommandDict.get("fd")[0])
 
-        if Options.uiFvName:
-            if Options.uiFvName.upper() in FdfParserObj.Profile.FvDict:
-                GenFds.OnlyGenerateThisFv = Options.uiFvName
+        if FdsCommandDict.get("fv"):
+            if FdsCommandDict.get("fv")[0].upper() in FdfParserObj.Profile.FvDict:
+                GenFds.OnlyGenerateThisFv = FdsCommandDict.get("fv")[0]
             else:
                 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
-                                "No such an FV in FDF file: %s" % Options.uiFvName)
+                                "No such an FV in FDF file: %s" % FdsCommandDict.get("fv")[0])
 
-        if Options.uiCapName:
-            if Options.uiCapName.upper() in FdfParserObj.Profile.CapsuleDict:
-                GenFds.OnlyGenerateThisCap = Options.uiCapName
+        if FdsCommandDict.get("cap"):
+            if FdsCommandDict.get("cap")[0].upper() in FdfParserObj.Profile.CapsuleDict:
+                GenFds.OnlyGenerateThisCap = FdsCommandDict.get("cap")[0]
             else:
                 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
-                                "No such a Capsule in FDF file: %s" % Options.uiCapName)
+                                "No such a Capsule in FDF file: %s" % FdsCommandDict.get("cap")[0])
 
         GenFdsGlobalVariable.WorkSpace = BuildWorkSpace
         if ArchList:
@@ -337,7 +345,7 @@ def main():
         EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError=False)
         ReturnCode = FORMAT_INVALID
     except FatalError as X:
-        if Options.debug is not None:
+        if FdsCommandDict.get("debug") is not None:
             import traceback
             EdkLogger.quiet(traceback.format_exc())
         ReturnCode = X.args[0]
@@ -356,6 +364,30 @@ def main():
         ClearDuplicatedInf()
     return ReturnCode
 
+def OptionsToCommandDict(Options):
+    FdsCommandDict = {}
+    FdsCommandDict["verbose"] = Options.verbose
+    FdsCommandDict["FixedAddress"] = Options.FixedAddress
+    FdsCommandDict["quiet"] = Options.quiet
+    FdsCommandDict["debug"] = Options.debug
+    FdsCommandDict["Workspace"] = Options.Workspace
+    FdsCommandDict["GenfdsMultiThread"] = Options.GenfdsMultiThread
+    FdsCommandDict["fdf_file"] = [PathClass(Options.filename)] if Options.filename else []
+    FdsCommandDict["build_target"] = Options.BuildTarget
+    FdsCommandDict["toolchain_tag"] = Options.ToolChain
+    FdsCommandDict["active_platform"] = Options.activePlatform
+    FdsCommandDict["OptionPcd"] = Options.OptionPcd
+    FdsCommandDict["conf_directory"] = Options.ConfDirectory
+    FdsCommandDict["IgnoreSources"] = Options.IgnoreSources
+    FdsCommandDict["macro"] = Options.Macros
+    FdsCommandDict["build_architecture_list"] = Options.archList
+    FdsCommandDict["platform_build_directory"] = Options.outputDir
+    FdsCommandDict["fd"] = [Options.uiFdName] if Options.uiFdName else []
+    FdsCommandDict["fv"] = [Options.uiFvName] if Options.uiFvName else []
+    FdsCommandDict["cap"] = [Options.uiCapName] if Options.uiCapName else []
+    return FdsCommandDict
+
+
 gParamCheck = []
 def SingleCheckCallback(option, opt_str, value, parser):
     if option not in gParamCheck:
@@ -716,6 +748,7 @@ class GenFds(object):
             os.remove(GuidXRefFileName)
         GuidXRefFile.close()
 
+
 if __name__ == '__main__':
     r = main()
     ## 0-127 is a safe return range, and 1 is a standard default error
diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py
index d74082fc26..d87b13c090 100644
--- a/BaseTools/Source/Python/build/build.py
+++ b/BaseTools/Source/Python/build/build.py
@@ -52,7 +52,7 @@ from PatchPcdValue.PatchPcdValue import *
 
 import Common.EdkLogger
 import Common.GlobalData as GlobalData
-from GenFds.GenFds import GenFds
+from GenFds.GenFds import GenFds, GenFdsApi
 
 from collections import OrderedDict, defaultdict
 
@@ -1392,7 +1392,7 @@ class Build():
 
         # genfds
         if Target == 'fds':
-            LaunchCommand(AutoGenObject.GenFdsCommand, AutoGenObject.MakeFileDir)
+            GenFdsApi(AutoGenObject.GenFdsCommandDict, self.Db)
             return True
 
         # run
@@ -2136,7 +2136,7 @@ class Build():
                         # Generate FD image if there's a FDF file found
                         #
                         GenFdsStart = time.time()
-                        LaunchCommand(Wa.GenFdsCommand, os.getcwd())
+                        GenFdsApi(Wa.GenFdsCommandDict, self.Db)
 
                         #
                         # Create MAP file for all platform FVs after GenFds.
-- 
2.14.1.windows.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH V2] BaseTools: AutoGen and GenFds share the parser data.
  2018-11-23  7:04 [PATCH V2] BaseTools: AutoGen and GenFds share the parser data Zhaozh1x
@ 2018-11-26  5:28 ` Feng, Bob C
  2018-12-20 10:28 ` Ard Biesheuvel
  1 sibling, 0 replies; 4+ messages in thread
From: Feng, Bob C @ 2018-11-26  5:28 UTC (permalink / raw)
  To: Zhao, ZhiqiangX, edk2-devel@lists.01.org; +Cc: Gao, Liming, Carsey, Jaben

Reviewed-by: Bob Feng<bob.c.feng@intel.com>

-----Original Message-----
From: Zhao, ZhiqiangX 
Sent: Friday, November 23, 2018 3:05 PM
To: edk2-devel@lists.01.org
Cc: Zhao, ZhiqiangX <zhiqiangx.zhao@intel.com>; Gao, Liming <liming.gao@intel.com>; Carsey, Jaben <jaben.carsey@intel.com>; Feng, Bob C <bob.c.feng@intel.com>
Subject: [PATCH V2] BaseTools: AutoGen and GenFds share the parser data.

V2:
Extract the common part of new API and the original main() function into one function.

V1:
https://bugzilla.tianocore.org/show_bug.cgi?id=1288

Currently, AutoGen and GenFds run in different python interpreters. The parser are duplicated. This patch is going to create new API for GenFds and have the build to call that API instead of executing GenFds.py. As such, the GenFds and build can share the parser data.

This patch is expected to save the time of GenFds about 2~3 seconds.
More details will be logged in BZ.

This is the summary measure data generated from python cProfile for building Ovmf.

Currently:
8379147 function calls (8135450 primitive calls) in 12.580 seconds

After applying this patch:
3428712 function calls (3418881 primitive calls) in 8.944 seconds

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: ZhiqiangX Zhao <zhiqiangx.zhao@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Carsey Jaben <jaben.carsey@intel.com>
Cc: Bob Feng <bob.c.feng@intel.com>
---
 BaseTools/Source/Python/AutoGen/AutoGen.py |   4 +
 BaseTools/Source/Python/GenFds/GenFds.py   | 141 ++++++++++++++++++-----------
 BaseTools/Source/Python/build/build.py     |   6 +-
 3 files changed, 94 insertions(+), 57 deletions(-)

diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py
index f3560bfc78..10ce7eb962 100644
--- a/BaseTools/Source/Python/AutoGen/AutoGen.py
+++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
@@ -935,6 +935,10 @@ class WorkspaceAutoGen(AutoGen):
     def GenFdsCommand(self):
         return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
 
+    @property
+    def GenFdsCommandDict(self):
+        return GenMake.TopLevelMakefile(self)._TemplateDict
+
     ## Create makefile for the platform and modules in it
     #
     #   @param      CreateDepsMakeFile      Flag indicating if the makefile for
diff --git a/BaseTools/Source/Python/GenFds/GenFds.py b/BaseTools/Source/Python/GenFds/GenFds.py
index 0c8091b798..d24091c06c 100644
--- a/BaseTools/Source/Python/GenFds/GenFds.py
+++ b/BaseTools/Source/Python/GenFds/GenFds.py
@@ -35,7 +35,7 @@ from Common.Misc import DirCache, PathClass, GuidStructureStringToGuidString  from Common.Misc import SaveFileOnChange, ClearDuplicatedInf  from Common.BuildVersion import gBUILD_VERSION  from Common.MultipleWorkspace import MultipleWorkspace as mws -from Common.BuildToolError import FatalError, GENFDS_ERROR, CODE_ERROR, FORMAT_INVALID, RESOURCE_NOT_AVAILABLE, FILE_NOT_FOUND, OPTION_MISSING, FORMAT_NOT_SUPPORTED,OPTION_VALUE_INVALID
+from Common.BuildToolError import FatalError, GENFDS_ERROR, CODE_ERROR, 
+FORMAT_INVALID, RESOURCE_NOT_AVAILABLE, FILE_NOT_FOUND, OPTION_MISSING, 
+FORMAT_NOT_SUPPORTED, OPTION_VALUE_INVALID, PARAMETER_INVALID
 from Workspace.WorkspaceDatabase import WorkspaceDatabase
 
 from .FdfParser import FdfParser, Warning @@ -59,43 +59,45 @@ __copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation  All rights reserv  def main():
     global Options
     Options = myOptionParser()
+    EdkLogger.Initialize()
+    return GenFdsApi(OptionsToCommandDict(Options))
 
+def GenFdsApi(FdsCommandDict, WorkSpaceDataBase=None):
     global Workspace
     Workspace = ""
     ArchList = None
     ReturnCode = 0
 
-    EdkLogger.Initialize()
     try:
-        if Options.verbose:
+        if FdsCommandDict.get("verbose"):
             EdkLogger.SetLevel(EdkLogger.VERBOSE)
             GenFdsGlobalVariable.VerboseMode = True
 
-        if Options.FixedAddress:
+        if FdsCommandDict.get("FixedAddress"):
             GenFdsGlobalVariable.FixedLoadAddress = True
 
-        if Options.quiet:
+        if FdsCommandDict.get("quiet"):
             EdkLogger.SetLevel(EdkLogger.QUIET)
-        if Options.debug:
-            EdkLogger.SetLevel(Options.debug + 1)
-            GenFdsGlobalVariable.DebugLevel = Options.debug
+        if FdsCommandDict.get("debug"):
+            EdkLogger.SetLevel(FdsCommandDict.get("debug") + 1)
+            GenFdsGlobalVariable.DebugLevel = 
+ FdsCommandDict.get("debug")
         else:
             EdkLogger.SetLevel(EdkLogger.INFO)
 
-        if not Options.Workspace:
+        if not FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE')):
             EdkLogger.error("GenFds", OPTION_MISSING, "WORKSPACE not defined",
                             ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
-        elif not os.path.exists(Options.Workspace):
+        elif not os.path.exists(FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE'))):
             EdkLogger.error("GenFds", PARAMETER_INVALID, "WORKSPACE is invalid",
                             ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
         else:
-            Workspace = os.path.normcase(Options.Workspace)
+            Workspace = 
+ os.path.normcase(FdsCommandDict.get("Workspace",os.environ.get('WORKSP
+ ACE')))
             GenFdsGlobalVariable.WorkSpaceDir = Workspace
             if 'EDK_SOURCE' in os.environ:
                 GenFdsGlobalVariable.EdkSourceDir = os.path.normcase(os.environ['EDK_SOURCE'])
-            if Options.debug:
+            if FdsCommandDict.get("debug"):
                 GenFdsGlobalVariable.VerboseLogger("Using Workspace:" + Workspace)
-            if Options.GenfdsMultiThread:
+            if FdsCommandDict.get("GenfdsMultiThread"):
                 GenFdsGlobalVariable.EnableGenfdsMultiThread = True
         os.chdir(GenFdsGlobalVariable.WorkSpaceDir)
 
@@ -103,8 +105,8 @@ def main():
         PackagesPath = os.getenv("PACKAGES_PATH")
         mws.setWs(GenFdsGlobalVariable.WorkSpaceDir, PackagesPath)
 
-        if Options.filename:
-            FdfFilename = Options.filename
+        if FdsCommandDict.get("fdf_file"):
+            FdfFilename = FdsCommandDict.get("fdf_file")[0].Path
             FdfFilename = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename)
 
             if FdfFilename[0:2] == '..':
@@ -119,14 +121,14 @@ def main():
         else:
             EdkLogger.error("GenFds", OPTION_MISSING, "Missing FDF filename")
 
-        if Options.BuildTarget:
-            GenFdsGlobalVariable.TargetName = Options.BuildTarget
+        if FdsCommandDict.get("build_target"):
+            GenFdsGlobalVariable.TargetName = 
+ FdsCommandDict.get("build_target")
 
-        if Options.ToolChain:
-            GenFdsGlobalVariable.ToolChainTag = Options.ToolChain
+        if FdsCommandDict.get("toolchain_tag"):
+            GenFdsGlobalVariable.ToolChainTag = 
+ FdsCommandDict.get("toolchain_tag")
 
-        if Options.activePlatform:
-            ActivePlatform = Options.activePlatform
+        if FdsCommandDict.get("active_platform"):
+            ActivePlatform = FdsCommandDict.get("active_platform")
             ActivePlatform = GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform)
 
             if ActivePlatform[0:2] == '..':
@@ -140,12 +142,12 @@ def main():
         else:
             EdkLogger.error("GenFds", OPTION_MISSING, "Missing active platform")
 
-        GlobalData.BuildOptionPcd = Options.OptionPcd if Options.OptionPcd else {}
+        GlobalData.BuildOptionPcd = FdsCommandDict.get("OptionPcd") if 
+ FdsCommandDict.get("OptionPcd") else {}
         GenFdsGlobalVariable.ActivePlatform = PathClass(NormPath(ActivePlatform))
 
-        if Options.ConfDirectory:
+        if FdsCommandDict.get("conf_directory"):
             # Get alternate Conf location, if it is absolute, then just use the absolute directory name
-            ConfDirectoryPath = os.path.normpath(Options.ConfDirectory)
+            ConfDirectoryPath = 
+ os.path.normpath(FdsCommandDict.get("conf_directory"))
             if ConfDirectoryPath.startswith('"'):
                 ConfDirectoryPath = ConfDirectoryPath[1:]
             if ConfDirectoryPath.endswith('"'):
@@ -169,14 +171,14 @@ def main():
             TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)
             # if no build target given in command line, get it from target.txt
             if not GenFdsGlobalVariable.TargetName:
-                BuildTargetList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TARGET]
+                BuildTargetList = 
+ TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TARGET]
                 if len(BuildTargetList) != 1:
                     EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for Target.")
                 GenFdsGlobalVariable.TargetName = BuildTargetList[0]
 
             # if no tool chain given in command line, get it from target.txt
             if not GenFdsGlobalVariable.ToolChainTag:
-                ToolChainList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_TAG]
+                ToolChainList = 
+ TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_TAG]
                 if ToolChainList is None or len(ToolChainList) == 0:
                     EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.")
                 if len(ToolChainList) != 1:
@@ -186,10 +188,10 @@ def main():
             EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile)
 
         #Set global flag for build mode
-        GlobalData.gIgnoreSource = Options.IgnoreSources
+        GlobalData.gIgnoreSource = FdsCommandDict.get("IgnoreSources")
 
-        if Options.Macros:
-            for Pair in Options.Macros:
+        if FdsCommandDict.get("macro"):
+            for Pair in FdsCommandDict.get("macro"):
                 if Pair.startswith('"'):
                     Pair = Pair[1:]
                 if Pair.endswith('"'):
@@ -224,8 +226,11 @@ def main():
 
         """call Workspace build create database"""
         GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))
-        BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath)
-        BuildWorkSpace.InitDatabase()
+        if WorkSpaceDataBase:
+            BuildWorkSpace = WorkSpaceDataBase
+        else:
+            BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath)
+            BuildWorkSpace.InitDatabase()
 
         #
         # Get files real name in workspace dir @@ -233,23 +238,23 @@ def main():
         GlobalData.gAllFiles = DirCache(Workspace)
         GlobalData.gWorkspace = Workspace
 
-        if Options.archList:
-            ArchList = Options.archList.split(',')
+        if FdsCommandDict.get("build_architecture_list"):
+            ArchList = 
+ FdsCommandDict.get("build_architecture_list").split(',')
         else:
-            ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, Options.BuildTarget, Options.ToolChain].SupArchList
+            ArchList = 
+ BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 
+ TAB_COMMON, FdsCommandDict.get("build_target"), 
+ FdsCommandDict.get("toolchain_tag")].SupArchList
 
-        TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, Options.BuildTarget, Options.ToolChain].SupArchList) & set(ArchList)
+        TargetArchList = 
+ set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 
+ TAB_COMMON, FdsCommandDict.get("build_target"), 
+ FdsCommandDict.get("toolchain_tag")].SupArchList) & set(ArchList)
         if len(TargetArchList) == 0:
             EdkLogger.error("GenFds", GENFDS_ERROR, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList), str(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON].SupArchList)))
 
         for Arch in ArchList:
-            GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, Options.BuildTarget, Options.ToolChain].OutputDirectory)
+            GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = 
+ NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatfor
+ m, Arch, FdsCommandDict.get("build_target"), 
+ FdsCommandDict.get("toolchain_tag")].OutputDirectory)
 
         # assign platform name based on last entry in ArchList
-        GenFdsGlobalVariable.PlatformName = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, ArchList[-1], Options.BuildTarget, Options.ToolChain].PlatformName
+        GenFdsGlobalVariable.PlatformName = 
+ BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 
+ ArchList[-1], FdsCommandDict.get("build_target"), 
+ FdsCommandDict.get("toolchain_tag")].PlatformName
 
-        if Options.outputDir:
-            OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(Options.outputDir)
+        if FdsCommandDict.get("platform_build_directory"):
+            OutputDirFromCommandLine = 
+ GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdsCommandDict.get("platfor
+ m_build_directory"))
             if not os.path.isabs (OutputDirFromCommandLine):
                 OutputDirFromCommandLine = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, OutputDirFromCommandLine)
             for Arch in ArchList:
@@ -271,32 +276,35 @@ def main():
             GenFdsGlobalVariable.OutputDirDict[Key] = OutputDir
 
         """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
-        FdfParserObj = FdfParser(FdfFilename)
-        FdfParserObj.ParseFile()
+        if WorkSpaceDataBase:
+            FdfParserObj = GlobalData.gFdfParser
+        else:
+            FdfParserObj = FdfParser(FdfFilename)
+            FdfParserObj.ParseFile()
 
         if FdfParserObj.CycleReferenceCheck():
             EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Cycle Reference Detected in FDF file")
 
-        if Options.uiFdName:
-            if Options.uiFdName.upper() in FdfParserObj.Profile.FdDict:
-                GenFds.OnlyGenerateThisFd = Options.uiFdName
+        if FdsCommandDict.get("fd"):
+            if FdsCommandDict.get("fd")[0].upper() in FdfParserObj.Profile.FdDict:
+                GenFds.OnlyGenerateThisFd = FdsCommandDict.get("fd")[0]
             else:
                 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
-                                "No such an FD in FDF file: %s" % Options.uiFdName)
+                                "No such an FD in FDF file: %s" % 
+ FdsCommandDict.get("fd")[0])
 
-        if Options.uiFvName:
-            if Options.uiFvName.upper() in FdfParserObj.Profile.FvDict:
-                GenFds.OnlyGenerateThisFv = Options.uiFvName
+        if FdsCommandDict.get("fv"):
+            if FdsCommandDict.get("fv")[0].upper() in FdfParserObj.Profile.FvDict:
+                GenFds.OnlyGenerateThisFv = FdsCommandDict.get("fv")[0]
             else:
                 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
-                                "No such an FV in FDF file: %s" % Options.uiFvName)
+                                "No such an FV in FDF file: %s" % 
+ FdsCommandDict.get("fv")[0])
 
-        if Options.uiCapName:
-            if Options.uiCapName.upper() in FdfParserObj.Profile.CapsuleDict:
-                GenFds.OnlyGenerateThisCap = Options.uiCapName
+        if FdsCommandDict.get("cap"):
+            if FdsCommandDict.get("cap")[0].upper() in FdfParserObj.Profile.CapsuleDict:
+                GenFds.OnlyGenerateThisCap = 
+ FdsCommandDict.get("cap")[0]
             else:
                 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
-                                "No such a Capsule in FDF file: %s" % Options.uiCapName)
+                                "No such a Capsule in FDF file: %s" % 
+ FdsCommandDict.get("cap")[0])
 
         GenFdsGlobalVariable.WorkSpace = BuildWorkSpace
         if ArchList:
@@ -337,7 +345,7 @@ def main():
         EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError=False)
         ReturnCode = FORMAT_INVALID
     except FatalError as X:
-        if Options.debug is not None:
+        if FdsCommandDict.get("debug") is not None:
             import traceback
             EdkLogger.quiet(traceback.format_exc())
         ReturnCode = X.args[0]
@@ -356,6 +364,30 @@ def main():
         ClearDuplicatedInf()
     return ReturnCode
 
+def OptionsToCommandDict(Options):
+    FdsCommandDict = {}
+    FdsCommandDict["verbose"] = Options.verbose
+    FdsCommandDict["FixedAddress"] = Options.FixedAddress
+    FdsCommandDict["quiet"] = Options.quiet
+    FdsCommandDict["debug"] = Options.debug
+    FdsCommandDict["Workspace"] = Options.Workspace
+    FdsCommandDict["GenfdsMultiThread"] = Options.GenfdsMultiThread
+    FdsCommandDict["fdf_file"] = [PathClass(Options.filename)] if Options.filename else []
+    FdsCommandDict["build_target"] = Options.BuildTarget
+    FdsCommandDict["toolchain_tag"] = Options.ToolChain
+    FdsCommandDict["active_platform"] = Options.activePlatform
+    FdsCommandDict["OptionPcd"] = Options.OptionPcd
+    FdsCommandDict["conf_directory"] = Options.ConfDirectory
+    FdsCommandDict["IgnoreSources"] = Options.IgnoreSources
+    FdsCommandDict["macro"] = Options.Macros
+    FdsCommandDict["build_architecture_list"] = Options.archList
+    FdsCommandDict["platform_build_directory"] = Options.outputDir
+    FdsCommandDict["fd"] = [Options.uiFdName] if Options.uiFdName else []
+    FdsCommandDict["fv"] = [Options.uiFvName] if Options.uiFvName else []
+    FdsCommandDict["cap"] = [Options.uiCapName] if Options.uiCapName else []
+    return FdsCommandDict
+
+
 gParamCheck = []
 def SingleCheckCallback(option, opt_str, value, parser):
     if option not in gParamCheck:
@@ -716,6 +748,7 @@ class GenFds(object):
             os.remove(GuidXRefFileName)
         GuidXRefFile.close()
 
+
 if __name__ == '__main__':
     r = main()
     ## 0-127 is a safe return range, and 1 is a standard default error diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py
index d74082fc26..d87b13c090 100644
--- a/BaseTools/Source/Python/build/build.py
+++ b/BaseTools/Source/Python/build/build.py
@@ -52,7 +52,7 @@ from PatchPcdValue.PatchPcdValue import *
 
 import Common.EdkLogger
 import Common.GlobalData as GlobalData
-from GenFds.GenFds import GenFds
+from GenFds.GenFds import GenFds, GenFdsApi
 
 from collections import OrderedDict, defaultdict
 
@@ -1392,7 +1392,7 @@ class Build():
 
         # genfds
         if Target == 'fds':
-            LaunchCommand(AutoGenObject.GenFdsCommand, AutoGenObject.MakeFileDir)
+            GenFdsApi(AutoGenObject.GenFdsCommandDict, self.Db)
             return True
 
         # run
@@ -2136,7 +2136,7 @@ class Build():
                         # Generate FD image if there's a FDF file found
                         #
                         GenFdsStart = time.time()
-                        LaunchCommand(Wa.GenFdsCommand, os.getcwd())
+                        GenFdsApi(Wa.GenFdsCommandDict, self.Db)
 
                         #
                         # Create MAP file for all platform FVs after GenFds.
--
2.14.1.windows.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH V2] BaseTools: AutoGen and GenFds share the parser data.
  2018-11-23  7:04 [PATCH V2] BaseTools: AutoGen and GenFds share the parser data Zhaozh1x
  2018-11-26  5:28 ` Feng, Bob C
@ 2018-12-20 10:28 ` Ard Biesheuvel
  2018-12-20 10:36   ` Feng, Bob C
  1 sibling, 1 reply; 4+ messages in thread
From: Ard Biesheuvel @ 2018-12-20 10:28 UTC (permalink / raw)
  To: Zhaozh1x, Liming Gao, Feng, Bob C; +Cc: edk2-devel@lists.01.org, Carsey Jaben

On Fri, 23 Nov 2018 at 08:04, Zhaozh1x <zhiqiangx.zhao@intel.com> wrote:
>
> V2:
> Extract the common part of new API and the original main() function
> into one function.
>
> V1:
> https://bugzilla.tianocore.org/show_bug.cgi?id=1288
>
> Currently, AutoGen and GenFds run in different python interpreters. The
> parser are duplicated. This patch is going to create new API for GenFds
> and have the build to call that API instead of executing GenFds.py. As
> such, the GenFds and build can share the parser data.
>
> This patch is expected to save the time of GenFds about 2~3 seconds.
> More details will be logged in BZ.
>
> This is the summary measure data generated from python cProfile for
> building Ovmf.
>
> Currently:
> 8379147 function calls (8135450 primitive calls) in 12.580 seconds
>
> After applying this patch:
> 3428712 function calls (3418881 primitive calls) in 8.944 seconds
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: ZhiqiangX Zhao <zhiqiangx.zhao@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Carsey Jaben <jaben.carsey@intel.com>
> Cc: Bob Feng <bob.c.feng@intel.com>
> ---
>  BaseTools/Source/Python/AutoGen/AutoGen.py |   4 +
>  BaseTools/Source/Python/GenFds/GenFds.py   | 141 ++++++++++++++++++-----------
>  BaseTools/Source/Python/build/build.py     |   6 +-
>  3 files changed, 94 insertions(+), 57 deletions(-)
>

I am currently seeing a regression which is probably caused by this
change (or a related one)

When building several targets at a time, e.g.,

build -p <platform> -b DEBUG -b RELEASE

only the first one gets built completely (including the FD image), and
the latter one is only built partially.

I filed a bug here
https://bugzilla.tianocore.org/show_bug.cgi?id=1418




> diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py
> index f3560bfc78..10ce7eb962 100644
> --- a/BaseTools/Source/Python/AutoGen/AutoGen.py
> +++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
> @@ -935,6 +935,10 @@ class WorkspaceAutoGen(AutoGen):
>      def GenFdsCommand(self):
>          return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
>
> +    @property
> +    def GenFdsCommandDict(self):
> +        return GenMake.TopLevelMakefile(self)._TemplateDict
> +
>      ## Create makefile for the platform and modules in it
>      #
>      #   @param      CreateDepsMakeFile      Flag indicating if the makefile for
> diff --git a/BaseTools/Source/Python/GenFds/GenFds.py b/BaseTools/Source/Python/GenFds/GenFds.py
> index 0c8091b798..d24091c06c 100644
> --- a/BaseTools/Source/Python/GenFds/GenFds.py
> +++ b/BaseTools/Source/Python/GenFds/GenFds.py
> @@ -35,7 +35,7 @@ from Common.Misc import DirCache, PathClass, GuidStructureStringToGuidString
>  from Common.Misc import SaveFileOnChange, ClearDuplicatedInf
>  from Common.BuildVersion import gBUILD_VERSION
>  from Common.MultipleWorkspace import MultipleWorkspace as mws
> -from Common.BuildToolError import FatalError, GENFDS_ERROR, CODE_ERROR, FORMAT_INVALID, RESOURCE_NOT_AVAILABLE, FILE_NOT_FOUND, OPTION_MISSING, FORMAT_NOT_SUPPORTED,OPTION_VALUE_INVALID
> +from Common.BuildToolError import FatalError, GENFDS_ERROR, CODE_ERROR, FORMAT_INVALID, RESOURCE_NOT_AVAILABLE, FILE_NOT_FOUND, OPTION_MISSING, FORMAT_NOT_SUPPORTED, OPTION_VALUE_INVALID, PARAMETER_INVALID
>  from Workspace.WorkspaceDatabase import WorkspaceDatabase
>
>  from .FdfParser import FdfParser, Warning
> @@ -59,43 +59,45 @@ __copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation  All rights reserv
>  def main():
>      global Options
>      Options = myOptionParser()
> +    EdkLogger.Initialize()
> +    return GenFdsApi(OptionsToCommandDict(Options))
>
> +def GenFdsApi(FdsCommandDict, WorkSpaceDataBase=None):
>      global Workspace
>      Workspace = ""
>      ArchList = None
>      ReturnCode = 0
>
> -    EdkLogger.Initialize()
>      try:
> -        if Options.verbose:
> +        if FdsCommandDict.get("verbose"):
>              EdkLogger.SetLevel(EdkLogger.VERBOSE)
>              GenFdsGlobalVariable.VerboseMode = True
>
> -        if Options.FixedAddress:
> +        if FdsCommandDict.get("FixedAddress"):
>              GenFdsGlobalVariable.FixedLoadAddress = True
>
> -        if Options.quiet:
> +        if FdsCommandDict.get("quiet"):
>              EdkLogger.SetLevel(EdkLogger.QUIET)
> -        if Options.debug:
> -            EdkLogger.SetLevel(Options.debug + 1)
> -            GenFdsGlobalVariable.DebugLevel = Options.debug
> +        if FdsCommandDict.get("debug"):
> +            EdkLogger.SetLevel(FdsCommandDict.get("debug") + 1)
> +            GenFdsGlobalVariable.DebugLevel = FdsCommandDict.get("debug")
>          else:
>              EdkLogger.SetLevel(EdkLogger.INFO)
>
> -        if not Options.Workspace:
> +        if not FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE')):
>              EdkLogger.error("GenFds", OPTION_MISSING, "WORKSPACE not defined",
>                              ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
> -        elif not os.path.exists(Options.Workspace):
> +        elif not os.path.exists(FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE'))):
>              EdkLogger.error("GenFds", PARAMETER_INVALID, "WORKSPACE is invalid",
>                              ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
>          else:
> -            Workspace = os.path.normcase(Options.Workspace)
> +            Workspace = os.path.normcase(FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE')))
>              GenFdsGlobalVariable.WorkSpaceDir = Workspace
>              if 'EDK_SOURCE' in os.environ:
>                  GenFdsGlobalVariable.EdkSourceDir = os.path.normcase(os.environ['EDK_SOURCE'])
> -            if Options.debug:
> +            if FdsCommandDict.get("debug"):
>                  GenFdsGlobalVariable.VerboseLogger("Using Workspace:" + Workspace)
> -            if Options.GenfdsMultiThread:
> +            if FdsCommandDict.get("GenfdsMultiThread"):
>                  GenFdsGlobalVariable.EnableGenfdsMultiThread = True
>          os.chdir(GenFdsGlobalVariable.WorkSpaceDir)
>
> @@ -103,8 +105,8 @@ def main():
>          PackagesPath = os.getenv("PACKAGES_PATH")
>          mws.setWs(GenFdsGlobalVariable.WorkSpaceDir, PackagesPath)
>
> -        if Options.filename:
> -            FdfFilename = Options.filename
> +        if FdsCommandDict.get("fdf_file"):
> +            FdfFilename = FdsCommandDict.get("fdf_file")[0].Path
>              FdfFilename = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename)
>
>              if FdfFilename[0:2] == '..':
> @@ -119,14 +121,14 @@ def main():
>          else:
>              EdkLogger.error("GenFds", OPTION_MISSING, "Missing FDF filename")
>
> -        if Options.BuildTarget:
> -            GenFdsGlobalVariable.TargetName = Options.BuildTarget
> +        if FdsCommandDict.get("build_target"):
> +            GenFdsGlobalVariable.TargetName = FdsCommandDict.get("build_target")
>
> -        if Options.ToolChain:
> -            GenFdsGlobalVariable.ToolChainTag = Options.ToolChain
> +        if FdsCommandDict.get("toolchain_tag"):
> +            GenFdsGlobalVariable.ToolChainTag = FdsCommandDict.get("toolchain_tag")
>
> -        if Options.activePlatform:
> -            ActivePlatform = Options.activePlatform
> +        if FdsCommandDict.get("active_platform"):
> +            ActivePlatform = FdsCommandDict.get("active_platform")
>              ActivePlatform = GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform)
>
>              if ActivePlatform[0:2] == '..':
> @@ -140,12 +142,12 @@ def main():
>          else:
>              EdkLogger.error("GenFds", OPTION_MISSING, "Missing active platform")
>
> -        GlobalData.BuildOptionPcd = Options.OptionPcd if Options.OptionPcd else {}
> +        GlobalData.BuildOptionPcd = FdsCommandDict.get("OptionPcd") if FdsCommandDict.get("OptionPcd") else {}
>          GenFdsGlobalVariable.ActivePlatform = PathClass(NormPath(ActivePlatform))
>
> -        if Options.ConfDirectory:
> +        if FdsCommandDict.get("conf_directory"):
>              # Get alternate Conf location, if it is absolute, then just use the absolute directory name
> -            ConfDirectoryPath = os.path.normpath(Options.ConfDirectory)
> +            ConfDirectoryPath = os.path.normpath(FdsCommandDict.get("conf_directory"))
>              if ConfDirectoryPath.startswith('"'):
>                  ConfDirectoryPath = ConfDirectoryPath[1:]
>              if ConfDirectoryPath.endswith('"'):
> @@ -169,14 +171,14 @@ def main():
>              TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)
>              # if no build target given in command line, get it from target.txt
>              if not GenFdsGlobalVariable.TargetName:
> -                BuildTargetList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TARGET]
> +                BuildTargetList = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TARGET]
>                  if len(BuildTargetList) != 1:
>                      EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for Target.")
>                  GenFdsGlobalVariable.TargetName = BuildTargetList[0]
>
>              # if no tool chain given in command line, get it from target.txt
>              if not GenFdsGlobalVariable.ToolChainTag:
> -                ToolChainList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_TAG]
> +                ToolChainList = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_TAG]
>                  if ToolChainList is None or len(ToolChainList) == 0:
>                      EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.")
>                  if len(ToolChainList) != 1:
> @@ -186,10 +188,10 @@ def main():
>              EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile)
>
>          #Set global flag for build mode
> -        GlobalData.gIgnoreSource = Options.IgnoreSources
> +        GlobalData.gIgnoreSource = FdsCommandDict.get("IgnoreSources")
>
> -        if Options.Macros:
> -            for Pair in Options.Macros:
> +        if FdsCommandDict.get("macro"):
> +            for Pair in FdsCommandDict.get("macro"):
>                  if Pair.startswith('"'):
>                      Pair = Pair[1:]
>                  if Pair.endswith('"'):
> @@ -224,8 +226,11 @@ def main():
>
>          """call Workspace build create database"""
>          GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))
> -        BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath)
> -        BuildWorkSpace.InitDatabase()
> +        if WorkSpaceDataBase:
> +            BuildWorkSpace = WorkSpaceDataBase
> +        else:
> +            BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath)
> +            BuildWorkSpace.InitDatabase()
>
>          #
>          # Get files real name in workspace dir
> @@ -233,23 +238,23 @@ def main():
>          GlobalData.gAllFiles = DirCache(Workspace)
>          GlobalData.gWorkspace = Workspace
>
> -        if Options.archList:
> -            ArchList = Options.archList.split(',')
> +        if FdsCommandDict.get("build_architecture_list"):
> +            ArchList = FdsCommandDict.get("build_architecture_list").split(',')
>          else:
> -            ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, Options.BuildTarget, Options.ToolChain].SupArchList
> +            ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].SupArchList
>
> -        TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, Options.BuildTarget, Options.ToolChain].SupArchList) & set(ArchList)
> +        TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].SupArchList) & set(ArchList)
>          if len(TargetArchList) == 0:
>              EdkLogger.error("GenFds", GENFDS_ERROR, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList), str(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON].SupArchList)))
>
>          for Arch in ArchList:
> -            GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, Options.BuildTarget, Options.ToolChain].OutputDirectory)
> +            GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].OutputDirectory)
>
>          # assign platform name based on last entry in ArchList
> -        GenFdsGlobalVariable.PlatformName = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, ArchList[-1], Options.BuildTarget, Options.ToolChain].PlatformName
> +        GenFdsGlobalVariable.PlatformName = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, ArchList[-1], FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].PlatformName
>
> -        if Options.outputDir:
> -            OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(Options.outputDir)
> +        if FdsCommandDict.get("platform_build_directory"):
> +            OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdsCommandDict.get("platform_build_directory"))
>              if not os.path.isabs (OutputDirFromCommandLine):
>                  OutputDirFromCommandLine = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, OutputDirFromCommandLine)
>              for Arch in ArchList:
> @@ -271,32 +276,35 @@ def main():
>              GenFdsGlobalVariable.OutputDirDict[Key] = OutputDir
>
>          """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
> -        FdfParserObj = FdfParser(FdfFilename)
> -        FdfParserObj.ParseFile()
> +        if WorkSpaceDataBase:
> +            FdfParserObj = GlobalData.gFdfParser
> +        else:
> +            FdfParserObj = FdfParser(FdfFilename)
> +            FdfParserObj.ParseFile()
>
>          if FdfParserObj.CycleReferenceCheck():
>              EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Cycle Reference Detected in FDF file")
>
> -        if Options.uiFdName:
> -            if Options.uiFdName.upper() in FdfParserObj.Profile.FdDict:
> -                GenFds.OnlyGenerateThisFd = Options.uiFdName
> +        if FdsCommandDict.get("fd"):
> +            if FdsCommandDict.get("fd")[0].upper() in FdfParserObj.Profile.FdDict:
> +                GenFds.OnlyGenerateThisFd = FdsCommandDict.get("fd")[0]
>              else:
>                  EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
> -                                "No such an FD in FDF file: %s" % Options.uiFdName)
> +                                "No such an FD in FDF file: %s" % FdsCommandDict.get("fd")[0])
>
> -        if Options.uiFvName:
> -            if Options.uiFvName.upper() in FdfParserObj.Profile.FvDict:
> -                GenFds.OnlyGenerateThisFv = Options.uiFvName
> +        if FdsCommandDict.get("fv"):
> +            if FdsCommandDict.get("fv")[0].upper() in FdfParserObj.Profile.FvDict:
> +                GenFds.OnlyGenerateThisFv = FdsCommandDict.get("fv")[0]
>              else:
>                  EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
> -                                "No such an FV in FDF file: %s" % Options.uiFvName)
> +                                "No such an FV in FDF file: %s" % FdsCommandDict.get("fv")[0])
>
> -        if Options.uiCapName:
> -            if Options.uiCapName.upper() in FdfParserObj.Profile.CapsuleDict:
> -                GenFds.OnlyGenerateThisCap = Options.uiCapName
> +        if FdsCommandDict.get("cap"):
> +            if FdsCommandDict.get("cap")[0].upper() in FdfParserObj.Profile.CapsuleDict:
> +                GenFds.OnlyGenerateThisCap = FdsCommandDict.get("cap")[0]
>              else:
>                  EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
> -                                "No such a Capsule in FDF file: %s" % Options.uiCapName)
> +                                "No such a Capsule in FDF file: %s" % FdsCommandDict.get("cap")[0])
>
>          GenFdsGlobalVariable.WorkSpace = BuildWorkSpace
>          if ArchList:
> @@ -337,7 +345,7 @@ def main():
>          EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError=False)
>          ReturnCode = FORMAT_INVALID
>      except FatalError as X:
> -        if Options.debug is not None:
> +        if FdsCommandDict.get("debug") is not None:
>              import traceback
>              EdkLogger.quiet(traceback.format_exc())
>          ReturnCode = X.args[0]
> @@ -356,6 +364,30 @@ def main():
>          ClearDuplicatedInf()
>      return ReturnCode
>
> +def OptionsToCommandDict(Options):
> +    FdsCommandDict = {}
> +    FdsCommandDict["verbose"] = Options.verbose
> +    FdsCommandDict["FixedAddress"] = Options.FixedAddress
> +    FdsCommandDict["quiet"] = Options.quiet
> +    FdsCommandDict["debug"] = Options.debug
> +    FdsCommandDict["Workspace"] = Options.Workspace
> +    FdsCommandDict["GenfdsMultiThread"] = Options.GenfdsMultiThread
> +    FdsCommandDict["fdf_file"] = [PathClass(Options.filename)] if Options.filename else []
> +    FdsCommandDict["build_target"] = Options.BuildTarget
> +    FdsCommandDict["toolchain_tag"] = Options.ToolChain
> +    FdsCommandDict["active_platform"] = Options.activePlatform
> +    FdsCommandDict["OptionPcd"] = Options.OptionPcd
> +    FdsCommandDict["conf_directory"] = Options.ConfDirectory
> +    FdsCommandDict["IgnoreSources"] = Options.IgnoreSources
> +    FdsCommandDict["macro"] = Options.Macros
> +    FdsCommandDict["build_architecture_list"] = Options.archList
> +    FdsCommandDict["platform_build_directory"] = Options.outputDir
> +    FdsCommandDict["fd"] = [Options.uiFdName] if Options.uiFdName else []
> +    FdsCommandDict["fv"] = [Options.uiFvName] if Options.uiFvName else []
> +    FdsCommandDict["cap"] = [Options.uiCapName] if Options.uiCapName else []
> +    return FdsCommandDict
> +
> +
>  gParamCheck = []
>  def SingleCheckCallback(option, opt_str, value, parser):
>      if option not in gParamCheck:
> @@ -716,6 +748,7 @@ class GenFds(object):
>              os.remove(GuidXRefFileName)
>          GuidXRefFile.close()
>
> +
>  if __name__ == '__main__':
>      r = main()
>      ## 0-127 is a safe return range, and 1 is a standard default error
> diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py
> index d74082fc26..d87b13c090 100644
> --- a/BaseTools/Source/Python/build/build.py
> +++ b/BaseTools/Source/Python/build/build.py
> @@ -52,7 +52,7 @@ from PatchPcdValue.PatchPcdValue import *
>
>  import Common.EdkLogger
>  import Common.GlobalData as GlobalData
> -from GenFds.GenFds import GenFds
> +from GenFds.GenFds import GenFds, GenFdsApi
>
>  from collections import OrderedDict, defaultdict
>
> @@ -1392,7 +1392,7 @@ class Build():
>
>          # genfds
>          if Target == 'fds':
> -            LaunchCommand(AutoGenObject.GenFdsCommand, AutoGenObject.MakeFileDir)
> +            GenFdsApi(AutoGenObject.GenFdsCommandDict, self.Db)
>              return True
>
>          # run
> @@ -2136,7 +2136,7 @@ class Build():
>                          # Generate FD image if there's a FDF file found
>                          #
>                          GenFdsStart = time.time()
> -                        LaunchCommand(Wa.GenFdsCommand, os.getcwd())
> +                        GenFdsApi(Wa.GenFdsCommandDict, self.Db)
>
>                          #
>                          # Create MAP file for all platform FVs after GenFds.
> --
> 2.14.1.windows.1
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH V2] BaseTools: AutoGen and GenFds share the parser data.
  2018-12-20 10:28 ` Ard Biesheuvel
@ 2018-12-20 10:36   ` Feng, Bob C
  0 siblings, 0 replies; 4+ messages in thread
From: Feng, Bob C @ 2018-12-20 10:36 UTC (permalink / raw)
  To: Ard Biesheuvel, Zhao, ZhiqiangX, Gao, Liming
  Cc: edk2-devel@lists.01.org, Carsey, Jaben

OK.  I'll look at this issue.

Thanks,
Bob

-----Original Message-----
From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org] 
Sent: Thursday, December 20, 2018 6:28 PM
To: Zhao, ZhiqiangX <zhiqiangx.zhao@intel.com>; Gao, Liming <liming.gao@intel.com>; Feng, Bob C <bob.c.feng@intel.com>
Cc: edk2-devel@lists.01.org; Carsey, Jaben <jaben.carsey@intel.com>
Subject: Re: [edk2] [PATCH V2] BaseTools: AutoGen and GenFds share the parser data.

On Fri, 23 Nov 2018 at 08:04, Zhaozh1x <zhiqiangx.zhao@intel.com> wrote:
>
> V2:
> Extract the common part of new API and the original main() function 
> into one function.
>
> V1:
> https://bugzilla.tianocore.org/show_bug.cgi?id=1288
>
> Currently, AutoGen and GenFds run in different python interpreters. 
> The parser are duplicated. This patch is going to create new API for 
> GenFds and have the build to call that API instead of executing 
> GenFds.py. As such, the GenFds and build can share the parser data.
>
> This patch is expected to save the time of GenFds about 2~3 seconds.
> More details will be logged in BZ.
>
> This is the summary measure data generated from python cProfile for 
> building Ovmf.
>
> Currently:
> 8379147 function calls (8135450 primitive calls) in 12.580 seconds
>
> After applying this patch:
> 3428712 function calls (3418881 primitive calls) in 8.944 seconds
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: ZhiqiangX Zhao <zhiqiangx.zhao@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Carsey Jaben <jaben.carsey@intel.com>
> Cc: Bob Feng <bob.c.feng@intel.com>
> ---
>  BaseTools/Source/Python/AutoGen/AutoGen.py |   4 +
>  BaseTools/Source/Python/GenFds/GenFds.py   | 141 ++++++++++++++++++-----------
>  BaseTools/Source/Python/build/build.py     |   6 +-
>  3 files changed, 94 insertions(+), 57 deletions(-)
>

I am currently seeing a regression which is probably caused by this change (or a related one)

When building several targets at a time, e.g.,

build -p <platform> -b DEBUG -b RELEASE

only the first one gets built completely (including the FD image), and the latter one is only built partially.

I filed a bug here
https://bugzilla.tianocore.org/show_bug.cgi?id=1418




> diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py 
> b/BaseTools/Source/Python/AutoGen/AutoGen.py
> index f3560bfc78..10ce7eb962 100644
> --- a/BaseTools/Source/Python/AutoGen/AutoGen.py
> +++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
> @@ -935,6 +935,10 @@ class WorkspaceAutoGen(AutoGen):
>      def GenFdsCommand(self):
>          return 
> (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMak
> efile(self)._TemplateDict)).strip()
>
> +    @property
> +    def GenFdsCommandDict(self):
> +        return GenMake.TopLevelMakefile(self)._TemplateDict
> +
>      ## Create makefile for the platform and modules in it
>      #
>      #   @param      CreateDepsMakeFile      Flag indicating if the makefile for
> diff --git a/BaseTools/Source/Python/GenFds/GenFds.py 
> b/BaseTools/Source/Python/GenFds/GenFds.py
> index 0c8091b798..d24091c06c 100644
> --- a/BaseTools/Source/Python/GenFds/GenFds.py
> +++ b/BaseTools/Source/Python/GenFds/GenFds.py
> @@ -35,7 +35,7 @@ from Common.Misc import DirCache, PathClass, 
> GuidStructureStringToGuidString  from Common.Misc import 
> SaveFileOnChange, ClearDuplicatedInf  from Common.BuildVersion import 
> gBUILD_VERSION  from Common.MultipleWorkspace import MultipleWorkspace 
> as mws -from Common.BuildToolError import FatalError, GENFDS_ERROR, 
> CODE_ERROR, FORMAT_INVALID, RESOURCE_NOT_AVAILABLE, FILE_NOT_FOUND, 
> OPTION_MISSING, FORMAT_NOT_SUPPORTED,OPTION_VALUE_INVALID
> +from Common.BuildToolError import FatalError, GENFDS_ERROR, 
> +CODE_ERROR, FORMAT_INVALID, RESOURCE_NOT_AVAILABLE, FILE_NOT_FOUND, 
> +OPTION_MISSING, FORMAT_NOT_SUPPORTED, OPTION_VALUE_INVALID, 
> +PARAMETER_INVALID
>  from Workspace.WorkspaceDatabase import WorkspaceDatabase
>
>  from .FdfParser import FdfParser, Warning @@ -59,43 +59,45 @@ 
> __copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation  All 
> rights reserv  def main():
>      global Options
>      Options = myOptionParser()
> +    EdkLogger.Initialize()
> +    return GenFdsApi(OptionsToCommandDict(Options))
>
> +def GenFdsApi(FdsCommandDict, WorkSpaceDataBase=None):
>      global Workspace
>      Workspace = ""
>      ArchList = None
>      ReturnCode = 0
>
> -    EdkLogger.Initialize()
>      try:
> -        if Options.verbose:
> +        if FdsCommandDict.get("verbose"):
>              EdkLogger.SetLevel(EdkLogger.VERBOSE)
>              GenFdsGlobalVariable.VerboseMode = True
>
> -        if Options.FixedAddress:
> +        if FdsCommandDict.get("FixedAddress"):
>              GenFdsGlobalVariable.FixedLoadAddress = True
>
> -        if Options.quiet:
> +        if FdsCommandDict.get("quiet"):
>              EdkLogger.SetLevel(EdkLogger.QUIET)
> -        if Options.debug:
> -            EdkLogger.SetLevel(Options.debug + 1)
> -            GenFdsGlobalVariable.DebugLevel = Options.debug
> +        if FdsCommandDict.get("debug"):
> +            EdkLogger.SetLevel(FdsCommandDict.get("debug") + 1)
> +            GenFdsGlobalVariable.DebugLevel = 
> + FdsCommandDict.get("debug")
>          else:
>              EdkLogger.SetLevel(EdkLogger.INFO)
>
> -        if not Options.Workspace:
> +        if not FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE')):
>              EdkLogger.error("GenFds", OPTION_MISSING, "WORKSPACE not defined",
>                              ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
> -        elif not os.path.exists(Options.Workspace):
> +        elif not os.path.exists(FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE'))):
>              EdkLogger.error("GenFds", PARAMETER_INVALID, "WORKSPACE is invalid",
>                              ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
>          else:
> -            Workspace = os.path.normcase(Options.Workspace)
> +            Workspace = 
> + os.path.normcase(FdsCommandDict.get("Workspace",os.environ.get('WORK
> + SPACE')))
>              GenFdsGlobalVariable.WorkSpaceDir = Workspace
>              if 'EDK_SOURCE' in os.environ:
>                  GenFdsGlobalVariable.EdkSourceDir = os.path.normcase(os.environ['EDK_SOURCE'])
> -            if Options.debug:
> +            if FdsCommandDict.get("debug"):
>                  GenFdsGlobalVariable.VerboseLogger("Using Workspace:" + Workspace)
> -            if Options.GenfdsMultiThread:
> +            if FdsCommandDict.get("GenfdsMultiThread"):
>                  GenFdsGlobalVariable.EnableGenfdsMultiThread = True
>          os.chdir(GenFdsGlobalVariable.WorkSpaceDir)
>
> @@ -103,8 +105,8 @@ def main():
>          PackagesPath = os.getenv("PACKAGES_PATH")
>          mws.setWs(GenFdsGlobalVariable.WorkSpaceDir, PackagesPath)
>
> -        if Options.filename:
> -            FdfFilename = Options.filename
> +        if FdsCommandDict.get("fdf_file"):
> +            FdfFilename = FdsCommandDict.get("fdf_file")[0].Path
>              FdfFilename = 
> GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename)
>
>              if FdfFilename[0:2] == '..':
> @@ -119,14 +121,14 @@ def main():
>          else:
>              EdkLogger.error("GenFds", OPTION_MISSING, "Missing FDF 
> filename")
>
> -        if Options.BuildTarget:
> -            GenFdsGlobalVariable.TargetName = Options.BuildTarget
> +        if FdsCommandDict.get("build_target"):
> +            GenFdsGlobalVariable.TargetName = 
> + FdsCommandDict.get("build_target")
>
> -        if Options.ToolChain:
> -            GenFdsGlobalVariable.ToolChainTag = Options.ToolChain
> +        if FdsCommandDict.get("toolchain_tag"):
> +            GenFdsGlobalVariable.ToolChainTag = 
> + FdsCommandDict.get("toolchain_tag")
>
> -        if Options.activePlatform:
> -            ActivePlatform = Options.activePlatform
> +        if FdsCommandDict.get("active_platform"):
> +            ActivePlatform = FdsCommandDict.get("active_platform")
>              ActivePlatform = 
> GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform)
>
>              if ActivePlatform[0:2] == '..':
> @@ -140,12 +142,12 @@ def main():
>          else:
>              EdkLogger.error("GenFds", OPTION_MISSING, "Missing active 
> platform")
>
> -        GlobalData.BuildOptionPcd = Options.OptionPcd if Options.OptionPcd else {}
> +        GlobalData.BuildOptionPcd = FdsCommandDict.get("OptionPcd") 
> + if FdsCommandDict.get("OptionPcd") else {}
>          GenFdsGlobalVariable.ActivePlatform = 
> PathClass(NormPath(ActivePlatform))
>
> -        if Options.ConfDirectory:
> +        if FdsCommandDict.get("conf_directory"):
>              # Get alternate Conf location, if it is absolute, then just use the absolute directory name
> -            ConfDirectoryPath = os.path.normpath(Options.ConfDirectory)
> +            ConfDirectoryPath = 
> + os.path.normpath(FdsCommandDict.get("conf_directory"))
>              if ConfDirectoryPath.startswith('"'):
>                  ConfDirectoryPath = ConfDirectoryPath[1:]
>              if ConfDirectoryPath.endswith('"'):
> @@ -169,14 +171,14 @@ def main():
>              TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)
>              # if no build target given in command line, get it from target.txt
>              if not GenFdsGlobalVariable.TargetName:
> -                BuildTargetList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TARGET]
> +                BuildTargetList = 
> + TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TARGET]
>                  if len(BuildTargetList) != 1:
>                      EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for Target.")
>                  GenFdsGlobalVariable.TargetName = BuildTargetList[0]
>
>              # if no tool chain given in command line, get it from target.txt
>              if not GenFdsGlobalVariable.ToolChainTag:
> -                ToolChainList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_TAG]
> +                ToolChainList = 
> + TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_TAG]
>                  if ToolChainList is None or len(ToolChainList) == 0:
>                      EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.")
>                  if len(ToolChainList) != 1:
> @@ -186,10 +188,10 @@ def main():
>              EdkLogger.error("GenFds", FILE_NOT_FOUND, 
> ExtraData=BuildConfigurationFile)
>
>          #Set global flag for build mode
> -        GlobalData.gIgnoreSource = Options.IgnoreSources
> +        GlobalData.gIgnoreSource = 
> + FdsCommandDict.get("IgnoreSources")
>
> -        if Options.Macros:
> -            for Pair in Options.Macros:
> +        if FdsCommandDict.get("macro"):
> +            for Pair in FdsCommandDict.get("macro"):
>                  if Pair.startswith('"'):
>                      Pair = Pair[1:]
>                  if Pair.endswith('"'):
> @@ -224,8 +226,11 @@ def main():
>
>          """call Workspace build create database"""
>          GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))
> -        BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath)
> -        BuildWorkSpace.InitDatabase()
> +        if WorkSpaceDataBase:
> +            BuildWorkSpace = WorkSpaceDataBase
> +        else:
> +            BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath)
> +            BuildWorkSpace.InitDatabase()
>
>          #
>          # Get files real name in workspace dir @@ -233,23 +238,23 @@ 
> def main():
>          GlobalData.gAllFiles = DirCache(Workspace)
>          GlobalData.gWorkspace = Workspace
>
> -        if Options.archList:
> -            ArchList = Options.archList.split(',')
> +        if FdsCommandDict.get("build_architecture_list"):
> +            ArchList = 
> + FdsCommandDict.get("build_architecture_list").split(',')
>          else:
> -            ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, Options.BuildTarget, Options.ToolChain].SupArchList
> +            ArchList = 
> + BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 
> + TAB_COMMON, FdsCommandDict.get("build_target"), 
> + FdsCommandDict.get("toolchain_tag")].SupArchList
>
> -        TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, Options.BuildTarget, Options.ToolChain].SupArchList) & set(ArchList)
> +        TargetArchList = 
> + set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 
> + TAB_COMMON, FdsCommandDict.get("build_target"), 
> + FdsCommandDict.get("toolchain_tag")].SupArchList) & set(ArchList)
>          if len(TargetArchList) == 0:
>              EdkLogger.error("GenFds", GENFDS_ERROR, "Target ARCH %s 
> not in platform supported ARCH %s" % (str(ArchList), 
> str(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 
> TAB_COMMON].SupArchList)))
>
>          for Arch in ArchList:
> -            GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, Options.BuildTarget, Options.ToolChain].OutputDirectory)
> +            GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = 
> + NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatf
> + orm, Arch, FdsCommandDict.get("build_target"), 
> + FdsCommandDict.get("toolchain_tag")].OutputDirectory)
>
>          # assign platform name based on last entry in ArchList
> -        GenFdsGlobalVariable.PlatformName = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, ArchList[-1], Options.BuildTarget, Options.ToolChain].PlatformName
> +        GenFdsGlobalVariable.PlatformName = 
> + BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 
> + ArchList[-1], FdsCommandDict.get("build_target"), 
> + FdsCommandDict.get("toolchain_tag")].PlatformName
>
> -        if Options.outputDir:
> -            OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(Options.outputDir)
> +        if FdsCommandDict.get("platform_build_directory"):
> +            OutputDirFromCommandLine = 
> + GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdsCommandDict.get("platf
> + orm_build_directory"))
>              if not os.path.isabs (OutputDirFromCommandLine):
>                  OutputDirFromCommandLine = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, OutputDirFromCommandLine)
>              for Arch in ArchList:
> @@ -271,32 +276,35 @@ def main():
>              GenFdsGlobalVariable.OutputDirDict[Key] = OutputDir
>
>          """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
> -        FdfParserObj = FdfParser(FdfFilename)
> -        FdfParserObj.ParseFile()
> +        if WorkSpaceDataBase:
> +            FdfParserObj = GlobalData.gFdfParser
> +        else:
> +            FdfParserObj = FdfParser(FdfFilename)
> +            FdfParserObj.ParseFile()
>
>          if FdfParserObj.CycleReferenceCheck():
>              EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Cycle 
> Reference Detected in FDF file")
>
> -        if Options.uiFdName:
> -            if Options.uiFdName.upper() in FdfParserObj.Profile.FdDict:
> -                GenFds.OnlyGenerateThisFd = Options.uiFdName
> +        if FdsCommandDict.get("fd"):
> +            if FdsCommandDict.get("fd")[0].upper() in FdfParserObj.Profile.FdDict:
> +                GenFds.OnlyGenerateThisFd = 
> + FdsCommandDict.get("fd")[0]
>              else:
>                  EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
> -                                "No such an FD in FDF file: %s" % Options.uiFdName)
> +                                "No such an FD in FDF file: %s" % 
> + FdsCommandDict.get("fd")[0])
>
> -        if Options.uiFvName:
> -            if Options.uiFvName.upper() in FdfParserObj.Profile.FvDict:
> -                GenFds.OnlyGenerateThisFv = Options.uiFvName
> +        if FdsCommandDict.get("fv"):
> +            if FdsCommandDict.get("fv")[0].upper() in FdfParserObj.Profile.FvDict:
> +                GenFds.OnlyGenerateThisFv = 
> + FdsCommandDict.get("fv")[0]
>              else:
>                  EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
> -                                "No such an FV in FDF file: %s" % Options.uiFvName)
> +                                "No such an FV in FDF file: %s" % 
> + FdsCommandDict.get("fv")[0])
>
> -        if Options.uiCapName:
> -            if Options.uiCapName.upper() in FdfParserObj.Profile.CapsuleDict:
> -                GenFds.OnlyGenerateThisCap = Options.uiCapName
> +        if FdsCommandDict.get("cap"):
> +            if FdsCommandDict.get("cap")[0].upper() in FdfParserObj.Profile.CapsuleDict:
> +                GenFds.OnlyGenerateThisCap = 
> + FdsCommandDict.get("cap")[0]
>              else:
>                  EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
> -                                "No such a Capsule in FDF file: %s" % Options.uiCapName)
> +                                "No such a Capsule in FDF file: %s" % 
> + FdsCommandDict.get("cap")[0])
>
>          GenFdsGlobalVariable.WorkSpace = BuildWorkSpace
>          if ArchList:
> @@ -337,7 +345,7 @@ def main():
>          EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError=False)
>          ReturnCode = FORMAT_INVALID
>      except FatalError as X:
> -        if Options.debug is not None:
> +        if FdsCommandDict.get("debug") is not None:
>              import traceback
>              EdkLogger.quiet(traceback.format_exc())
>          ReturnCode = X.args[0]
> @@ -356,6 +364,30 @@ def main():
>          ClearDuplicatedInf()
>      return ReturnCode
>
> +def OptionsToCommandDict(Options):
> +    FdsCommandDict = {}
> +    FdsCommandDict["verbose"] = Options.verbose
> +    FdsCommandDict["FixedAddress"] = Options.FixedAddress
> +    FdsCommandDict["quiet"] = Options.quiet
> +    FdsCommandDict["debug"] = Options.debug
> +    FdsCommandDict["Workspace"] = Options.Workspace
> +    FdsCommandDict["GenfdsMultiThread"] = Options.GenfdsMultiThread
> +    FdsCommandDict["fdf_file"] = [PathClass(Options.filename)] if Options.filename else []
> +    FdsCommandDict["build_target"] = Options.BuildTarget
> +    FdsCommandDict["toolchain_tag"] = Options.ToolChain
> +    FdsCommandDict["active_platform"] = Options.activePlatform
> +    FdsCommandDict["OptionPcd"] = Options.OptionPcd
> +    FdsCommandDict["conf_directory"] = Options.ConfDirectory
> +    FdsCommandDict["IgnoreSources"] = Options.IgnoreSources
> +    FdsCommandDict["macro"] = Options.Macros
> +    FdsCommandDict["build_architecture_list"] = Options.archList
> +    FdsCommandDict["platform_build_directory"] = Options.outputDir
> +    FdsCommandDict["fd"] = [Options.uiFdName] if Options.uiFdName else []
> +    FdsCommandDict["fv"] = [Options.uiFvName] if Options.uiFvName else []
> +    FdsCommandDict["cap"] = [Options.uiCapName] if Options.uiCapName else []
> +    return FdsCommandDict
> +
> +
>  gParamCheck = []
>  def SingleCheckCallback(option, opt_str, value, parser):
>      if option not in gParamCheck:
> @@ -716,6 +748,7 @@ class GenFds(object):
>              os.remove(GuidXRefFileName)
>          GuidXRefFile.close()
>
> +
>  if __name__ == '__main__':
>      r = main()
>      ## 0-127 is a safe return range, and 1 is a standard default 
> error diff --git a/BaseTools/Source/Python/build/build.py 
> b/BaseTools/Source/Python/build/build.py
> index d74082fc26..d87b13c090 100644
> --- a/BaseTools/Source/Python/build/build.py
> +++ b/BaseTools/Source/Python/build/build.py
> @@ -52,7 +52,7 @@ from PatchPcdValue.PatchPcdValue import *
>
>  import Common.EdkLogger
>  import Common.GlobalData as GlobalData -from GenFds.GenFds import 
> GenFds
> +from GenFds.GenFds import GenFds, GenFdsApi
>
>  from collections import OrderedDict, defaultdict
>
> @@ -1392,7 +1392,7 @@ class Build():
>
>          # genfds
>          if Target == 'fds':
> -            LaunchCommand(AutoGenObject.GenFdsCommand, AutoGenObject.MakeFileDir)
> +            GenFdsApi(AutoGenObject.GenFdsCommandDict, self.Db)
>              return True
>
>          # run
> @@ -2136,7 +2136,7 @@ class Build():
>                          # Generate FD image if there's a FDF file found
>                          #
>                          GenFdsStart = time.time()
> -                        LaunchCommand(Wa.GenFdsCommand, os.getcwd())
> +                        GenFdsApi(Wa.GenFdsCommandDict, self.Db)
>
>                          #
>                          # Create MAP file for all platform FVs after GenFds.
> --
> 2.14.1.windows.1
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-12-20 10:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-11-23  7:04 [PATCH V2] BaseTools: AutoGen and GenFds share the parser data Zhaozh1x
2018-11-26  5:28 ` Feng, Bob C
2018-12-20 10:28 ` Ard Biesheuvel
2018-12-20 10:36   ` Feng, Bob C

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox