Skip to content

Commit

Permalink
Report parser sqlite3 (#654)
Browse files Browse the repository at this point in the history
Adds new invocables for generating a database containing workspace information and reports to run against the database.

1. `stuart_parse` is a new invocable tied to a settings file that is used to parse workspace and environment information for a given package (or multiple packages). It creates a standalone sqlite3 database that can be queried using sql queries or reports managed by `stuart_report` can be run against the database.
2. `stuart_report` is a standalone executable that manages multiple reports that can be run against the database.

Stuart Parse can be run on a platform package (typically associated with a PlatformBuild.py file) or non-platform packages (typically associated with a CISettings.py file).

## Initial Reports

1. Coverage report: `stuart_report coverage` is a report that consumes a cobertura report generated from host based unit tests in the workspace, and re-organizes the report per INF rather than per executable to more accurately show test coverage.
2. Usage report: `stuart_report usage` is a report that generates an html document showing all INFs (both library and component) that are used to build a platform, and which submodule (or BASE repo) the INF comes from.
3. Component Library Report: `stuart_report component-libs` is a report that prints to the terminal (or a file) the actual list of library instances used to build a specific component. It can print in flat mode, or show a recursive list of dependencies for the component.
  • Loading branch information
Javagedes committed Nov 2, 2023
1 parent 2aa65f7 commit 4753cf6
Show file tree
Hide file tree
Showing 14 changed files with 1,487 additions and 3 deletions.
11 changes: 9 additions & 2 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@
"etree",
"executables",
"extdep",
"fileFlagsMask",
"fdfp",
"FileFlagsMask",
"gitattributes",
"gitbash",
"gitignore",
Expand All @@ -62,6 +63,7 @@
"gnupg",
"iasl",
"imxfamily",
"infp",
"invocable",
"invocables",
"isabs",
Expand All @@ -87,14 +89,18 @@
"ovmf",
"openpyxl",
"packagename",
"pathsep",
"Pathsep",
"pcds",
"Pdbs",
"pecoff",
"pefile",
"pkgconfig",
"PKGS",
"plotly",
"plotlyjs",
"plugintypes",
"pousr",
"ppis",
"prebuild",
"prepended",
"pygit",
Expand Down Expand Up @@ -126,6 +132,7 @@
"submodule",
"submodules",
"tianocore",
"tinydb",
"toolchain",
"toolext",
"toollib",
Expand Down
11 changes: 11 additions & 0 deletions docs/user/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,17 @@ This includes compiler plugin, which builds each package for the required
targets. Stuart will checkpoint the original environment and restore that
checkpoint between each test.

### stuart_parse

Will parse and Edk2 workspace and create a standalone sqlite3 database that
can be queried through sql tools or by stuart_report to generate common
uefi/edk2 focused reports.

### stuart_report

Consumes the sqlite3 database generated by stuart_report that can run prebuilt
queries and reports against the database.

## Living with Stuart

### .gitignore
Expand Down
71 changes: 71 additions & 0 deletions docs/user/integrate/reporting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Reporting on a EDK2 workspace

Stuart provides both a library implementation and an invocable for parsing an EDK2 workspace, creating a database, and
running generic reports against the database. Reporting is supported both on regular packages (built with
`stuart_ci_build`) and platform packages (built with `stuart_build`).

There are three [stuart commands](/#what-can-i-ask-stuart-to-do) to create a database, then a fourth command to run
reports against the database: `stuart_setup`/`stuart_ci_setup`, `stuart_update`, and `stuart_parse`. From there, a
developer can directly query the sqlite3 database or call `stuart_report <report>` to run a pre-build report.

## Getting Started

Similar to [building with stuart](/integrate/build/), it needs a settings file to configure itself. This settings file
must provide a settings manager subclass for each of the commands mentioned above. Please review the steps provided in
[building with stuart](/integrate/build/) on the steps necessary for integrate the above mentioned commands.

The only additional integration is to integrate `stuart_parse`, which needs the [`ParseSettingsManager`](/api/invocables/edk2_parse/#edk2toolext.invocables.edk2_parse.ParseSettingsManager)
to work. No additional methods need to be implemented, `ParseSettingsManager` just needs to be present.

## Stuart Parse

`Stuart_parse` is responsible for actually parsing the workspace and creating the database. `stuart_parse` is smart in
that it can determine if you are attempting to parse a specific platform package, or normal packages by the presence of
the `UefiBuilder` object or not. If the `UefiBuilder` object is detected, it knows that a platform package is being
parsed, and it uses the `UefiBuilder` configure the environment before parsing.

If the `UefiBuilder` object is not present, it assumes you are parsing the workspace in regards to one or multiple
regular packages. Similar to when running `stuart_ci_build`, you can filter on packages (`-p <pkg>`) amd architectures
(`-a <arch>`). When `stuart_parse` executes in this method, it parses the environment once per package, and all reports
allow you to generatea report given a specific environment.

1. Subclass the [ParseSettingsManager](/api/invocables/edk2_parse/#edk2toolext.invocables.edk2_parse.ParseSettingsManager)
to the same python object as the [UefiBuilder](/api/environment/uefi_build/#edk2toolext.environment.uefi_build.UefiBuilder)
is subclassed to. This scenario is used to parse the workspace in terms of platform packages.

2. Associate the [ParseSettingsManager](/api/invocables/edk2_parse/#edk2toolext.invocables.edk2_parse.ParseSettingsManager)
to the same python object as the [CiBuildSettingsManager](/api/invocables/edk2_ci_build/#edk2toolext.invocables.edk2_ci_build.CiBuildSettingsManager)
is subclassed to. This scenario is used to parse the workspace in terms of non-platform packages.

```python
# Before implementation (platform package)
class PlatformSettingsManager(BuildSettingsManager, UefiBuilder):
...

# After implementation (platform package)
class PlatformSettingsManager(BuildSettingsManager, UefiBuilder, ParseSettingsManager):
...

# Before implementation (non-platform package)
class CiSettingsManager(CiBuildSettingsManager):
...

# After implementation (non-platform package)
class CiSettingsManger(CiBuildSettingsManager, ParseSettingsManager):
...
```

Attaching directly to the same object as the `UefiBuilder` or `CiBuildSettingsManager` is for convenience; as long
as the `UefiBuilder` or `CiBuildSettingsManager` is in the file (or is a parent of a class in the file), the parser
will work as expected.

**WARNING**: ParseSettingsManager does add additional command line arguments that are used when attached to the same
object as the `CIBuildSettingsManager`, but also exist when attached to the `UefiBuilder` This may create argument
parser conflicts between platform added arguments and default arguments, that will need to be resolved.

## Stuart Report

`Stuart_report` is a standalone command line tool that is not need to be associated with a python settings file. It
only needs access to the database. Out of convenience, it assumes the database exists where `stuart_report` generates
it in the workspace, however you can override that with the `-db` command line argument. Simply run `stuart_report -h`
to view all reports, or review [Using Reports](/using/reporting/)
160 changes: 160 additions & 0 deletions docs/user/using/reporting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Reporting

Top take your EDK2 workspace from freshly cloned, to parsed and ready to be reported on, you only need to execute three
commands. If you've properly [installed](/using/install) edk2-pytool-extensions, then these commands will be available
to execute as seen below:

```cmd
stuart_setup (or stuart_ci_setup) -c path/to/SettingsFile.py
stuart_update -c path/to/SettingsFile.py
stuart_parse -c path/to/SettingsFile.py
```

From there, you will use stuart_report (or sql queries against the database) to run reports / queries against the database.

## Stuart Parse

### Command Line Interface

Similar to all other invocables, the user can use the `-h` flag review a detailed description of the CLI interface,
however for convenience, here are the options available:

``` cmd
Optional Arguments:
--append, --Append, --APPEND Run only environment aware parsers and append them to the database.
-p, --pkg, --pkg-dir Packages to parse (CI builder only)
-a, --arch Architectures to use when parsing (CI builder only)
-t, --target Targets (DEBUG, etc.) to use when parsing (CI builder only)
```

### Example usage

``` cmd
:: parse the workspace for mu_tiano_platform's QemuQ35Pkg in debug mode
stuart_parse -c Platforms/QemuQ35Pkg/PlatformBuild.py TARGET=DEBUG
:: parse the workspace for mu_tiano_platform's QemuQ35Pkg in release mode, appending the results to the existing database
stuart_parse -c Platforms/QemuQ35Pkg/PlatformBuild.py --append TARGET=RELEASE
:: parse the workspace for all packages supported in mu_basecore
stuart_parse -c .pytool/CISettings.py
:: parse the workspace for all packages supported in mu_basecore, filtering the packages
stuart_parse -c .pytool/CISettings.py -p MdePkg -p MdeModulePkg
:: parse the workspace for all packages supported in mu_basecore, only using DEBUG
stuart_parse -c .pytool/CISettings.py -t DEBUG
```

## Stuart Report

### Command line arguments

``` cmd
usage: A tool to generate reports on a edk2 workspace. [-h] [--verbose] [-db DATABASE] {coverage,component-libs,usage} ...
positional arguments:
{coverage,component-libs,usage}
options:
-h, --help show this help message and exit
--verbose, --VERBOSE, -v
verbose
-db DATABASE, --database DATABASE, --DATABASE DATABASE
The database to use when generating reports. Can be a comma separated list of db's to merge. Globbing is supported.
```

Review the command line arguments with `stuart_report -h`. As you can tell, the
command line interface for the tool itself is simple, only truly needing a path
to the database to use. Out of convenience, the default path for the database
is Reports/DATABASE.db, as that is where the database is generated when running
`stuart_parse`. If the database is moved or renamed, you will need to manually
link it with the `-db, --database`.

Each available report (positional argument) has it's own subset of command line
arguments so before running a report, it is important to review it's interface
also `stuart_report <Report> -h` to see the customizations / necessary
arguments for the report.

#### Coverage Report

`stuart_report coverage` converts coverage xml results into a similar coverage
xml that re-organizes the data to be based off the library INF rather than the
executed binary used for testing. It provides a more accurate representation of
the current code coverage as most UEFI developers will care about code coverage
of a specific library. Additionally, some files are used in multiple INFs,
which this report will more accurately depict.

Due to the complex nature involved in building a UEFI package, code coverage
results can also contain code coverage results for INFs outside of the package
the developer cares about. This tool allows for the filtering of results to
specific packages.

``` cmd
usage: A tool to generate reports on a edk2 workspace. coverage [-h] [-o OUTPUT] [-s {inf}] [-p PACKAGE_LIST] [-ws WORKSPACE] [--library] xml
Reorganizes an xml coverage report by INF rather than executable.
positional arguments:
xml The path to the XML file parse.
options:
-h, --help show this help message and exit
-o OUTPUT, --output OUTPUT, --Output OUTPUT, --OUTPUT OUTPUT
The path to the output XML file.
-s {inf}, --scope {inf}, --Scope {inf}, --SCOPE {inf}
The scope to associate coverage data
-p PACKAGE_LIST, --package PACKAGE_LIST, --Package PACKAGE_LIST, --PACKAGE PACKAGE_LIST
The package to include in the report. Can be specified multiple times.
-ws WORKSPACE, --workspace WORKSPACE, --Workspace WORKSPACE, --WORKSPACE WORKSPACE
The Workspace root associated with the xml argument.
--library To only show results for library INFs
```

#### Usage Report

`stuart_report usage` generates a standalone html document (requires internat)
that contains pie charts showing the different library and component INFs that
are used to build the specific package parsed, and which submodules (or BASE)
they come from. It also contains a table of all INFs used, and a table of all
environment variables used when building the package.

``` cmd
usage: A tool to generate reports on a edk2 workspace. usage [-h] [-e ENV_ID] [-o OUTPUT]
Generates a report of INF usage for a specific build.
options:
-h, --help show this help message and exit
-e ENV_ID, -env ENV_ID
The environment id to generate the report for. Defaults to the latest environment.
-o OUTPUT, -output OUTPUT
The output file to write the report to. Defaults to 'usage_report.html'.
```

#### Component Library Report

`stuart_report component-libs` prints to the terminal (or writes to a file) the
actual list of library instances (and their associated library classes) used to
create the component. This is based off the package dsc that was parsed. The
report will print a flat version, providing each library compiled into the
component, or a recursive list of dependencies for each library.

``` cmd
usage: A tool to generate reports on a edk2 workspace. component-libs [-h] [-o FILE] [-d DEPTH] [-f] [-s] [-e ENV_ID] component
Dumps the library instances used by component.
positional arguments:
component The component to query.
options:
-h, --help show this help message and exit
-o FILE, --out FILE The file, to write the report to. Defaults to stdout.
-d DEPTH, --depth DEPTH
The depth to recurse when printing libraries used.
-f, --flatten Flatten the list of libraries used in the component.
-s, --sort Sort the libraries listed in alphabetical order.
-e ENV_ID, --env ENV_ID
The environment id to generate the report for.
```
Loading

0 comments on commit 4753cf6

Please sign in to comment.