+## @file WindowsVsToolChain.py\r
+# Plugin to configures paths for the VS2017 and VS2019 tool chain\r
+##\r
+# This plugin works in conjuncture with the tools_def\r
+#\r
+# Copyright (c) Microsoft Corporation\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+##\r
+import os\r
+import logging\r
+from edk2toolext.environment.plugintypes.uefi_build_plugin import IUefiBuildPlugin\r
+import edk2toollib.windows.locate_tools as locate_tools\r
+from edk2toollib.windows.locate_tools import FindWithVsWhere\r
+from edk2toolext.environment import shell_environment\r
+from edk2toolext.environment import version_aggregator\r
+\r
+class WindowsVsToolChain(IUefiBuildPlugin):\r
+\r
+ def do_post_build(self, thebuilder):\r
+ return 0\r
+\r
+ def do_pre_build(self, thebuilder):\r
+ self.Logger = logging.getLogger("WindowsVsToolChain")\r
+\r
+#\r
+ # VS2017 - Follow VS2017 where there is potential for many versions of the tools.\r
+ # If a specific version is required then the user must set both env variables:\r
+ ## VS150INSTALLPATH: base install path on system to VC install dir. Here you will find the VC folder, etc\r
+ ## VS150TOOLVER: version number for the VC compiler tools\r
+ ## VS2017_PREFIX: path to MSVC compiler folder with trailing slash (can be used instead of two vars above)\r
+ if thebuilder.env.GetValue("TOOL_CHAIN_TAG") == "VS2017":\r
+\r
+ # check to see if full path already configured\r
+ if shell_environment.GetEnvironment().get_shell_var("VS2017_PREFIX") != None:\r
+ self.Logger.info("VS2017_PREFIX is already set.")\r
+\r
+ else:\r
+ install_path = self._get_vs_install_path("VS2017".lower(), "VS150INSTALLPATH")\r
+ vc_ver = self._get_vc_version(install_path, "VS150TOOLVER")\r
+\r
+ if install_path is None or vc_ver is None:\r
+ self.Logger.error("Failed to configure environment for VS2017")\r
+ return -1\r
+\r
+ version_aggregator.GetVersionAggregator().ReportVersion(\r
+ "Visual Studio Install Path", install_path, version_aggregator.VersionTypes.INFO)\r
+ version_aggregator.GetVersionAggregator().ReportVersion(\r
+ "VC Version", vc_ver, version_aggregator.VersionTypes.TOOL)\r
+\r
+ #make VS2017_PREFIX to align with tools_def.txt\r
+ prefix = os.path.join(install_path, "VC", "Tools", "MSVC", vc_ver)\r
+ prefix = prefix + os.path.sep\r
+ shell_environment.GetEnvironment().set_shell_var("VS2017_PREFIX", prefix)\r
+\r
+ # now confirm it exists\r
+ if not os.path.exists(shell_environment.GetEnvironment().get_shell_var("VS2017_PREFIX")):\r
+ self.Logger.error("Path for VS2017 toolchain is invalid")\r
+ return -2\r
+\r
+ #\r
+ # VS2019 - Follow VS2019 where there is potential for many versions of the tools.\r
+ # If a specific version is required then the user must set both env variables:\r
+ ## VS160INSTALLPATH: base install path on system to VC install dir. Here you will find the VC folder, etc\r
+ ## VS160TOOLVER: version number for the VC compiler tools\r
+ ## VS2019_PREFIX: path to MSVC compiler folder with trailing slash (can be used instead of two vars above)\r
+ elif thebuilder.env.GetValue("TOOL_CHAIN_TAG") == "VS2019":\r
+\r
+ # check to see if full path already configured\r
+ if shell_environment.GetEnvironment().get_shell_var("VS2019_PREFIX") != None:\r
+ self.Logger.info("VS2019_PREFIX is already set.")\r
+\r
+ else:\r
+ install_path = self._get_vs_install_path("VS2019".lower(), "VS160INSTALLPATH")\r
+ vc_ver = self._get_vc_version(install_path, "VS160TOOLVER")\r
+\r
+ if install_path is None or vc_ver is None:\r
+ self.Logger.error("Failed to configure environment for VS2019")\r
+ return -1\r
+\r
+ version_aggregator.GetVersionAggregator().ReportVersion(\r
+ "Visual Studio Install Path", install_path, version_aggregator.VersionTypes.INFO)\r
+ version_aggregator.GetVersionAggregator().ReportVersion(\r
+ "VC Version", vc_ver, version_aggregator.VersionTypes.TOOL)\r
+\r
+ #make VS2019_PREFIX to align with tools_def.txt\r
+ prefix = os.path.join(install_path, "VC", "Tools", "MSVC", vc_ver)\r
+ prefix = prefix + os.path.sep\r
+ shell_environment.GetEnvironment().set_shell_var("VS2019_PREFIX", prefix)\r
+\r
+ # now confirm it exists\r
+ if not os.path.exists(shell_environment.GetEnvironment().get_shell_var("VS2019_PREFIX")):\r
+ self.Logger.error("Path for VS2019 toolchain is invalid")\r
+ return -2\r
+\r
+ return 0\r
+\r
+ def _get_vs_install_path(self, vs_version, varname):\r
+ # check if already specified\r
+ path = shell_environment.GetEnvironment().get_shell_var(varname)\r
+ if(path is None):\r
+ # Not specified...find latest\r
+ (rc, path) = FindWithVsWhere(vs_version=vs_version)\r
+ if rc == 0 and path is not None and os.path.exists(path):\r
+ self.Logger.debug("Found VS instance for %s", vs_version)\r
+ else:\r
+ self.Logger.error("Failed to find VS instance with VsWhere (%d)" % rc)\r
+ return path\r
+\r
+ def _get_vc_version(self, path, varname):\r
+ # check if already specified\r
+ vc_ver = shell_environment.GetEnvironment().get_shell_var(varname)\r
+ if (path is None):\r
+ self.Logger.critical("Failed to find Visual Studio tools. Might need to check for VS install")\r
+ return vc_ver\r
+ if(vc_ver is None):\r
+ # Not specified...find latest\r
+ p2 = os.path.join(path, "VC", "Tools", "MSVC")\r
+ if not os.path.isdir(p2):\r
+ self.Logger.critical(\r
+ "Failed to find VC tools. Might need to check for VS install")\r
+ return vc_ver\r
+ vc_ver = os.listdir(p2)[-1].strip() # get last in list\r
+ self.Logger.debug("Found VC Tool version is %s" % vc_ver)\r
+ return vc_ver\r
+\r
+\r