[edk2-devel] [PATCH V2] BaseTools:Fix GenFds issue for BuildOption replace GenFdsOption

Fan, ZhijuX posted 1 patch 2 weeks ago
Failed in applying to current master (apply log)
BaseTools/Source/Python/AutoGen/BuildEngine.py     |  56 +++++++----
BaseTools/Source/Python/Common/GlobalData.py       |   2 +-
.../Source/Python/Common/TargetTxtClassObject.py   |  64 +++++++++------
.../Source/Python/Common/ToolDefClassObject.py     |  48 +++++++---
BaseTools/Source/Python/Common/buildoptions.py     |  93 ------------------
BaseTools/Source/Python/GenFds/GenFds.py           |   4 +-
.../Source/Python/GenFds/GenFdsGlobalVariable.py   |  17 ++--
BaseTools/Source/Python/Workspace/DscBuildData.py  |   9 +-
BaseTools/Source/Python/build/build.py             |  32 +++++--
BaseTools/Source/Python/build/buildoptions.py      | 105 +++++++++++++++++++++
10 files changed, 261 insertions(+), 169 deletions(-)
delete mode 100644 BaseTools/Source/Python/Common/buildoptions.py
create mode 100644 BaseTools/Source/Python/build/buildoptions.py

[edk2-devel] [PATCH V2] BaseTools:Fix GenFds issue for BuildOption replace GenFdsOption

Posted by Fan, ZhijuX 2 weeks ago
BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=2455

BuildOption is used by TargetTxtClassObj.py
GenFdsOption is used by GenFds.py
When the GenFds tool is used alone (e.g. python3 -m GenFds.GenFds -h)
With the OptionParser function, the first detected function
prints the help message

import TargetTxtClassObj to GenFds,
The BuildOption will be executed and replace GenFdsOption

We removed all objects associated with this problem that
were created directly during the import process
(e.g. BuildOption, BuildTarget = MyOptionParser(),
 TargetTxt = TargetTxtDict())

The Patch is going to fix this issue

Signed-off-by: Zhiju.Fan <zhijux.fan@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Bob Feng <bob.c.feng@intel.com>
---
 BaseTools/Source/Python/AutoGen/BuildEngine.py     |  56 +++++++----
 BaseTools/Source/Python/Common/GlobalData.py       |   2 +-
 .../Source/Python/Common/TargetTxtClassObject.py   |  64 +++++++++------
 .../Source/Python/Common/ToolDefClassObject.py     |  48 +++++++---
 BaseTools/Source/Python/Common/buildoptions.py     |  93 ------------------
 BaseTools/Source/Python/GenFds/GenFds.py           |   4 +-
 .../Source/Python/GenFds/GenFdsGlobalVariable.py   |  17 ++--
 BaseTools/Source/Python/Workspace/DscBuildData.py  |   9 +-
 BaseTools/Source/Python/build/build.py             |  32 +++++--
 BaseTools/Source/Python/build/buildoptions.py      | 105 +++++++++++++++++++++
 10 files changed, 261 insertions(+), 169 deletions(-)
 delete mode 100644 BaseTools/Source/Python/Common/buildoptions.py
 create mode 100644 BaseTools/Source/Python/build/buildoptions.py

The method by which the optimization function gets the 
parameter value
add bugzilla to patch

diff --git a/BaseTools/Source/Python/AutoGen/BuildEngine.py b/BaseTools/Source/Python/AutoGen/BuildEngine.py
index 069a3a1c9d..d602414ca4 100644
--- a/BaseTools/Source/Python/AutoGen/BuildEngine.py
+++ b/BaseTools/Source/Python/AutoGen/BuildEngine.py
@@ -20,7 +20,7 @@ from Common.BuildToolError import *
 from Common.Misc import tdict, PathClass
 from Common.StringUtils import NormPath
 from Common.DataType import *
-from Common.TargetTxtClassObject import TargetTxt
+from Common.TargetTxtClassObject import TargetTxtDict
 gDefaultBuildRuleFile = 'build_rule.txt'
 AutoGenReqBuildRuleVerNum = '0.1'
 
@@ -588,24 +588,42 @@ class BuildRule:
         _UnknownSection    : SkipSection,
     }
 
-def GetBuildRule():
-    BuildRuleFile = None
-    if TAB_TAT_DEFINES_BUILD_RULE_CONF in TargetTxt.TargetTxtDictionary:
-        BuildRuleFile = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
-    if not BuildRuleFile:
-        BuildRuleFile = gDefaultBuildRuleFile
-    RetVal = BuildRule(BuildRuleFile)
-    if RetVal._FileVersion == "":
-        RetVal._FileVersion = AutoGenReqBuildRuleVerNum
-    else:
-        if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :
-            # If Build Rule's version is less than the version number required by the tools, halting the build.
-            EdkLogger.error("build", AUTOGEN_ERROR,
-                            ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
-                             % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))
-    return RetVal
-
-BuildRuleObj = GetBuildRule()
+class ToolBuildRule():
+
+    def __new__(cls, *args, **kw):
+        if not hasattr(cls, '_instance'):
+            orig = super(ToolBuildRule, cls)
+            cls._instance = orig.__new__(cls, *args, **kw)
+        return cls._instance
+
+    def __init__(self):
+        if not hasattr(self, 'ToolBuildRule'):
+            self._ToolBuildRule = None
+
+    @property
+    def ToolBuildRule(self):
+        if not self._ToolBuildRule:
+            self._GetBuildRule()
+        return self._ToolBuildRule
+
+    def _GetBuildRule(self):
+        BuildRuleFile = None
+        TargetObj = TargetTxtDict()
+        TargetTxt = TargetObj.Target
+        if TAB_TAT_DEFINES_BUILD_RULE_CONF in TargetTxt.TargetTxtDictionary:
+            BuildRuleFile = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
+        if not BuildRuleFile:
+            BuildRuleFile = gDefaultBuildRuleFile
+        RetVal = BuildRule(BuildRuleFile)
+        if RetVal._FileVersion == "":
+            RetVal._FileVersion = AutoGenReqBuildRuleVerNum
+        else:
+            if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :
+                # If Build Rule's version is less than the version number required by the tools, halting the build.
+                EdkLogger.error("build", AUTOGEN_ERROR,
+                                ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
+                                 % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))
+        self._ToolBuildRule = RetVal
 
 # This acts like the main() function for the script, unless it is 'import'ed into another
 # script.
diff --git a/BaseTools/Source/Python/Common/GlobalData.py b/BaseTools/Source/Python/Common/GlobalData.py
index 0b3ebe035d..8ac29eb7a6 100755
--- a/BaseTools/Source/Python/Common/GlobalData.py
+++ b/BaseTools/Source/Python/Common/GlobalData.py
@@ -70,7 +70,7 @@ gAutoGenPhase = False
 # The Conf dir outside the workspace dir
 #
 gConfDirectory = ''
-
+gCmdConfDir = ''
 gBuildDirectory = ''
 #
 # The relative default database file path
diff --git a/BaseTools/Source/Python/Common/TargetTxtClassObject.py b/BaseTools/Source/Python/Common/TargetTxtClassObject.py
index 723b9405bf..57212172fe 100644
--- a/BaseTools/Source/Python/Common/TargetTxtClassObject.py
+++ b/BaseTools/Source/Python/Common/TargetTxtClassObject.py
@@ -10,7 +10,7 @@
 #
 from __future__ import print_function
 from __future__ import absolute_import
-from Common.buildoptions import BuildOption,BuildTarget
+
 import Common.GlobalData as GlobalData
 import Common.LongFilePathOs as os
 from . import EdkLogger
@@ -144,29 +144,47 @@ class TargetTxtClassObject(object):
 #
 # @retval Target An instance of TargetTxtClassObject() with loaded target.txt
 #
-def TargetTxtDict():
-    Target = TargetTxtClassObject()
-    if BuildOption.ConfDirectory:
-        # Get alternate Conf location, if it is absolute, then just use the absolute directory name
-        ConfDirectoryPath = os.path.normpath(BuildOption.ConfDirectory)
-
-        if not os.path.isabs(ConfDirectoryPath):
-            # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
-            # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
-            ConfDirectoryPath = mws.join(os.environ["WORKSPACE"], ConfDirectoryPath)
-    else:
-        if "CONF_PATH" in os.environ:
-            ConfDirectoryPath = os.path.normcase(os.path.normpath(os.environ["CONF_PATH"]))
+
+class TargetTxtDict():
+
+    def __new__(cls, *args, **kw):
+        if not hasattr(cls, '_instance'):
+            orig = super(TargetTxtDict, cls)
+            cls._instance = orig.__new__(cls, *args, **kw)
+        return cls._instance
+
+    def __init__(self):
+        if not hasattr(self, 'Target'):
+            self.TxtTarget = None
+
+    @property
+    def Target(self):
+        if not self.TxtTarget:
+            self._GetTarget()
+        return self.TxtTarget
+
+    def _GetTarget(self):
+        Target = TargetTxtClassObject()
+        ConfDirectory = GlobalData.gCmdConfDir
+        if ConfDirectory:
+            # Get alternate Conf location, if it is absolute, then just use the absolute directory name
+            ConfDirectoryPath = os.path.normpath(ConfDirectory)
+
+            if not os.path.isabs(ConfDirectoryPath):
+                # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
+                # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
+                ConfDirectoryPath = mws.join(os.environ["WORKSPACE"], ConfDirectoryPath)
         else:
-            # Get standard WORKSPACE/Conf use the absolute path to the WORKSPACE/Conf
-            ConfDirectoryPath = mws.join(os.environ["WORKSPACE"], 'Conf')
-    GlobalData.gConfDirectory = ConfDirectoryPath
-    targettxt = os.path.normpath(os.path.join(ConfDirectoryPath, gDefaultTargetTxtFile))
-    if os.path.exists(targettxt):
-        Target.LoadTargetTxtFile(targettxt)
-    return Target
-
-TargetTxt = TargetTxtDict()
+            if "CONF_PATH" in os.environ:
+                ConfDirectoryPath = os.path.normcase(os.path.normpath(os.environ["CONF_PATH"]))
+            else:
+                # Get standard WORKSPACE/Conf use the absolute path to the WORKSPACE/Conf
+                ConfDirectoryPath = mws.join(os.environ["WORKSPACE"], 'Conf')
+        GlobalData.gConfDirectory = ConfDirectoryPath
+        targettxt = os.path.normpath(os.path.join(ConfDirectoryPath, gDefaultTargetTxtFile))
+        if os.path.exists(targettxt):
+            Target.LoadTargetTxtFile(targettxt)
+        self.TxtTarget = Target
 
 ##
 #
diff --git a/BaseTools/Source/Python/Common/ToolDefClassObject.py b/BaseTools/Source/Python/Common/ToolDefClassObject.py
index 063fa00584..8e70407cb9 100644
--- a/BaseTools/Source/Python/Common/ToolDefClassObject.py
+++ b/BaseTools/Source/Python/Common/ToolDefClassObject.py
@@ -14,7 +14,7 @@ import re
 from . import EdkLogger
 
 from .BuildToolError import *
-from Common.TargetTxtClassObject import TargetTxt
+from Common.TargetTxtClassObject import TargetTxtDict
 from Common.LongFilePathSupport import OpenLongFilePath as open
 from Common.Misc import PathClass
 from Common.StringUtils import NormPath
@@ -262,20 +262,40 @@ class ToolDefClassObject(object):
 #
 # @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt
 #
-def ToolDefDict(ConfDir):
-    Target = TargetTxt
-    ToolDef = ToolDefClassObject()
-    if TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
-        ToolsDefFile = Target.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
-        if ToolsDefFile:
-            ToolDef.LoadToolDefFile(os.path.normpath(ToolsDefFile))
-        else:
-            ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
-    else:
-        ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
-    return ToolDef
 
-ToolDef = ToolDefDict((os.path.join(os.getenv("WORKSPACE"),"Conf")))
+
+class ToolDefDict():
+
+    def __new__(cls, ConfDir, *args, **kw):
+        if not hasattr(cls, '_instance'):
+            orig = super(ToolDefDict, cls)
+            cls._instance = orig.__new__(cls, *args, **kw)
+        return cls._instance
+
+    def __init__(self, ConfDir):
+        self.ConfDir = ConfDir
+        if not hasattr(self, 'ToolDef'):
+            self._ToolDef = None
+
+    @property
+    def ToolDef(self):
+        if not self._ToolDef:
+            self._GetToolDef()
+        return self._ToolDef
+
+    def _GetToolDef(self):
+        TargetObj = TargetTxtDict()
+        Target = TargetObj.Target
+        ToolDef = ToolDefClassObject()
+        if TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
+            ToolsDefFile = Target.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
+            if ToolsDefFile:
+                ToolDef.LoadToolDefFile(os.path.normpath(ToolsDefFile))
+            else:
+                ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(self.ConfDir, gDefaultToolsDefFile)))
+        else:
+            ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(self.ConfDir, gDefaultToolsDefFile)))
+        self._ToolDef = ToolDef
 
 ##
 #
diff --git a/BaseTools/Source/Python/Common/buildoptions.py b/BaseTools/Source/Python/Common/buildoptions.py
deleted file mode 100644
index a717c58d8c..0000000000
--- a/BaseTools/Source/Python/Common/buildoptions.py
+++ /dev/null
@@ -1,93 +0,0 @@
-## @file
-# build a platform or a module
-#
-#  Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
-#  Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
-#  Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
-#
-#  SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-
-# Version and Copyright
-from Common.BuildVersion import gBUILD_VERSION
-from optparse import OptionParser
-VersionNumber = "0.60" + ' ' + gBUILD_VERSION
-__version__ = "%prog Version " + VersionNumber
-__copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation  All rights reserved."
-
-gParamCheck = []
-def SingleCheckCallback(option, opt_str, value, parser):
-    if option not in gParamCheck:
-        setattr(parser.values, option.dest, value)
-        gParamCheck.append(option)
-    else:
-        parser.error("Option %s only allows one instance in command line!" % option)
-
-def MyOptionParser():
-    Parser = OptionParser(description=__copyright__, version=__version__, prog="build.exe", usage="%prog [options] [all|fds|genc|genmake|clean|cleanall|cleanlib|modules|libraries|run]")
-    Parser.add_option("-a", "--arch", action="append", type="choice", choices=['IA32', 'X64', 'EBC', 'ARM', 'AARCH64'], dest="TargetArch",
-        help="ARCHS is one of list: IA32, X64, ARM, AARCH64 or EBC, which overrides target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option.")
-    Parser.add_option("-p", "--platform", action="callback", type="string", dest="PlatformFile", callback=SingleCheckCallback,
-        help="Build the platform specified by the DSC file name argument, overriding target.txt's ACTIVE_PLATFORM definition.")
-    Parser.add_option("-m", "--module", action="callback", type="string", dest="ModuleFile", callback=SingleCheckCallback,
-        help="Build the module specified by the INF file name argument.")
-    Parser.add_option("-b", "--buildtarget", type="string", dest="BuildTarget", help="Using the TARGET to build the platform, overriding target.txt's TARGET definition.",
-                      action="append")
-    Parser.add_option("-t", "--tagname", action="append", type="string", dest="ToolChain",
-        help="Using the Tool Chain Tagname to build the platform, overriding target.txt's TOOL_CHAIN_TAG definition.")
-    Parser.add_option("-x", "--sku-id", action="callback", type="string", dest="SkuId", callback=SingleCheckCallback,
-        help="Using this name of SKU ID to build the platform, overriding SKUID_IDENTIFIER in DSC file.")
-
-    Parser.add_option("-n", action="callback", type="int", dest="ThreadNumber", callback=SingleCheckCallback,
-        help="Build the platform using multi-threaded compiler. The value overrides target.txt's MAX_CONCURRENT_THREAD_NUMBER. When value is set to 0, tool automatically detect number of "\
-             "processor threads, set value to 1 means disable multi-thread build, and set value to more than 1 means user specify the threads number to build.")
-
-    Parser.add_option("-f", "--fdf", action="callback", type="string", dest="FdfFile", callback=SingleCheckCallback,
-        help="The name of the FDF file to use, which overrides the setting in the DSC file.")
-    Parser.add_option("-r", "--rom-image", action="append", type="string", dest="RomImage", default=[],
-        help="The name of FD to be generated. The name must be from [FD] section in FDF file.")
-    Parser.add_option("-i", "--fv-image", action="append", type="string", dest="FvImage", default=[],
-        help="The name of FV to be generated. The name must be from [FV] section in FDF file.")
-    Parser.add_option("-C", "--capsule-image", action="append", type="string", dest="CapName", default=[],
-        help="The name of Capsule to be generated. The name must be from [Capsule] section in FDF file.")
-    Parser.add_option("-u", "--skip-autogen", action="store_true", dest="SkipAutoGen", help="Skip AutoGen step.")
-    Parser.add_option("-e", "--re-parse", action="store_true", dest="Reparse", help="Re-parse all meta-data files.")
-
-    Parser.add_option("-c", "--case-insensitive", action="store_true", dest="CaseInsensitive", default=False, help="Don't check case of file name.")
-
-    Parser.add_option("-w", "--warning-as-error", action="store_true", dest="WarningAsError", help="Treat warning in tools as error.")
-    Parser.add_option("-j", "--log", action="store", dest="LogFile", help="Put log in specified file as well as on console.")
-
-    Parser.add_option("-s", "--silent", action="store_true", type=None, dest="SilentMode",
-        help="Make use of silent mode of (n)make.")
-    Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
-    Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\
-                                                                               "including library instances selected, final dependency expression, "\
-                                                                               "and warning messages, etc.")
-    Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")
-    Parser.add_option("-D", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".")
-
-    Parser.add_option("-y", "--report-file", action="store", dest="ReportFile", help="Create/overwrite the report to the specified filename.")
-    Parser.add_option("-Y", "--report-type", action="append", type="choice", choices=['PCD', 'LIBRARY', 'FLASH', 'DEPEX', 'BUILD_FLAGS', 'FIXED_ADDRESS', 'HASH', 'EXECUTION_ORDER'], dest="ReportType", default=[],
-        help="Flags that control the type of build report to generate.  Must be one of: [PCD, LIBRARY, FLASH, DEPEX, BUILD_FLAGS, FIXED_ADDRESS, HASH, EXECUTION_ORDER].  "\
-             "To specify more than one flag, repeat this option on the command line and the default flag set is [PCD, LIBRARY, FLASH, DEPEX, HASH, BUILD_FLAGS, FIXED_ADDRESS]")
-    Parser.add_option("-F", "--flag", action="store", type="string", dest="Flag",
-        help="Specify the specific option to parse EDK UNI file. Must be one of: [-c, -s]. -c is for EDK framework UNI file, and -s is for EDK UEFI UNI file. "\
-             "This option can also be specified by setting *_*_*_BUILD_FLAGS in [BuildOptions] section of platform DSC. If they are both specified, this value "\
-             "will override the setting in [BuildOptions] section of platform DSC.")
-    Parser.add_option("-N", "--no-cache", action="store_true", dest="DisableCache", default=False, help="Disable build cache mechanism")
-    Parser.add_option("--conf", action="store", type="string", dest="ConfDirectory", help="Specify the customized Conf directory.")
-    Parser.add_option("--check-usage", action="store_true", dest="CheckUsage", default=False, help="Check usage content of entries listed in INF file.")
-    Parser.add_option("--ignore-sources", action="store_true", dest="IgnoreSources", default=False, help="Focus to a binary build and ignore all source files")
-    Parser.add_option("--pcd", action="append", dest="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
-    Parser.add_option("-l", "--cmd-len", action="store", type="int", dest="CommandLength", help="Specify the maximum line length of build command. Default is 4096.")
-    Parser.add_option("--hash", action="store_true", dest="UseHashCache", default=False, help="Enable hash-based caching during build process.")
-    Parser.add_option("--binary-destination", action="store", type="string", dest="BinCacheDest", help="Generate a cache of binary files in the specified directory.")
-    Parser.add_option("--binary-source", action="store", type="string", dest="BinCacheSource", help="Consume a cache of binary files from the specified directory.")
-    Parser.add_option("--genfds-multi-thread", action="store_true", dest="GenfdsMultiThread", default=True, help="Enable GenFds multi thread to generate ffs file.")
-    Parser.add_option("--no-genfds-multi-thread", action="store_true", dest="NoGenfdsMultiThread", default=False, help="Disable GenFds multi thread to generate ffs file.")
-    Parser.add_option("--disable-include-path-check", action="store_true", dest="DisableIncludePathCheck", default=False, help="Disable the include path check for outside of package.")
-    (Opt, Args) = Parser.parse_args()
-    return (Opt, Args)
-
-BuildOption, BuildTarget = MyOptionParser()
diff --git a/BaseTools/Source/Python/GenFds/GenFds.py b/BaseTools/Source/Python/GenFds/GenFds.py
index d8bc28e4d0..d5511f4c40 100644
--- a/BaseTools/Source/Python/GenFds/GenFds.py
+++ b/BaseTools/Source/Python/GenFds/GenFds.py
@@ -20,7 +20,7 @@ from linecache import getlines
 from io import BytesIO
 
 import Common.LongFilePathOs as os
-from Common.TargetTxtClassObject import TargetTxt
+from Common.TargetTxtClassObject import TargetTxtDict
 from Common.DataType import *
 import Common.GlobalData as GlobalData
 from Common import EdkLogger
@@ -210,6 +210,8 @@ def GenFdsApi(FdsCommandDict, WorkSpaceDataBase=None):
         BuildConfigurationFile = os.path.normpath(os.path.join(ConfDirectoryPath, "target.txt"))
         if os.path.isfile(BuildConfigurationFile) == True:
             # if no build target given in command line, get it from target.txt
+            TargetObj = TargetTxtDict()
+            TargetTxt = TargetObj.Target
             if not GenFdsGlobalVariable.TargetName:
                 BuildTargetList = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TARGET]
                 if len(BuildTargetList) != 1:
diff --git a/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
index 6e1ff7fe04..dc1727c466 100644
--- a/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
+++ b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
@@ -23,9 +23,9 @@ from Common.BuildToolError import COMMAND_FAILURE,GENFDS_ERROR
 from Common import EdkLogger
 from Common.Misc import SaveFileOnChange
 
-from Common.TargetTxtClassObject import TargetTxt
-from Common.ToolDefClassObject import ToolDef
-from AutoGen.BuildEngine import BuildRuleObj
+from Common.TargetTxtClassObject import TargetTxtDict
+from Common.ToolDefClassObject import ToolDefDict
+from AutoGen.BuildEngine import ToolBuildRule
 import Common.DataType as DataType
 from Common.Misc import PathClass
 from Common.LongFilePathSupport import OpenLongFilePath as open
@@ -96,12 +96,15 @@ class GenFdsGlobalVariable:
     def _LoadBuildRule():
         if GenFdsGlobalVariable.__BuildRuleDatabase:
             return GenFdsGlobalVariable.__BuildRuleDatabase
-        GenFdsGlobalVariable.__BuildRuleDatabase = BuildRuleObj
-        ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
+        BuildRule = ToolBuildRule()
+        GenFdsGlobalVariable.__BuildRuleDatabase = BuildRule.ToolBuildRule
+        TargetObj = TargetTxtDict()
+        ToolDefinitionFile = TargetObj.Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
         if ToolDefinitionFile == '':
             ToolDefinitionFile = "Conf/tools_def.txt"
         if os.path.isfile(ToolDefinitionFile):
-            ToolDefinition = ToolDef.ToolsDefTxtDatabase
+            ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
+            ToolDefinition = ToolDefObj.ToolDef.ToolsDefTxtDatabase
             if DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDefinition \
                and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY] \
                and ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]:
@@ -830,6 +833,8 @@ class GenFdsGlobalVariable:
 #  @param  NameGuid         The Guid name
 #
 def FindExtendTool(KeyStringList, CurrentArchList, NameGuid):
+    ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
+    ToolDef = ToolDefObj.ToolDef
     ToolDb = ToolDef.ToolsDefTxtDatabase
     # if user not specify filter, try to deduce it from global data.
     if KeyStringList is None or KeyStringList == []:
diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
index 03a15bbf3e..c65a0dd346 100644
--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -19,8 +19,8 @@ from Common.Misc import *
 from types import *
 from Common.Expression import *
 from CommonDataClass.CommonClass import SkuInfoClass
-from Common.TargetTxtClassObject import TargetTxt
-from Common.ToolDefClassObject import ToolDef
+from Common.TargetTxtClassObject import TargetTxtDict
+from Common.ToolDefClassObject import ToolDefDict
 from .MetaDataTable import *
 from .MetaFileTable import *
 from .MetaFileParser import *
@@ -3296,6 +3296,8 @@ class DscBuildData(PlatformBuildClassObject):
     @property
     def ToolChainFamily(self):
         self._ToolChainFamily = TAB_COMPILER_MSFT
+        TargetObj = TargetTxtDict()
+        TargetTxt = TargetObj.Target
         BuildConfigurationFile = os.path.normpath(os.path.join(GlobalData.gConfDirectory, "target.txt"))
         if os.path.isfile(BuildConfigurationFile) == True:
             ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
@@ -3303,7 +3305,8 @@ class DscBuildData(PlatformBuildClassObject):
                 ToolDefinitionFile = "tools_def.txt"
                 ToolDefinitionFile = os.path.normpath(mws.join(self.WorkspaceDir, 'Conf', ToolDefinitionFile))
             if os.path.isfile(ToolDefinitionFile) == True:
-                ToolDefinition = ToolDef.ToolsDefTxtDatabase
+                ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
+                ToolDefinition = ToolDefObj.ToolDef.ToolsDefTxtDatabase
                 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
                    or self._Toolchain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
                    or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self._Toolchain]:
diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py
index 3cc4220e2f..34acdccbdb 100755
--- a/BaseTools/Source/Python/build/build.py
+++ b/BaseTools/Source/Python/build/build.py
@@ -26,7 +26,7 @@ from threading import Thread,Event,BoundedSemaphore
 import threading
 from subprocess import Popen,PIPE, STDOUT
 from collections import OrderedDict, defaultdict
-from Common.buildoptions import BuildOption,BuildTarget
+
 from AutoGen.PlatformAutoGen import PlatformAutoGen
 from AutoGen.ModuleAutoGen import ModuleAutoGen
 from AutoGen.WorkspaceAutoGen import WorkspaceAutoGen
@@ -35,8 +35,9 @@ from AutoGen.AutoGenWorker import AutoGenWorkerInProcess,AutoGenManager,\
 from AutoGen import GenMake
 from Common import Misc as Utils
 
-from Common.TargetTxtClassObject import TargetTxt
-from Common.ToolDefClassObject import ToolDef
+from Common.TargetTxtClassObject import TargetTxtDict
+from Common.ToolDefClassObject import ToolDefDict
+from buildoptions import MyOptionParser
 from Common.Misc import PathClass,SaveFileOnChange,RemoveDirectory
 from Common.StringUtils import NormPath
 from Common.MultipleWorkspace import MultipleWorkspace as mws
@@ -731,11 +732,13 @@ class Build():
         self.ConfDirectory = BuildOptions.ConfDirectory
         self.SpawnMode      = True
         self.BuildReport    = BuildReport(BuildOptions.ReportFile, BuildOptions.ReportType)
-        self.TargetTxt      = TargetTxt
-        self.ToolDef        = ToolDef
         self.AutoGenTime    = 0
         self.MakeTime       = 0
         self.GenFdsTime     = 0
+        TargetObj = TargetTxtDict()
+        ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"),"Conf")))
+        self.TargetTxt = TargetObj.Target
+        self.ToolDef = ToolDefObj.ToolDef
         GlobalData.BuildOptionPcd     = BuildOptions.OptionPcd if BuildOptions.OptionPcd else []
         #Set global flag for build mode
         GlobalData.gIgnoreSource = BuildOptions.IgnoreSources
@@ -816,8 +819,10 @@ class Build():
             EdkLogger.quiet("%-16s = %s" % ("POSTBUILD", self.Postbuild))
         if self.Prebuild:
             self.LaunchPrebuild()
-            self.TargetTxt = TargetTxt
-            self.ToolDef   = ToolDef
+            TargetObj = TargetTxtDict()
+            ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
+            self.TargetTxt = TargetObj.Target
+            self.ToolDef = ToolDefObj.ToolDef
         if not (self.LaunchPrebuildFlag and os.path.exists(self.PlatformBuildPath)):
             self.InitBuild()
 
@@ -2438,9 +2443,15 @@ def LogBuildTime(Time):
     else:
         return None
 def ThreadNum():
+    OptionParser = MyOptionParser()
+    if not OptionParser.BuildOption and not OptionParser.BuildTarget:
+        OptionParser.GetOption()
+    BuildOption, BuildTarget = OptionParser.BuildOption, OptionParser.BuildTarget
     ThreadNumber = BuildOption.ThreadNumber
+    GlobalData.gCmdConfDir = BuildOption.ConfDirectory
     if ThreadNumber is None:
-        ThreadNumber = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER]
+        TargetObj = TargetTxtDict()
+        ThreadNumber = TargetObj.Target.TargetTxtDictionary[TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER]
         if ThreadNumber == '':
             ThreadNumber = 0
         else:
@@ -2475,7 +2486,10 @@ def Main():
     #
     # Parse the options and args
     #
-    Option, Target = BuildOption, BuildTarget
+    OptionParser = MyOptionParser()
+    if not OptionParser.BuildOption and not OptionParser.BuildTarget:
+        OptionParser.GetOption()
+    Option, Target = OptionParser.BuildOption, OptionParser.BuildTarget
     GlobalData.gOptions = Option
     GlobalData.gCaseInsensitive = Option.CaseInsensitive
 
diff --git a/BaseTools/Source/Python/build/buildoptions.py b/BaseTools/Source/Python/build/buildoptions.py
new file mode 100644
index 0000000000..4ad95b9f4f
--- /dev/null
+++ b/BaseTools/Source/Python/build/buildoptions.py
@@ -0,0 +1,105 @@
+## @file
+# build a platform or a module
+#
+#  Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
+#  Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+# Version and Copyright
+from Common.BuildVersion import gBUILD_VERSION
+from optparse import OptionParser
+VersionNumber = "0.60" + ' ' + gBUILD_VERSION
+__version__ = "%prog Version " + VersionNumber
+__copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation  All rights reserved."
+
+gParamCheck = []
+def SingleCheckCallback(option, opt_str, value, parser):
+    if option not in gParamCheck:
+        setattr(parser.values, option.dest, value)
+        gParamCheck.append(option)
+    else:
+        parser.error("Option %s only allows one instance in command line!" % option)
+
+
+class MyOptionParser():
+
+    def __new__(cls, *args, **kw):
+        if not hasattr(cls, '_instance'):
+            orig = super(MyOptionParser, cls)
+            cls._instance = orig.__new__(cls, *args, **kw)
+        return cls._instance
+
+    def __init__(self):
+        if not hasattr(self, 'BuildOption'):
+            self.BuildOption = None
+        if not hasattr(self, 'BuildTarget'):
+            self.BuildTarget = None
+
+    def GetOption(self):
+        Parser = OptionParser(description=__copyright__, version=__version__, prog="build.exe", usage="%prog [options] [all|fds|genc|genmake|clean|cleanall|cleanlib|modules|libraries|run]")
+        Parser.add_option("-a", "--arch", action="append", type="choice", choices=['IA32', 'X64', 'EBC', 'ARM', 'AARCH64'], dest="TargetArch",
+            help="ARCHS is one of list: IA32, X64, ARM, AARCH64 or EBC, which overrides target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option.")
+        Parser.add_option("-p", "--platform", action="callback", type="string", dest="PlatformFile", callback=SingleCheckCallback,
+            help="Build the platform specified by the DSC file name argument, overriding target.txt's ACTIVE_PLATFORM definition.")
+        Parser.add_option("-m", "--module", action="callback", type="string", dest="ModuleFile", callback=SingleCheckCallback,
+            help="Build the module specified by the INF file name argument.")
+        Parser.add_option("-b", "--buildtarget", type="string", dest="BuildTarget", help="Using the TARGET to build the platform, overriding target.txt's TARGET definition.",
+                          action="append")
+        Parser.add_option("-t", "--tagname", action="append", type="string", dest="ToolChain",
+            help="Using the Tool Chain Tagname to build the platform, overriding target.txt's TOOL_CHAIN_TAG definition.")
+        Parser.add_option("-x", "--sku-id", action="callback", type="string", dest="SkuId", callback=SingleCheckCallback,
+            help="Using this name of SKU ID to build the platform, overriding SKUID_IDENTIFIER in DSC file.")
+
+        Parser.add_option("-n", action="callback", type="int", dest="ThreadNumber", callback=SingleCheckCallback,
+            help="Build the platform using multi-threaded compiler. The value overrides target.txt's MAX_CONCURRENT_THREAD_NUMBER. When value is set to 0, tool automatically detect number of "\
+                 "processor threads, set value to 1 means disable multi-thread build, and set value to more than 1 means user specify the threads number to build.")
+
+        Parser.add_option("-f", "--fdf", action="callback", type="string", dest="FdfFile", callback=SingleCheckCallback,
+            help="The name of the FDF file to use, which overrides the setting in the DSC file.")
+        Parser.add_option("-r", "--rom-image", action="append", type="string", dest="RomImage", default=[],
+            help="The name of FD to be generated. The name must be from [FD] section in FDF file.")
+        Parser.add_option("-i", "--fv-image", action="append", type="string", dest="FvImage", default=[],
+            help="The name of FV to be generated. The name must be from [FV] section in FDF file.")
+        Parser.add_option("-C", "--capsule-image", action="append", type="string", dest="CapName", default=[],
+            help="The name of Capsule to be generated. The name must be from [Capsule] section in FDF file.")
+        Parser.add_option("-u", "--skip-autogen", action="store_true", dest="SkipAutoGen", help="Skip AutoGen step.")
+        Parser.add_option("-e", "--re-parse", action="store_true", dest="Reparse", help="Re-parse all meta-data files.")
+
+        Parser.add_option("-c", "--case-insensitive", action="store_true", dest="CaseInsensitive", default=False, help="Don't check case of file name.")
+
+        Parser.add_option("-w", "--warning-as-error", action="store_true", dest="WarningAsError", help="Treat warning in tools as error.")
+        Parser.add_option("-j", "--log", action="store", dest="LogFile", help="Put log in specified file as well as on console.")
+
+        Parser.add_option("-s", "--silent", action="store_true", type=None, dest="SilentMode",
+            help="Make use of silent mode of (n)make.")
+        Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
+        Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\
+                                                                                   "including library instances selected, final dependency expression, "\
+                                                                                   "and warning messages, etc.")
+        Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")
+        Parser.add_option("-D", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".")
+
+        Parser.add_option("-y", "--report-file", action="store", dest="ReportFile", help="Create/overwrite the report to the specified filename.")
+        Parser.add_option("-Y", "--report-type", action="append", type="choice", choices=['PCD', 'LIBRARY', 'FLASH', 'DEPEX', 'BUILD_FLAGS', 'FIXED_ADDRESS', 'HASH', 'EXECUTION_ORDER'], dest="ReportType", default=[],
+            help="Flags that control the type of build report to generate.  Must be one of: [PCD, LIBRARY, FLASH, DEPEX, BUILD_FLAGS, FIXED_ADDRESS, HASH, EXECUTION_ORDER].  "\
+                 "To specify more than one flag, repeat this option on the command line and the default flag set is [PCD, LIBRARY, FLASH, DEPEX, HASH, BUILD_FLAGS, FIXED_ADDRESS]")
+        Parser.add_option("-F", "--flag", action="store", type="string", dest="Flag",
+            help="Specify the specific option to parse EDK UNI file. Must be one of: [-c, -s]. -c is for EDK framework UNI file, and -s is for EDK UEFI UNI file. "\
+                 "This option can also be specified by setting *_*_*_BUILD_FLAGS in [BuildOptions] section of platform DSC. If they are both specified, this value "\
+                 "will override the setting in [BuildOptions] section of platform DSC.")
+        Parser.add_option("-N", "--no-cache", action="store_true", dest="DisableCache", default=False, help="Disable build cache mechanism")
+        Parser.add_option("--conf", action="store", type="string", dest="ConfDirectory", help="Specify the customized Conf directory.")
+        Parser.add_option("--check-usage", action="store_true", dest="CheckUsage", default=False, help="Check usage content of entries listed in INF file.")
+        Parser.add_option("--ignore-sources", action="store_true", dest="IgnoreSources", default=False, help="Focus to a binary build and ignore all source files")
+        Parser.add_option("--pcd", action="append", dest="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
+        Parser.add_option("-l", "--cmd-len", action="store", type="int", dest="CommandLength", help="Specify the maximum line length of build command. Default is 4096.")
+        Parser.add_option("--hash", action="store_true", dest="UseHashCache", default=False, help="Enable hash-based caching during build process.")
+        Parser.add_option("--binary-destination", action="store", type="string", dest="BinCacheDest", help="Generate a cache of binary files in the specified directory.")
+        Parser.add_option("--binary-source", action="store", type="string", dest="BinCacheSource", help="Consume a cache of binary files from the specified directory.")
+        Parser.add_option("--genfds-multi-thread", action="store_true", dest="GenfdsMultiThread", default=True, help="Enable GenFds multi thread to generate ffs file.")
+        Parser.add_option("--no-genfds-multi-thread", action="store_true", dest="NoGenfdsMultiThread", default=False, help="Disable GenFds multi thread to generate ffs file.")
+        Parser.add_option("--disable-include-path-check", action="store_true", dest="DisableIncludePathCheck", default=False, help="Disable the include path check for outside of package.")
+        self.BuildOption, self.BuildTarget = Parser.parse_args()
-- 
2.14.1.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#53144): https://edk2.groups.io/g/devel/message/53144
Mute This Topic: https://groups.io/mt/69596912/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [PATCH V2] BaseTools:Fix GenFds issue for BuildOption replace GenFdsOption

Posted by Bob Feng 1 week ago
Reviewed-by: Bob Feng <bob.c.feng@intel.com>

-----Original Message-----
From: Fan, ZhijuX 
Sent: Friday, January 10, 2020 4:30 PM
To: devel@edk2.groups.io
Cc: Gao, Liming <liming.gao@intel.com>; Feng, Bob C <bob.c.feng@intel.com>
Subject: [PATCH V2] BaseTools:Fix GenFds issue for BuildOption replace GenFdsOption

BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=2455

BuildOption is used by TargetTxtClassObj.py GenFdsOption is used by GenFds.py When the GenFds tool is used alone (e.g. python3 -m GenFds.GenFds -h) With the OptionParser function, the first detected function prints the help message

import TargetTxtClassObj to GenFds,
The BuildOption will be executed and replace GenFdsOption

We removed all objects associated with this problem that were created directly during the import process (e.g. BuildOption, BuildTarget = MyOptionParser(),  TargetTxt = TargetTxtDict())

The Patch is going to fix this issue

Signed-off-by: Zhiju.Fan <zhijux.fan@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Bob Feng <bob.c.feng@intel.com>
---
 BaseTools/Source/Python/AutoGen/BuildEngine.py     |  56 +++++++----
 BaseTools/Source/Python/Common/GlobalData.py       |   2 +-
 .../Source/Python/Common/TargetTxtClassObject.py   |  64 +++++++++------
 .../Source/Python/Common/ToolDefClassObject.py     |  48 +++++++---
 BaseTools/Source/Python/Common/buildoptions.py     |  93 ------------------
 BaseTools/Source/Python/GenFds/GenFds.py           |   4 +-
 .../Source/Python/GenFds/GenFdsGlobalVariable.py   |  17 ++--
 BaseTools/Source/Python/Workspace/DscBuildData.py  |   9 +-
 BaseTools/Source/Python/build/build.py             |  32 +++++--
 BaseTools/Source/Python/build/buildoptions.py      | 105 +++++++++++++++++++++
 10 files changed, 261 insertions(+), 169 deletions(-)  delete mode 100644 BaseTools/Source/Python/Common/buildoptions.py
 create mode 100644 BaseTools/Source/Python/build/buildoptions.py

The method by which the optimization function gets the parameter value add bugzilla to patch

diff --git a/BaseTools/Source/Python/AutoGen/BuildEngine.py b/BaseTools/Source/Python/AutoGen/BuildEngine.py
index 069a3a1c9d..d602414ca4 100644
--- a/BaseTools/Source/Python/AutoGen/BuildEngine.py
+++ b/BaseTools/Source/Python/AutoGen/BuildEngine.py
@@ -20,7 +20,7 @@ from Common.BuildToolError import *  from Common.Misc import tdict, PathClass  from Common.StringUtils import NormPath  from Common.DataType import * -from Common.TargetTxtClassObject import TargetTxt
+from Common.TargetTxtClassObject import TargetTxtDict
 gDefaultBuildRuleFile = 'build_rule.txt'
 AutoGenReqBuildRuleVerNum = '0.1'
 
@@ -588,24 +588,42 @@ class BuildRule:
         _UnknownSection    : SkipSection,
     }
 
-def GetBuildRule():
-    BuildRuleFile = None
-    if TAB_TAT_DEFINES_BUILD_RULE_CONF in TargetTxt.TargetTxtDictionary:
-        BuildRuleFile = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
-    if not BuildRuleFile:
-        BuildRuleFile = gDefaultBuildRuleFile
-    RetVal = BuildRule(BuildRuleFile)
-    if RetVal._FileVersion == "":
-        RetVal._FileVersion = AutoGenReqBuildRuleVerNum
-    else:
-        if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :
-            # If Build Rule's version is less than the version number required by the tools, halting the build.
-            EdkLogger.error("build", AUTOGEN_ERROR,
-                            ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
-                             % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))
-    return RetVal
-
-BuildRuleObj = GetBuildRule()
+class ToolBuildRule():
+
+    def __new__(cls, *args, **kw):
+        if not hasattr(cls, '_instance'):
+            orig = super(ToolBuildRule, cls)
+            cls._instance = orig.__new__(cls, *args, **kw)
+        return cls._instance
+
+    def __init__(self):
+        if not hasattr(self, 'ToolBuildRule'):
+            self._ToolBuildRule = None
+
+    @property
+    def ToolBuildRule(self):
+        if not self._ToolBuildRule:
+            self._GetBuildRule()
+        return self._ToolBuildRule
+
+    def _GetBuildRule(self):
+        BuildRuleFile = None
+        TargetObj = TargetTxtDict()
+        TargetTxt = TargetObj.Target
+        if TAB_TAT_DEFINES_BUILD_RULE_CONF in TargetTxt.TargetTxtDictionary:
+            BuildRuleFile = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
+        if not BuildRuleFile:
+            BuildRuleFile = gDefaultBuildRuleFile
+        RetVal = BuildRule(BuildRuleFile)
+        if RetVal._FileVersion == "":
+            RetVal._FileVersion = AutoGenReqBuildRuleVerNum
+        else:
+            if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :
+                # If Build Rule's version is less than the version number required by the tools, halting the build.
+                EdkLogger.error("build", AUTOGEN_ERROR,
+                                ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
+                                 % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))
+        self._ToolBuildRule = RetVal
 
 # This acts like the main() function for the script, unless it is 'import'ed into another  # script.
diff --git a/BaseTools/Source/Python/Common/GlobalData.py b/BaseTools/Source/Python/Common/GlobalData.py
index 0b3ebe035d..8ac29eb7a6 100755
--- a/BaseTools/Source/Python/Common/GlobalData.py
+++ b/BaseTools/Source/Python/Common/GlobalData.py
@@ -70,7 +70,7 @@ gAutoGenPhase = False
 # The Conf dir outside the workspace dir  #  gConfDirectory = ''
-
+gCmdConfDir = ''
 gBuildDirectory = ''
 #
 # The relative default database file path diff --git a/BaseTools/Source/Python/Common/TargetTxtClassObject.py b/BaseTools/Source/Python/Common/TargetTxtClassObject.py
index 723b9405bf..57212172fe 100644
--- a/BaseTools/Source/Python/Common/TargetTxtClassObject.py
+++ b/BaseTools/Source/Python/Common/TargetTxtClassObject.py
@@ -10,7 +10,7 @@
 #
 from __future__ import print_function
 from __future__ import absolute_import
-from Common.buildoptions import BuildOption,BuildTarget
+
 import Common.GlobalData as GlobalData
 import Common.LongFilePathOs as os
 from . import EdkLogger
@@ -144,29 +144,47 @@ class TargetTxtClassObject(object):
 #
 # @retval Target An instance of TargetTxtClassObject() with loaded target.txt  # -def TargetTxtDict():
-    Target = TargetTxtClassObject()
-    if BuildOption.ConfDirectory:
-        # Get alternate Conf location, if it is absolute, then just use the absolute directory name
-        ConfDirectoryPath = os.path.normpath(BuildOption.ConfDirectory)
-
-        if not os.path.isabs(ConfDirectoryPath):
-            # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
-            # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
-            ConfDirectoryPath = mws.join(os.environ["WORKSPACE"], ConfDirectoryPath)
-    else:
-        if "CONF_PATH" in os.environ:
-            ConfDirectoryPath = os.path.normcase(os.path.normpath(os.environ["CONF_PATH"]))
+
+class TargetTxtDict():
+
+    def __new__(cls, *args, **kw):
+        if not hasattr(cls, '_instance'):
+            orig = super(TargetTxtDict, cls)
+            cls._instance = orig.__new__(cls, *args, **kw)
+        return cls._instance
+
+    def __init__(self):
+        if not hasattr(self, 'Target'):
+            self.TxtTarget = None
+
+    @property
+    def Target(self):
+        if not self.TxtTarget:
+            self._GetTarget()
+        return self.TxtTarget
+
+    def _GetTarget(self):
+        Target = TargetTxtClassObject()
+        ConfDirectory = GlobalData.gCmdConfDir
+        if ConfDirectory:
+            # Get alternate Conf location, if it is absolute, then just use the absolute directory name
+            ConfDirectoryPath = os.path.normpath(ConfDirectory)
+
+            if not os.path.isabs(ConfDirectoryPath):
+                # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
+                # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
+                ConfDirectoryPath = mws.join(os.environ["WORKSPACE"], 
+ ConfDirectoryPath)
         else:
-            # Get standard WORKSPACE/Conf use the absolute path to the WORKSPACE/Conf
-            ConfDirectoryPath = mws.join(os.environ["WORKSPACE"], 'Conf')
-    GlobalData.gConfDirectory = ConfDirectoryPath
-    targettxt = os.path.normpath(os.path.join(ConfDirectoryPath, gDefaultTargetTxtFile))
-    if os.path.exists(targettxt):
-        Target.LoadTargetTxtFile(targettxt)
-    return Target
-
-TargetTxt = TargetTxtDict()
+            if "CONF_PATH" in os.environ:
+                ConfDirectoryPath = os.path.normcase(os.path.normpath(os.environ["CONF_PATH"]))
+            else:
+                # Get standard WORKSPACE/Conf use the absolute path to the WORKSPACE/Conf
+                ConfDirectoryPath = mws.join(os.environ["WORKSPACE"], 'Conf')
+        GlobalData.gConfDirectory = ConfDirectoryPath
+        targettxt = os.path.normpath(os.path.join(ConfDirectoryPath, gDefaultTargetTxtFile))
+        if os.path.exists(targettxt):
+            Target.LoadTargetTxtFile(targettxt)
+        self.TxtTarget = Target
 
 ##
 #
diff --git a/BaseTools/Source/Python/Common/ToolDefClassObject.py b/BaseTools/Source/Python/Common/ToolDefClassObject.py
index 063fa00584..8e70407cb9 100644
--- a/BaseTools/Source/Python/Common/ToolDefClassObject.py
+++ b/BaseTools/Source/Python/Common/ToolDefClassObject.py
@@ -14,7 +14,7 @@ import re
 from . import EdkLogger
 
 from .BuildToolError import *
-from Common.TargetTxtClassObject import TargetTxt
+from Common.TargetTxtClassObject import TargetTxtDict
 from Common.LongFilePathSupport import OpenLongFilePath as open  from Common.Misc import PathClass  from Common.StringUtils import NormPath @@ -262,20 +262,40 @@ class ToolDefClassObject(object):
 #
 # @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt  # -def ToolDefDict(ConfDir):
-    Target = TargetTxt
-    ToolDef = ToolDefClassObject()
-    if TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
-        ToolsDefFile = Target.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
-        if ToolsDefFile:
-            ToolDef.LoadToolDefFile(os.path.normpath(ToolsDefFile))
-        else:
-            ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
-    else:
-        ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
-    return ToolDef
 
-ToolDef = ToolDefDict((os.path.join(os.getenv("WORKSPACE"),"Conf")))
+
+class ToolDefDict():
+
+    def __new__(cls, ConfDir, *args, **kw):
+        if not hasattr(cls, '_instance'):
+            orig = super(ToolDefDict, cls)
+            cls._instance = orig.__new__(cls, *args, **kw)
+        return cls._instance
+
+    def __init__(self, ConfDir):
+        self.ConfDir = ConfDir
+        if not hasattr(self, 'ToolDef'):
+            self._ToolDef = None
+
+    @property
+    def ToolDef(self):
+        if not self._ToolDef:
+            self._GetToolDef()
+        return self._ToolDef
+
+    def _GetToolDef(self):
+        TargetObj = TargetTxtDict()
+        Target = TargetObj.Target
+        ToolDef = ToolDefClassObject()
+        if TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
+            ToolsDefFile = Target.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
+            if ToolsDefFile:
+                ToolDef.LoadToolDefFile(os.path.normpath(ToolsDefFile))
+            else:
+                ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(self.ConfDir, gDefaultToolsDefFile)))
+        else:
+            ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(self.ConfDir, gDefaultToolsDefFile)))
+        self._ToolDef = ToolDef
 
 ##
 #
diff --git a/BaseTools/Source/Python/Common/buildoptions.py b/BaseTools/Source/Python/Common/buildoptions.py
deleted file mode 100644
index a717c58d8c..0000000000
--- a/BaseTools/Source/Python/Common/buildoptions.py
+++ /dev/null
@@ -1,93 +0,0 @@
-## @file
-# build a platform or a module
-#
-#  Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR> -#  Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR> -#  Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR> -# -#  SPDX-License-Identifier: BSD-2-Clause-Patent -#
-
-# Version and Copyright
-from Common.BuildVersion import gBUILD_VERSION -from optparse import OptionParser -VersionNumber = "0.60" + ' ' + gBUILD_VERSION -__version__ = "%prog Version " + VersionNumber -__copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation  All rights reserved."
-
-gParamCheck = []
-def SingleCheckCallback(option, opt_str, value, parser):
-    if option not in gParamCheck:
-        setattr(parser.values, option.dest, value)
-        gParamCheck.append(option)
-    else:
-        parser.error("Option %s only allows one instance in command line!" % option)
-
-def MyOptionParser():
-    Parser = OptionParser(description=__copyright__, version=__version__, prog="build.exe", usage="%prog [options] [all|fds|genc|genmake|clean|cleanall|cleanlib|modules|libraries|run]")
-    Parser.add_option("-a", "--arch", action="append", type="choice", choices=['IA32', 'X64', 'EBC', 'ARM', 'AARCH64'], dest="TargetArch",
-        help="ARCHS is one of list: IA32, X64, ARM, AARCH64 or EBC, which overrides target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option.")
-    Parser.add_option("-p", "--platform", action="callback", type="string", dest="PlatformFile", callback=SingleCheckCallback,
-        help="Build the platform specified by the DSC file name argument, overriding target.txt's ACTIVE_PLATFORM definition.")
-    Parser.add_option("-m", "--module", action="callback", type="string", dest="ModuleFile", callback=SingleCheckCallback,
-        help="Build the module specified by the INF file name argument.")
-    Parser.add_option("-b", "--buildtarget", type="string", dest="BuildTarget", help="Using the TARGET to build the platform, overriding target.txt's TARGET definition.",
-                      action="append")
-    Parser.add_option("-t", "--tagname", action="append", type="string", dest="ToolChain",
-        help="Using the Tool Chain Tagname to build the platform, overriding target.txt's TOOL_CHAIN_TAG definition.")
-    Parser.add_option("-x", "--sku-id", action="callback", type="string", dest="SkuId", callback=SingleCheckCallback,
-        help="Using this name of SKU ID to build the platform, overriding SKUID_IDENTIFIER in DSC file.")
-
-    Parser.add_option("-n", action="callback", type="int", dest="ThreadNumber", callback=SingleCheckCallback,
-        help="Build the platform using multi-threaded compiler. The value overrides target.txt's MAX_CONCURRENT_THREAD_NUMBER. When value is set to 0, tool automatically detect number of "\
-             "processor threads, set value to 1 means disable multi-thread build, and set value to more than 1 means user specify the threads number to build.")
-
-    Parser.add_option("-f", "--fdf", action="callback", type="string", dest="FdfFile", callback=SingleCheckCallback,
-        help="The name of the FDF file to use, which overrides the setting in the DSC file.")
-    Parser.add_option("-r", "--rom-image", action="append", type="string", dest="RomImage", default=[],
-        help="The name of FD to be generated. The name must be from [FD] section in FDF file.")
-    Parser.add_option("-i", "--fv-image", action="append", type="string", dest="FvImage", default=[],
-        help="The name of FV to be generated. The name must be from [FV] section in FDF file.")
-    Parser.add_option("-C", "--capsule-image", action="append", type="string", dest="CapName", default=[],
-        help="The name of Capsule to be generated. The name must be from [Capsule] section in FDF file.")
-    Parser.add_option("-u", "--skip-autogen", action="store_true", dest="SkipAutoGen", help="Skip AutoGen step.")
-    Parser.add_option("-e", "--re-parse", action="store_true", dest="Reparse", help="Re-parse all meta-data files.")
-
-    Parser.add_option("-c", "--case-insensitive", action="store_true", dest="CaseInsensitive", default=False, help="Don't check case of file name.")
-
-    Parser.add_option("-w", "--warning-as-error", action="store_true", dest="WarningAsError", help="Treat warning in tools as error.")
-    Parser.add_option("-j", "--log", action="store", dest="LogFile", help="Put log in specified file as well as on console.")
-
-    Parser.add_option("-s", "--silent", action="store_true", type=None, dest="SilentMode",
-        help="Make use of silent mode of (n)make.")
-    Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
-    Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\
-                                                                               "including library instances selected, final dependency expression, "\
-                                                                               "and warning messages, etc.")
-    Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")
-    Parser.add_option("-D", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".")
-
-    Parser.add_option("-y", "--report-file", action="store", dest="ReportFile", help="Create/overwrite the report to the specified filename.")
-    Parser.add_option("-Y", "--report-type", action="append", type="choice", choices=['PCD', 'LIBRARY', 'FLASH', 'DEPEX', 'BUILD_FLAGS', 'FIXED_ADDRESS', 'HASH', 'EXECUTION_ORDER'], dest="ReportType", default=[],
-        help="Flags that control the type of build report to generate.  Must be one of: [PCD, LIBRARY, FLASH, DEPEX, BUILD_FLAGS, FIXED_ADDRESS, HASH, EXECUTION_ORDER].  "\
-             "To specify more than one flag, repeat this option on the command line and the default flag set is [PCD, LIBRARY, FLASH, DEPEX, HASH, BUILD_FLAGS, FIXED_ADDRESS]")
-    Parser.add_option("-F", "--flag", action="store", type="string", dest="Flag",
-        help="Specify the specific option to parse EDK UNI file. Must be one of: [-c, -s]. -c is for EDK framework UNI file, and -s is for EDK UEFI UNI file. "\
-             "This option can also be specified by setting *_*_*_BUILD_FLAGS in [BuildOptions] section of platform DSC. If they are both specified, this value "\
-             "will override the setting in [BuildOptions] section of platform DSC.")
-    Parser.add_option("-N", "--no-cache", action="store_true", dest="DisableCache", default=False, help="Disable build cache mechanism")
-    Parser.add_option("--conf", action="store", type="string", dest="ConfDirectory", help="Specify the customized Conf directory.")
-    Parser.add_option("--check-usage", action="store_true", dest="CheckUsage", default=False, help="Check usage content of entries listed in INF file.")
-    Parser.add_option("--ignore-sources", action="store_true", dest="IgnoreSources", default=False, help="Focus to a binary build and ignore all source files")
-    Parser.add_option("--pcd", action="append", dest="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
-    Parser.add_option("-l", "--cmd-len", action="store", type="int", dest="CommandLength", help="Specify the maximum line length of build command. Default is 4096.")
-    Parser.add_option("--hash", action="store_true", dest="UseHashCache", default=False, help="Enable hash-based caching during build process.")
-    Parser.add_option("--binary-destination", action="store", type="string", dest="BinCacheDest", help="Generate a cache of binary files in the specified directory.")
-    Parser.add_option("--binary-source", action="store", type="string", dest="BinCacheSource", help="Consume a cache of binary files from the specified directory.")
-    Parser.add_option("--genfds-multi-thread", action="store_true", dest="GenfdsMultiThread", default=True, help="Enable GenFds multi thread to generate ffs file.")
-    Parser.add_option("--no-genfds-multi-thread", action="store_true", dest="NoGenfdsMultiThread", default=False, help="Disable GenFds multi thread to generate ffs file.")
-    Parser.add_option("--disable-include-path-check", action="store_true", dest="DisableIncludePathCheck", default=False, help="Disable the include path check for outside of package.")
-    (Opt, Args) = Parser.parse_args()
-    return (Opt, Args)
-
-BuildOption, BuildTarget = MyOptionParser() diff --git a/BaseTools/Source/Python/GenFds/GenFds.py b/BaseTools/Source/Python/GenFds/GenFds.py
index d8bc28e4d0..d5511f4c40 100644
--- a/BaseTools/Source/Python/GenFds/GenFds.py
+++ b/BaseTools/Source/Python/GenFds/GenFds.py
@@ -20,7 +20,7 @@ from linecache import getlines  from io import BytesIO
 
 import Common.LongFilePathOs as os
-from Common.TargetTxtClassObject import TargetTxt
+from Common.TargetTxtClassObject import TargetTxtDict
 from Common.DataType import *
 import Common.GlobalData as GlobalData
 from Common import EdkLogger
@@ -210,6 +210,8 @@ def GenFdsApi(FdsCommandDict, WorkSpaceDataBase=None):
         BuildConfigurationFile = os.path.normpath(os.path.join(ConfDirectoryPath, "target.txt"))
         if os.path.isfile(BuildConfigurationFile) == True:
             # if no build target given in command line, get it from target.txt
+            TargetObj = TargetTxtDict()
+            TargetTxt = TargetObj.Target
             if not GenFdsGlobalVariable.TargetName:
                 BuildTargetList = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TARGET]
                 if len(BuildTargetList) != 1:
diff --git a/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
index 6e1ff7fe04..dc1727c466 100644
--- a/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
+++ b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
@@ -23,9 +23,9 @@ from Common.BuildToolError import COMMAND_FAILURE,GENFDS_ERROR  from Common import EdkLogger  from Common.Misc import SaveFileOnChange
 
-from Common.TargetTxtClassObject import TargetTxt -from Common.ToolDefClassObject import ToolDef -from AutoGen.BuildEngine import BuildRuleObj
+from Common.TargetTxtClassObject import TargetTxtDict from 
+Common.ToolDefClassObject import ToolDefDict from AutoGen.BuildEngine 
+import ToolBuildRule
 import Common.DataType as DataType
 from Common.Misc import PathClass
 from Common.LongFilePathSupport import OpenLongFilePath as open @@ -96,12 +96,15 @@ class GenFdsGlobalVariable:
     def _LoadBuildRule():
         if GenFdsGlobalVariable.__BuildRuleDatabase:
             return GenFdsGlobalVariable.__BuildRuleDatabase
-        GenFdsGlobalVariable.__BuildRuleDatabase = BuildRuleObj
-        ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
+        BuildRule = ToolBuildRule()
+        GenFdsGlobalVariable.__BuildRuleDatabase = BuildRule.ToolBuildRule
+        TargetObj = TargetTxtDict()
+        ToolDefinitionFile = 
+ TargetObj.Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHA
+ IN_CONF]
         if ToolDefinitionFile == '':
             ToolDefinitionFile = "Conf/tools_def.txt"
         if os.path.isfile(ToolDefinitionFile):
-            ToolDefinition = ToolDef.ToolsDefTxtDatabase
+            ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
+            ToolDefinition = ToolDefObj.ToolDef.ToolsDefTxtDatabase
             if DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDefinition \
                and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY] \
                and ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]:
@@ -830,6 +833,8 @@ class GenFdsGlobalVariable:
 #  @param  NameGuid         The Guid name
 #
 def FindExtendTool(KeyStringList, CurrentArchList, NameGuid):
+    ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
+    ToolDef = ToolDefObj.ToolDef
     ToolDb = ToolDef.ToolsDefTxtDatabase
     # if user not specify filter, try to deduce it from global data.
     if KeyStringList is None or KeyStringList == []:
diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
index 03a15bbf3e..c65a0dd346 100644
--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -19,8 +19,8 @@ from Common.Misc import *  from types import *  from Common.Expression import *  from CommonDataClass.CommonClass import SkuInfoClass -from Common.TargetTxtClassObject import TargetTxt -from Common.ToolDefClassObject import ToolDef
+from Common.TargetTxtClassObject import TargetTxtDict from 
+Common.ToolDefClassObject import ToolDefDict
 from .MetaDataTable import *
 from .MetaFileTable import *
 from .MetaFileParser import *
@@ -3296,6 +3296,8 @@ class DscBuildData(PlatformBuildClassObject):
     @property
     def ToolChainFamily(self):
         self._ToolChainFamily = TAB_COMPILER_MSFT
+        TargetObj = TargetTxtDict()
+        TargetTxt = TargetObj.Target
         BuildConfigurationFile = os.path.normpath(os.path.join(GlobalData.gConfDirectory, "target.txt"))
         if os.path.isfile(BuildConfigurationFile) == True:
             ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
@@ -3303,7 +3305,8 @@ class DscBuildData(PlatformBuildClassObject):
                 ToolDefinitionFile = "tools_def.txt"
                 ToolDefinitionFile = os.path.normpath(mws.join(self.WorkspaceDir, 'Conf', ToolDefinitionFile))
             if os.path.isfile(ToolDefinitionFile) == True:
-                ToolDefinition = ToolDef.ToolsDefTxtDatabase
+                ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
+                ToolDefinition = ToolDefObj.ToolDef.ToolsDefTxtDatabase
                 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
                    or self._Toolchain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
                    or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self._Toolchain]:
diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py
index 3cc4220e2f..34acdccbdb 100755
--- a/BaseTools/Source/Python/build/build.py
+++ b/BaseTools/Source/Python/build/build.py
@@ -26,7 +26,7 @@ from threading import Thread,Event,BoundedSemaphore  import threading  from subprocess import Popen,PIPE, STDOUT  from collections import OrderedDict, defaultdict -from Common.buildoptions import BuildOption,BuildTarget
+
 from AutoGen.PlatformAutoGen import PlatformAutoGen  from AutoGen.ModuleAutoGen import ModuleAutoGen  from AutoGen.WorkspaceAutoGen import WorkspaceAutoGen @@ -35,8 +35,9 @@ from AutoGen.AutoGenWorker import AutoGenWorkerInProcess,AutoGenManager,\
 from AutoGen import GenMake
 from Common import Misc as Utils
 
-from Common.TargetTxtClassObject import TargetTxt -from Common.ToolDefClassObject import ToolDef
+from Common.TargetTxtClassObject import TargetTxtDict from 
+Common.ToolDefClassObject import ToolDefDict from buildoptions import 
+MyOptionParser
 from Common.Misc import PathClass,SaveFileOnChange,RemoveDirectory
 from Common.StringUtils import NormPath  from Common.MultipleWorkspace import MultipleWorkspace as mws @@ -731,11 +732,13 @@ class Build():
         self.ConfDirectory = BuildOptions.ConfDirectory
         self.SpawnMode      = True
         self.BuildReport    = BuildReport(BuildOptions.ReportFile, BuildOptions.ReportType)
-        self.TargetTxt      = TargetTxt
-        self.ToolDef        = ToolDef
         self.AutoGenTime    = 0
         self.MakeTime       = 0
         self.GenFdsTime     = 0
+        TargetObj = TargetTxtDict()
+        ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"),"Conf")))
+        self.TargetTxt = TargetObj.Target
+        self.ToolDef = ToolDefObj.ToolDef
         GlobalData.BuildOptionPcd     = BuildOptions.OptionPcd if BuildOptions.OptionPcd else []
         #Set global flag for build mode
         GlobalData.gIgnoreSource = BuildOptions.IgnoreSources @@ -816,8 +819,10 @@ class Build():
             EdkLogger.quiet("%-16s = %s" % ("POSTBUILD", self.Postbuild))
         if self.Prebuild:
             self.LaunchPrebuild()
-            self.TargetTxt = TargetTxt
-            self.ToolDef   = ToolDef
+            TargetObj = TargetTxtDict()
+            ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
+            self.TargetTxt = TargetObj.Target
+            self.ToolDef = ToolDefObj.ToolDef
         if not (self.LaunchPrebuildFlag and os.path.exists(self.PlatformBuildPath)):
             self.InitBuild()
 
@@ -2438,9 +2443,15 @@ def LogBuildTime(Time):
     else:
         return None
 def ThreadNum():
+    OptionParser = MyOptionParser()
+    if not OptionParser.BuildOption and not OptionParser.BuildTarget:
+        OptionParser.GetOption()
+    BuildOption, BuildTarget = OptionParser.BuildOption, 
+ OptionParser.BuildTarget
     ThreadNumber = BuildOption.ThreadNumber
+    GlobalData.gCmdConfDir = BuildOption.ConfDirectory
     if ThreadNumber is None:
-        ThreadNumber = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER]
+        TargetObj = TargetTxtDict()
+        ThreadNumber = 
+ TargetObj.Target.TargetTxtDictionary[TAB_TAT_DEFINES_MAX_CONCURRENT_TH
+ READ_NUMBER]
         if ThreadNumber == '':
             ThreadNumber = 0
         else:
@@ -2475,7 +2486,10 @@ def Main():
     #
     # Parse the options and args
     #
-    Option, Target = BuildOption, BuildTarget
+    OptionParser = MyOptionParser()
+    if not OptionParser.BuildOption and not OptionParser.BuildTarget:
+        OptionParser.GetOption()
+    Option, Target = OptionParser.BuildOption, OptionParser.BuildTarget
     GlobalData.gOptions = Option
     GlobalData.gCaseInsensitive = Option.CaseInsensitive
 
diff --git a/BaseTools/Source/Python/build/buildoptions.py b/BaseTools/Source/Python/build/buildoptions.py
new file mode 100644
index 0000000000..4ad95b9f4f
--- /dev/null
+++ b/BaseTools/Source/Python/build/buildoptions.py
@@ -0,0 +1,105 @@
+## @file
+# build a platform or a module
+#
+#  Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR> #  
+Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR> 
+#  Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR> 
+# #  SPDX-License-Identifier: BSD-2-Clause-Patent #
+
+# Version and Copyright
+from Common.BuildVersion import gBUILD_VERSION from optparse import 
+OptionParser VersionNumber = "0.60" + ' ' + gBUILD_VERSION __version__ 
+= "%prog Version " + VersionNumber __copyright__ = "Copyright (c) 2007 
+- 2018, Intel Corporation  All rights reserved."
+
+gParamCheck = []
+def SingleCheckCallback(option, opt_str, value, parser):
+    if option not in gParamCheck:
+        setattr(parser.values, option.dest, value)
+        gParamCheck.append(option)
+    else:
+        parser.error("Option %s only allows one instance in command 
+line!" % option)
+
+
+class MyOptionParser():
+
+    def __new__(cls, *args, **kw):
+        if not hasattr(cls, '_instance'):
+            orig = super(MyOptionParser, cls)
+            cls._instance = orig.__new__(cls, *args, **kw)
+        return cls._instance
+
+    def __init__(self):
+        if not hasattr(self, 'BuildOption'):
+            self.BuildOption = None
+        if not hasattr(self, 'BuildTarget'):
+            self.BuildTarget = None
+
+    def GetOption(self):
+        Parser = OptionParser(description=__copyright__, version=__version__, prog="build.exe", usage="%prog [options] [all|fds|genc|genmake|clean|cleanall|cleanlib|modules|libraries|run]")
+        Parser.add_option("-a", "--arch", action="append", type="choice", choices=['IA32', 'X64', 'EBC', 'ARM', 'AARCH64'], dest="TargetArch",
+            help="ARCHS is one of list: IA32, X64, ARM, AARCH64 or EBC, which overrides target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option.")
+        Parser.add_option("-p", "--platform", action="callback", type="string", dest="PlatformFile", callback=SingleCheckCallback,
+            help="Build the platform specified by the DSC file name argument, overriding target.txt's ACTIVE_PLATFORM definition.")
+        Parser.add_option("-m", "--module", action="callback", type="string", dest="ModuleFile", callback=SingleCheckCallback,
+            help="Build the module specified by the INF file name argument.")
+        Parser.add_option("-b", "--buildtarget", type="string", dest="BuildTarget", help="Using the TARGET to build the platform, overriding target.txt's TARGET definition.",
+                          action="append")
+        Parser.add_option("-t", "--tagname", action="append", type="string", dest="ToolChain",
+            help="Using the Tool Chain Tagname to build the platform, overriding target.txt's TOOL_CHAIN_TAG definition.")
+        Parser.add_option("-x", "--sku-id", action="callback", type="string", dest="SkuId", callback=SingleCheckCallback,
+            help="Using this name of SKU ID to build the platform, 
+ overriding SKUID_IDENTIFIER in DSC file.")
+
+        Parser.add_option("-n", action="callback", type="int", dest="ThreadNumber", callback=SingleCheckCallback,
+            help="Build the platform using multi-threaded compiler. The value overrides target.txt's MAX_CONCURRENT_THREAD_NUMBER. When value is set to 0, tool automatically detect number of "\
+                 "processor threads, set value to 1 means disable 
+ multi-thread build, and set value to more than 1 means user specify 
+ the threads number to build.")
+
+        Parser.add_option("-f", "--fdf", action="callback", type="string", dest="FdfFile", callback=SingleCheckCallback,
+            help="The name of the FDF file to use, which overrides the setting in the DSC file.")
+        Parser.add_option("-r", "--rom-image", action="append", type="string", dest="RomImage", default=[],
+            help="The name of FD to be generated. The name must be from [FD] section in FDF file.")
+        Parser.add_option("-i", "--fv-image", action="append", type="string", dest="FvImage", default=[],
+            help="The name of FV to be generated. The name must be from [FV] section in FDF file.")
+        Parser.add_option("-C", "--capsule-image", action="append", type="string", dest="CapName", default=[],
+            help="The name of Capsule to be generated. The name must be from [Capsule] section in FDF file.")
+        Parser.add_option("-u", "--skip-autogen", action="store_true", dest="SkipAutoGen", help="Skip AutoGen step.")
+        Parser.add_option("-e", "--re-parse", action="store_true", 
+ dest="Reparse", help="Re-parse all meta-data files.")
+
+        Parser.add_option("-c", "--case-insensitive", 
+ action="store_true", dest="CaseInsensitive", default=False, 
+ help="Don't check case of file name.")
+
+        Parser.add_option("-w", "--warning-as-error", action="store_true", dest="WarningAsError", help="Treat warning in tools as error.")
+        Parser.add_option("-j", "--log", action="store", 
+ dest="LogFile", help="Put log in specified file as well as on 
+ console.")
+
+        Parser.add_option("-s", "--silent", action="store_true", type=None, dest="SilentMode",
+            help="Make use of silent mode of (n)make.")
+        Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
+        Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\
+                                                                                   "including library instances selected, final dependency expression, "\
+                                                                                   "and warning messages, etc.")
+        Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")
+        Parser.add_option("-D", "--define", action="append", 
+ type="string", dest="Macros", help="Macro: \"Name [= Value]\".")
+
+        Parser.add_option("-y", "--report-file", action="store", dest="ReportFile", help="Create/overwrite the report to the specified filename.")
+        Parser.add_option("-Y", "--report-type", action="append", type="choice", choices=['PCD', 'LIBRARY', 'FLASH', 'DEPEX', 'BUILD_FLAGS', 'FIXED_ADDRESS', 'HASH', 'EXECUTION_ORDER'], dest="ReportType", default=[],
+            help="Flags that control the type of build report to generate.  Must be one of: [PCD, LIBRARY, FLASH, DEPEX, BUILD_FLAGS, FIXED_ADDRESS, HASH, EXECUTION_ORDER].  "\
+                 "To specify more than one flag, repeat this option on the command line and the default flag set is [PCD, LIBRARY, FLASH, DEPEX, HASH, BUILD_FLAGS, FIXED_ADDRESS]")
+        Parser.add_option("-F", "--flag", action="store", type="string", dest="Flag",
+            help="Specify the specific option to parse EDK UNI file. Must be one of: [-c, -s]. -c is for EDK framework UNI file, and -s is for EDK UEFI UNI file. "\
+                 "This option can also be specified by setting *_*_*_BUILD_FLAGS in [BuildOptions] section of platform DSC. If they are both specified, this value "\
+                 "will override the setting in [BuildOptions] section of platform DSC.")
+        Parser.add_option("-N", "--no-cache", action="store_true", dest="DisableCache", default=False, help="Disable build cache mechanism")
+        Parser.add_option("--conf", action="store", type="string", dest="ConfDirectory", help="Specify the customized Conf directory.")
+        Parser.add_option("--check-usage", action="store_true", dest="CheckUsage", default=False, help="Check usage content of entries listed in INF file.")
+        Parser.add_option("--ignore-sources", action="store_true", dest="IgnoreSources", default=False, help="Focus to a binary build and ignore all source files")
+        Parser.add_option("--pcd", action="append", dest="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
+        Parser.add_option("-l", "--cmd-len", action="store", type="int", dest="CommandLength", help="Specify the maximum line length of build command. Default is 4096.")
+        Parser.add_option("--hash", action="store_true", dest="UseHashCache", default=False, help="Enable hash-based caching during build process.")
+        Parser.add_option("--binary-destination", action="store", type="string", dest="BinCacheDest", help="Generate a cache of binary files in the specified directory.")
+        Parser.add_option("--binary-source", action="store", type="string", dest="BinCacheSource", help="Consume a cache of binary files from the specified directory.")
+        Parser.add_option("--genfds-multi-thread", action="store_true", dest="GenfdsMultiThread", default=True, help="Enable GenFds multi thread to generate ffs file.")
+        Parser.add_option("--no-genfds-multi-thread", action="store_true", dest="NoGenfdsMultiThread", default=False, help="Disable GenFds multi thread to generate ffs file.")
+        Parser.add_option("--disable-include-path-check", action="store_true", dest="DisableIncludePathCheck", default=False, help="Disable the include path check for outside of package.")
+        self.BuildOption, self.BuildTarget = Parser.parse_args()
--
2.14.1.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#53177): https://edk2.groups.io/g/devel/message/53177
Mute This Topic: https://groups.io/mt/69596912/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-