summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Bettis <jbettis@google.com>2022-03-16 11:36:19 -0600
committerCommit Bot <commit-bot@chromium.org>2022-03-17 16:48:32 +0000
commit5e836acebf45a2666e8fb752175718df28b26ccb (patch)
treeb3836c20894baffb5e24118f0b3f04e21db6f25e
parent02de90dc5dd322059d3636ea6b4dd222da094d8e (diff)
downloadchrome-ec-5e836acebf45a2666e8fb752175718df28b26ccb.tar.gz
cq: Export binary and ram sizes in cq build metric
Change firmware_builder.py to export metrics. Here is an example ``` { "targetName": "nereid", "platformName": "it8xxx2", "fwSection": [ { "region": "RO_ROM", "used": 298164, "total": 1048576 }, { "region": "RO_RAM", "used": 51764, "total": 57344 }, { "region": "RO_IDT_LIST", "total": 2048 }, { "region": "RW_ROM", "used": 298164, "total": 1048576 }, { "region": "RW_RAM", "used": 51764, "total": 57344 }, { "region": "RW_IDT_LIST", "total": 2048 } ] }, ``` Also formatted to make cros lint happy. BRANCH=None BUG=b:223846977 TEST=Ran commands in README. Signed-off-by: Jeremy Bettis <jbettis@google.com> Change-Id: Ic1c53d0ce2ba273af714b74f8fc057d9237b5b02 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3529669 Reviewed-by: Jett Rink <jettrink@chromium.org> Commit-Queue: Jeremy Bettis <jbettis@chromium.org> Tested-by: Jeremy Bettis <jbettis@chromium.org>
-rw-r--r--zephyr/README.md11
-rwxr-xr-xzephyr/firmware_builder.py149
2 files changed, 109 insertions, 51 deletions
diff --git a/zephyr/README.md b/zephyr/README.md
index e23aa15a82..880988488e 100644
--- a/zephyr/README.md
+++ b/zephyr/README.md
@@ -28,12 +28,13 @@ To test the cq builder script run these commands:
```
rm -rf /tmp/artifact_bundles /tmp/artifact_bundle_metadata \
~/chromiumos/src/platform/ec/build
-cd ~/chromiumos/src/platform/ec/zephyr
-./firmware_builder.py --metrics /tmp/metrics build && \
-./firmware_builder.py --metrics /tmp/metrics test && \
-./firmware_builder.py --metrics /tmp/metrics bundle && \
-echo PASSED
+( cd ~/chromiumos/src/platform/ec/zephyr ; \
+./firmware_builder.py --metrics /tmp/metrics-build build && \
+./firmware_builder.py --metrics /tmp/metrics-test test && \
+./firmware_builder.py --metrics /tmp/metrics-bundle bundle && \
+echo PASSED )
cat /tmp/artifact_bundle_metadata
+cat /tmp/metrics-build
ls -l /tmp/artifact_bundles/
```
diff --git a/zephyr/firmware_builder.py b/zephyr/firmware_builder.py
index 912b734ae6..fe71fb1ddc 100755
--- a/zephyr/firmware_builder.py
+++ b/zephyr/firmware_builder.py
@@ -26,15 +26,60 @@ DEFAULT_BUNDLE_METADATA_FILE = '/tmp/artifact_bundle_metadata'
def build(opts):
"""Builds all Zephyr firmware targets"""
- # TODO(b/169178847): Add appropriate metric information
- metrics = firmware_pb2.FwBuildMetricList()
- with open(opts.metrics, 'w') as f:
- f.write(json_format.MessageToJson(metrics))
+ metric_list = firmware_pb2.FwBuildMetricList()
cmd = ['zmake', '-D', 'build', '-a']
if opts.code_coverage:
cmd.append('--coverage')
- return subprocess.run(cmd, cwd=pathlib.Path(__file__).parent).returncode
+ subprocess.run(cmd, cwd=pathlib.Path(__file__).parent, check=True)
+ if not opts.code_coverage:
+ zephyr_dir = pathlib.Path(__file__).parent
+ platform_ec = zephyr_dir.resolve().parent
+ for project in zmake.project.find_projects(zephyr_dir).values():
+ if project.config.is_test:
+ continue
+ build_dir = (
+ platform_ec / 'build' / 'zephyr' / project.config.project_name
+ )
+ metric = metric_list.value.add()
+ metric.target_name = project.config.project_name
+ metric.platform_name = project.config.zephyr_board
+ for (variant, _) in project.iter_builds():
+ build_log = build_dir / f'build-{variant}' / 'build.log'
+ parse_buildlog(build_log, metric, variant.upper())
+ with open(opts.metrics, 'w') as f:
+ f.write(json_format.MessageToJson(metric_list))
+ return 0
+
+
+UNITS = {
+ 'B': 1,
+ 'KB': 1024,
+ 'MB': 1024 * 1024,
+ 'GB': 1024 * 1024 * 1024,
+}
+
+
+def parse_buildlog(filename, metric, variant):
+ with open(filename, 'r') as infile:
+ # Skip over all lines until the memory report is found
+ while True:
+ line = infile.readline()
+ if not line:
+ return
+ if line.startswith('Memory region'):
+ break
+
+ for line in infile.readlines():
+ # Skip any lines that are not part of the report
+ if not line.startswith(' '):
+ continue
+ parts = line.split()
+ fw_section = metric.fw_section.add()
+ fw_section.region = variant + '_' + parts[0][:-1]
+ fw_section.used = int(parts[1]) * UNITS[parts[2]]
+ fw_section.total = int(parts[3]) * UNITS[parts[4]]
+ fw_section.track_on_gerrit = False
def bundle(opts):
@@ -47,9 +92,12 @@ def bundle(opts):
def get_bundle_dir(opts):
"""Get the directory for the bundle from opts or use the default.
- Also create the directory if it doesn't exist."""
- bundle_dir = (opts.output_dir
- if opts.output_dir else DEFAULT_BUNDLE_DIRECTORY)
+ Also create the directory if it doesn't exist.
+ """
+ if opts.output_dir:
+ bundle_dir = opts.output_dir
+ else:
+ bundle_dir = DEFAULT_BUNDLE_DIRECTORY
bundle_dir = pathlib.Path(bundle_dir)
if not bundle_dir.is_dir():
bundle_dir.mkdir()
@@ -58,8 +106,9 @@ def get_bundle_dir(opts):
def write_metadata(opts, info):
"""Write the metadata about the bundle."""
- bundle_metadata_file = (opts.metadata
- if opts.metadata else DEFAULT_BUNDLE_METADATA_FILE)
+ bundle_metadata_file = (
+ opts.metadata if opts.metadata else DEFAULT_BUNDLE_METADATA_FILE
+ )
with open(bundle_metadata_file, 'w') as f:
f.write(json_format.MessageToJson(info))
@@ -71,19 +120,20 @@ def bundle_coverage(opts):
bundle_dir = get_bundle_dir(opts)
zephyr_dir = pathlib.Path(__file__).parent
platform_ec = zephyr_dir.resolve().parent
- build_dir = platform_ec / "build" / "zephyr"
+ build_dir = platform_ec / 'build' / 'zephyr'
tarball_name = 'coverage.tbz2'
tarball_path = bundle_dir / tarball_name
cmd = ['tar', 'cvfj', tarball_path, 'lcov.info']
subprocess.run(cmd, cwd=build_dir, check=True)
meta = info.objects.add()
meta.file_name = tarball_name
- meta.lcov_info.type = firmware_pb2.FirmwareArtifactInfo.LcovTarballInfo.LcovType.LCOV
+ meta.lcov_info.type = (
+ firmware_pb2.FirmwareArtifactInfo.LcovTarballInfo.LcovType.LCOV
+ )
write_metadata(opts, info)
-
def bundle_firmware(opts):
"""Bundles the artifacts from each target into its own tarball."""
info = firmware_pb2.FirmwareArtifactInfo()
@@ -94,16 +144,19 @@ def bundle_firmware(opts):
for project in zmake.project.find_projects(zephyr_dir).values():
if project.config.is_test:
continue
- build_dir = platform_ec / "build" / "zephyr" / project.config.project_name
+ build_dir = (
+ platform_ec / 'build' / 'zephyr' / project.config.project_name
+ )
artifacts_dir = build_dir / 'output'
- tarball_name = '{}.firmware.tbz2'.format(project.config.project_name)
+ tarball_name = f'{project.config.project_name}.firmware.tbz2'
tarball_path = bundle_dir.joinpath(tarball_name)
cmd = ['tar', 'cvfj', tarball_path, '.']
subprocess.run(cmd, cwd=artifacts_dir, check=True)
meta = info.objects.add()
meta.file_name = tarball_name
meta.tarball_info.type = (
- firmware_pb2.FirmwareArtifactInfo.TarballInfo.FirmwareType.EC)
+ firmware_pb2.FirmwareArtifactInfo.TarballInfo.FirmwareType.EC
+ )
# TODO(kmshelton): Populate the rest of metadata contents as it
# gets defined in infra/proto/src/chromite/api/firmware.proto.
@@ -124,8 +177,8 @@ def test(opts):
subprocess.run([zephyr_dir / 'zmake' / 'run_tests.sh'], check=True)
# Run formatting checks on all BUILD.py files.
- config_files = zephyr_dir.rglob("**/BUILD.py")
- subprocess.run(["black", "--diff", "--check", *config_files], check=True)
+ config_files = zephyr_dir.rglob('**/BUILD.py')
+ subprocess.run(['black', '--diff', '--check', *config_files], check=True)
cmd = ['zmake', '-D', 'test', '-a', '--no-rebuild']
if opts.code_coverage:
@@ -135,33 +188,32 @@ def test(opts):
return rv
if opts.code_coverage:
platform_ec = zephyr_dir.parent
- build_dir = platform_ec / "build" / "zephyr"
+ build_dir = platform_ec / 'build' / 'zephyr'
# Merge lcov files here because bundle failures are "infra" failures.
cmd = [
- "/usr/bin/lcov",
- "-o",
- build_dir / "fullpaths.info",
- "--rc",
- "lcov_branch_coverage=1",
- "-a", build_dir / 'all_tests.info',
- "-a", build_dir / 'all_builds.info',
+ '/usr/bin/lcov',
+ '-o',
+ build_dir / 'fullpaths.info',
+ '--rc',
+ 'lcov_branch_coverage=1',
+ '-a',
+ build_dir / 'all_tests.info',
+ '-a',
+ build_dir / 'all_builds.info',
]
- rv = subprocess.run(cmd, cwd=pathlib.Path(__file__).parent).returncode
- if rv != 0:
- return rv
+ subprocess.run(cmd, cwd=pathlib.Path(__file__).parent, check=True)
# Make filenames relative to platform/ec
- cmd = ["sed", "-e", "s|^SF:.*/platform/ec/|SF:|"]
- with open(build_dir / "fullpaths.info") as infile, open(
- build_dir / "lcov.info", "w"
+ cmd = ['sed', '-e', 's|^SF:.*/platform/ec/|SF:|']
+ with open(build_dir / 'fullpaths.info') as infile, open(
+ build_dir / 'lcov.info', 'w'
) as outfile:
- rv = subprocess.run(
+ subprocess.run(
cmd,
cwd=pathlib.Path(__file__).parent,
stdin=infile,
stdout=outfile,
- ).returncode
- if rv != 0:
- return rv
+ check=True,
+ )
return 0
@@ -171,7 +223,7 @@ def main(args):
opts = parse_args(args)
if not hasattr(opts, 'func'):
- print("Must select a valid sub command!")
+ print('Must select a valid sub command!')
return -1
# Run selected sub command function
@@ -197,15 +249,19 @@ def parse_args(args):
parser.add_argument(
'--metadata',
required=False,
- help=('Full pathname for the file in which to write build artifact '
- 'metadata.'),
+ help=(
+ 'Full pathname for the file in which to write build artifact '
+ 'metadata.'
+ ),
)
parser.add_argument(
'--output-dir',
required=False,
- help=
- 'Full pathname for the directory in which to bundle build artifacts.',
+ help=(
+ 'Full pathname for the directory in which to bundle build '
+ 'artifacts.',
+ )
)
parser.add_argument(
@@ -227,13 +283,14 @@ def parse_args(args):
# Would make this required=True, but not available until 3.7
sub_cmds = parser.add_subparsers()
- build_cmd = sub_cmds.add_parser('build',
- help='Builds all firmware targets')
+ build_cmd = sub_cmds.add_parser('build', help='Builds all firmware targets')
build_cmd.set_defaults(func=build)
- build_cmd = sub_cmds.add_parser('bundle',
- help='Creates a tarball containing build '
- 'artifacts from all firmware targets')
+ build_cmd = sub_cmds.add_parser(
+ 'bundle',
+ help='Creates a tarball containing build '
+ 'artifacts from all firmware targets',
+ )
build_cmd.set_defaults(func=bundle)
test_cmd = sub_cmds.add_parser('test', help='Runs all firmware unit tests')