]>
git.proxmox.com Git - mirror_edk2.git/blob - .pytool/Plugin/LibraryClassCheck/LibraryClassCheck.py
20d87f13f5240613bc47b9d98339ac4f24545ac3
1 # @file LibraryClassCheck.py
3 # Copyright (c) Microsoft Corporation.
4 # SPDX-License-Identifier: BSD-2-Clause-Patent
8 from edk2toolext
.environment
.plugintypes
.ci_build_plugin
import ICiBuildPlugin
9 from edk2toollib
.uefi
.edk2
.parsers
.dec_parser
import DecParser
10 from edk2toollib
.uefi
.edk2
.parsers
.inf_parser
import InfParser
11 from edk2toolext
.environment
.var_dict
import VarDict
14 class LibraryClassCheck(ICiBuildPlugin
):
16 A CiBuildPlugin that scans the code tree and library classes for undeclared
19 Configuration options:
20 "LibraryClassCheck": {
21 IgnoreHeaderFile: [], # Ignore a file found on disk
22 IgnoreLibraryClass: [] # Ignore a declaration found in dec file
26 def GetTestName(self
, packagename
: str, environment
: VarDict
) -> tuple:
27 """ Provide the testcase name and classname for use in reporting
28 testclassname: a descriptive string for the testcase can include whitespace
29 classname: should be patterned <packagename>.<plugin>.<optionally any unique condition>
32 packagename: string containing name of package to build
33 environment: The VarDict for the test to run in
35 a tuple containing the testcase name and the classname
36 (testcasename, classname)
38 return ("Check library class declarations in " + packagename
, packagename
+ ".LibraryClassCheck")
40 def __GetPkgDec(self
, rootpath
):
42 allEntries
= os
.listdir(rootpath
)
43 for entry
in allEntries
:
44 if entry
.lower().endswith(".dec"):
45 return(os
.path
.join(rootpath
, entry
))
47 logging
.error("Unable to find DEC for package:{0}".format(rootpath
))
52 # External function of plugin. This function is used to perform the task of the MuBuild Plugin
54 # - package is the edk2 path to package. This means workspace/packagepath relative.
55 # - edk2path object configured with workspace and packages path
56 # - PkgConfig Object (dict) for the pkg
58 # - Plugin Manager Instance
59 # - Plugin Helper Obj Instance
61 # - output_stream the StringIO output stream from this plugin via logging
62 def RunBuildPlugin(self
, packagename
, Edk2pathObj
, pkgconfig
, environment
, PLM
, PLMHelper
, tc
, output_stream
=None):
64 LibraryClassIgnore
= []
66 abs_pkg_path
= Edk2pathObj
.GetAbsolutePathOnThisSytemFromEdk2RelativePath(packagename
)
67 abs_dec_path
= self
.__GetPkgDec
(abs_pkg_path
)
68 wsr_dec_path
= Edk2pathObj
.GetEdk2RelativePathFromAbsolutePath(abs_dec_path
)
70 if abs_dec_path
is None or wsr_dec_path
== "" or not os
.path
.isfile(abs_dec_path
):
72 tc
.LogStdError("No DEC file {0} in package {1}".format(abs_dec_path
, abs_pkg_path
))
75 # Get all include folders
77 dec
.SetBaseAbsPath(Edk2pathObj
.WorkspacePath
).SetPackagePaths(Edk2pathObj
.PackagePathList
)
78 dec
.ParseFile(wsr_dec_path
)
82 for includepath
in dec
.IncludePaths
:
83 ## Get all header files in the library folder
84 AbsLibraryIncludePath
= os
.path
.join(abs_pkg_path
, includepath
, "Library")
85 if(not os
.path
.isdir(AbsLibraryIncludePath
)):
88 hfiles
= self
.WalkDirectoryForExtension([".h"], AbsLibraryIncludePath
)
89 hfiles
= [os
.path
.relpath(x
,abs_pkg_path
) for x
in hfiles
] # make package root relative path
90 hfiles
= [x
.replace("\\", "/") for x
in hfiles
] # make package relative path
92 AllHeaderFiles
.extend(hfiles
)
94 if len(AllHeaderFiles
) == 0:
96 tc
.LogStdError(f
"No Library include folder in any Include path")
99 # Remove ignored paths
100 if "IgnoreHeaderFile" in pkgconfig
:
101 for a
in pkgconfig
["IgnoreHeaderFile"]:
103 tc
.LogStdOut("Ignoring Library Header File {0}".format(a
))
104 AllHeaderFiles
.remove(a
)
106 tc
.LogStdError("LibraryClassCheck.IgnoreHeaderFile -> {0} not found. Invalid Header File".format(a
))
107 logging
.info("LibraryClassCheck.IgnoreHeaderFile -> {0} not found. Invalid Header File".format(a
))
109 if "IgnoreLibraryClass" in pkgconfig
:
110 LibraryClassIgnore
= pkgconfig
["IgnoreLibraryClass"]
113 ## Attempt to find library classes
114 for lcd
in dec
.LibraryClasses
:
115 ## Check for correct file path separator
117 tc
.LogStdError("LibraryClassCheck.DecFilePathSeparator -> {0} invalid.".format(lcd
.path
))
118 logging
.error("LibraryClassCheck.DecFilePathSeparator -> {0} invalid.".format(lcd
.path
))
122 if lcd
.name
in LibraryClassIgnore
:
123 tc
.LogStdOut("Ignoring Library Class Name {0}".format(lcd
.name
))
124 LibraryClassIgnore
.remove(lcd
.name
)
127 logging
.debug(f
"Looking for Library Class {lcd.path}")
129 AllHeaderFiles
.remove(lcd
.path
)
132 tc
.LogStdError(f
"Library {lcd.name} with path {lcd.path} not found in package filesystem")
133 logging
.error(f
"Library {lcd.name} with path {lcd.path} not found in package filesystem")
136 ## any remaining AllHeaderFiles are not described in DEC
137 for h
in AllHeaderFiles
:
138 tc
.LogStdError(f
"Library Header File {h} not declared in package DEC {wsr_dec_path}")
139 logging
.error(f
"Library Header File {h} not declared in package DEC {wsr_dec_path}")
142 ## Warn about any invalid library class names in the ignore list
143 for r
in LibraryClassIgnore
:
144 tc
.LogStdError("LibraryClassCheck.IgnoreLibraryClass -> {0} not found. Library Class not found".format(r
))
145 logging
.info("LibraryClassCheck.IgnoreLibraryClass -> {0} not found. Library Class not found".format(r
))
148 # If XML object exists, add result
149 if overall_status
!= 0:
150 tc
.SetFailed("LibraryClassCheck {0} Failed. Errors {1}".format(wsr_dec_path
, overall_status
), "CHECK_FAILED")
153 return overall_status