diff options
author | Jeremy Bettis <jbettis@google.com> | 2022-03-16 11:36:19 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-03-17 16:48:32 +0000 |
commit | 5e836acebf45a2666e8fb752175718df28b26ccb (patch) | |
tree | b3836c20894baffb5e24118f0b3f04e21db6f25e | |
parent | 02de90dc5dd322059d3636ea6b4dd222da094d8e (diff) | |
download | chrome-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.md | 11 | ||||
-rwxr-xr-x | zephyr/firmware_builder.py | 149 |
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') |