[edk2-devel] [Patch v3 06/22] BaseTools: Add BaseTools plugins to support CI

Michael D Kinney michael.d.kinney at intel.com
Tue Oct 29 19:55:01 UTC 2019


From: Sean Brogan <sean.brogan at microsoft.com>

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

Add the following plugins that are required to support
EDK II Continuous Integration (CI) builds.  These plugins
are added to BaseTools because that support EDK II BaseTools
features.

* BuildToolsReportGenerator
* LinuxGcc5ToolChain
* WindowsResourceCompiler
* WindowsVsToolChain

Cc: Bob Feng <bob.c.feng at intel.com>
Cc: Liming Gao <liming.gao at intel.com>
Signed-off-by: Michael D Kinney <michael.d.kinney at intel.com>
---
 .../BuildToolsReportGenerator.py              |  69 ++++++++++
 .../BuildToolsReportGenerator_plug_in.yaml    |  12 ++
 .../BuildToolsReport_Template.html            | 126 ++++++++++++++++++
 .../LinuxGcc5ToolChain/LinuxGcc5ToolChain.py  |  85 ++++++++++++
 .../LinuxGcc5ToolChain_plug_in.yaml           |  12 ++
 .../WindowsResourceCompiler/WinRcPath.py      |  29 ++++
 .../WinRcPath_plug_in.yaml                    |  13 ++
 .../WindowsVsToolChain/WindowsVsToolChain.py  | 126 ++++++++++++++++++
 .../WindowsVsToolChain_plug_in.yaml           |  11 ++
 9 files changed, 483 insertions(+)
 create mode 100644 BaseTools/Plugin/BuildToolsReport/BuildToolsReportGenerator.py
 create mode 100644 BaseTools/Plugin/BuildToolsReport/BuildToolsReportGenerator_plug_in.yaml
 create mode 100644 BaseTools/Plugin/BuildToolsReport/BuildToolsReport_Template.html
 create mode 100644 BaseTools/Plugin/LinuxGcc5ToolChain/LinuxGcc5ToolChain.py
 create mode 100644 BaseTools/Plugin/LinuxGcc5ToolChain/LinuxGcc5ToolChain_plug_in.yaml
 create mode 100644 BaseTools/Plugin/WindowsResourceCompiler/WinRcPath.py
 create mode 100644 BaseTools/Plugin/WindowsResourceCompiler/WinRcPath_plug_in.yaml
 create mode 100644 BaseTools/Plugin/WindowsVsToolChain/WindowsVsToolChain.py
 create mode 100644 BaseTools/Plugin/WindowsVsToolChain/WindowsVsToolChain_plug_in.yaml

diff --git a/BaseTools/Plugin/BuildToolsReport/BuildToolsReportGenerator.py b/BaseTools/Plugin/BuildToolsReport/BuildToolsReportGenerator.py
new file mode 100644
index 0000000000..d5df9f2f9b
--- /dev/null
+++ b/BaseTools/Plugin/BuildToolsReport/BuildToolsReportGenerator.py
@@ -0,0 +1,69 @@
+##
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+import os
+import logging
+import json
+
+try:
+    from edk2toolext.environment.plugintypes.uefi_build_plugin import IUefiBuildPlugin
+
+    class BuildToolsReportGenerator(IUefiBuildPlugin):
+        def do_report(self, thebuilder):
+            try:
+                from edk2toolext.environment import version_aggregator
+            except ImportError:
+                logging.critical("Loading BuildToolsReportGenerator failed, please update your Edk2-PyTool-Extensions")
+                return 0
+
+            OutputReport = os.path.join(thebuilder.env.GetValue("BUILD_OUTPUT_BASE"), "BUILD_TOOLS_REPORT")
+            OutputReport = os.path.normpath(OutputReport)
+            if not os.path.isdir(os.path.dirname(OutputReport)):
+                os.makedirs(os.path.dirname(OutputReport))
+
+            Report = BuildToolsReport()
+            Report.MakeReport(version_aggregator.GetVersionAggregator().GetAggregatedVersionInformation(), OutputReport=OutputReport)
+
+        def do_pre_build(self, thebuilder):
+            self.do_report(thebuilder)
+            return 0
+
+        def do_post_build(self, thebuilder):
+            self.do_report(thebuilder)
+            return 0
+
+except ImportError:
+    pass
+
+
+class BuildToolsReport(object):
+    MY_FOLDER = os.path.dirname(os.path.realpath(__file__))
+    VERSION = "1.00"
+
+    def __init__(self):
+        pass
+
+    def MakeReport(self, BuildTools, OutputReport="BuildToolsReport"):
+        logging.info("Writing BuildToolsReports to {0}".format(OutputReport))
+        versions_list = []
+        for key, value in BuildTools.items():
+            versions_list.append(value)
+        versions_list = sorted(versions_list, key=lambda k: k['type'])
+        json_dict = {"modules": versions_list,
+                     "PluginVersion": BuildToolsReport.VERSION}
+
+        htmlfile = open(OutputReport + ".html", "w")
+        jsonfile = open(OutputReport + ".json", "w")
+        template = open(os.path.join(BuildToolsReport.MY_FOLDER, "BuildToolsReport_Template.html"), "r")
+
+        for line in template.readlines():
+            if "%TO_BE_FILLED_IN_BY_PYTHON_SCRIPT%" in line:
+                line = line.replace("%TO_BE_FILLED_IN_BY_PYTHON_SCRIPT%", json.dumps(json_dict))
+            htmlfile.write(line)
+
+        jsonfile.write(json.dumps(versions_list, indent=4))
+
+        jsonfile.close()
+        template.close()
+        htmlfile.close()
diff --git a/BaseTools/Plugin/BuildToolsReport/BuildToolsReportGenerator_plug_in.yaml b/BaseTools/Plugin/BuildToolsReport/BuildToolsReportGenerator_plug_in.yaml
new file mode 100644
index 0000000000..50afd53926
--- /dev/null
+++ b/BaseTools/Plugin/BuildToolsReport/BuildToolsReportGenerator_plug_in.yaml
@@ -0,0 +1,12 @@
+##
+# Build Plugin used to output html report of all versions collected
+# during the build
+#
+# Copyright (c) 2019, Microsoft Corporation
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+  "scope": "global",
+  "name": "Build Tools Report Generator",
+  "module": "BuildToolsReportGenerator"
+}
diff --git a/BaseTools/Plugin/BuildToolsReport/BuildToolsReport_Template.html b/BaseTools/Plugin/BuildToolsReport/BuildToolsReport_Template.html
new file mode 100644
index 0000000000..26350ab425
--- /dev/null
+++ b/BaseTools/Plugin/BuildToolsReport/BuildToolsReport_Template.html
@@ -0,0 +1,126 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible">
+    <title>Build Tools Report</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="stylesheet" type="text/css" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css" />
+    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.15/css/dataTables.bootstrap.min.css" />
+    <style>
+        div.attribution {
+            border: 1px solid #ddd;
+            background-color: #bbb;
+            padding-left: 20px;
+        }
+    </style>
+</head>
+<body>
+    <div class="container-fluid">
+        <h1>Build Tools Report</h1>
+        <ul class="nav nav-tabs">
+            <li class="active"><a data-toggle="tab" href="#tabs-1">Tools</a></li>
+            <li><a data-toggle="tab" href="#tabs-2">About</a></li>
+        </ul>
+        <div class="tab-content">
+            <div id="tabs-1" class="tab-pane fade in active">
+                <table id="modinfo" class="table table-striped table-bordered table-hover" cellspacing="0">
+                    <thead>
+                        <tr>
+                            <th>Key</th>
+                            <th>Value</th>
+                            <th>Type</th>
+                        </tr>
+                    </thead>
+                    <tbody></tbody>
+                </table>
+            </div>
+            <div id="tabs-2" class="tab-pane">
+                <div class="row">
+                    <div class="col-xs-7">
+                        <p></p>
+                        <p>
+                            Build Tools Report Template Version: <span id="ReportTemplateVersion">1.00</span><br />
+                            Build Tools Report Plugin Version: <span id='ReportToolVersion'></span><br />
+                        </p>
+                        <h3>License</h3>
+                        <hr />
+                        <div id="ToolLicenseContent">
+                            <p>
+                                <span class="copyright">Copyright (c) Microsoft Corporation. All rights reserved.</span><br />
+                                <span class="license">
+                                    SPDX-License-Identifier: BSD-2-Clause-Patent
+                                </span>
+                            </p>
+                        </div>
+                    </div>
+                    <div id="AttributionListWrapper" class="col-xs-5">
+                        <h3>External Licenses</h3>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- Javascript libraries -->
+    <script type="text/javascript" charset="utf8" src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
+    <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.15/js/jquery.dataTables.min.js"></script>
+    <script type="text/javascript" charset="utf8" src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"></script>
+    <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.15/js/dataTables.bootstrap.min.js"></script>
+
+    <script>
+        var EmbeddedJd = %TO_BE_FILLED_IN_BY_PYTHON_SCRIPT%;
+    </script>
+    <!-- Add javascript here -->
+    <script>
+        var MODULE_TABLE_OFFSET = 350;  //Space needed for other stuff besides the Table
+        $(document).ready(function () {
+            $('span#ReportToolVersion').text(EmbeddedJd.PluginVersion);
+            //To support tabs and correct column width we need this change
+            $('a[data-toggle="tab"][href="#tabs-1"]').on('shown.bs.tab', function (e) {
+                $.fn.dataTable.tables({ visible: true, api: true }).columns.adjust();
+            });
+            //table for modules
+            var mTable = $('table#modinfo').dataTable({
+                "aaData": EmbeddedJd.modules,
+                "paginate": false,
+                "autoWidth": false,
+                "scrollY": ($(window).height() - MODULE_TABLE_OFFSET) + "px",
+                "aaSorting": [[2, "asc"]],
+                "aoColumnDefs": [
+                    {
+                        "mData": "name",
+                        "aTargets": [0]
+                    },
+
+                    {
+                        "mData": "version",
+                        "aTargets": [1]
+                    },
+                    {
+                        "mData": "type",
+                        "aTargets": [2],
+                    }
+                ] //end of column def
+            }); //end of modules table
+
+            //
+            // Create Attribution List for all external libraries used
+            //
+            [
+                { Title: "JQuery", Copyright: "Copyright 2017 The jQuery Foundation", Version: $.fn.jquery, LicenseType: "MIT", LicenseLink: "https://jquery.org/license/" },
+                { Title: "DataTables", Copyright: "DataTables designed and created by SpryMedia Ltd Copyright 2007-2017", Version: $.fn.dataTable.version, LicenseType: "MIT", LicenseLink: "https://datatables.net/license/mit" },
+                { Title: "BootStrap", Copyright: "Code and documentation copyright 2011-2017 the Bootstrap Authors and Twitter, Inc.", Version: "3.3.7", LicenseType: "MIT", LicenseLink: "https://github.com/twbs/bootstrap/blob/master/LICENSE" }
+            ].forEach(function (element) {
+                $("<div class='attribution'><h4>" + element.Title + "</h4><p>Version: <span class='version'>" + element.Version + "</span><br /><span class='copyright'>" +
+                    element.Copyright + "</span><br />License: <a class='license' href='" + element.LicenseLink + "'>" + element.LicenseType + "</a></p></div>").appendTo("div#AttributionListWrapper");
+            });
+        });
+        $(window).resize(function() {
+            $.fn.dataTable.tables({ visible: true, api: true }).columns.adjust();
+        });
+
+
+    </script>
+</body>
+</html>
diff --git a/BaseTools/Plugin/LinuxGcc5ToolChain/LinuxGcc5ToolChain.py b/BaseTools/Plugin/LinuxGcc5ToolChain/LinuxGcc5ToolChain.py
new file mode 100644
index 0000000000..c31641e931
--- /dev/null
+++ b/BaseTools/Plugin/LinuxGcc5ToolChain/LinuxGcc5ToolChain.py
@@ -0,0 +1,85 @@
+# @file LinuxGcc5ToolChain.py
+# Plugin to configures paths for GCC5 ARM/AARCH64 Toolchain
+##
+# This plugin works in conjuncture with the tools_def
+#
+# Copyright (c) Microsoft Corporation
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+import os
+import logging
+from edk2toolext.environment.plugintypes.uefi_build_plugin import IUefiBuildPlugin
+from edk2toolext.environment import shell_environment
+
+
+class LinuxGcc5ToolChain(IUefiBuildPlugin):
+
+    def do_post_build(self, thebuilder):
+        return 0
+
+    def do_pre_build(self, thebuilder):
+        self.Logger = logging.getLogger("LinuxGcc5ToolChain")
+
+        #
+        # GCC5 - The ARM and AARCH64 compilers need their paths set if available
+        if thebuilder.env.GetValue("TOOL_CHAIN_TAG") == "GCC5":
+
+            # Start with AARACH64 compiler
+            ret = self._check_aarch64()
+            if ret != 0:
+                self.Logger.critical("Failed in check aarch64")
+                return ret
+
+            # Check arm compiler
+            ret = self._check_arm()
+            if ret != 0:
+                self.Logger.critical("Failed in check arm")
+                return ret
+
+        return 0
+
+    def _check_arm(self):
+        # check to see if full path already configured
+        if shell_environment.GetEnvironment().get_shell_var("GCC5_ARM_PREFIX") is not None:
+            self.Logger.info("GCC5_ARM_PREFIX is already set.")
+
+        else:
+            # now check for install dir.  If set then set the Prefix
+            install_path = shell_environment.GetEnvironment().get_shell_var("GCC5_ARM_INSTALL")
+            if install_path is None:
+                return 0
+
+            # make GCC5_ARM_PREFIX to align with tools_def.txt
+            prefix = os.path.join(install_path, "bin", "arm-linux-gnueabihf-")
+            shell_environment.GetEnvironment().set_shell_var("GCC5_ARM_PREFIX", prefix)
+
+        # now confirm it exists
+        if not os.path.exists(shell_environment.GetEnvironment().get_shell_var("GCC5_ARM_PREFIX") + "gcc"):
+            self.Logger.error("Path for GCC5_ARM_PREFIX toolchain is invalid")
+            return -2
+
+        return 0
+
+    def _check_aarch64(self):
+        # check to see if full path already configured
+        if shell_environment.GetEnvironment().get_shell_var("GCC5_AARCH64_PREFIX") is not None:
+            self.Logger.info("GCC5_AARCH64_PREFIX is already set.")
+
+        else:
+            # now check for install dir.  If set then set the Prefix
+            install_path = shell_environment.GetEnvironment(
+            ).get_shell_var("GCC5_AARCH64_INSTALL")
+            if install_path is None:
+                return 0
+
+            # make GCC5_AARCH64_PREFIX to align with tools_def.txt
+            prefix = os.path.join(install_path, "bin", "aarch64-linux-gnu-")
+            shell_environment.GetEnvironment().set_shell_var("GCC5_AARCH64_PREFIX", prefix)
+
+        # now confirm it exists
+        if not os.path.exists(shell_environment.GetEnvironment().get_shell_var("GCC5_AARCH64_PREFIX") + "gcc"):
+            self.Logger.error(
+                "Path for GCC5_AARCH64_PREFIX toolchain is invalid")
+            return -2
+
+        return 0
diff --git a/BaseTools/Plugin/LinuxGcc5ToolChain/LinuxGcc5ToolChain_plug_in.yaml b/BaseTools/Plugin/LinuxGcc5ToolChain/LinuxGcc5ToolChain_plug_in.yaml
new file mode 100644
index 0000000000..91cfcfbb28
--- /dev/null
+++ b/BaseTools/Plugin/LinuxGcc5ToolChain/LinuxGcc5ToolChain_plug_in.yaml
@@ -0,0 +1,12 @@
+##
+# Build Plugin used to set the path
+# for the GCC5 ARM/AARCH64 downloaded compilers
+#
+# Copyright (c) 2019, Microsoft Corporation
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+  "scope": "global-nix",
+  "name": "Linux GCC5 Tool Chain Support",
+  "module": "LinuxGcc5ToolChain"
+}
diff --git a/BaseTools/Plugin/WindowsResourceCompiler/WinRcPath.py b/BaseTools/Plugin/WindowsResourceCompiler/WinRcPath.py
new file mode 100644
index 0000000000..ec2f2d1298
--- /dev/null
+++ b/BaseTools/Plugin/WindowsResourceCompiler/WinRcPath.py
@@ -0,0 +1,29 @@
+## @file WinRcPath.py
+# Plugin to find Windows SDK Resource Compiler rc.exe
+##
+# This plugin works in conjuncture with the tools_def to support rc.exe
+#
+# Copyright (c) Microsoft Corporation
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+import os
+from edk2toolext.environment.plugintypes.uefi_build_plugin import IUefiBuildPlugin
+import edk2toollib.windows.locate_tools as locate_tools
+from edk2toolext.environment import shell_environment
+from edk2toolext.environment import version_aggregator
+
+class WinRcPath(IUefiBuildPlugin):
+
+    def do_post_build(self, thebuilder):
+        return 0
+
+    def do_pre_build(self, thebuilder):
+        #get the locate tools module
+        path = locate_tools.FindToolInWinSdk("rc.exe")
+        if path is None:
+            thebuilder.logging.warning("Failed to find rc.exe")
+        else:
+            p = os.path.abspath(os.path.dirname(path))
+            shell_environment.GetEnvironment().set_shell_var("WINSDK_PATH_FOR_RC_EXE", p)
+            version_aggregator.GetVersionAggregator().ReportVersion("WINSDK_PATH_FOR_RC_EXE", p, version_aggregator.VersionTypes.INFO)
+        return 0
diff --git a/BaseTools/Plugin/WindowsResourceCompiler/WinRcPath_plug_in.yaml b/BaseTools/Plugin/WindowsResourceCompiler/WinRcPath_plug_in.yaml
new file mode 100644
index 0000000000..030ebe776c
--- /dev/null
+++ b/BaseTools/Plugin/WindowsResourceCompiler/WinRcPath_plug_in.yaml
@@ -0,0 +1,13 @@
+##
+# Build Plugin used to set the path to rc.exe on windows.
+# The plugin is able to use python to locate the tool as to avoid
+# hard-coding the path
+#
+# Copyright (c) 2019, Microsoft Corporation
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+  "scope": "global-win",
+  "name": "Windows RC Path Support",
+  "module": "WinRcPath"
+}
diff --git a/BaseTools/Plugin/WindowsVsToolChain/WindowsVsToolChain.py b/BaseTools/Plugin/WindowsVsToolChain/WindowsVsToolChain.py
new file mode 100644
index 0000000000..a8202e5992
--- /dev/null
+++ b/BaseTools/Plugin/WindowsVsToolChain/WindowsVsToolChain.py
@@ -0,0 +1,126 @@
+## @file WindowsVsToolChain.py
+# Plugin to configures paths for the VS2017 and VS2019 tool chain
+##
+# This plugin works in conjuncture with the tools_def
+#
+# Copyright (c) Microsoft Corporation
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+import os
+import logging
+from edk2toolext.environment.plugintypes.uefi_build_plugin import IUefiBuildPlugin
+import edk2toollib.windows.locate_tools as locate_tools
+from edk2toollib.windows.locate_tools import FindWithVsWhere
+from edk2toolext.environment import shell_environment
+from edk2toolext.environment import version_aggregator
+
+class WindowsVsToolChain(IUefiBuildPlugin):
+
+    def do_post_build(self, thebuilder):
+        return 0
+
+    def do_pre_build(self, thebuilder):
+        self.Logger = logging.getLogger("WindowsVsToolChain")
+
+#
+        # VS2017 - Follow VS2017 where there is potential for many versions of the tools.
+        # If a specific version is required then the user must set both env variables:
+        ## VS150INSTALLPATH:  base install path on system to VC install dir.  Here you will find the VC folder, etc
+        ## VS150TOOLVER:      version number for the VC compiler tools
+        ## VS2017_PREFIX:     path to MSVC compiler folder with trailing slash (can be used instead of two vars above)
+        if thebuilder.env.GetValue("TOOL_CHAIN_TAG") == "VS2017":
+
+            # check to see if full path already configured
+            if shell_environment.GetEnvironment().get_shell_var("VS2017_PREFIX") != None:
+                self.Logger.info("VS2017_PREFIX is already set.")
+
+            else:
+                install_path = self._get_vs_install_path("VS2017".lower(), "VS150INSTALLPATH")
+                vc_ver = self._get_vc_version(install_path, "VS150TOOLVER")
+
+                if install_path is None or vc_ver is None:
+                    self.Logger.error("Failed to configure environment for VS2017")
+                    return -1
+
+                version_aggregator.GetVersionAggregator().ReportVersion(
+                    "Visual Studio Install Path", install_path, version_aggregator.VersionTypes.INFO)
+                version_aggregator.GetVersionAggregator().ReportVersion(
+                    "VC Version", vc_ver, version_aggregator.VersionTypes.TOOL)
+
+                #make VS2017_PREFIX to align with tools_def.txt
+                prefix = os.path.join(install_path, "VC", "Tools", "MSVC", vc_ver)
+                prefix = prefix + os.path.sep
+                shell_environment.GetEnvironment().set_shell_var("VS2017_PREFIX", prefix)
+
+            # now confirm it exists
+            if not os.path.exists(shell_environment.GetEnvironment().get_shell_var("VS2017_PREFIX")):
+                self.Logger.error("Path for VS2017 toolchain is invalid")
+                return -2
+
+        #
+        # VS2019 - Follow VS2019 where there is potential for many versions of the tools.
+        # If a specific version is required then the user must set both env variables:
+        ## VS160INSTALLPATH:  base install path on system to VC install dir.  Here you will find the VC folder, etc
+        ## VS160TOOLVER:      version number for the VC compiler tools
+        ## VS2019_PREFIX:     path to MSVC compiler folder with trailing slash (can be used instead of two vars above)
+        elif thebuilder.env.GetValue("TOOL_CHAIN_TAG") == "VS2019":
+
+            # check to see if full path already configured
+            if shell_environment.GetEnvironment().get_shell_var("VS2019_PREFIX") != None:
+                self.Logger.info("VS2019_PREFIX is already set.")
+
+            else:
+                install_path = self._get_vs_install_path("VS2019".lower(), "VS160INSTALLPATH")
+                vc_ver = self._get_vc_version(install_path, "VS160TOOLVER")
+
+                if install_path is None or vc_ver is None:
+                    self.Logger.error("Failed to configure environment for VS2019")
+                    return -1
+
+                version_aggregator.GetVersionAggregator().ReportVersion(
+                    "Visual Studio Install Path", install_path, version_aggregator.VersionTypes.INFO)
+                version_aggregator.GetVersionAggregator().ReportVersion(
+                    "VC Version", vc_ver, version_aggregator.VersionTypes.TOOL)
+
+                #make VS2019_PREFIX to align with tools_def.txt
+                prefix = os.path.join(install_path, "VC", "Tools", "MSVC", vc_ver)
+                prefix = prefix + os.path.sep
+                shell_environment.GetEnvironment().set_shell_var("VS2019_PREFIX", prefix)
+
+            # now confirm it exists
+            if not os.path.exists(shell_environment.GetEnvironment().get_shell_var("VS2019_PREFIX")):
+                self.Logger.error("Path for VS2019 toolchain is invalid")
+                return -2
+
+        return 0
+
+    def _get_vs_install_path(self, vs_version, varname):
+        # check if already specified
+        path = shell_environment.GetEnvironment().get_shell_var(varname)
+        if(path is None):
+            # Not specified...find latest
+            (rc, path) = FindWithVsWhere(vs_version=vs_version)
+            if rc == 0 and path is not None and os.path.exists(path):
+                self.Logger.debug("Found VS instance for %s", vs_version)
+            else:
+                self.Logger.error("Failed to find VS instance with VsWhere (%d)" % rc)
+        return path
+
+    def _get_vc_version(self, path, varname):
+        # check if already specified
+        vc_ver = shell_environment.GetEnvironment().get_shell_var(varname)
+        if (path is None):
+            self.Logger.critical("Failed to find Visual Studio tools.  Might need to check for VS install")
+            return vc_ver
+        if(vc_ver is None):
+            # Not specified...find latest
+            p2 = os.path.join(path, "VC", "Tools", "MSVC")
+            if not os.path.isdir(p2):
+                self.Logger.critical(
+                    "Failed to find VC tools.  Might need to check for VS install")
+                return vc_ver
+            vc_ver = os.listdir(p2)[-1].strip()  # get last in list
+            self.Logger.debug("Found VC Tool version is %s" % vc_ver)
+        return vc_ver
+
+
diff --git a/BaseTools/Plugin/WindowsVsToolChain/WindowsVsToolChain_plug_in.yaml b/BaseTools/Plugin/WindowsVsToolChain/WindowsVsToolChain_plug_in.yaml
new file mode 100644
index 0000000000..0d7acc2e6d
--- /dev/null
+++ b/BaseTools/Plugin/WindowsVsToolChain/WindowsVsToolChain_plug_in.yaml
@@ -0,0 +1,11 @@
+##
+# Build Plugin used to set the path to the visual studio tools chain
+#
+# Copyright (c) 2019, Microsoft Corporation
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+  "scope": "global-win",
+  "name": "Windows Visual Studio Tool Chain Support",
+  "module": "WindowsVsToolChain"
+}
-- 
2.21.0.windows.1


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

View/Reply Online (#49590): https://edk2.groups.io/g/devel/message/49590
Mute This Topic: https://groups.io/mt/39614169/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list