summaryrefslogtreecommitdiff
path: root/BaseTools/Plugin/CodeQL/CodeQlBuildPlugin.py
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Plugin/CodeQL/CodeQlBuildPlugin.py')
-rw-r--r--BaseTools/Plugin/CodeQL/CodeQlBuildPlugin.py338
1 files changed, 169 insertions, 169 deletions
diff --git a/BaseTools/Plugin/CodeQL/CodeQlBuildPlugin.py b/BaseTools/Plugin/CodeQL/CodeQlBuildPlugin.py
index 2f6c928c21..06898dfec6 100644
--- a/BaseTools/Plugin/CodeQL/CodeQlBuildPlugin.py
+++ b/BaseTools/Plugin/CodeQL/CodeQlBuildPlugin.py
@@ -1,169 +1,169 @@
-# @file CodeQlBuildPlugin.py
-#
-# A build plugin that produces CodeQL results for the present build.
-#
-# Copyright (c) Microsoft Corporation. All rights reserved.
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-##
-
-import glob
-import logging
-import os
-import stat
-from common import codeql_plugin
-from pathlib import Path
-
-from edk2toolext import edk2_logging
-from edk2toolext.environment.plugintypes.uefi_build_plugin import \
- IUefiBuildPlugin
-from edk2toolext.environment.uefi_build import UefiBuilder
-from edk2toollib.uefi.edk2.path_utilities import Edk2Path
-from edk2toollib.utility_functions import GetHostInfo, RemoveTree
-
-
-class CodeQlBuildPlugin(IUefiBuildPlugin):
-
- def do_pre_build(self, builder: UefiBuilder) -> int:
- """CodeQL pre-build functionality.
-
- Args:
- builder (UefiBuilder): A UEFI builder object for this build.
-
- Returns:
- int: The plugin return code. Zero indicates the plugin ran
- successfully. A non-zero value indicates an unexpected error
- occurred during plugin execution.
- """
-
- if not builder.SkipBuild:
- self.builder = builder
- self.package = builder.edk2path.GetContainingPackage(
- builder.edk2path.GetAbsolutePathOnThisSystemFromEdk2RelativePath(
- builder.env.GetValue("ACTIVE_PLATFORM")
- )
- )
-
- self.target = builder.env.GetValue("TARGET")
-
- self.build_output_dir = builder.env.GetValue("BUILD_OUTPUT_BASE")
-
- self.codeql_db_path = codeql_plugin.get_codeql_db_path(
- builder.ws, self.package, self.target)
-
- edk2_logging.log_progress(f"{self.package} will be built for CodeQL")
- edk2_logging.log_progress(f" CodeQL database will be written to "
- f"{self.codeql_db_path}")
-
- self.codeql_path = codeql_plugin.get_codeql_cli_path()
- if not self.codeql_path:
- logging.critical("CodeQL build enabled but CodeQL CLI application "
- "not found.")
- return -1
-
- # CodeQL can only generate a database on clean build
- #
- # Note: builder.CleanTree() cannot be used here as some platforms
- # have build steps that run before this plugin that store
- # files in the build output directory.
- #
- # CodeQL does not care about with those files or many others such
- # as the FV directory, build logs, etc. so instead focus on
- # removing only the directories with compilation/linker output
- # for the architectures being built (that need clean runs for
- # CodeQL to work).
- targets = self.builder.env.GetValue("TARGET_ARCH").split(" ")
- for target in targets:
- directory_to_delete = Path(self.build_output_dir, target)
-
- if directory_to_delete.is_dir():
- logging.debug(f"Removing {str(directory_to_delete)} to have a "
- f"clean build for CodeQL.")
- RemoveTree(str(directory_to_delete))
-
- # CodeQL CLI does not handle spaces passed in CLI commands well
- # (perhaps at all) as discussed here:
- # 1. https://github.com/github/codeql-cli-binaries/issues/73
- # 2. https://github.com/github/codeql/issues/4910
- #
- # Since it's unclear how quotes are handled and may change in the
- # future, this code is going to use the workaround to place the
- # command in an executable file that is instead passed to CodeQL.
- self.codeql_cmd_path = Path(self.build_output_dir, "codeql_build_command")
-
- build_params = self._get_build_params()
-
- codeql_build_cmd = ""
- if GetHostInfo().os == "Windows":
- self.codeql_cmd_path = self.codeql_cmd_path.parent / (
- self.codeql_cmd_path.name + '.bat')
- elif GetHostInfo().os == "Linux":
- self.codeql_cmd_path = self.codeql_cmd_path.parent / (
- self.codeql_cmd_path.name + '.sh')
- codeql_build_cmd += f"#!/bin/bash{os.linesep * 2}"
- codeql_build_cmd += "build " + build_params
-
- self.codeql_cmd_path.parent.mkdir(exist_ok=True, parents=True)
- self.codeql_cmd_path.write_text(encoding='utf8', data=codeql_build_cmd)
-
- if GetHostInfo().os == "Linux":
- os.chmod(self.codeql_cmd_path,
- os.stat(self.codeql_cmd_path).st_mode | stat.S_IEXEC)
- for f in glob.glob(os.path.join(
- os.path.dirname(self.codeql_path), '**/*'), recursive=True):
- os.chmod(f, os.stat(f).st_mode | stat.S_IEXEC)
-
- codeql_params = (f'database create {self.codeql_db_path} '
- f'--language=cpp '
- f'--source-root={builder.ws} '
- f'--command={self.codeql_cmd_path}')
-
- # Set environment variables so the CodeQL build command is picked up
- # as the active build command.
- #
- # Note: Requires recent changes in edk2-pytool-extensions (0.20.0)
- # to support reading these variables.
- builder.env.SetValue(
- "EDK_BUILD_CMD", self.codeql_path, "Set in CodeQL Build Plugin")
- builder.env.SetValue(
- "EDK_BUILD_PARAMS", codeql_params, "Set in CodeQL Build Plugin")
-
- return 0
-
- def _get_build_params(self) -> str:
- """Returns the build command parameters for this build.
-
- Based on the well-defined `build` command-line parameters.
-
- Returns:
- str: A string representing the parameters for the build command.
- """
- build_params = f"-p {self.builder.env.GetValue('ACTIVE_PLATFORM')}"
- build_params += f" -b {self.target}"
- build_params += f" -t {self.builder.env.GetValue('TOOL_CHAIN_TAG')}"
-
- max_threads = self.builder.env.GetValue('MAX_CONCURRENT_THREAD_NUMBER')
- if max_threads is not None:
- build_params += f" -n {max_threads}"
-
- rt = self.builder.env.GetValue("TARGET_ARCH").split(" ")
- for t in rt:
- build_params += " -a " + t
-
- if (self.builder.env.GetValue("BUILDREPORTING") == "TRUE"):
- build_params += (" -y " +
- self.builder.env.GetValue("BUILDREPORT_FILE"))
- rt = self.builder.env.GetValue("BUILDREPORT_TYPES").split(" ")
- for t in rt:
- build_params += " -Y " + t
-
- # add special processing to handle building a single module
- mod = self.builder.env.GetValue("BUILDMODULE")
- if (mod is not None and len(mod.strip()) > 0):
- build_params += " -m " + mod
- edk2_logging.log_progress("Single Module Build: " + mod)
-
- build_vars = self.builder.env.GetAllBuildKeyValues(self.target)
- for key, value in build_vars.items():
- build_params += " -D " + key + "=" + value
-
- return build_params
+# @file CodeQlBuildPlugin.py
+#
+# A build plugin that produces CodeQL results for the present build.
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+import glob
+import logging
+import os
+import stat
+from common import codeql_plugin
+from pathlib import Path
+
+from edk2toolext import edk2_logging
+from edk2toolext.environment.plugintypes.uefi_build_plugin import \
+ IUefiBuildPlugin
+from edk2toolext.environment.uefi_build import UefiBuilder
+from edk2toollib.uefi.edk2.path_utilities import Edk2Path
+from edk2toollib.utility_functions import GetHostInfo, RemoveTree
+
+
+class CodeQlBuildPlugin(IUefiBuildPlugin):
+
+ def do_pre_build(self, builder: UefiBuilder) -> int:
+ """CodeQL pre-build functionality.
+
+ Args:
+ builder (UefiBuilder): A UEFI builder object for this build.
+
+ Returns:
+ int: The plugin return code. Zero indicates the plugin ran
+ successfully. A non-zero value indicates an unexpected error
+ occurred during plugin execution.
+ """
+
+ if not builder.SkipBuild:
+ self.builder = builder
+ self.package = builder.edk2path.GetContainingPackage(
+ builder.edk2path.GetAbsolutePathOnThisSystemFromEdk2RelativePath(
+ builder.env.GetValue("ACTIVE_PLATFORM")
+ )
+ )
+
+ self.target = builder.env.GetValue("TARGET")
+
+ self.build_output_dir = builder.env.GetValue("BUILD_OUTPUT_BASE")
+
+ self.codeql_db_path = codeql_plugin.get_codeql_db_path(
+ builder.ws, self.package, self.target)
+
+ edk2_logging.log_progress(f"{self.package} will be built for CodeQL")
+ edk2_logging.log_progress(f" CodeQL database will be written to "
+ f"{self.codeql_db_path}")
+
+ self.codeql_path = codeql_plugin.get_codeql_cli_path()
+ if not self.codeql_path:
+ logging.critical("CodeQL build enabled but CodeQL CLI application "
+ "not found.")
+ return -1
+
+ # CodeQL can only generate a database on clean build
+ #
+ # Note: builder.CleanTree() cannot be used here as some platforms
+ # have build steps that run before this plugin that store
+ # files in the build output directory.
+ #
+ # CodeQL does not care about with those files or many others such
+ # as the FV directory, build logs, etc. so instead focus on
+ # removing only the directories with compilation/linker output
+ # for the architectures being built (that need clean runs for
+ # CodeQL to work).
+ targets = self.builder.env.GetValue("TARGET_ARCH").split(" ")
+ for target in targets:
+ directory_to_delete = Path(self.build_output_dir, target)
+
+ if directory_to_delete.is_dir():
+ logging.debug(f"Removing {str(directory_to_delete)} to have a "
+ f"clean build for CodeQL.")
+ RemoveTree(str(directory_to_delete))
+
+ # CodeQL CLI does not handle spaces passed in CLI commands well
+ # (perhaps at all) as discussed here:
+ # 1. https://github.com/github/codeql-cli-binaries/issues/73
+ # 2. https://github.com/github/codeql/issues/4910
+ #
+ # Since it's unclear how quotes are handled and may change in the
+ # future, this code is going to use the workaround to place the
+ # command in an executable file that is instead passed to CodeQL.
+ self.codeql_cmd_path = Path(self.build_output_dir, "codeql_build_command")
+
+ build_params = self._get_build_params()
+
+ codeql_build_cmd = ""
+ if GetHostInfo().os == "Windows":
+ self.codeql_cmd_path = self.codeql_cmd_path.parent / (
+ self.codeql_cmd_path.name + '.bat')
+ elif GetHostInfo().os == "Linux":
+ self.codeql_cmd_path = self.codeql_cmd_path.parent / (
+ self.codeql_cmd_path.name + '.sh')
+ codeql_build_cmd += f"#!/bin/bash{os.linesep * 2}"
+ codeql_build_cmd += "build " + build_params
+
+ self.codeql_cmd_path.parent.mkdir(exist_ok=True, parents=True)
+ self.codeql_cmd_path.write_text(encoding='utf8', data=codeql_build_cmd)
+
+ if GetHostInfo().os == "Linux":
+ os.chmod(self.codeql_cmd_path,
+ os.stat(self.codeql_cmd_path).st_mode | stat.S_IEXEC)
+ for f in glob.glob(os.path.join(
+ os.path.dirname(self.codeql_path), '**/*'), recursive=True):
+ os.chmod(f, os.stat(f).st_mode | stat.S_IEXEC)
+
+ codeql_params = (f'database create {self.codeql_db_path} '
+ f'--language=cpp '
+ f'--source-root={builder.ws} '
+ f'--command={self.codeql_cmd_path}')
+
+ # Set environment variables so the CodeQL build command is picked up
+ # as the active build command.
+ #
+ # Note: Requires recent changes in edk2-pytool-extensions (0.20.0)
+ # to support reading these variables.
+ builder.env.SetValue(
+ "EDK_BUILD_CMD", self.codeql_path, "Set in CodeQL Build Plugin")
+ builder.env.SetValue(
+ "EDK_BUILD_PARAMS", codeql_params, "Set in CodeQL Build Plugin")
+
+ return 0
+
+ def _get_build_params(self) -> str:
+ """Returns the build command parameters for this build.
+
+ Based on the well-defined `build` command-line parameters.
+
+ Returns:
+ str: A string representing the parameters for the build command.
+ """
+ build_params = f"-p {self.builder.env.GetValue('ACTIVE_PLATFORM')}"
+ build_params += f" -b {self.target}"
+ build_params += f" -t {self.builder.env.GetValue('TOOL_CHAIN_TAG')}"
+
+ max_threads = self.builder.env.GetValue('MAX_CONCURRENT_THREAD_NUMBER')
+ if max_threads is not None:
+ build_params += f" -n {max_threads}"
+
+ rt = self.builder.env.GetValue("TARGET_ARCH").split(" ")
+ for t in rt:
+ build_params += " -a " + t
+
+ if (self.builder.env.GetValue("BUILDREPORTING") == "TRUE"):
+ build_params += (" -y " +
+ self.builder.env.GetValue("BUILDREPORT_FILE"))
+ rt = self.builder.env.GetValue("BUILDREPORT_TYPES").split(" ")
+ for t in rt:
+ build_params += " -Y " + t
+
+ # add special processing to handle building a single module
+ mod = self.builder.env.GetValue("BUILDMODULE")
+ if (mod is not None and len(mod.strip()) > 0):
+ build_params += " -m " + mod
+ edk2_logging.log_progress("Single Module Build: " + mod)
+
+ build_vars = self.builder.env.GetAllBuildKeyValues(self.target)
+ for key, value in build_vars.items():
+ build_params += " -D " + key + "=" + value
+
+ return build_params