mirror of https://github.com/acidanthera/audk.git
128 lines
5.3 KiB
Python
128 lines
5.3 KiB
Python
|
# @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
|