diff options
author | Kevin Shelton <kmshelton@chromium.org> | 2021-03-30 15:11:37 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-04-05 22:55:46 +0000 |
commit | 0e85e435cfdc234b5b6b7df1c88e63ee1cb8752e (patch) | |
tree | 9934205701978c5f3a69ea88b000b4c85ac97f0c | |
parent | 362e02845295c56a3c1fbb4c5fd39b318a45253c (diff) | |
download | chrome-ec-0e85e435cfdc234b5b6b7df1c88e63ee1cb8752e.tar.gz |
zephyr: firmware_builder bundle functionality
Ports bundle functionality (excluding LCOV info bundling) from
platform/ec/firmware_builder.py.
BUG=b:176926834
BRANCH=None
TEST=./firmware_builder.py --metrics=/tmp/metrics build,
./firmware_builder.py --metrics=/tmp/metrics bundle,
./firmware_builder.py --output-dir=/tmp/testbundle
--metrics=/tmp/metrics --metadata=/tmp/testmetadata bundle,
./firmware_builder.py --metrics=/tmp/metrics --code-coverage
bundle,
bundle with code-coverage option raises an exception as expected,
build included some errors that are unrelated to this change,
e.g.: "Zmake/ERROR: Including boilerplate (Zephyr base):
Signed-off-by: Kevin Shelton <kmshelton@chromium.org>
Change-Id: I3b7a5a0d2ec8415320bdf289b1d64210feeb39c3
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2797541
Reviewed-by: Jack Rosenthal <jrosenth@chromium.org>
-rwxr-xr-x | zephyr/firmware_builder.py | 116 |
1 files changed, 106 insertions, 10 deletions
diff --git a/zephyr/firmware_builder.py b/zephyr/firmware_builder.py index 7a32c45a81..540274105b 100755 --- a/zephyr/firmware_builder.py +++ b/zephyr/firmware_builder.py @@ -10,16 +10,19 @@ This is the entry point for the custom firmware builder workflow recipe. import argparse import multiprocessing -import os -import shutil +import pathlib import subprocess import sys +import zmake.project # TODO(crbug/1181505): Code outside of chromite should not be importing from # chromite.api.gen. Import json_format after that so we get the matching one. from chromite.api.gen.chromite.api import firmware_pb2 from google.protobuf import json_format +DEFAULT_BUNDLE_DIRECTORY = '/tmp/artifact_bundles' +DEFAULT_BUNDLE_METADATA_FILE = '/tmp/artifact_bundle_metadata' + def build(opts): """Builds all Zephyr firmware targets""" @@ -28,26 +31,84 @@ def build(opts): with open(opts.metrics, 'w') as f: f.write(json_format.MessageToJson(metrics)) - temp_build_dir = os.path.join('/tmp', 'zbuild') - targets = [ 'projects/kohaku', 'projects/posix-ec', 'projects/volteer/volteer', ] for target in targets: - if os.path.exists(temp_build_dir): - shutil.rmtree(temp_build_dir) - print('Building {}'.format(target)) - rv = subprocess.run( - ['zmake', '-D', 'configure', '-b', '-B', temp_build_dir, target], - cwd=os.path.dirname(__file__)).returncode + cmd = ['zmake', '-D', 'configure', '-b', target] + rv = subprocess.run(cmd, cwd=pathlib.Path(__file__).parent).returncode if rv != 0: return rv return 0 +def bundle(opts): + if opts.code_coverage: + bundle_coverage(opts) + else: + bundle_firmware(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) + bundle_dir = pathlib.Path(bundle_dir) + if not bundle_dir.is_dir(): + bundle_dir.mkdir() + return bundle_dir + + +def write_metadata(opts, info): + """Write the metadata about the bundle.""" + 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)) + + +def bundle_coverage(opts): + """Bundles the artifacts from code coverage into its own tarball.""" + raise NotImplementedError + + +def bundle_firmware(opts): + """Bundles the artifacts from each target into its own tarball.""" + info = firmware_pb2.FirmwareArtifactInfo() + info.bcs_version_info.version_string = opts.bcs_version + bundle_dir = get_bundle_dir(opts) + zephyr_dir = pathlib.Path(__file__).parent + platform_ec = zephyr_dir.resolve().parent + for project in zmake.project.find_projects(zephyr_dir): + build_dir = zmake.util.resolve_build_dir(platform_ec, + project.project_dir, None) + artifacts_dir = build_dir / 'output' + # TODO(kmshelton): Remove once the build command does not rely + # on a pre-defined list of targets. + if not artifacts_dir.is_dir(): + continue + project_identifier = '_'.join( + project.project_dir. + parts[project.project_dir.parts.index('projects') + 1:]) + tarball_name = '{}.firmware.tbz2'.format(project_identifier) + 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) + # TODO(kmshelton): Populate the rest of metadata contents as it + # gets defined in infra/proto/src/chromite/api/firmware.proto. + + write_metadata(opts, info) + + def test(opts): """Runs all of the unit tests for Zephyr firmware""" # TODO(b/169178847): Add appropriate metric information @@ -86,6 +147,36 @@ def parse_args(args): help='File to write the json-encoded MetricsList proto message.', ) + parser.add_argument( + '--metadata', + required=False, + help=('Full pathname for the file in which to write build artifact ' + 'metadata.'), + ) + + parser.add_argument( + '--output-dir', + required=False, + help= + 'Full pathanme for the directory in which to bundle build artifacts.', + ) + + parser.add_argument( + '--code-coverage', + required=False, + action='store_true', + help='Build host-based unit tests for code coverage.', + ) + + parser.add_argument( + '--bcs-version', + dest='bcs_version', + default='', + required=False, + # TODO(b/180008931): make this required=True. + help='BCS version to include in metadata.', + ) + # Would make this required=True, but not available until 3.7 sub_cmds = parser.add_subparsers() @@ -93,6 +184,11 @@ def parse_args(args): 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.set_defaults(func=bundle) + test_cmd = sub_cmds.add_parser('test', help='Runs all firmware unit tests') test_cmd.set_defaults(func=test) |