VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/BaseTools/Plugin/WindowsVsToolChain/WindowsVsToolChain.py@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 17.8 KB
Line 
1# @file WindowsVsToolChain.py
2# Plugin to configure the environment for the VS2017, VS2019, and VS2022 toolchains
3#
4# This plugin also runs for CLANGPDB toolchain on Windows as that toolchain
5# leverages nmake from VS and needs to the SDK paths for unit tests
6##
7# This plugin works in conjuncture with the tools_def
8#
9# Copyright (c) Microsoft Corporation
10# SPDX-License-Identifier: BSD-2-Clause-Patent
11##
12import os
13import logging
14from edk2toolext.environment.plugintypes.uefi_build_plugin import IUefiBuildPlugin
15import edk2toollib.windows.locate_tools as locate_tools
16from edk2toollib.windows.locate_tools import FindWithVsWhere
17from edk2toolext.environment import shell_environment
18from edk2toolext.environment import version_aggregator
19from edk2toollib.utility_functions import GetHostInfo
20
21
22class WindowsVsToolChain(IUefiBuildPlugin):
23
24 def do_post_build(self, thebuilder):
25 return 0
26
27 def do_pre_build(self, thebuilder):
28 self.Logger = logging.getLogger("WindowsVsToolChain")
29 interesting_keys = ["ExtensionSdkDir", "INCLUDE", "LIB", "LIBPATH", "UniversalCRTSdkDir",
30 "UCRTVersion", "WindowsLibPath", "WindowsSdkBinPath", "WindowsSdkDir", "WindowsSdkVerBinPath",
31 "WindowsSDKVersion", "VCToolsInstallDir", "Path"]
32
33 #
34 # VS2017 - Follow VS2017 where there is potential for many versions of the tools.
35 # If a specific version is required then the user must set both env variables:
36 # VS150INSTALLPATH: base install path on system to VC install dir. Here you will find the VC folder, etc
37 # VS150TOOLVER: version number for the VC compiler tools
38 # VS2017_PREFIX: path to MSVC compiler folder with trailing slash (can be used instead of two vars above)
39 # VS2017_HOST: set the host architecture to use for host tools, and host libs, etc
40 if thebuilder.env.GetValue("TOOL_CHAIN_TAG") == "VS2017":
41
42 # check to see if host is configured
43 # HostType for VS2017 should be (defined in tools_def):
44 # x86 == 32bit Intel
45 # x64 == 64bit Intel
46 # arm == 32bit Arm
47 # arm64 == 64bit Arm
48 #
49 HostType = shell_environment.GetEnvironment().get_shell_var("VS2017_HOST")
50 if HostType is not None:
51 HostType = HostType.lower()
52 self.Logger.info(
53 f"HOST TYPE defined by environment. Host Type is {HostType}")
54 else:
55 HostInfo = GetHostInfo()
56 if HostInfo.arch == "x86":
57 if HostInfo.bit == "32":
58 HostType = "x86"
59 elif HostInfo.bit == "64":
60 HostType = "x64"
61 else:
62 raise NotImplementedError()
63
64 # VS2017_HOST options are not exactly the same as QueryVcVariables. This translates.
65 VC_HOST_ARCH_TRANSLATOR = {
66 "x86": "x86", "x64": "AMD64", "arm": "not supported", "arm64": "not supported"}
67
68 # check to see if full path already configured
69 if shell_environment.GetEnvironment().get_shell_var("VS2017_PREFIX") != None:
70 self.Logger.info("VS2017_PREFIX is already set.")
71
72 else:
73 install_path = self._get_vs_install_path(
74 "VS2017".lower(), "VS150INSTALLPATH")
75 vc_ver = self._get_vc_version(install_path, "VS150TOOLVER")
76
77 if install_path is None or vc_ver is None:
78 self.Logger.error(
79 "Failed to configure environment for VS2017")
80 return -1
81
82 version_aggregator.GetVersionAggregator().ReportVersion(
83 "Visual Studio Install Path", install_path, version_aggregator.VersionTypes.INFO)
84 version_aggregator.GetVersionAggregator().ReportVersion(
85 "VC Version", vc_ver, version_aggregator.VersionTypes.TOOL)
86
87 # make VS2017_PREFIX to align with tools_def.txt
88 prefix = os.path.join(install_path, "VC",
89 "Tools", "MSVC", vc_ver)
90 prefix = prefix + os.path.sep
91 shell_environment.GetEnvironment().set_shell_var("VS2017_PREFIX", prefix)
92 shell_environment.GetEnvironment().set_shell_var("VS2017_HOST", HostType)
93
94 shell_env = shell_environment.GetEnvironment()
95 # Use the tools lib to determine the correct values for the vars that interest us.
96 vs_vars = locate_tools.QueryVcVariables(
97 interesting_keys, VC_HOST_ARCH_TRANSLATOR[HostType], vs_version="vs2017")
98 for (k, v) in vs_vars.items():
99 shell_env.set_shell_var(k, v)
100
101 # now confirm it exists
102 if not os.path.exists(shell_environment.GetEnvironment().get_shell_var("VS2017_PREFIX")):
103 self.Logger.error("Path for VS2017 toolchain is invalid")
104 return -2
105
106 #
107 # VS2019 - Follow VS2019 where there is potential for many versions of the tools.
108 # If a specific version is required then the user must set both env variables:
109 # VS160INSTALLPATH: base install path on system to VC install dir. Here you will find the VC folder, etc
110 # VS160TOOLVER: version number for the VC compiler tools
111 # VS2019_PREFIX: path to MSVC compiler folder with trailing slash (can be used instead of two vars above)
112 # VS2017_HOST: set the host architecture to use for host tools, and host libs, etc
113 elif thebuilder.env.GetValue("TOOL_CHAIN_TAG") == "VS2019":
114
115 # check to see if host is configured
116 # HostType for VS2019 should be (defined in tools_def):
117 # x86 == 32bit Intel
118 # x64 == 64bit Intel
119 # arm == 32bit Arm
120 # arm64 == 64bit Arm
121 #
122 HostType = shell_environment.GetEnvironment().get_shell_var("VS2019_HOST")
123 if HostType is not None:
124 HostType = HostType.lower()
125 self.Logger.info(
126 f"HOST TYPE defined by environment. Host Type is {HostType}")
127 else:
128 HostInfo = GetHostInfo()
129 if HostInfo.arch == "x86":
130 if HostInfo.bit == "32":
131 HostType = "x86"
132 elif HostInfo.bit == "64":
133 HostType = "x64"
134 else:
135 raise NotImplementedError()
136
137 # VS2019_HOST options are not exactly the same as QueryVcVariables. This translates.
138 VC_HOST_ARCH_TRANSLATOR = {
139 "x86": "x86", "x64": "AMD64", "arm": "not supported", "arm64": "not supported"}
140
141 # check to see if full path already configured
142 if shell_environment.GetEnvironment().get_shell_var("VS2019_PREFIX") != None:
143 self.Logger.info("VS2019_PREFIX is already set.")
144
145 else:
146 install_path = self._get_vs_install_path(
147 "VS2019".lower(), "VS160INSTALLPATH")
148 vc_ver = self._get_vc_version(install_path, "VS160TOOLVER")
149
150 if install_path is None or vc_ver is None:
151 self.Logger.error(
152 "Failed to configure environment for VS2019")
153 return -1
154
155 version_aggregator.GetVersionAggregator().ReportVersion(
156 "Visual Studio Install Path", install_path, version_aggregator.VersionTypes.INFO)
157 version_aggregator.GetVersionAggregator().ReportVersion(
158 "VC Version", vc_ver, version_aggregator.VersionTypes.TOOL)
159
160 # make VS2019_PREFIX to align with tools_def.txt
161 prefix = os.path.join(install_path, "VC",
162 "Tools", "MSVC", vc_ver)
163 prefix = prefix + os.path.sep
164 shell_environment.GetEnvironment().set_shell_var("VS2019_PREFIX", prefix)
165 shell_environment.GetEnvironment().set_shell_var("VS2019_HOST", HostType)
166
167 shell_env = shell_environment.GetEnvironment()
168 # Use the tools lib to determine the correct values for the vars that interest us.
169 vs_vars = locate_tools.QueryVcVariables(
170 interesting_keys, VC_HOST_ARCH_TRANSLATOR[HostType], vs_version="vs2019")
171 for (k, v) in vs_vars.items():
172 shell_env.set_shell_var(k, v)
173
174 # now confirm it exists
175 if not os.path.exists(shell_environment.GetEnvironment().get_shell_var("VS2019_PREFIX")):
176 self.Logger.error("Path for VS2019 toolchain is invalid")
177 return -2
178
179 #
180 # VS2022 - VS2022 allows a user to install many copies/versions of the tools.
181 # If a specific version is required then the user must set both env variables:
182 # VS170INSTALLPATH: base install path on system to VC install dir. Here you will find the VC folder, etc
183 # VS170TOOLVER: version number for the VC compiler tools
184 # VS2022_PREFIX: path to MSVC compiler folder with trailing slash (can be used instead of two vars above)
185 # VS2022_HOST: set the host architecture to use for host tools, and host libs, etc
186 elif thebuilder.env.GetValue("TOOL_CHAIN_TAG") == "VS2022":
187
188 # check to see if host is configured
189 # HostType for VS2022 should be (defined in tools_def):
190 # x86 == 32bit Intel
191 # x64 == 64bit Intel
192 # arm == 32bit Arm
193 # arm64 == 64bit Arm
194 #
195 HostType = shell_environment.GetEnvironment().get_shell_var("VS2022_HOST")
196 if HostType is not None:
197 HostType = HostType.lower()
198 self.Logger.info(
199 f"HOST TYPE defined by environment. Host Type is {HostType}")
200 else:
201 HostInfo = GetHostInfo()
202 if HostInfo.arch == "x86":
203 if HostInfo.bit == "32":
204 HostType = "x86"
205 elif HostInfo.bit == "64":
206 HostType = "x64"
207 else:
208 raise NotImplementedError()
209
210 # VS2022_HOST options are not exactly the same as QueryVcVariables. This translates.
211 VC_HOST_ARCH_TRANSLATOR = {
212 "x86": "x86", "x64": "AMD64", "arm": "not supported", "arm64": "not supported"}
213
214 # check to see if full path already configured
215 if shell_environment.GetEnvironment().get_shell_var("VS2022_PREFIX") is not None:
216 self.Logger.debug("VS2022_PREFIX is already set.")
217
218 else:
219 install_path = self._get_vs_install_path(
220 "VS2022".lower(), "VS170INSTALLPATH")
221 vc_ver = self._get_vc_version(install_path, "VS170TOOLVER")
222
223 if install_path is None or vc_ver is None:
224 self.Logger.error(
225 "Failed to configure environment for VS2022")
226 return -1
227
228 version_aggregator.GetVersionAggregator().ReportVersion(
229 "Visual Studio Install Path", install_path, version_aggregator.VersionTypes.INFO)
230 version_aggregator.GetVersionAggregator().ReportVersion(
231 "VC Version", vc_ver, version_aggregator.VersionTypes.TOOL)
232
233 # make VS2022_PREFIX to align with tools_def.txt
234 prefix = os.path.join(install_path, "VC",
235 "Tools", "MSVC", vc_ver)
236 prefix = prefix + os.path.sep
237 shell_environment.GetEnvironment().set_shell_var("VS2022_PREFIX", prefix)
238 shell_environment.GetEnvironment().set_shell_var("VS2022_HOST", HostType)
239
240 shell_env = shell_environment.GetEnvironment()
241 # Use the tools lib to determine the correct values for the vars that interest us.
242 vs_vars = locate_tools.QueryVcVariables(
243 interesting_keys, VC_HOST_ARCH_TRANSLATOR[HostType], vs_version="VS2022")
244 for (k, v) in vs_vars.items():
245 shell_env.set_shell_var(k, v)
246
247 # now confirm it exists
248 if not os.path.exists(shell_environment.GetEnvironment().get_shell_var("VS2022_PREFIX")):
249 self.Logger.error("Path for VS2022 toolchain is invalid")
250 return -2
251
252 #
253 # CLANGPDB on Windows uses nmake from
254 # the VS compiler toolchain. Find a version and set
255 # as the CLANG_HOST_BIN path if not already set.
256 #
257 # Also get the platform header files, SDK, etc based on the
258 # host type. This is used for unit test compilation.
259 # If CLANG_VS_HOST is not set then find the host type based on Host Info.
260 ##
261 elif thebuilder.env.GetValue("TOOL_CHAIN_TAG") == "CLANGPDB":
262 HostInfo = GetHostInfo()
263
264 # check to see if host is configured
265 # HostType for VS tools should be (defined in tools_def):
266 # x86 == 32bit Intel
267 # x64 == 64bit Intel
268 # arm == 32bit Arm
269 # arm64 == 64bit Arm
270 #
271 HostType = shell_environment.GetEnvironment().get_shell_var("CLANG_VS_HOST")
272 if HostType is not None:
273 HostType = HostType.lower()
274 self.Logger.info(
275 f"CLANG_VS_HOST defined by environment. Value is {HostType}")
276 else:
277 #figure it out based on host info
278 if HostInfo.arch == "x86":
279 if HostInfo.bit == "32":
280 HostType = "x86"
281 elif HostInfo.bit == "64":
282 HostType = "x64"
283 else:
284 # anything other than x86 or x64 is not supported
285 raise NotImplementedError()
286
287 # CLANG_VS_HOST options are not exactly the same as QueryVcVariables. This translates.
288 VC_HOST_ARCH_TRANSLATOR = {
289 "x86": "x86", "x64": "AMD64", "arm": "not supported", "arm64": "not supported"}
290
291 # now get the environment variables for the platform
292 shell_env = shell_environment.GetEnvironment()
293 # Use the tools lib to determine the correct values for the vars that interest us.
294 vs_vars = locate_tools.QueryVcVariables(
295 interesting_keys, VC_HOST_ARCH_TRANSLATOR[HostType])
296 for (k, v) in vs_vars.items():
297 shell_env.set_shell_var(k, v)
298
299 ##
300 # If environment already has CLANG_HOST_BIN set then user has already
301 # set the path to the VS tools like nmake.exe
302 ##
303 if shell_environment.GetEnvironment().get_shell_var("CLANG_HOST_BIN") is not None:
304 self.Logger.debug("CLANG_HOST_BIN is already set.")
305
306 else:
307 install_path = self._get_vs_install_path(None, None)
308 vc_ver = self._get_vc_version(install_path, None)
309
310 if install_path is None or vc_ver is None:
311 self.Logger.error("Failed to configure environment for VS")
312 return -1
313
314 version_aggregator.GetVersionAggregator().ReportVersion(
315 "Visual Studio Install Path", install_path, version_aggregator.VersionTypes.INFO)
316 version_aggregator.GetVersionAggregator().ReportVersion(
317 "VC Version", vc_ver, version_aggregator.VersionTypes.TOOL)
318
319 # make path align with tools_def.txt
320 prefix = os.path.join(install_path, "VC", "Tools", "MSVC", vc_ver)
321 clang_host_bin_prefix = os.path.join(prefix, "bin", "Host%s" % HostType, HostType)
322
323 # now confirm it exists
324 if not os.path.exists(clang_host_bin_prefix):
325 self.Logger.error("Path for VS toolchain is invalid")
326 return -2
327
328 # The environment is using nmake (not make) so add "n" to the end of the path.
329 # The rest of the command is derived from definitions in tools.def.
330 shell_environment.GetEnvironment().set_shell_var("CLANG_HOST_BIN", os.path.join(clang_host_bin_prefix, "n"))
331
332 return 0
333
334 def _get_vs_install_path(self, vs_version, varname):
335 # check if already specified
336 path = None
337 if varname is not None:
338 path = shell_environment.GetEnvironment().get_shell_var(varname)
339
340 if(path is None):
341 # Not specified...find latest
342 try:
343 path = FindWithVsWhere(vs_version=vs_version)
344 except (EnvironmentError, ValueError, RuntimeError) as e:
345 self.Logger.error(str(e))
346 return None
347
348 if path is not None and os.path.exists(path):
349 self.Logger.debug("Found VS instance for %s", vs_version)
350 else:
351 self.Logger.error(
352 f"VsWhere successfully executed, but could not find VS instance for {vs_version}.")
353 return path
354
355 def _get_vc_version(self, path, varname):
356 # check if already specified
357 vc_ver = shell_environment.GetEnvironment().get_shell_var(varname)
358 if (path is None):
359 self.Logger.critical(
360 "Failed to find Visual Studio tools. Might need to check for VS install")
361 return vc_ver
362 if(vc_ver is None):
363 # Not specified...find latest
364 p2 = os.path.join(path, "VC", "Tools", "MSVC")
365 if not os.path.isdir(p2):
366 self.Logger.critical(
367 "Failed to find VC tools. Might need to check for VS install")
368 return vc_ver
369 vc_ver = os.listdir(p2)[-1].strip() # get last in list
370 self.Logger.debug("Found VC Tool version is %s" % vc_ver)
371 return vc_ver
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette