]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Edk2ToolsBuild.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Edk2ToolsBuild.py
1 # @file Edk2ToolsBuild.py
2 # Invocable class that builds the basetool c files.
3 #
4 # Supports VS2017, VS2019, and GCC5
5 ##
6 # Copyright (c) Microsoft Corporation
7 #
8 # SPDX-License-Identifier: BSD-2-Clause-Patent
9 ##
10 import os
11 import sys
12 import logging
13 import argparse
14 import multiprocessing
15 from edk2toolext import edk2_logging
16 from edk2toolext.environment import self_describing_environment
17 from edk2toolext.base_abstract_invocable import BaseAbstractInvocable
18 from edk2toollib.utility_functions import RunCmd
19 from edk2toollib.windows.locate_tools import QueryVcVariables
20
21
22 class Edk2ToolsBuild(BaseAbstractInvocable):
23
24 def ParseCommandLineOptions(self):
25 ''' parse arguments '''
26 ParserObj = argparse.ArgumentParser()
27 ParserObj.add_argument("-t", "--tool_chain_tag", dest="tct", default="VS2017",
28 help="Set the toolchain used to compile the build tools")
29 args = ParserObj.parse_args()
30 self.tool_chain_tag = args.tct
31
32 def GetWorkspaceRoot(self):
33 ''' Return the workspace root for initializing the SDE '''
34
35 # this is the bastools dir...not the traditional EDK2 workspace root
36 return os.path.dirname(os.path.abspath(__file__))
37
38 def GetActiveScopes(self):
39 ''' return tuple containing scopes that should be active for this process '''
40
41 # for now don't use scopes
42 return ('global',)
43
44 def GetLoggingLevel(self, loggerType):
45 ''' Get the logging level for a given type (return Logging.Level)
46 base == lowest logging level supported
47 con == Screen logging
48 txt == plain text file logging
49 md == markdown file logging
50 '''
51 if(loggerType == "con"):
52 return logging.ERROR
53 else:
54 return logging.DEBUG
55
56 def GetLoggingFolderRelativeToRoot(self):
57 ''' Return a path to folder for log files '''
58 return "BaseToolsBuild"
59
60 def GetVerifyCheckRequired(self):
61 ''' Will call self_describing_environment.VerifyEnvironment if this returns True '''
62 return True
63
64 def GetLoggingFileName(self, loggerType):
65 ''' Get the logging file name for the type.
66 Return None if the logger shouldn't be created
67
68 base == lowest logging level supported
69 con == Screen logging
70 txt == plain text file logging
71 md == markdown file logging
72 '''
73 return "BASETOOLS_BUILD"
74
75 def WritePathEnvFile(self, OutputDir):
76 ''' Write a PyTool path env file for future PyTool based edk2 builds'''
77 content = '''##
78 # Set shell variable EDK_TOOLS_BIN to this folder
79 #
80 # Autogenerated by Edk2ToolsBuild.py
81 #
82 # Copyright (c), Microsoft Corporation
83 # SPDX-License-Identifier: BSD-2-Clause-Patent
84 ##
85 {
86 "id": "You-Built-BaseTools",
87 "scope": "edk2-build",
88 "flags": ["set_shell_var", "set_path"],
89 "var_name": "EDK_TOOLS_BIN"
90 }
91 '''
92 with open(os.path.join(OutputDir, "basetoolsbin_path_env.yaml"), "w") as f:
93 f.write(content)
94
95 def Go(self):
96 logging.info("Running Python version: " + str(sys.version_info))
97
98 (build_env, shell_env) = self_describing_environment.BootstrapEnvironment(
99 self.GetWorkspaceRoot(), self.GetActiveScopes())
100
101 # # Bind our current execution environment into the shell vars.
102 ph = os.path.dirname(sys.executable)
103 if " " in ph:
104 ph = '"' + ph + '"'
105 shell_env.set_shell_var("PYTHON_HOME", ph)
106 # PYTHON_COMMAND is required to be set for using edk2 python builds.
107 pc = sys.executable
108 if " " in pc:
109 pc = '"' + pc + '"'
110 shell_env.set_shell_var("PYTHON_COMMAND", pc)
111
112 if self.tool_chain_tag.lower().startswith("vs"):
113
114 # # Update environment with required VC vars.
115 interesting_keys = ["ExtensionSdkDir", "INCLUDE", "LIB"]
116 interesting_keys.extend(
117 ["LIBPATH", "Path", "UniversalCRTSdkDir", "UCRTVersion", "WindowsLibPath", "WindowsSdkBinPath"])
118 interesting_keys.extend(
119 ["WindowsSdkDir", "WindowsSdkVerBinPath", "WindowsSDKVersion", "VCToolsInstallDir"])
120 vc_vars = QueryVcVariables(
121 interesting_keys, 'x86', vs_version=self.tool_chain_tag.lower())
122 for key in vc_vars.keys():
123 logging.debug(f"Var - {key} = {vc_vars[key]}")
124 if key.lower() == 'path':
125 shell_env.insert_path(vc_vars[key])
126 else:
127 shell_env.set_shell_var(key, vc_vars[key])
128
129 self.OutputDir = os.path.join(
130 shell_env.get_shell_var("EDK_TOOLS_PATH"), "Bin", "Win32")
131
132 # compiled tools need to be added to path because antlr is referenced
133 shell_env.insert_path(self.OutputDir)
134
135 # Actually build the tools.
136 ret = RunCmd('nmake.exe', None,
137 workingdir=shell_env.get_shell_var("EDK_TOOLS_PATH"))
138 if ret != 0:
139 raise Exception("Failed to build.")
140
141 self.WritePathEnvFile(self.OutputDir)
142 return ret
143
144 elif self.tool_chain_tag.lower().startswith("gcc"):
145 cpu_count = self.GetCpuThreads()
146 ret = RunCmd("make", f"-C . -j {cpu_count}", workingdir=shell_env.get_shell_var("EDK_TOOLS_PATH"))
147 if ret != 0:
148 raise Exception("Failed to build.")
149
150 self.OutputDir = os.path.join(
151 shell_env.get_shell_var("EDK_TOOLS_PATH"), "Source", "C", "bin")
152
153 self.WritePathEnvFile(self.OutputDir)
154 return ret
155
156 logging.critical("Tool Chain not supported")
157 return -1
158
159 def GetCpuThreads(self) -> int:
160 ''' Function to return number of cpus. If error return 1'''
161 cpus = 1
162 try:
163 cpus = multiprocessing.cpu_count()
164 except:
165 # from the internet there are cases where cpu_count is not implemented.
166 # will handle error by just doing single proc build
167 pass
168 return cpus
169
170
171
172 def main():
173 Edk2ToolsBuild().Invoke()
174
175
176 if __name__ == "__main__":
177 main()