Skip to content

scripts: Add HTML build report script#104431

Open
grahamroff-dev wants to merge 3 commits intozephyrproject-rtos:mainfrom
grahamroff-dev:build-report
Open

scripts: Add HTML build report script#104431
grahamroff-dev wants to merge 3 commits intozephyrproject-rtos:mainfrom
grahamroff-dev:build-report

Conversation

@grahamroff-dev
Copy link
Contributor

@grahamroff-dev grahamroff-dev commented Feb 23, 2026

This change adds a script to generate an HTML report, invoked via west, providing a consolidated and user-friendly view of various build artifacts and metrics. This includes footprint information (as both tables and plots), configuration tracing, sys init levels, an interactive devicetree browser, and more.

Invoke using west build -t buildreport

An example of the HTML output is available at https://grahamroff-dev.github.io/zephyr-buildreport/index.html

There is inconsistency in naming convention for the Zephyr scripts, some use underscores (like ram_report) and many do not (like traceconfig, initlevels, debugserver). I chose "buildreport" (sounded more like a report on the build as opposed to "build_report" which sounds a bit like building a report) but any other suggestions on script naming are welcome.

I added the documentation to the "Optimization Tools" section as that is where the memory report tools are documented. The buildreport covers a lot more than just optimization though, so suggestions welcome if there is a better place.

@grahamroff-dev grahamroff-dev force-pushed the build-report branch 2 times, most recently from d34a4f6 to 4b39bb3 Compare February 24, 2026 01:08
@pdgendt
Copy link
Contributor

pdgendt commented Feb 24, 2026

This should not be a single commit, changes to the existing scripts check_init_priorities.py/edtlib.py/plot.py should each be a separate commit.

Comment on lines 1071 to 1075
dt_props:
A dict that maps property names to dtlib_Property objects.
This provides access to the complete list of properties on the node
including ones not declared in the binding.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alas, this is an abstraction violation we can't allow in edtlib. See the "general biased advice" at top of the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I acknowledge this goes against the abstraction advice, however that advice seems somewhat arbitrary ;)
Any suggestion on how to get a list of all the properties in a node? The current edtlib purposefully leaves out valid properties like #address-cells, leaving a consumer (the build report in this case) unable to get a complete list of properties. As an abstraction layer this is broken.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two problems I am trying to get around. First, in Node._init_prop a bunch of properties are simply skipped even though they appear in the devicetree:

        # Skip properties that start with '#', like '#size-cells', and mapping
        # properties like 'gpio-map'/'interrupt-map'
        if name[0] == "#" or name.endswith("-map"):
            return

Then in Node._check_undeclared_props the validation also allows a number of properties that will not appear in the Node.props list:

        wl = {"compatible", "status", "ranges", "phandle",
              "interrupt-parent", "interrupts-extended", "device_type"}

        for prop_name in self._node.props:
            # Allow a few special properties to not be declared in the binding
            if (prop_name.endswith("-controller")
                or prop_name.startswith("#")
                or prop_name in wl):
                continue

If I just iterate over Node.props then the table view will be missing a lot of important properties.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mbolivar I removed the change to edtlib by reparsing the dts file using dtlib directly, then pulling in the nodes and bindings that match.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how funny, this sounds like the same issue I hit yesterday on defaults in bindings being wholly ignored, #104478 @mbolivar there is some issue there

@pdgendt
Copy link
Contributor

pdgendt commented Feb 24, 2026

This should not be a single commit, changes to the existing scripts check_init_priorities.py/edtlib.py/plot.py should each be a separate commit.

Your last update did something wrong, the first commit now deletes the existing scripts, and later commits re-introduce them with changes...

You first need to update the existing scripts (not delete!), and add your new stuff after.

@grahamroff-dev
Copy link
Contributor Author

This should not be a single commit, changes to the existing scripts check_init_priorities.py/edtlib.py/plot.py should each be a separate commit.

Your last update did something wrong, the first commit now deletes the existing scripts, and later commits re-introduce them with changes...

You first need to update the existing scripts (not delete!), and add your new stuff after.

Sorry, messed up the rework of the commit history. Fixed.

Copy link
Contributor

@tejlmand tejlmand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invoke using west build -t buildreport

Doesn't work.
Did you forget to include some files in the commit ?

try:
import plotly.graph_objects as go
except ImportError:
sys.exit("Missing dependency: You need to install plotly.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plotly is part of requirements-extra.

Perhaps better to refer there instead, or in addition.

# used by scripts/footprint/plot.py for generating plots of size reports
plotly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I updated to handle missing plotly and just skip generating the plots, also updated the import error to suggest looking at requirements-extra.

@grahamroff-dev
Copy link
Contributor Author

Invoke using west build -t buildreport

Doesn't work. Did you forget to include some files in the commit ?

@tejlmand, I updated with missing cmake script changes, sorry about that, please try again.

In order to allow the plot.py functionality to be used by other
scripts, move the code into a separate function that can be
imported.

Signed-off-by: Graham Roff <grahamr@qti.qualcomm.com>
To allow other scripts to use the initlevel information determined
by the Validator class, expose an API to get them.

Signed-off-by: Graham Roff <grahamr@qti.qualcomm.com>
This change adds a script to generate an HTML report, invoked via
west, providing a consolidated and user-friendly view of various build
artifacts and metrics. This includes footprint information (as both
tables and plots), configuration tracing, sys init levels, an interactive
devicetree browser, and more.

Signed-off-by: Graham Roff <grahamr@qti.qualcomm.com>
Copy link
Contributor

@pdgendt pdgendt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to say, this looks impressive. The report output is nice, and provides a lot of info in an easy accessible way.

I do have a question regarding maintainership: Are you/Qualcomm going to oversee this? Should we create an area/subarea in the MAINTAINERS.yml file for this?

Copy link
Contributor

@tejlmand tejlmand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice tool.

Some minor nits.

One idea, comments from everyone are more than welcome.
When running ninja puncover, https://docs.zephyrproject.org/latest/develop/optimizations/tools.html#build-target-puncover
then the target will not only launch a webserver, but also open your default browser and connect to the page.

For consistency with puncover behavior, should west html_buildreport default open the generated page(s) in the user's default webbrowser ?
(this suggestion is not blocking the review)

message(" rom_plot - Build and create ROM usage in a sunburst chart as a visual representation")
message(" traceconfig - Generate a file in the build directory that details how each symbol got its final value")
message(" footprint - Create JSON RAM/ROM usage report in the build directory")
message(" buildreport - Generate an HTML report with footprint, traceconfig, initlevels, devicetree, and other details")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other commands, such as ram_report, rom_report, initlevels, etc produces textual output directly.

Commands not doing so or relies on dedicated program indicates this is their target name, such as pahole and puncover.

I would like buildreport to reflect in its name that this is not a textual output.

For example html_report / html_buildreport.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. There are number of locations whose name should be consistent. Currently the PR uses:

  • west command: west build -t buildreport
  • Script location: scripts/buildreport
  • Script name: buildreport.py
  • Output location: build/report

Based on suggestions so far I will update the west command to west build -t html_report and the default output location to build/html/report.

What are your thoughts on the script location and name? Would this be preferred:

  • Script location: scripts/html_report
  • Script name: html_report.py
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another naming idea could be "dashboard":

  • west command: west build -t dashboard or west build -t html_dashboard
  • Script location: scripts/dashboard
  • Script name: dashboard.py
  • Output location: build/html/dashboard
template = env.get_template("index.html")
context = {'build': self, 'title': 'Build Summary', 'current': 'home'}
fname = self.output_path / "index.html"
logger.info(f"Creating {fname}...")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are those extra dots really neccesary ?

It's annoying that I cannot just double click on line and copy it to the browser to open it.
I need to strip the extra dots.

Image
Suggested change
logger.info(f"Creating {fname}...")
logger.info(f"Creating {fname}")
buildreport
${PYTHON_EXECUTABLE}
${ZEPHYR_BASE}/scripts/buildreport/buildreport.py
--output ${CMAKE_BINARY_DIR}/report
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps move it a level down, such as:

Suggested change
--output ${CMAKE_BINARY_DIR}/report
--output ${CMAKE_BINARY_DIR}/html/report
@grahamroff-dev
Copy link
Contributor Author

grahamroff-dev commented Feb 27, 2026

@pdgendt ,

I have to say, this looks impressive. The report output is nice, and provides a lot of info in an easy accessible way.

Thanks! There is a lot of great tooling and build information available, and making it easy to generate and use without having to know about each on individually is the goal.

I do have a question regarding maintainership: Are you/Qualcomm going to oversee this? Should we create an area/subarea in the MAINTAINERS.yml file for this?

We (Qualcomm) have begun making extensive use of Zephyr internally (working on an open-source and upstreaming plan) and these optimization tools are a critical part of our work. So yes, absolutely willing to oversee and maintain it, with whatever mechanism makes the most sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment