From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../Plugin/LibraryClassCheck/LibraryClassCheck.py | 153 +++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 roms/edk2/.pytool/Plugin/LibraryClassCheck/LibraryClassCheck.py (limited to 'roms/edk2/.pytool/Plugin/LibraryClassCheck/LibraryClassCheck.py') diff --git a/roms/edk2/.pytool/Plugin/LibraryClassCheck/LibraryClassCheck.py b/roms/edk2/.pytool/Plugin/LibraryClassCheck/LibraryClassCheck.py new file mode 100644 index 000000000..20d87f13f --- /dev/null +++ b/roms/edk2/.pytool/Plugin/LibraryClassCheck/LibraryClassCheck.py @@ -0,0 +1,153 @@ +# @file LibraryClassCheck.py +# +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +## +import logging +import os +from edk2toolext.environment.plugintypes.ci_build_plugin import ICiBuildPlugin +from edk2toollib.uefi.edk2.parsers.dec_parser import DecParser +from edk2toollib.uefi.edk2.parsers.inf_parser import InfParser +from edk2toolext.environment.var_dict import VarDict + + +class LibraryClassCheck(ICiBuildPlugin): + """ + A CiBuildPlugin that scans the code tree and library classes for undeclared + files + + Configuration options: + "LibraryClassCheck": { + IgnoreHeaderFile: [], # Ignore a file found on disk + IgnoreLibraryClass: [] # Ignore a declaration found in dec file + } + """ + + def GetTestName(self, packagename: str, environment: VarDict) -> tuple: + """ Provide the testcase name and classname for use in reporting + testclassname: a descriptive string for the testcase can include whitespace + classname: should be patterned .. + + Args: + packagename: string containing name of package to build + environment: The VarDict for the test to run in + Returns: + a tuple containing the testcase name and the classname + (testcasename, classname) + """ + return ("Check library class declarations in " + packagename, packagename + ".LibraryClassCheck") + + def __GetPkgDec(self, rootpath): + try: + allEntries = os.listdir(rootpath) + for entry in allEntries: + if entry.lower().endswith(".dec"): + return(os.path.join(rootpath, entry)) + except Exception: + logging.error("Unable to find DEC for package:{0}".format(rootpath)) + + return None + + ## + # External function of plugin. This function is used to perform the task of the MuBuild Plugin + # + # - package is the edk2 path to package. This means workspace/packagepath relative. + # - edk2path object configured with workspace and packages path + # - PkgConfig Object (dict) for the pkg + # - EnvConfig Object + # - Plugin Manager Instance + # - Plugin Helper Obj Instance + # - Junit Logger + # - output_stream the StringIO output stream from this plugin via logging + def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM, PLMHelper, tc, output_stream=None): + overall_status = 0 + LibraryClassIgnore = [] + + abs_pkg_path = Edk2pathObj.GetAbsolutePathOnThisSytemFromEdk2RelativePath(packagename) + abs_dec_path = self.__GetPkgDec(abs_pkg_path) + wsr_dec_path = Edk2pathObj.GetEdk2RelativePathFromAbsolutePath(abs_dec_path) + + if abs_dec_path is None or wsr_dec_path == "" or not os.path.isfile(abs_dec_path): + tc.SetSkipped() + tc.LogStdError("No DEC file {0} in package {1}".format(abs_dec_path, abs_pkg_path)) + return -1 + + # Get all include folders + dec = DecParser() + dec.SetBaseAbsPath(Edk2pathObj.WorkspacePath).SetPackagePaths(Edk2pathObj.PackagePathList) + dec.ParseFile(wsr_dec_path) + + AllHeaderFiles = [] + + for includepath in dec.IncludePaths: + ## Get all header files in the library folder + AbsLibraryIncludePath = os.path.join(abs_pkg_path, includepath, "Library") + if(not os.path.isdir(AbsLibraryIncludePath)): + continue + + hfiles = self.WalkDirectoryForExtension([".h"], AbsLibraryIncludePath) + hfiles = [os.path.relpath(x,abs_pkg_path) for x in hfiles] # make package root relative path + hfiles = [x.replace("\\", "/") for x in hfiles] # make package relative path + + AllHeaderFiles.extend(hfiles) + + if len(AllHeaderFiles) == 0: + tc.SetSkipped() + tc.LogStdError(f"No Library include folder in any Include path") + return -1 + + # Remove ignored paths + if "IgnoreHeaderFile" in pkgconfig: + for a in pkgconfig["IgnoreHeaderFile"]: + try: + tc.LogStdOut("Ignoring Library Header File {0}".format(a)) + AllHeaderFiles.remove(a) + except: + tc.LogStdError("LibraryClassCheck.IgnoreHeaderFile -> {0} not found. Invalid Header File".format(a)) + logging.info("LibraryClassCheck.IgnoreHeaderFile -> {0} not found. Invalid Header File".format(a)) + + if "IgnoreLibraryClass" in pkgconfig: + LibraryClassIgnore = pkgconfig["IgnoreLibraryClass"] + + + ## Attempt to find library classes + for lcd in dec.LibraryClasses: + ## Check for correct file path separator + if "\\" in lcd.path: + tc.LogStdError("LibraryClassCheck.DecFilePathSeparator -> {0} invalid.".format(lcd.path)) + logging.error("LibraryClassCheck.DecFilePathSeparator -> {0} invalid.".format(lcd.path)) + overall_status += 1 + continue + + if lcd.name in LibraryClassIgnore: + tc.LogStdOut("Ignoring Library Class Name {0}".format(lcd.name)) + LibraryClassIgnore.remove(lcd.name) + continue + + logging.debug(f"Looking for Library Class {lcd.path}") + try: + AllHeaderFiles.remove(lcd.path) + + except ValueError: + tc.LogStdError(f"Library {lcd.name} with path {lcd.path} not found in package filesystem") + logging.error(f"Library {lcd.name} with path {lcd.path} not found in package filesystem") + overall_status += 1 + + ## any remaining AllHeaderFiles are not described in DEC + for h in AllHeaderFiles: + tc.LogStdError(f"Library Header File {h} not declared in package DEC {wsr_dec_path}") + logging.error(f"Library Header File {h} not declared in package DEC {wsr_dec_path}") + overall_status += 1 + + ## Warn about any invalid library class names in the ignore list + for r in LibraryClassIgnore: + tc.LogStdError("LibraryClassCheck.IgnoreLibraryClass -> {0} not found. Library Class not found".format(r)) + logging.info("LibraryClassCheck.IgnoreLibraryClass -> {0} not found. Library Class not found".format(r)) + + + # If XML object exists, add result + if overall_status != 0: + tc.SetFailed("LibraryClassCheck {0} Failed. Errors {1}".format(wsr_dec_path, overall_status), "CHECK_FAILED") + else: + tc.SetSuccess() + return overall_status -- cgit