diff options
Diffstat (limited to 'BaseTools/Edk2ToolsBuild.py')
| -rw-r--r-- | BaseTools/Edk2ToolsBuild.py | 376 |
1 files changed, 188 insertions, 188 deletions
diff --git a/BaseTools/Edk2ToolsBuild.py b/BaseTools/Edk2ToolsBuild.py index 425bb1b639..81acb9304c 100644 --- a/BaseTools/Edk2ToolsBuild.py +++ b/BaseTools/Edk2ToolsBuild.py @@ -1,188 +1,188 @@ -# @file Edk2ToolsBuild.py
-# Invocable class that builds the basetool c files.
-#
-# Supports VS2017, VS2019, and GCC5
-##
-# Copyright (c) Microsoft Corporation
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-##
-import os
-import sys
-import logging
-import argparse
-import multiprocessing
-from edk2toolext import edk2_logging
-from edk2toolext.environment import self_describing_environment
-from edk2toolext.base_abstract_invocable import BaseAbstractInvocable
-from edk2toollib.utility_functions import RunCmd
-from edk2toollib.windows.locate_tools import QueryVcVariables
-
-
-class Edk2ToolsBuild(BaseAbstractInvocable):
-
- def ParseCommandLineOptions(self):
- ''' parse arguments '''
- ParserObj = argparse.ArgumentParser()
- ParserObj.add_argument("-t", "--tool_chain_tag", dest="tct", default="VS2017",
- help="Set the toolchain used to compile the build tools")
- args = ParserObj.parse_args()
- self.tool_chain_tag = args.tct
-
- def GetWorkspaceRoot(self):
- ''' Return the workspace root for initializing the SDE '''
-
- # this is the bastools dir...not the traditional EDK2 workspace root
- return os.path.dirname(os.path.abspath(__file__))
-
- def GetActiveScopes(self):
- ''' return tuple containing scopes that should be active for this process '''
-
- # for now don't use scopes
- return ('global',)
-
- def GetLoggingLevel(self, loggerType):
- ''' Get the logging level for a given type (return Logging.Level)
- base == lowest logging level supported
- con == Screen logging
- txt == plain text file logging
- md == markdown file logging
- '''
- if(loggerType == "con"):
- return logging.ERROR
- else:
- return logging.DEBUG
-
- def GetLoggingFolderRelativeToRoot(self):
- ''' Return a path to folder for log files '''
- return "BaseToolsBuild"
-
- def GetVerifyCheckRequired(self):
- ''' Will call self_describing_environment.VerifyEnvironment if this returns True '''
- return True
-
- def GetLoggingFileName(self, loggerType):
- ''' Get the logging file name for the type.
- Return None if the logger shouldn't be created
-
- base == lowest logging level supported
- con == Screen logging
- txt == plain text file logging
- md == markdown file logging
- '''
- return "BASETOOLS_BUILD"
-
- def WritePathEnvFile(self, OutputDir):
- ''' Write a PyTool path env file for future PyTool based edk2 builds'''
- content = '''##
-# Set shell variable EDK_TOOLS_BIN to this folder
-#
-# Autogenerated by Edk2ToolsBuild.py
-#
-# Copyright (c), Microsoft Corporation
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-##
-{
- "id": "You-Built-BaseTools",
- "scope": "edk2-build",
- "flags": ["set_shell_var", "set_path"],
- "var_name": "EDK_TOOLS_BIN"
-}
-'''
- with open(os.path.join(OutputDir, "basetoolsbin_path_env.yaml"), "w") as f:
- f.write(content)
-
- def Go(self):
- logging.info("Running Python version: " + str(sys.version_info))
-
- (build_env, shell_env) = self_describing_environment.BootstrapEnvironment(
- self.GetWorkspaceRoot(), self.GetActiveScopes())
-
- # # Bind our current execution environment into the shell vars.
- ph = os.path.dirname(sys.executable)
- if " " in ph:
- ph = '"' + ph + '"'
- shell_env.set_shell_var("PYTHON_HOME", ph)
- # PYTHON_COMMAND is required to be set for using edk2 python builds.
- pc = sys.executable
- if " " in pc:
- pc = '"' + pc + '"'
- shell_env.set_shell_var("PYTHON_COMMAND", pc)
-
- if self.tool_chain_tag.lower().startswith("vs"):
-
- # # Update environment with required VC vars.
- interesting_keys = ["ExtensionSdkDir", "INCLUDE", "LIB"]
- interesting_keys.extend(
- ["LIBPATH", "Path", "UniversalCRTSdkDir", "UCRTVersion", "WindowsLibPath", "WindowsSdkBinPath"])
- interesting_keys.extend(
- ["WindowsSdkDir", "WindowsSdkVerBinPath", "WindowsSDKVersion", "VCToolsInstallDir"])
- vc_vars = QueryVcVariables(
- interesting_keys, 'x86', vs_version=self.tool_chain_tag.lower())
- for key in vc_vars.keys():
- logging.debug(f"Var - {key} = {vc_vars[key]}")
- if key.lower() == 'path':
- shell_env.set_path(vc_vars[key])
- else:
- shell_env.set_shell_var(key, vc_vars[key])
-
- self.OutputDir = os.path.join(
- shell_env.get_shell_var("EDK_TOOLS_PATH"), "Bin", "Win32")
-
- # compiled tools need to be added to path because antlr is referenced
- shell_env.insert_path(self.OutputDir)
-
- # Actually build the tools.
- output_stream = edk2_logging.create_output_stream()
- ret = RunCmd('nmake.exe', None,
- workingdir=shell_env.get_shell_var("EDK_TOOLS_PATH"))
- edk2_logging.remove_output_stream(output_stream)
- problems = edk2_logging.scan_compiler_output(output_stream)
- for level, problem in problems:
- logging.log(level, problem)
- if ret != 0:
- raise Exception("Failed to build.")
-
- self.WritePathEnvFile(self.OutputDir)
- return ret
-
- elif self.tool_chain_tag.lower().startswith("gcc"):
- cpu_count = self.GetCpuThreads()
-
- output_stream = edk2_logging.create_output_stream()
- ret = RunCmd("make", f"-C . -j {cpu_count}", workingdir=shell_env.get_shell_var("EDK_TOOLS_PATH"))
- edk2_logging.remove_output_stream(output_stream)
- problems = edk2_logging.scan_compiler_output(output_stream)
- for level, problem in problems:
- logging.log(level, problem)
- if ret != 0:
- raise Exception("Failed to build.")
-
- self.OutputDir = os.path.join(
- shell_env.get_shell_var("EDK_TOOLS_PATH"), "Source", "C", "bin")
-
- self.WritePathEnvFile(self.OutputDir)
- return ret
-
- logging.critical("Tool Chain not supported")
- return -1
-
- def GetCpuThreads(self) -> int:
- ''' Function to return number of cpus. If error return 1'''
- cpus = 1
- try:
- cpus = multiprocessing.cpu_count()
- except:
- # from the internet there are cases where cpu_count is not implemented.
- # will handle error by just doing single proc build
- pass
- return cpus
-
-
-
-def main():
- Edk2ToolsBuild().Invoke()
-
-
-if __name__ == "__main__":
- main()
+# @file Edk2ToolsBuild.py +# Invocable class that builds the basetool c files. +# +# Supports VS2017, VS2019, and GCC5 +## +# Copyright (c) Microsoft Corporation +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## +import os +import sys +import logging +import argparse +import multiprocessing +from edk2toolext import edk2_logging +from edk2toolext.environment import self_describing_environment +from edk2toolext.base_abstract_invocable import BaseAbstractInvocable +from edk2toollib.utility_functions import RunCmd +from edk2toollib.windows.locate_tools import QueryVcVariables + + +class Edk2ToolsBuild(BaseAbstractInvocable): + + def ParseCommandLineOptions(self): + ''' parse arguments ''' + ParserObj = argparse.ArgumentParser() + ParserObj.add_argument("-t", "--tool_chain_tag", dest="tct", default="VS2017", + help="Set the toolchain used to compile the build tools") + args = ParserObj.parse_args() + self.tool_chain_tag = args.tct + + def GetWorkspaceRoot(self): + ''' Return the workspace root for initializing the SDE ''' + + # this is the bastools dir...not the traditional EDK2 workspace root + return os.path.dirname(os.path.abspath(__file__)) + + def GetActiveScopes(self): + ''' return tuple containing scopes that should be active for this process ''' + + # for now don't use scopes + return ('global',) + + def GetLoggingLevel(self, loggerType): + ''' Get the logging level for a given type (return Logging.Level) + base == lowest logging level supported + con == Screen logging + txt == plain text file logging + md == markdown file logging + ''' + if(loggerType == "con"): + return logging.ERROR + else: + return logging.DEBUG + + def GetLoggingFolderRelativeToRoot(self): + ''' Return a path to folder for log files ''' + return "BaseToolsBuild" + + def GetVerifyCheckRequired(self): + ''' Will call self_describing_environment.VerifyEnvironment if this returns True ''' + return True + + def GetLoggingFileName(self, loggerType): + ''' Get the logging file name for the type. + Return None if the logger shouldn't be created + + base == lowest logging level supported + con == Screen logging + txt == plain text file logging + md == markdown file logging + ''' + return "BASETOOLS_BUILD" + + def WritePathEnvFile(self, OutputDir): + ''' Write a PyTool path env file for future PyTool based edk2 builds''' + content = '''## +# Set shell variable EDK_TOOLS_BIN to this folder +# +# Autogenerated by Edk2ToolsBuild.py +# +# Copyright (c), Microsoft Corporation +# SPDX-License-Identifier: BSD-2-Clause-Patent +## +{ + "id": "You-Built-BaseTools", + "scope": "edk2-build", + "flags": ["set_shell_var", "set_path"], + "var_name": "EDK_TOOLS_BIN" +} +''' + with open(os.path.join(OutputDir, "basetoolsbin_path_env.yaml"), "w") as f: + f.write(content) + + def Go(self): + logging.info("Running Python version: " + str(sys.version_info)) + + (build_env, shell_env) = self_describing_environment.BootstrapEnvironment( + self.GetWorkspaceRoot(), self.GetActiveScopes()) + + # # Bind our current execution environment into the shell vars. + ph = os.path.dirname(sys.executable) + if " " in ph: + ph = '"' + ph + '"' + shell_env.set_shell_var("PYTHON_HOME", ph) + # PYTHON_COMMAND is required to be set for using edk2 python builds. + pc = sys.executable + if " " in pc: + pc = '"' + pc + '"' + shell_env.set_shell_var("PYTHON_COMMAND", pc) + + if self.tool_chain_tag.lower().startswith("vs"): + + # # Update environment with required VC vars. + interesting_keys = ["ExtensionSdkDir", "INCLUDE", "LIB"] + interesting_keys.extend( + ["LIBPATH", "Path", "UniversalCRTSdkDir", "UCRTVersion", "WindowsLibPath", "WindowsSdkBinPath"]) + interesting_keys.extend( + ["WindowsSdkDir", "WindowsSdkVerBinPath", "WindowsSDKVersion", "VCToolsInstallDir"]) + vc_vars = QueryVcVariables( + interesting_keys, 'x86', vs_version=self.tool_chain_tag.lower()) + for key in vc_vars.keys(): + logging.debug(f"Var - {key} = {vc_vars[key]}") + if key.lower() == 'path': + shell_env.set_path(vc_vars[key]) + else: + shell_env.set_shell_var(key, vc_vars[key]) + + self.OutputDir = os.path.join( + shell_env.get_shell_var("EDK_TOOLS_PATH"), "Bin", "Win32") + + # compiled tools need to be added to path because antlr is referenced + shell_env.insert_path(self.OutputDir) + + # Actually build the tools. + output_stream = edk2_logging.create_output_stream() + ret = RunCmd('nmake.exe', None, + workingdir=shell_env.get_shell_var("EDK_TOOLS_PATH")) + edk2_logging.remove_output_stream(output_stream) + problems = edk2_logging.scan_compiler_output(output_stream) + for level, problem in problems: + logging.log(level, problem) + if ret != 0: + raise Exception("Failed to build.") + + self.WritePathEnvFile(self.OutputDir) + return ret + + elif self.tool_chain_tag.lower().startswith("gcc"): + cpu_count = self.GetCpuThreads() + + output_stream = edk2_logging.create_output_stream() + ret = RunCmd("make", f"-C . -j {cpu_count}", workingdir=shell_env.get_shell_var("EDK_TOOLS_PATH")) + edk2_logging.remove_output_stream(output_stream) + problems = edk2_logging.scan_compiler_output(output_stream) + for level, problem in problems: + logging.log(level, problem) + if ret != 0: + raise Exception("Failed to build.") + + self.OutputDir = os.path.join( + shell_env.get_shell_var("EDK_TOOLS_PATH"), "Source", "C", "bin") + + self.WritePathEnvFile(self.OutputDir) + return ret + + logging.critical("Tool Chain not supported") + return -1 + + def GetCpuThreads(self) -> int: + ''' Function to return number of cpus. If error return 1''' + cpus = 1 + try: + cpus = multiprocessing.cpu_count() + except: + # from the internet there are cases where cpu_count is not implemented. + # will handle error by just doing single proc build + pass + return cpus + + + +def main(): + Edk2ToolsBuild().Invoke() + + +if __name__ == "__main__": + main() |
