-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BaseTools/Plugin: Add DebugMacroCheck
Adds a plugin that finds debug macro formatting issues. These errors often creep into debug prints in error conditions not frequently executed and make debug more difficult when they are encountered. The code can be as a standalone script which is useful to find problems in a large codebase that has not been checked before or as a build plugin that notifies a developer of an error right away. The script was already used to find numerous issues in edk2 in the past so there's not many code fixes in this change. More details are available in the readme file: .pytool\Plugin\DebugMacroCheck\Readme.md Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Rebecca Cran <rebecca@bsdio.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Bob Feng <bob.c.feng@intel.com> Cc: Yuwei Chen <yuwei.chen@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
- Loading branch information
1 parent
97d367f
commit cbcf042
Showing
8 changed files
with
2,256 additions
and
0 deletions.
There are no files selected for viewing
127 changes: 127 additions & 0 deletions
127
BaseTools/Plugin/DebugMacroCheck/BuildPlugin/DebugMacroCheckBuildPlugin.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
# @file DebugMacroCheckBuildPlugin.py | ||
# | ||
# A build plugin that checks if DEBUG macros are formatted properly. | ||
# | ||
# In particular, that print format specifiers are defined | ||
# with the expected number of arguments in the variable | ||
# argument list. | ||
# | ||
# Copyright (c) Microsoft Corporation. All rights reserved. | ||
# SPDX-License-Identifier: BSD-2-Clause-Patent | ||
## | ||
|
||
import logging | ||
import os | ||
import pathlib | ||
import sys | ||
import yaml | ||
|
||
# Import the build plugin | ||
plugin_file = pathlib.Path(__file__) | ||
sys.path.append(str(plugin_file.parent.parent)) | ||
|
||
# flake8 (E402): Ignore flake8 module level import not at top of file | ||
import DebugMacroCheck # noqa: E402 | ||
|
||
from edk2toolext import edk2_logging # noqa: E402 | ||
from edk2toolext.environment.plugintypes.uefi_build_plugin import \ | ||
IUefiBuildPlugin # noqa: E402 | ||
from edk2toolext.environment.uefi_build import UefiBuilder # noqa: E402 | ||
from edk2toollib.uefi.edk2.path_utilities import Edk2Path # noqa: E402 | ||
from pathlib import Path # noqa: E402 | ||
|
||
|
||
class DebugMacroCheckBuildPlugin(IUefiBuildPlugin): | ||
|
||
def do_pre_build(self, builder: UefiBuilder) -> int: | ||
"""Debug Macro Check pre-build functionality. | ||
The plugin is invoked in pre-build since it can operate independently | ||
of build tools and to notify the user of any errors earlier in the | ||
build process to reduce feedback time. | ||
Args: | ||
builder (UefiBuilder): A UEFI builder object for this build. | ||
Returns: | ||
int: The number of debug macro errors found. Zero indicates the | ||
check either did not run or no errors were found. | ||
""" | ||
|
||
# Check if disabled in the environment | ||
env_disable = builder.env.GetValue("DISABLE_DEBUG_MACRO_CHECK") | ||
if env_disable: | ||
return 0 | ||
|
||
# Only run on targets with compilation | ||
build_target = builder.env.GetValue("TARGET").lower() | ||
if "no-target" in build_target: | ||
return 0 | ||
|
||
pp = builder.pp.split(os.pathsep) | ||
edk2 = Edk2Path(builder.ws, pp) | ||
package = edk2.GetContainingPackage( | ||
builder.mws.join(builder.ws, | ||
builder.env.GetValue( | ||
"ACTIVE_PLATFORM"))) | ||
package_path = Path( | ||
edk2.GetAbsolutePathOnThisSystemFromEdk2RelativePath( | ||
package)) | ||
|
||
# Every debug macro is printed at DEBUG logging level. | ||
# Ensure the level is above DEBUG while executing the macro check | ||
# plugin to avoid flooding the log handler. | ||
handler_level_context = [] | ||
for h in logging.getLogger().handlers: | ||
if h.level < logging.INFO: | ||
handler_level_context.append((h, h.level)) | ||
h.setLevel(logging.INFO) | ||
|
||
edk2_logging.log_progress("Checking DEBUG Macros") | ||
|
||
# There are two ways to specify macro substitution data for this | ||
# plugin. If multiple options are present, data is appended from | ||
# each option. | ||
# | ||
# 1. Specify the substitution data in the package CI YAML file. | ||
# 2. Specify a standalone substitution data YAML file. | ||
## | ||
sub_data = {} | ||
|
||
# 1. Allow substitution data to be specified in a "DebugMacroCheck" of | ||
# the package CI YAML file. This is used to provide a familiar per- | ||
# package customization flow for a package maintainer. | ||
package_config_file = Path( | ||
os.path.join( | ||
package_path, package + ".ci.yaml")) | ||
if package_config_file.is_file(): | ||
with open(package_config_file, 'r') as cf: | ||
package_config_file_data = yaml.safe_load(cf) | ||
if "DebugMacroCheck" in package_config_file_data and \ | ||
"StringSubstitutions" in \ | ||
package_config_file_data["DebugMacroCheck"]: | ||
logging.info(f"Loading substitution data in " | ||
f"{str(package_config_file)}") | ||
sub_data |= package_config_file_data["DebugMacroCheck"]["StringSubstitutions"] # noqa | ||
|
||
# 2. Allow a substitution file to be specified as an environment | ||
# variable. This is used to provide flexibility in how to specify a | ||
# substitution file. The value can be set anywhere prior to this plugin | ||
# getting called such as pre-existing build script. | ||
sub_file = builder.env.GetValue("DEBUG_MACRO_CHECK_SUB_FILE") | ||
if sub_file: | ||
logging.info(f"Loading substitution file {sub_file}") | ||
with open(sub_file, 'r') as sf: | ||
sub_data |= yaml.safe_load(sf) | ||
|
||
try: | ||
error_count = DebugMacroCheck.check_macros_in_directory( | ||
package_path, | ||
ignore_git_submodules=False, | ||
show_progress_bar=False, | ||
**sub_data) | ||
finally: | ||
for h, l in handler_level_context: | ||
h.setLevel(l) | ||
|
||
return error_count |
11 changes: 11 additions & 0 deletions
11
BaseTools/Plugin/DebugMacroCheck/BuildPlugin/DebugMacroCheck_plug_in.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
## @file | ||
# Build plugin used to check that debug macros are formatted properly. | ||
# | ||
# Copyright (c) Microsoft Corporation. All rights reserved. | ||
# SPDX-License-Identifier: BSD-2-Clause-Patent | ||
## | ||
{ | ||
"scope": "global", | ||
"name": "Debug Macro Check Plugin", | ||
"module": "DebugMacroCheckBuildPlugin" | ||
} |
Oops, something went wrong.